aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-02-04 17:29:51 +0000
committerGravatar senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-02-04 17:29:51 +0000
commited8659b51d9f2bad3f004df6033d72cc32d71c0d (patch)
treec9882164b3ce1c63e164bf0434c9505c95f80b6f /src/gpu/gl
parent83f7c659461d602e498569dab63f04b1b578b742 (diff)
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
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLIRect.h11
-rw-r--r--src/gpu/gl/GrGLProgram.cpp1
-rw-r--r--src/gpu/gl/GrGLProgram.h5
-rw-r--r--src/gpu/gl/GrGLRenderTarget.cpp13
-rw-r--r--src/gpu/gl/GrGLRenderTarget.h13
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp13
-rw-r--r--src/gpu/gl/GrGLTexture.cpp5
-rw-r--r--src/gpu/gl/GrGLTexture.h1
-rw-r--r--src/gpu/gl/GrGpuGL.cpp63
-rw-r--r--src/gpu/gl/GrGpuGL.h9
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp32
11 files changed, 110 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..7f5f999e10 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -147,6 +147,17 @@ static bool fbo_test(const GrGLInterface* gl, int w, int h) {
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 @@ 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 +510,18 @@ 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);
+ 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 @@ 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 +973,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 +1289,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 +1416,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 +1447,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 +1486,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 +1508,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 +1518,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 +1528,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 +1549,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 +1752,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 3b8c16fabf..5b24d40578 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();
}
}