diff options
author | 2013-02-05 19:50:46 +0000 | |
---|---|---|
committer | 2013-02-05 19:50:46 +0000 | |
commit | 3cb406bb88f5aa09cf9f5a9554b4b1314cf1a2ee (patch) | |
tree | 65c641a9f93913a6e131ebaf71aeea30f4d52827 /src/gpu/gl | |
parent | 0ac6f168f15393a3213c1c95f8adc4434132dcb2 (diff) |
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
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLIRect.h | 11 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLRenderTarget.cpp | 13 | ||||
-rw-r--r-- | src/gpu/gl/GrGLRenderTarget.h | 13 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.cpp | 13 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTexture.cpp | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTexture.h | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 75 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 32 |
11 files changed, 122 insertions, 56 deletions
diff --git a/src/gpu/gl/GrGLIRect.h b/src/gpu/gl/GrGLIRect.h index 038520d238..cbc4cb89f6 100644 --- a/src/gpu/gl/GrGLIRect.h +++ b/src/gpu/gl/GrGLIRect.h @@ -38,15 +38,20 @@ struct GrGLIRect { // sometimes we have a GrIRect from the client that we // want to simultaneously make relative to GL's viewport - // and convert from top-down to bottom-up. + // and (optionally) convert from top-down to bottom-up. void setRelativeTo(const GrGLIRect& glRect, int leftOffset, int topOffset, int width, - int height) { + int height, + GrSurfaceOrigin origin) { fLeft = glRect.fLeft + leftOffset; fWidth = width; - fBottom = glRect.fBottom + (glRect.fHeight - topOffset - height); + if (kBottomLeft_GrSurfaceOrigin == origin) { + fBottom = glRect.fBottom + (glRect.fHeight - topOffset - height); + } else { + fBottom = glRect.fBottom + topOffset; + } fHeight = height; GrAssert(fLeft >= 0); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 2aa723619b..a4f0df2fed 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -64,6 +64,7 @@ GrGLProgram::GrGLProgram(const GrGLContextInfo& gl, fViewMatrix = SkMatrix::InvalidMatrix(); fViewportSize.set(-1, -1); + fOrigin = (GrSurfaceOrigin) -1; fColor = GrColor_ILLEGAL; fColorFilterColor = GrColor_ILLEGAL; fRTHeight = -1; diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 513bf75d23..8b494c8cef 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -199,10 +199,11 @@ private: GrGLuint fGShaderID; GrGLuint fFShaderID; GrGLuint fProgramID; - // The matrix sent to GL is determined by both the client's matrix and - // the size of the viewport. + // The matrix sent to GL is determined by the client's matrix, + // the size of the viewport, and the origin of the render target. SkMatrix fViewMatrix; SkISize fViewportSize; + GrSurfaceOrigin fOrigin; // these reflect the current values of uniforms (GL uniform values travel with program) GrColor fColor; diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp index 47128e7064..69d7b9ca58 100644 --- a/src/gpu/gl/GrGLRenderTarget.cpp +++ b/src/gpu/gl/GrGLRenderTarget.cpp @@ -27,13 +27,15 @@ void GrGLRenderTarget::init(const Desc& desc, namespace { GrTextureDesc MakeDesc(GrTextureFlags flags, int width, int height, - GrPixelConfig config, int sampleCnt) { + GrPixelConfig config, int sampleCnt, + GrSurfaceOrigin origin) { GrTextureDesc temp; temp.fFlags = flags; temp.fWidth = width; temp.fHeight = height; temp.fConfig = config; temp.fSampleCnt = sampleCnt; + temp.fOrigin = origin; return temp; } @@ -49,9 +51,8 @@ GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu, texture, MakeDesc(kNone_GrTextureFlags, viewport.fWidth, viewport.fHeight, - desc.fConfig, desc.fSampleCnt), - texture->origin()) { - GrAssert(kBottomLeft_GrSurfaceOrigin == texture->origin()); + desc.fConfig, desc.fSampleCnt, + desc.fOrigin)) { GrAssert(NULL != texID); GrAssert(NULL != texture); // FBO 0 can't also be a texture, right? @@ -73,8 +74,8 @@ GrGLRenderTarget::GrGLRenderTarget(GrGpuGL* gpu, NULL, MakeDesc(kNone_GrTextureFlags, viewport.fWidth, viewport.fHeight, - desc.fConfig, desc.fSampleCnt), - kBottomLeft_GrSurfaceOrigin) { + desc.fConfig, desc.fSampleCnt, + desc.fOrigin)) { this->init(desc, viewport, NULL); } diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h index 9a39ca1c2c..ea6ae87b99 100644 --- a/src/gpu/gl/GrGLRenderTarget.h +++ b/src/gpu/gl/GrGLRenderTarget.h @@ -25,12 +25,13 @@ public: enum { kUnresolvableFBOID = 0 }; struct Desc { - GrGLuint fRTFBOID; - GrGLuint fTexFBOID; - GrGLuint fMSColorRenderbufferID; - bool fIsWrapped; - GrPixelConfig fConfig; - int fSampleCnt; + GrGLuint fRTFBOID; + GrGLuint fTexFBOID; + GrGLuint fMSColorRenderbufferID; + bool fIsWrapped; + GrPixelConfig fConfig; + int fSampleCnt; + GrSurfaceOrigin fOrigin; }; // creates a GrGLRenderTarget associated with a texture diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index a8514ad471..1618fe5416 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -260,6 +260,7 @@ void GrGLShaderBuilder::addVarying(GrSLType type, } const char* GrGLShaderBuilder::fragmentPosition() { +#if 1 if (fContext.caps().fragCoordConventionsSupport()) { if (!fSetupFragPosition) { fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n"); @@ -294,6 +295,18 @@ const char* GrGLShaderBuilder::fragmentPosition() { GrAssert(GrGLUniformManager::kInvalidUniformHandle != fRTHeightUniform); return kCoordName; } +#else + // This is the path we'll need to use once we have support for TopLeft + // render targets. + if (!fSetupFragPosition) { + fFSInputs.push_back().set(kVec4f_GrSLType, + GrGLShaderVar::kIn_TypeModifier, + "gl_FragCoord", + GrGLShaderVar::kDefault_Precision); + fSetupFragPosition = true; + } + return "gl_FragCoord"; +#endif } diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp index f798b31ea0..66d6371f06 100644 --- a/src/gpu/gl/GrGLTexture.cpp +++ b/src/gpu/gl/GrGLTexture.cpp @@ -28,7 +28,6 @@ void GrGLTexture::init(GrGpuGL* gpu, textureDesc.fIsWrapped)); if (NULL != rtDesc) { - GrAssert(kBottomLeft_GrSurfaceOrigin == textureDesc.fOrigin); GrGLIRect vp; vp.fLeft = 0; vp.fWidth = textureDesc.fWidth; @@ -42,14 +41,14 @@ void GrGLTexture::init(GrGpuGL* gpu, GrGLTexture::GrGLTexture(GrGpuGL* gpu, const Desc& textureDesc) - : INHERITED(gpu, textureDesc.fIsWrapped, textureDesc, textureDesc.fOrigin) { + : INHERITED(gpu, textureDesc.fIsWrapped, textureDesc) { this->init(gpu, textureDesc, NULL); } GrGLTexture::GrGLTexture(GrGpuGL* gpu, const Desc& textureDesc, const GrGLRenderTarget::Desc& rtDesc) - : INHERITED(gpu, textureDesc.fIsWrapped, textureDesc, textureDesc.fOrigin) { + : INHERITED(gpu, textureDesc.fIsWrapped, textureDesc) { this->init(gpu, textureDesc, &rtDesc); } diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h index 231482134b..79cea08663 100644 --- a/src/gpu/gl/GrGLTexture.h +++ b/src/gpu/gl/GrGLTexture.h @@ -59,7 +59,6 @@ public: struct Desc : public GrTextureDesc { GrGLuint fTextureID; bool fIsWrapped; - GrSurfaceOrigin fOrigin; }; // creates a texture that is also an RT diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 7ca07a0623..5c2e0cbcb3 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -476,6 +476,21 @@ void GrGpuGL::onResetContext() { 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 @@ GrTexture* GrGpuGL::onWrapBackendTexture(const GrBackendTextureDesc& desc) { 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 @@ GrTexture* GrGpuGL::onWrapBackendTexture(const GrBackendTextureDesc& desc) { 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 @@ GrRenderTarget* GrGpuGL::onWrapBackendRenderTarget(const GrBackendRenderTargetDe 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 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, 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 @@ void GrGpuGL::flushScissor() { 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 @@ bool GrGpuGL::readPixelsWillPayForYFlip(GrRenderTarget* renderTarget, 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 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, 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 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, // 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 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, 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 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, 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 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, // 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 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, // 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 @@ void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) { 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()) { diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index df9d8fc3c9..71cb699812 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -86,8 +86,7 @@ private: int width, int height, GrPixelConfig, void* buffer, - size_t rowBytes, - bool invertY) SK_OVERRIDE; + size_t rowBytes) SK_OVERRIDE; virtual void onWriteTexturePixels(GrTexture* texture, int left, int top, int width, int height, @@ -322,11 +321,13 @@ private: } fHWAAState; struct { - SkMatrix fViewMatrix; - SkISize fRTSize; + SkMatrix fViewMatrix; + SkISize fRTSize; + GrSurfaceOrigin fLastOrigin; void invalidate() { fViewMatrix = SkMatrix::InvalidMatrix(); fRTSize.fWidth = -1; // just make the first value compared illegal. + fLastOrigin = (GrSurfaceOrigin) -1; } } fHWPathMatrixState; diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index d5e8fbdd79..28f76de2ac 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -92,13 +92,19 @@ void GrGpuGL::flushViewMatrix(DrawType type) { const SkMatrix& vm = this->getDrawState().getViewMatrix(); if (kStencilPath_DrawType == type) { - if (fHWPathMatrixState.fViewMatrix != vm || + if (fHWPathMatrixState.fLastOrigin != rt->origin() || + fHWPathMatrixState.fViewMatrix != vm || fHWPathMatrixState.fRTSize != viewportSize) { // rescale the coords from skia's "device" coords to GL's normalized coords, - // and perform a y-flip. + // and perform a y-flip if required. SkMatrix m; - m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height()); - m.postTranslate(-SK_Scalar1, SK_Scalar1); + if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { + m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(-2) / rt->height()); + m.postTranslate(-SK_Scalar1, SK_Scalar1); + } else { + m.setScale(SkIntToScalar(2) / rt->width(), SkIntToScalar(2) / rt->height()); + m.postTranslate(-SK_Scalar1, -SK_Scalar1); + } m.preConcat(vm); // GL wants a column-major 4x4. @@ -128,14 +134,23 @@ void GrGpuGL::flushViewMatrix(DrawType type) { GL_CALL(LoadMatrixf(mv)); fHWPathMatrixState.fViewMatrix = vm; fHWPathMatrixState.fRTSize = viewportSize; + fHWPathMatrixState.fLastOrigin = rt->origin(); } - } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) || + } else if (fCurrentProgram->fOrigin != rt->origin() || + !fCurrentProgram->fViewMatrix.cheapEqualTo(vm) || fCurrentProgram->fViewportSize != viewportSize) { SkMatrix m; - m.setAll( - SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1, - 0,-SkIntToScalar(2) / viewportSize.fHeight, SK_Scalar1, + if (kBottomLeft_GrSurfaceOrigin == rt->origin()) { + m.setAll( + SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1, + 0,-SkIntToScalar(2) / viewportSize.fHeight, SK_Scalar1, + 0, 0, SkMatrix::I()[8]); + } else { + m.setAll( + SkIntToScalar(2) / viewportSize.fWidth, 0, -SK_Scalar1, + 0, SkIntToScalar(2) / viewportSize.fHeight,-SK_Scalar1, 0, 0, SkMatrix::I()[8]); + } m.setConcat(m, vm); // ES doesn't allow you to pass true to the transpose param, @@ -156,6 +171,7 @@ void GrGpuGL::flushViewMatrix(DrawType type) { mt); fCurrentProgram->fViewMatrix = vm; fCurrentProgram->fViewportSize = viewportSize; + fCurrentProgram->fOrigin = rt->origin(); } } |