|
1 diff --git a/gfx/gl/GLContextSkia.cpp b/gfx/gl/GLContextSkia.cpp |
|
2 --- a/gfx/gl/GLContextSkia.cpp |
|
3 +++ b/gfx/gl/GLContextSkia.cpp |
|
4 @@ -303,39 +303,47 @@ const GLubyte* glGetString_mozilla(GrGLe |
|
5 if (name == LOCAL_GL_VERSION) { |
|
6 if (sGLContext.get()->IsGLES2()) { |
|
7 return reinterpret_cast<const GLubyte*>("OpenGL ES 2.0"); |
|
8 } else { |
|
9 return reinterpret_cast<const GLubyte*>("2.0"); |
|
10 } |
|
11 } else if (name == LOCAL_GL_EXTENSIONS) { |
|
12 // Only expose the bare minimum extensions we want to support to ensure a functional Ganesh |
|
13 // as GLContext only exposes certain extensions |
|
14 static bool extensionsStringBuilt = false; |
|
15 - static char extensionsString[120]; |
|
16 + static char extensionsString[256]; |
|
17 |
|
18 if (!extensionsStringBuilt) { |
|
19 if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_texture_format_BGRA8888)) { |
|
20 strcpy(extensionsString, "GL_EXT_texture_format_BGRA8888 "); |
|
21 } |
|
22 |
|
23 if (sGLContext.get()->IsExtensionSupported(GLContext::OES_packed_depth_stencil)) { |
|
24 strcat(extensionsString, "GL_OES_packed_depth_stencil "); |
|
25 } |
|
26 |
|
27 if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_packed_depth_stencil)) { |
|
28 strcat(extensionsString, "GL_EXT_packed_depth_stencil "); |
|
29 } |
|
30 |
|
31 if (sGLContext.get()->IsExtensionSupported(GLContext::OES_rgb8_rgba8)) { |
|
32 strcat(extensionsString, "GL_OES_rgb8_rgba8 "); |
|
33 } |
|
34 |
|
35 + if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_bgra)) { |
|
36 + strcat(extensionsString, "GL_EXT_bgra "); |
|
37 + } |
|
38 + |
|
39 + if (sGLContext.get()->IsExtensionSupported(GLContext::EXT_read_format_bgra)) { |
|
40 + strcat(extensionsString, "GL_EXT_read_format_bgra "); |
|
41 + } |
|
42 + |
|
43 extensionsStringBuilt = true; |
|
44 } |
|
45 |
|
46 return reinterpret_cast<const GLubyte*>(extensionsString); |
|
47 |
|
48 } else if (name == LOCAL_GL_SHADING_LANGUAGE_VERSION) { |
|
49 if (sGLContext.get()->IsGLES2()) { |
|
50 return reinterpret_cast<const GLubyte*>("OpenGL ES GLSL ES 1.0"); |
|
51 } else { |
|
52 return reinterpret_cast<const GLubyte*>("1.10"); |
|
53 diff --git a/gfx/skia/src/gpu/gl/GrGpuGL.cpp b/gfx/skia/src/gpu/gl/GrGpuGL.cpp |
|
54 --- a/gfx/skia/src/gpu/gl/GrGpuGL.cpp |
|
55 +++ b/gfx/skia/src/gpu/gl/GrGpuGL.cpp |
|
56 @@ -1,18 +1,18 @@ |
|
57 /* |
|
58 * Copyright 2011 Google Inc. |
|
59 * |
|
60 * Use of this source code is governed by a BSD-style license that can be |
|
61 * found in the LICENSE file. |
|
62 */ |
|
63 |
|
64 - |
|
65 +#include <algorithm> |
|
66 #include "GrGpuGL.h" |
|
67 #include "GrGLStencilBuffer.h" |
|
68 #include "GrGLPath.h" |
|
69 #include "GrGLShaderBuilder.h" |
|
70 #include "GrTemplates.h" |
|
71 #include "GrTypes.h" |
|
72 #include "SkTemplates.h" |
|
73 |
|
74 static const GrGLuint GR_MAX_GLUINT = ~0U; |
|
75 static const GrGLint GR_INVAL_GLINT = ~0; |
|
76 @@ -1381,29 +1381,67 @@ bool GrGpuGL::readPixelsWillPayForYFlip( |
|
77 // Note the rowBytes might be tight to the passed in data, but if data |
|
78 // gets clipped in x to the target the rowBytes will no longer be tight. |
|
79 if (left >= 0 && (left + width) < renderTarget->width()) { |
|
80 return 0 == rowBytes || |
|
81 GrBytesPerPixel(config) * width == rowBytes; |
|
82 } else { |
|
83 return false; |
|
84 } |
|
85 } |
|
86 |
|
87 +static void swizzleRow(void* buffer, int byteLen) { |
|
88 + uint8_t* src = (uint8_t*)buffer; |
|
89 + uint8_t* end = src + byteLen; |
|
90 + |
|
91 + GrAssert((end - src) % 4 == 0); |
|
92 + |
|
93 + for (; src != end; src += 4) { |
|
94 + std::swap(src[0], src[2]); |
|
95 + } |
|
96 +} |
|
97 + |
|
98 +bool GrGpuGL::canReadBGRA() const |
|
99 +{ |
|
100 + if (kDesktop_GrGLBinding == this->glBinding() || |
|
101 + this->hasExtension("GL_EXT_bgra")) |
|
102 + return true; |
|
103 + |
|
104 + if (this->hasExtension("GL_EXT_read_format_bgra")) { |
|
105 + GrGLint readFormat = 0; |
|
106 + GrGLint readType = 0; |
|
107 + |
|
108 + GL_CALL(GetIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat)); |
|
109 + GL_CALL(GetIntegerv(GR_GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType)); |
|
110 + |
|
111 + return readFormat == GR_GL_BGRA && readType == GR_GL_UNSIGNED_BYTE; |
|
112 + } |
|
113 + |
|
114 + return false; |
|
115 +} |
|
116 + |
|
117 bool GrGpuGL::onReadPixels(GrRenderTarget* target, |
|
118 int left, int top, |
|
119 int width, int height, |
|
120 GrPixelConfig config, |
|
121 void* buffer, |
|
122 size_t rowBytes) { |
|
123 GrGLenum format; |
|
124 GrGLenum type; |
|
125 bool flipY = kBottomLeft_GrSurfaceOrigin == target->origin(); |
|
126 + bool needSwizzle = false; |
|
127 + |
|
128 + if (kBGRA_8888_GrPixelConfig == config && !this->canReadBGRA()) { |
|
129 + // Read RGBA and swizzle after |
|
130 + config = kRGBA_8888_GrPixelConfig; |
|
131 + needSwizzle = true; |
|
132 + } |
|
133 + |
|
134 if (!this->configToGLFormats(config, false, NULL, &format, &type)) { |
|
135 return false; |
|
136 } |
|
137 size_t bpp = GrBytesPerPixel(config); |
|
138 if (!adjust_pixel_ops_params(target->width(), target->height(), bpp, |
|
139 &left, &top, &width, &height, |
|
140 const_cast<const void**>(&buffer), |
|
141 &rowBytes)) { |
|
142 return false; |
|
143 } |
|
144 @@ -1478,35 +1516,46 @@ bool GrGpuGL::onReadPixels(GrRenderTarge |
|
145 scratch.reset(tightRowBytes); |
|
146 void* tmpRow = scratch.get(); |
|
147 // flip y in-place by rows |
|
148 const int halfY = height >> 1; |
|
149 char* top = reinterpret_cast<char*>(buffer); |
|
150 char* bottom = top + (height - 1) * rowBytes; |
|
151 for (int y = 0; y < halfY; y++) { |
|
152 memcpy(tmpRow, top, tightRowBytes); |
|
153 memcpy(top, bottom, tightRowBytes); |
|
154 memcpy(bottom, tmpRow, tightRowBytes); |
|
155 + |
|
156 + if (needSwizzle) { |
|
157 + swizzleRow(top, tightRowBytes); |
|
158 + swizzleRow(bottom, tightRowBytes); |
|
159 + } |
|
160 + |
|
161 top += rowBytes; |
|
162 bottom -= rowBytes; |
|
163 } |
|
164 } |
|
165 } else { |
|
166 - GrAssert(readDst != buffer); GrAssert(rowBytes != tightRowBytes); |
|
167 + GrAssert(readDst != buffer); |
|
168 + GrAssert(rowBytes != tightRowBytes); |
|
169 // copy from readDst to buffer while flipping y |
|
170 // const int halfY = height >> 1; |
|
171 const char* src = reinterpret_cast<const char*>(readDst); |
|
172 char* dst = reinterpret_cast<char*>(buffer); |
|
173 if (flipY) { |
|
174 dst += (height-1) * rowBytes; |
|
175 } |
|
176 for (int y = 0; y < height; y++) { |
|
177 memcpy(dst, src, tightRowBytes); |
|
178 + if (needSwizzle) { |
|
179 + swizzleRow(dst, tightRowBytes); |
|
180 + } |
|
181 + |
|
182 src += readDstRowBytes; |
|
183 if (!flipY) { |
|
184 dst += rowBytes; |
|
185 } else { |
|
186 dst -= rowBytes; |
|
187 } |
|
188 } |
|
189 } |
|
190 return true; |
|
191 } |
|
192 diff --git a/gfx/skia/src/gpu/gl/GrGpuGL.h b/gfx/skia/src/gpu/gl/GrGpuGL.h |
|
193 --- a/gfx/skia/src/gpu/gl/GrGpuGL.h |
|
194 +++ b/gfx/skia/src/gpu/gl/GrGpuGL.h |
|
195 @@ -243,20 +243,22 @@ private: |
|
196 GrPixelConfig dataConfig, |
|
197 const void* data, |
|
198 size_t rowBytes); |
|
199 |
|
200 bool createRenderTargetObjects(int width, int height, |
|
201 GrGLuint texID, |
|
202 GrGLRenderTarget::Desc* desc); |
|
203 |
|
204 void fillInConfigRenderableTable(); |
|
205 |
|
206 + bool canReadBGRA() const; |
|
207 + |
|
208 GrGLContext fGLContext; |
|
209 |
|
210 // GL program-related state |
|
211 ProgramCache* fProgramCache; |
|
212 SkAutoTUnref<GrGLProgram> fCurrentProgram; |
|
213 |
|
214 /////////////////////////////////////////////////////////////////////////// |
|
215 ///@name Caching of GL State |
|
216 ///@{ |
|
217 int fHWActiveTextureUnitIdx; |