Implement support for origin-TopLeft render targets. Note that the default behaviour remains the same: textures default to origin-TopLeft, render targets default to origin-BottomLeft, and backend textures default to origin-BottomLeft. However, the caller can override the default by setting fOrigin in GrTextureDesc, GrBackendTextureDesc or GrBackendRenderTargetDesc.
Review URL: https://codereview.appspot.com/7230049
git-svn-id: http://skia.googlecode.com/svn/trunk@7594 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 7ca07a0..5c2e0cb 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -476,6 +476,21 @@
fHWConstAttribCoverage = GrColor_ILLEGAL;
}
+namespace {
+
+GrSurfaceOrigin resolve_origin(GrSurfaceOrigin origin, bool renderTarget) {
+ // By default, GrRenderTargets are GL's normal orientation so that they
+ // can be drawn to by the outside world without the client having
+ // to render upside down.
+ if (kDefault_GrSurfaceOrigin == origin) {
+ return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
+ } else {
+ return origin;
+ }
+}
+
+}
+
GrTexture* GrGpuGL::onWrapBackendTexture(const GrBackendTextureDesc& desc) {
if (!this->configToGLFormats(desc.fConfig, false, NULL, NULL, NULL)) {
return NULL;
@@ -485,12 +500,6 @@
return NULL;
}
- // FIXME: add support for TopLeft RT's by flipping all draws.
- if (desc.fFlags & kRenderTarget_GrBackendTextureFlag &&
- kBottomLeft_GrSurfaceOrigin != desc.fOrigin) {
- return NULL;
- }
-
int maxSize = this->getCaps().maxTextureSize();
if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
return NULL;
@@ -505,16 +514,26 @@
glTexDesc.fSampleCnt = desc.fSampleCnt;
glTexDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle);
glTexDesc.fIsWrapped = true;
- glTexDesc.fOrigin = desc.fOrigin;
+ bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrBackendTextureFlag);
+ // FIXME: this should be calling resolve_origin(), but Chrome code is currently
+ // assuming the old behaviour, which is that backend textures are always
+ // BottomLeft, even for non-RT's. Once Chrome is fixed, change this to:
+ // glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
+ if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
+ glTexDesc.fOrigin = kBottomLeft_GrSurfaceOrigin;
+ } else {
+ glTexDesc.fOrigin = desc.fOrigin;
+ }
GrGLTexture* texture = NULL;
- if (desc.fFlags & kRenderTarget_GrBackendTextureFlag) {
+ if (renderTarget) {
GrGLRenderTarget::Desc glRTDesc;
glRTDesc.fRTFBOID = 0;
glRTDesc.fTexFBOID = 0;
glRTDesc.fMSColorRenderbufferID = 0;
glRTDesc.fConfig = desc.fConfig;
glRTDesc.fSampleCnt = desc.fSampleCnt;
+ glRTDesc.fOrigin = glTexDesc.fOrigin;
if (!this->createRenderTargetObjects(glTexDesc.fWidth,
glTexDesc.fHeight,
glTexDesc.fTextureID,
@@ -541,6 +560,12 @@
glDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
glDesc.fSampleCnt = desc.fSampleCnt;
glDesc.fIsWrapped = true;
+ glDesc.fOrigin = desc.fOrigin;
+ if (glDesc.fRTFBOID == 0) {
+ GrAssert(desc.fOrigin == kBottomLeft_GrSurfaceOrigin);
+ }
+
+ glDesc.fOrigin = resolve_origin(desc.fOrigin, true);
GrGLIRect viewport;
viewport.fLeft = 0;
viewport.fBottom = 0;
@@ -960,10 +985,8 @@
const Caps& caps = this->getCaps();
- // We keep GrRenderTargets in GL's normal orientation so that they
- // can be drawn to by the outside world without the client having
- // to render upside down.
- glTexDesc.fOrigin = renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
+ glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
+ glRTDesc.fOrigin = glTexDesc.fOrigin;
glRTDesc.fSampleCnt = desc.fSampleCnt;
if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() &&
@@ -1278,7 +1301,8 @@
fScissorState.fRect.fLeft,
fScissorState.fRect.fTop,
fScissorState.fRect.width(),
- fScissorState.fRect.height());
+ fScissorState.fRect.height(),
+ rt->origin());
// if the scissor fully contains the viewport then we fall through and
// disable the scissor test.
if (!scissor.contains(vp)) {
@@ -1404,6 +1428,11 @@
int width, int height,
GrPixelConfig config,
size_t rowBytes) const {
+ // If this rendertarget is aready TopLeft, we don't need to flip.
+ if (kTopLeft_GrSurfaceOrigin == renderTarget->origin()) {
+ return false;
+ }
+
// if GL can do the flip then we'll never pay for it.
if (this->glCaps().packFlipYSupport()) {
return false;
@@ -1430,10 +1459,10 @@
int width, int height,
GrPixelConfig config,
void* buffer,
- size_t rowBytes,
- bool invertY) {
+ size_t rowBytes) {
GrGLenum format;
GrGLenum type;
+ bool flipY = kBottomLeft_GrSurfaceOrigin == target->origin();
if (!this->configToGLFormats(config, false, NULL, &format, &type)) {
return false;
}
@@ -1469,7 +1498,7 @@
// the read rect is viewport-relative
GrGLIRect readRect;
- readRect.setRelativeTo(glvp, left, top, width, height);
+ readRect.setRelativeTo(glvp, left, top, width, height, target->origin());
size_t tightRowBytes = bpp * width;
if (0 == rowBytes) {
@@ -1491,7 +1520,7 @@
readDst = scratch.get();
}
}
- if (!invertY && this->glCaps().packFlipYSupport()) {
+ if (flipY && this->glCaps().packFlipYSupport()) {
GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1));
}
GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom,
@@ -1501,9 +1530,9 @@
GrAssert(this->glCaps().packRowLengthSupport());
GL_CALL(PixelStorei(GR_GL_PACK_ROW_LENGTH, 0));
}
- if (!invertY && this->glCaps().packFlipYSupport()) {
+ if (flipY && this->glCaps().packFlipYSupport()) {
GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 0));
- invertY = true;
+ flipY = false;
}
// now reverse the order of the rows, since GL's are bottom-to-top, but our
@@ -1511,7 +1540,7 @@
// that the above readPixels did not overwrite the padding.
if (readDst == buffer) {
GrAssert(rowBytes == readDstRowBytes);
- if (!invertY) {
+ if (flipY) {
scratch.reset(tightRowBytes);
void* tmpRow = scratch.get();
// flip y in-place by rows
@@ -1532,13 +1561,13 @@
// const int halfY = height >> 1;
const char* src = reinterpret_cast<const char*>(readDst);
char* dst = reinterpret_cast<char*>(buffer);
- if (!invertY) {
+ if (flipY) {
dst += (height-1) * rowBytes;
}
for (int y = 0; y < height; y++) {
memcpy(dst, src, tightRowBytes);
src += readDstRowBytes;
- if (invertY) {
+ if (!flipY) {
dst += rowBytes;
} else {
dst -= rowBytes;
@@ -1735,7 +1764,7 @@
const GrIRect dirtyRect = rt->getResolveRect();
GrGLIRect r;
r.setRelativeTo(vp, dirtyRect.fLeft, dirtyRect.fTop,
- dirtyRect.width(), dirtyRect.height());
+ dirtyRect.width(), dirtyRect.height(), target->origin());
GrAutoTRestore<ScissorState> asr;
if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {