Resubmit 2717 w/ fix workaround OS X GL bug.
git-svn-id: http://skia.googlecode.com/svn/trunk@2719 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp
index facfac9..cd37a54 100644
--- a/src/gpu/GrGpuGL.cpp
+++ b/src/gpu/GrGpuGL.cpp
@@ -439,7 +439,15 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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;
}