Resubmit 2717 w/ fix workaround OS X GL bug.
git-svn-id: http://skia.googlecode.com/svn/trunk@2719 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
484be2bafd
commit
a85449dac1
@ -78,9 +78,9 @@
|
||||
* The GrGLInterface field fCallback specifies the function ptr and there is an
|
||||
* additional field fCallbackData of type intptr_t for client data.
|
||||
*
|
||||
* GR_GL_RGBA_8888_READBACK_SLOW: Set this to 1 if it is known that performing
|
||||
* glReadPixels with format=GL_RGBA, type=GL_UNISIGNED_BYTE is significantly
|
||||
* slower than format=GL_BGRA, type=GL_UNISIGNED_BYTE.
|
||||
* GR_GL_RGBA_8888_PIXEL_OPS_SLOW: Set this to 1 if it is known that performing
|
||||
* glReadPixels / glTex(Sub)Image with format=GL_RGBA, type=GL_UNISIGNED_BYTE is
|
||||
* significantly slower than format=GL_BGRA, type=GL_UNISIGNED_BYTE.
|
||||
*/
|
||||
|
||||
#if !defined(GR_GL_LOG_CALLS)
|
||||
@ -115,8 +115,8 @@
|
||||
#define GR_GL_PER_GL_FUNC_CALLBACK 0
|
||||
#endif
|
||||
|
||||
#if !defined(GR_GL_RGBA_8888_READBACK_SLOW)
|
||||
#define GR_GL_RGBA_8888_READBACK_SLOW 0
|
||||
#if !defined(GR_GL_RGBA_8888_PIXEL_OPS_SLOW)
|
||||
#define GR_GL_RGBA_8888_PIXEL_OPS_SLOW 0
|
||||
#endif
|
||||
|
||||
#if(GR_GL_NO_CONSTANT_ATTRIBUTES) && (GR_GL_ATTRIBUTE_MATRICES)
|
||||
|
@ -14,8 +14,8 @@
|
||||
// ANGLE creates a temp VB for vertex attributes not specified per-vertex.
|
||||
#define GR_GL_NO_CONSTANT_ATTRIBUTES GR_WIN32_BUILD
|
||||
|
||||
// RGBA Readbacks are a slow path in ANGLE
|
||||
#define GR_GL_RGBA_8888_READBACK_SLOW GR_WIN32_BUILD
|
||||
// For RGBA teximage/readpixels ANGLE will sw-convert to/from BGRA.
|
||||
#define GR_GL_RGBA_8888_PIXEL_OPS_SLOW GR_WIN32_BUILD
|
||||
|
||||
// cmd buffer allocates memory and memsets it to zero when it sees glBufferData
|
||||
// with NULL.
|
||||
|
@ -1667,11 +1667,7 @@ bool GrContext::internalReadTexturePixels(GrTexture* texture,
|
||||
uint32_t flags) {
|
||||
SK_TRACE_EVENT0("GrContext::readTexturePixels");
|
||||
|
||||
// TODO: code read pixels for textures that aren't rendertargets
|
||||
|
||||
if (!(kDontFlush_PixelOpsFlag & flags)) {
|
||||
this->flush();
|
||||
}
|
||||
// TODO: code read pixels for textures that aren't also rendertargets
|
||||
GrRenderTarget* target = texture->asRenderTarget();
|
||||
if (NULL != target) {
|
||||
return this->internalReadRenderTargetPixels(target,
|
||||
@ -1803,6 +1799,31 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
|
||||
// TODO: when underlying api has a direct way to do this we should use it
|
||||
// (e.g. glDrawPixels on desktop GL).
|
||||
|
||||
// If the RT is also a texture and we don't have to do PM/UPM conversion
|
||||
// then take the texture path, which we expect to be at least as fast or
|
||||
// faster since it doesn't use an intermediate texture as we do below.
|
||||
|
||||
#if !GR_MAC_BUILD
|
||||
// At least some drivers on the Mac get confused when glTexImage2D is called
|
||||
// on a texture attached to an FBO. The FBO still sees the old image. TODO:
|
||||
// determine what OS versions and/or HW is affected.
|
||||
if (NULL != target->asTexture() &&
|
||||
GrPixelConfigIsUnpremultiplied(target->config()) ==
|
||||
GrPixelConfigIsUnpremultiplied(config)) {
|
||||
|
||||
this->internalWriteTexturePixels(target->asTexture(),
|
||||
left, top, width, height,
|
||||
config, buffer, rowBytes, flags);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool swapRAndB = fGpu->preferredReadPixelsConfig(config) ==
|
||||
GrPixelConfigSwapRAndB(config);
|
||||
if (swapRAndB) {
|
||||
config = GrPixelConfigSwapRAndB(config);
|
||||
}
|
||||
|
||||
const GrTextureDesc desc = {
|
||||
kNone_GrTextureFlags, kNone_GrAALevel, width, height, { config }
|
||||
};
|
||||
@ -1827,6 +1848,7 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
|
||||
sampler.setClampNoFilter();
|
||||
matrix.setIDiv(texture->width(), texture->height());
|
||||
sampler.setMatrix(matrix);
|
||||
sampler.setRAndBSwap(swapRAndB);
|
||||
fGpu->setSamplerState(0, sampler);
|
||||
|
||||
GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
|
||||
|
@ -194,6 +194,13 @@ public:
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above but applies to writeTexturePixels
|
||||
*/
|
||||
virtual GrPixelConfig preferredWritePixelsConfig(GrPixelConfig config) {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenGL's readPixels returns the result bottom-to-top while the skia
|
||||
* API is top-to-bottom. Thus we have to do a y-axis flip. The obvious
|
||||
@ -247,6 +254,7 @@ public:
|
||||
|
||||
/**
|
||||
* Updates the pixels in a rectangle of a texture.
|
||||
*
|
||||
* @param left left edge of the rectangle to write (inclusive)
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
|
@ -439,7 +439,15 @@ void GrGpuGL::initStencilFormats() {
|
||||
}
|
||||
|
||||
GrPixelConfig GrGpuGL::preferredReadPixelsConfig(GrPixelConfig config) {
|
||||
if (GR_GL_RGBA_8888_READBACK_SLOW && GrPixelConfigIsRGBA8888(config)) {
|
||||
if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) {
|
||||
return GrPixelConfigSwapRAndB(config);
|
||||
} else {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
GrPixelConfig GrGpuGL::preferredWritePixelsConfig(GrPixelConfig config) {
|
||||
if (GR_GL_RGBA_8888_PIXEL_OPS_SLOW && GrPixelConfigIsRGBA8888(config)) {
|
||||
return GrPixelConfigSwapRAndB(config);
|
||||
} else {
|
||||
return config;
|
||||
@ -693,21 +701,46 @@ void GrGpuGL::onWriteTexturePixels(GrTexture* texture,
|
||||
this->uploadTexData(desc, left, top, width, height, config, buffer, rowBytes);
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool adjust_pixel_ops_params(int surfaceWidth,
|
||||
int surfaceHeight,
|
||||
size_t bpp,
|
||||
int* left, int* top, int* width, int* height,
|
||||
const void** data,
|
||||
size_t* rowBytes) {
|
||||
if (!*rowBytes) {
|
||||
*rowBytes = *width * bpp;
|
||||
}
|
||||
|
||||
GrIRect subRect = GrIRect::MakeXYWH(*left, *top, *width, *height);
|
||||
GrIRect bounds = GrIRect::MakeWH(surfaceWidth, surfaceHeight);
|
||||
|
||||
if (!subRect.intersect(bounds)) {
|
||||
return false;
|
||||
}
|
||||
*data = reinterpret_cast<const void*>(reinterpret_cast<intptr_t>(*data) +
|
||||
(subRect.fTop - *top) * *rowBytes + (subRect.fLeft - *left) * bpp);
|
||||
|
||||
*left = subRect.fLeft;
|
||||
*top = subRect.fTop;
|
||||
*width = subRect.width();
|
||||
*height = subRect.height();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dataConfig,
|
||||
const void* data,
|
||||
size_t rowBytes) {
|
||||
GrIRect bounds = GrIRect::MakeWH(desc.fWidth, desc.fHeight);
|
||||
GrIRect subrect = GrIRect::MakeXYWH(left, top, width, height);
|
||||
if (!bounds.contains(subrect)) {
|
||||
|
||||
size_t bpp = GrBytesPerPixel(dataConfig);
|
||||
if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top,
|
||||
&width, &height, &data, &rowBytes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ES2 glCompressedTexSubImage2D doesn't support any formats
|
||||
// (at least without extensions)
|
||||
GrAssert(desc.fInternalFormat != GR_GL_PALETTE8_RGBA8 ||
|
||||
bounds == subrect);
|
||||
size_t trimRowBytes = width * bpp;
|
||||
|
||||
// in case we need a temporary, trimmed copy of the src pixels
|
||||
SkAutoSMalloc<128 * 128> tempStorage;
|
||||
@ -720,11 +753,6 @@ void GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bpp = GrBytesPerPixel(dataConfig);
|
||||
size_t trimRowBytes = width * bpp;
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
}
|
||||
/*
|
||||
* check whether to allocate a temporary buffer for flipping y or
|
||||
* because our srcData has extra bytes past each row. If so, we need
|
||||
@ -758,13 +786,14 @@ void GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc,
|
||||
}
|
||||
dst += trimRowBytes;
|
||||
}
|
||||
// now point dat to our copied version
|
||||
// now point data to our copied version
|
||||
data = tempStorage.get();
|
||||
}
|
||||
}
|
||||
|
||||
GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp)));
|
||||
if (bounds == subrect) {
|
||||
if (0 == left && 0 == top &&
|
||||
desc.fWidth == width && desc.fHeight == height) {
|
||||
GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, desc.fInternalFormat,
|
||||
desc.fWidth, desc.fHeight, 0,
|
||||
externalFormat, externalType, data));
|
||||
@ -1320,9 +1349,18 @@ bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget,
|
||||
size_t rowBytes) {
|
||||
// if we have to do memcpy to handle non-trim rowBytes then we
|
||||
// get the flip for free. Otherwise it costs.
|
||||
return this->glCaps().fPackRowLengthSupport ||
|
||||
0 == rowBytes ||
|
||||
GrBytesPerPixel(config) * width == rowBytes;
|
||||
if (this->glCaps().fPackRowLengthSupport) {
|
||||
return true;
|
||||
}
|
||||
// If we have to do memcpys to handle rowBytes then y-flip is free
|
||||
// Note the rowBytes might be tight to the passed in data, but if data
|
||||
// gets clipped in x to the target the rowBytes will no longer be tight.
|
||||
if (left >= 0 && (left + width) < renderTarget->width()) {
|
||||
return 0 == rowBytes ||
|
||||
GrBytesPerPixel(config) * width == rowBytes;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GrGpuGL::onReadPixels(GrRenderTarget* target,
|
||||
@ -1338,6 +1376,13 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
|
||||
if (!this->canBeTexture(config, &internalFormat, &format, &type)) {
|
||||
return false;
|
||||
}
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
if (!adjust_pixel_ops_params(target->width(), target->height(), bpp,
|
||||
&left, &top, &width, &height,
|
||||
const_cast<const void**>(&buffer),
|
||||
&rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// resolve the render target if necessary
|
||||
GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
|
||||
@ -1366,7 +1411,7 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
|
||||
GrGLIRect readRect;
|
||||
readRect.setRelativeTo(glvp, left, top, width, height);
|
||||
|
||||
size_t tightRowBytes = GrBytesPerPixel(config) * width;
|
||||
size_t tightRowBytes = bpp * width;
|
||||
if (0 == rowBytes) {
|
||||
rowBytes = tightRowBytes;
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ public:
|
||||
|
||||
virtual GrPixelConfig preferredReadPixelsConfig(GrPixelConfig config)
|
||||
SK_OVERRIDE;
|
||||
virtual GrPixelConfig preferredWritePixelsConfig(GrPixelConfig config)
|
||||
SK_OVERRIDE;
|
||||
|
||||
virtual bool readPixelsWillPayForYFlip(
|
||||
GrRenderTarget* renderTarget,
|
||||
|
Loading…
Reference in New Issue
Block a user