Implement support for origin-TopLeft render targets in GL backend.
Review URL: https://codereview.appspot.com/7230049
git-svn-id: http://skia.googlecode.com/svn/trunk@7545 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 7ca07a0..7f5f999 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -147,6 +147,17 @@
return status == GR_GL_FRAMEBUFFER_COMPLETE;
}
+static 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;
+ }
+}
+
GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
GrAssert(ctxInfo.isInitialized());
@@ -485,12 +496,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 +510,18 @@
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);
+ glTexDesc.fOrigin = resolve_origin(desc.fOrigin, renderTarget);
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 +548,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 +973,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 +1289,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 +1416,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 +1447,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 +1486,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 +1508,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 +1518,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 +1528,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 +1549,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 +1752,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()) {