michael@0: diff --git a/gfx/gl/GLContextSkia.cpp b/gfx/gl/GLContextSkia.cpp michael@0: --- a/gfx/gl/GLContextSkia.cpp michael@0: +++ b/gfx/gl/GLContextSkia.cpp michael@0: @@ -303,39 +303,47 @@ const GLubyte* glGetString_mozilla(GrGLe michael@0: if (name == LOCAL_GL_VERSION) { michael@0: if (sGLContext.get()->IsGLES2()) { michael@0: return reinterpret_cast("OpenGL ES 2.0"); michael@0: } else { michael@0: return reinterpret_cast("2.0"); michael@0: } michael@0: } else if (name == LOCAL_GL_EXTENSIONS) { michael@0: // Only expose the bare minimum extensions we want to support to ensure a functional Ganesh michael@0: // as GLContext only exposes certain extensions michael@0: static bool extensionsStringBuilt = false; michael@0: - static char extensionsString[120]; michael@0: + static char extensionsString[256]; michael@0: michael@0: if (!extensionsStringBuilt) { michael@0: if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_texture_format_BGRA8888)) { michael@0: strcpy(extensionsString, "GL_EXT_texture_format_BGRA8888 "); michael@0: } michael@0: michael@0: if (sGLContext.get()->IsExtensionSupported(GLContext::OES_packed_depth_stencil)) { michael@0: strcat(extensionsString, "GL_OES_packed_depth_stencil "); michael@0: } michael@0: michael@0: if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_packed_depth_stencil)) { michael@0: strcat(extensionsString, "GL_EXT_packed_depth_stencil "); michael@0: } michael@0: michael@0: if (sGLContext.get()->IsExtensionSupported(GLContext::OES_rgb8_rgba8)) { michael@0: strcat(extensionsString, "GL_OES_rgb8_rgba8 "); michael@0: } michael@0: michael@0: + if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_bgra)) { michael@0: + strcat(extensionsString, "GL_EXT_bgra "); michael@0: + } michael@0: + michael@0: + if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_read_format_bgra)) { michael@0: + strcat(extensionsString, "GL_EXT_read_format_bgra "); michael@0: + } michael@0: + michael@0: extensionsStringBuilt = true; michael@0: } michael@0: michael@0: return reinterpret_cast(extensionsString); michael@0: michael@0: } else if (name == LOCAL_GL_SHADING_LANGUAGE_VERSION) { michael@0: if (sGLContext.get()->IsGLES2()) { michael@0: return reinterpret_cast("OpenGL ES GLSL ES 1.0"); michael@0: } else { michael@0: return reinterpret_cast("1.10"); michael@0: diff --git a/gfx/skia/src/gpu/gl/GrGpuGL.cpp b/gfx/skia/src/gpu/gl/GrGpuGL.cpp michael@0: --- a/gfx/skia/src/gpu/gl/GrGpuGL.cpp michael@0: +++ b/gfx/skia/src/gpu/gl/GrGpuGL.cpp michael@0: @@ -1,18 +1,18 @@ michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: - michael@0: +#include michael@0: #include "GrGpuGL.h" michael@0: #include "GrGLStencilBuffer.h" michael@0: #include "GrGLPath.h" michael@0: #include "GrGLShaderBuilder.h" michael@0: #include "GrTemplates.h" michael@0: #include "GrTypes.h" michael@0: #include "SkTemplates.h" michael@0: michael@0: static const GrGLuint GR_MAX_GLUINT = ~0U; michael@0: static const GrGLint GR_INVAL_GLINT = ~0; michael@0: @@ -1381,29 +1381,67 @@ bool GrGpuGL::readPixelsWillPayForYFlip( michael@0: // Note the rowBytes might be tight to the passed in data, but if data michael@0: // gets clipped in x to the target the rowBytes will no longer be tight. michael@0: if (left >= 0 && (left + width) < renderTarget->width()) { michael@0: return 0 == rowBytes || michael@0: GrBytesPerPixel(config) * width == rowBytes; michael@0: } else { michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: +static void swizzleRow(void* buffer, int byteLen) { michael@0: + uint8_t* src = (uint8_t*)buffer; michael@0: + uint8_t* end = src + byteLen; michael@0: + michael@0: + GrAssert((end - src) % 4 == 0); michael@0: + michael@0: + for (; src != end; src += 4) { michael@0: + std::swap(src[0], src[2]); michael@0: + } michael@0: +} michael@0: + michael@0: +bool GrGpuGL::canReadBGRA() const michael@0: +{ michael@0: + if (kDesktop_GrGLBinding == this->glBinding() || michael@0: + this->hasExtension("GL_EXT_bgra")) michael@0: + return true; michael@0: + michael@0: + if (this->hasExtension("GL_EXT_read_format_bgra")) { michael@0: + GrGLint readFormat = 0; michael@0: + GrGLint readType = 0; michael@0: + michael@0: + GL_CALL(GetIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat)); michael@0: + GL_CALL(GetIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType)); michael@0: + michael@0: + return readFormat == GR_GL_BGRA && readType == GR_GL_UNSIGNED_BYTE; michael@0: + } michael@0: + michael@0: + return false; michael@0: +} michael@0: + michael@0: bool GrGpuGL::onReadPixels(GrRenderTarget* target, michael@0: int left, int top, michael@0: int width, int height, michael@0: GrPixelConfig config, michael@0: void* buffer, michael@0: size_t rowBytes) { michael@0: GrGLenum format; michael@0: GrGLenum type; michael@0: bool flipY = kBottomLeft_GrSurfaceOrigin == target->origin(); michael@0: + bool needSwizzle = false; michael@0: + michael@0: + if (kBGRA_8888_GrPixelConfig == config && !this->canReadBGRA()) { michael@0: + // Read RGBA and swizzle after michael@0: + config = kRGBA_8888_GrPixelConfig; michael@0: + needSwizzle = true; michael@0: + } michael@0: + michael@0: if (!this->configToGLFormats(config, false, NULL, &format, &type)) { michael@0: return false; michael@0: } michael@0: size_t bpp = GrBytesPerPixel(config); michael@0: if (!adjust_pixel_ops_params(target->width(), target->height(), bpp, michael@0: &left, &top, &width, &height, michael@0: const_cast(&buffer), michael@0: &rowBytes)) { michael@0: return false; michael@0: } michael@0: @@ -1478,35 +1516,46 @@ bool GrGpuGL::onReadPixels(GrRenderTarge michael@0: scratch.reset(tightRowBytes); michael@0: void* tmpRow = scratch.get(); michael@0: // flip y in-place by rows michael@0: const int halfY = height >> 1; michael@0: char* top = reinterpret_cast(buffer); michael@0: char* bottom = top + (height - 1) * rowBytes; michael@0: for (int y = 0; y < halfY; y++) { michael@0: memcpy(tmpRow, top, tightRowBytes); michael@0: memcpy(top, bottom, tightRowBytes); michael@0: memcpy(bottom, tmpRow, tightRowBytes); michael@0: + michael@0: + if (needSwizzle) { michael@0: + swizzleRow(top, tightRowBytes); michael@0: + swizzleRow(bottom, tightRowBytes); michael@0: + } michael@0: + michael@0: top += rowBytes; michael@0: bottom -= rowBytes; michael@0: } michael@0: } michael@0: } else { michael@0: - GrAssert(readDst != buffer); GrAssert(rowBytes != tightRowBytes); michael@0: + GrAssert(readDst != buffer); michael@0: + GrAssert(rowBytes != tightRowBytes); michael@0: // copy from readDst to buffer while flipping y michael@0: // const int halfY = height >> 1; michael@0: const char* src = reinterpret_cast(readDst); michael@0: char* dst = reinterpret_cast(buffer); michael@0: if (flipY) { michael@0: dst += (height-1) * rowBytes; michael@0: } michael@0: for (int y = 0; y < height; y++) { michael@0: memcpy(dst, src, tightRowBytes); michael@0: + if (needSwizzle) { michael@0: + swizzleRow(dst, tightRowBytes); michael@0: + } michael@0: + michael@0: src += readDstRowBytes; michael@0: if (!flipY) { michael@0: dst += rowBytes; michael@0: } else { michael@0: dst -= rowBytes; michael@0: } michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: diff --git a/gfx/skia/src/gpu/gl/GrGpuGL.h b/gfx/skia/src/gpu/gl/GrGpuGL.h michael@0: --- a/gfx/skia/src/gpu/gl/GrGpuGL.h michael@0: +++ b/gfx/skia/src/gpu/gl/GrGpuGL.h michael@0: @@ -243,20 +243,22 @@ private: michael@0: GrPixelConfig dataConfig, michael@0: const void* data, michael@0: size_t rowBytes); michael@0: michael@0: bool createRenderTargetObjects(int width, int height, michael@0: GrGLuint texID, michael@0: GrGLRenderTarget::Desc* desc); michael@0: michael@0: void fillInConfigRenderableTable(); michael@0: michael@0: + bool canReadBGRA() const; michael@0: + michael@0: GrGLContext fGLContext; michael@0: michael@0: // GL program-related state michael@0: ProgramCache* fProgramCache; michael@0: SkAutoTUnref fCurrentProgram; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////// michael@0: ///@name Caching of GL State michael@0: ///@{ michael@0: int fHWActiveTextureUnitIdx;