Permalink
Browse files

Implement support for origin-TopLeft render targets. Note that the de…

…fault 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
  • Loading branch information...
1 parent ba00d45 commit f1d7de241cc6f7f370ef327ee285eca1ff586045 senorblanco@chromium.org committed Feb 5, 2013
@@ -141,9 +141,8 @@ class GrRenderTarget : public GrSurface {
GrRenderTarget(GrGpu* gpu,
bool isWrapped,
GrTexture* texture,
- const GrTextureDesc& desc,
- GrSurfaceOrigin origin)
- : INHERITED(gpu, isWrapped, desc, origin)
+ const GrTextureDesc& desc)
+ : INHERITED(gpu, isWrapped, desc)
, fStencilBuffer(NULL)
, fTexture(texture) {
fResolveRect.setLargestInverted();
View
@@ -34,8 +34,8 @@ class GrSurface : public GrResource {
int height() const { return fDesc.fHeight; }
GrSurfaceOrigin origin() const {
- GrAssert(kTopLeft_GrSurfaceOrigin == fOrigin || kBottomLeft_GrSurfaceOrigin == fOrigin);
- return fOrigin;
+ GrAssert(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin || kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin);
+ return fDesc.fOrigin;
}
/**
@@ -104,17 +104,14 @@ class GrSurface : public GrResource {
uint32_t pixelOpsFlags = 0) = 0;
protected:
- GrSurface(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc, GrSurfaceOrigin origin)
+ GrSurface(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
: INHERITED(gpu, isWrapped)
- , fDesc(desc)
- , fOrigin(origin) {
+ , fDesc(desc) {
}
GrTextureDesc fDesc;
private:
- GrSurfaceOrigin fOrigin;
-
typedef GrResource INHERITED;
};
View
@@ -140,8 +140,8 @@ class GrTexture : public GrSurface {
// base class cons sets to NULL
// subclass cons can create and set
- GrTexture(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc, GrSurfaceOrigin origin)
- : INHERITED(gpu, isWrapped, desc, origin)
+ GrTexture(GrGpu* gpu, bool isWrapped, const GrTextureDesc& desc)
+ : INHERITED(gpu, isWrapped, desc)
, fRenderTarget(NULL) {
// only make sense if alloc size is pow2
View
@@ -428,13 +428,14 @@ enum {
/**
* Some textures will be stored such that the upper and left edges of the content meet at the
* the origin (in texture coord space) and for other textures the lower and left edges meet at
- * the origin. Render-targets are always consistent with the convention of the underlying
- * backend API to make it easier to mix native backend rendering with Skia rendering.
+ * the origin. kDefault_GrSurfaceOrigin sets textures to TopLeft, and render targets
+ * to BottomLeft.
*/
enum GrSurfaceOrigin {
- kBottomLeft_GrSurfaceOrigin,
+ kDefault_GrSurfaceOrigin, // DEPRECATED; to be removed
kTopLeft_GrSurfaceOrigin,
+ kBottomLeft_GrSurfaceOrigin,
};
/**
@@ -443,13 +444,15 @@ enum GrSurfaceOrigin {
struct GrTextureDesc {
GrTextureDesc()
: fFlags(kNone_GrTextureFlags)
+ , fOrigin(kDefault_GrSurfaceOrigin)
, fWidth(0)
, fHeight(0)
, fConfig(kUnknown_GrPixelConfig)
, fSampleCnt(0) {
}
GrTextureFlags fFlags; //!< bitfield of TextureFlags
+ GrSurfaceOrigin fOrigin; //!< origin of the texture
int fWidth; //!< Width of the texture
int fHeight; //!< Height of the texture
@@ -640,6 +643,7 @@ struct GrBackendRenderTargetDesc {
int fWidth; //<! width in pixels
int fHeight; //<! height in pixels
GrPixelConfig fConfig; //<! color format
+ GrSurfaceOrigin fOrigin; //<! pixel origin
/**
* The number of samples per pixel. Gr uses this to influence decisions
* about applying other forms of anti-aliasing.
View
@@ -295,6 +295,7 @@ class SampleWindow::DefaultDeviceManager : public SampleWindow::DeviceManager {
desc.fWidth = SkScalarRound(win->width());
desc.fHeight = SkScalarRound(win->height());
desc.fConfig = kSkia8888_PM_GrPixelConfig;
+ desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
GR_GL_GetIntegerv(fCurIntf, GR_GL_SAMPLES, &desc.fSampleCnt);
GR_GL_GetIntegerv(fCurIntf, GR_GL_STENCIL_BITS, &desc.fStencilBits);
GrGLint buffer;
View
@@ -1328,10 +1328,6 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
- // flipY will get set to false when it is handled below using a scratch. However, in that case
- // we still want to do the read upside down.
- bool readUpsideDown = flipY;
-
if (unpremul && kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
// The unpremul flag is only allowed for these two configs.
return false;
@@ -1359,6 +1355,7 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
desc.fWidth = width;
desc.fHeight = height;
desc.fConfig = readConfig;
+ desc.fOrigin = kTopLeft_GrSurfaceOrigin;
// When a full readback is faster than a partial we could always make the scratch exactly
// match the passed rect. However, if we see many different size rectangles we will trash
@@ -1377,13 +1374,7 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
if (texture) {
// compute a matrix to perform the draw
SkMatrix textureMatrix;
- if (flipY) {
- textureMatrix.setTranslate(SK_Scalar1 * left,
- SK_Scalar1 * (top + height));
- textureMatrix.set(SkMatrix::kMScaleY, -SK_Scalar1);
- } else {
- textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
- }
+ textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
textureMatrix.postIDiv(src->width(), src->height());
SkAutoTUnref<const GrEffectRef> effect;
@@ -1404,7 +1395,6 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
textureMatrix));
}
swapRAndB = false; // we will handle the swap in the draw.
- flipY = false; // we already incorporated the y flip in the matrix
GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
GrDrawState* drawState = fGpu->drawState();
@@ -1423,11 +1413,11 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
}
if (!fGpu->readPixels(target,
left, top, width, height,
- readConfig, buffer, rowBytes, readUpsideDown)) {
+ readConfig, buffer, rowBytes)) {
return false;
}
// Perform any conversions we weren't able to perform using a scratch texture.
- if (unpremul || swapRAndB || flipY) {
+ if (unpremul || swapRAndB) {
// These are initialized to suppress a warning
SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
SkCanvas::Config8888 dstC8888 = SkCanvas::kNative_Premul_Config8888;
@@ -1439,47 +1429,11 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
GrAssert(c8888IsValid); // we should only do r/b swap on 8888 configs
srcC8888 = swap_config8888_red_and_blue(srcC8888);
}
- if (flipY) {
- size_t tightRB = width * GrBytesPerPixel(config);
- if (0 == rowBytes) {
- rowBytes = tightRB;
- }
- SkAutoSTMalloc<256, uint8_t> tempRow(tightRB);
- intptr_t top = reinterpret_cast<intptr_t>(buffer);
- intptr_t bot = top + (height - 1) * rowBytes;
- while (top < bot) {
- uint32_t* t = reinterpret_cast<uint32_t*>(top);
- uint32_t* b = reinterpret_cast<uint32_t*>(bot);
- uint32_t* temp = reinterpret_cast<uint32_t*>(tempRow.get());
- memcpy(temp, t, tightRB);
- if (c8888IsValid) {
- SkConvertConfig8888Pixels(t, tightRB, dstC8888,
- b, tightRB, srcC8888,
- width, 1);
- SkConvertConfig8888Pixels(b, tightRB, dstC8888,
- temp, tightRB, srcC8888,
- width, 1);
- } else {
- memcpy(t, b, tightRB);
- memcpy(b, temp, tightRB);
- }
- top += rowBytes;
- bot -= rowBytes;
- }
- // The above loop does nothing on the middle row when height is odd.
- if (top == bot && c8888IsValid && dstC8888 != srcC8888) {
- uint32_t* mid = reinterpret_cast<uint32_t*>(top);
- SkConvertConfig8888Pixels(mid, tightRB, dstC8888, mid, tightRB, srcC8888, width, 1);
- }
- } else {
- // if we aren't flipping Y then we have no reason to be here other than doing
- // conversions for 8888 (r/b swap or upm).
- GrAssert(c8888IsValid);
- uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
- SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
- b32, rowBytes, srcC8888,
- width, height);
- }
+ GrAssert(c8888IsValid);
+ uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
+ SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
+ b32, rowBytes, srcC8888,
+ width, height);
}
return true;
}
View
@@ -231,10 +231,10 @@ void GrGpu::forceRenderTargetFlush() {
bool GrGpu::readPixels(GrRenderTarget* target,
int left, int top, int width, int height,
GrPixelConfig config, void* buffer,
- size_t rowBytes, bool invertY) {
+ size_t rowBytes) {
this->handleDirtyContext();
return this->onReadPixels(target, left, top, width, height,
- config, buffer, rowBytes, invertY);
+ config, buffer, rowBytes);
}
void GrGpu::writeTexturePixels(GrTexture* texture,
View
@@ -234,8 +234,7 @@ class GrGpu : public GrDrawTarget {
*/
bool readPixels(GrRenderTarget* renderTarget,
int left, int top, int width, int height,
- GrPixelConfig config, void* buffer, size_t rowBytes,
- bool invertY);
+ GrPixelConfig config, void* buffer, size_t rowBytes);
/**
* Updates the pixels in a rectangle of a texture.
@@ -473,8 +472,7 @@ class GrGpu : public GrDrawTarget {
int left, int top, int width, int height,
GrPixelConfig,
void* buffer,
- size_t rowBytes,
- bool invertY) = 0;
+ size_t rowBytes) = 0;
// overridden by backend-specific derived class to perform the texture update
virtual void onWriteTexturePixels(GrTexture* texture,
View
@@ -165,14 +165,16 @@ GrResourceKey GrTexture::ComputeScratchKey(const GrTextureDesc& desc) {
GrCacheID::Key idKey;
// Instead of a client-provided key of the texture contents we create a key from the
// descriptor.
- GR_STATIC_ASSERT(sizeof(idKey) >= 12);
+ GR_STATIC_ASSERT(sizeof(idKey) >= 16);
GrAssert(desc.fHeight < (1 << 16));
GrAssert(desc.fWidth < (1 << 16));
idKey.fData32[0] = (desc.fWidth) | (desc.fHeight << 16);
idKey.fData32[1] = desc.fConfig | desc.fSampleCnt << 16;
idKey.fData32[2] = desc.fFlags;
- static const int kPadSize = sizeof(idKey) - 12;
- memset(idKey.fData8 + 12, 0, kPadSize);
+ idKey.fData32[3] = desc.fOrigin; // Only needs 2 bits actually
+ static const int kPadSize = sizeof(idKey) - 16;
+ GR_STATIC_ASSERT(kPadSize >= 0);
+ memset(idKey.fData8 + 16, 0, kPadSize);
GrCacheID cacheID(GrResourceKey::ScratchDomain(), idKey);
return GrResourceKey(cacheID, texture_resource_type(), 0);
View
@@ -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);
@@ -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;
View
@@ -199,10 +199,11 @@ class GrGLProgram : public GrRefCnt {
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;
@@ -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);
}
@@ -25,12 +25,13 @@ class GrGLRenderTarget : public GrRenderTarget {
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
@@ -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
}
Oops, something went wrong.

0 comments on commit f1d7de2

Please sign in to comment.