OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "gpu/command_buffer/service/gles2_cmd_srgb_converter.h" | |
6 | |
7 #include "gpu/command_buffer/service/texture_manager.h" | |
8 #include "ui/gl/gl_version_info.h" | |
9 | |
10 namespace { | |
11 | |
12 void CompileShader(GLuint shader, const char* shader_source) { | |
13 glShaderSource(shader, 1, &shader_source, 0); | |
14 glCompileShader(shader); | |
15 #ifndef NDEBUG | |
16 GLint compile_status; | |
17 glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | |
18 if (GL_TRUE != compile_status) | |
19 DLOG(ERROR) << "CopyTexImage: shader compilation failure."; | |
20 #endif | |
21 } | |
22 | |
23 } // anonymous namespace | |
24 | |
25 namespace gpu { | |
26 namespace gles2 { | |
27 | |
28 SRGBConverter::SRGBConverter( | |
29 const gles2::FeatureInfo* feature_info) | |
30 : feature_info_(feature_info) { | |
31 } | |
32 | |
33 SRGBConverter::~SRGBConverter() {} | |
34 | |
35 void SRGBConverter::InitializeSRGBDecoder( | |
36 const gles2::GLES2Decoder* decoder) { | |
37 if (srgb_decoder_initialized_) { | |
38 return; | |
39 } | |
40 | |
41 srgb_decoder_program_ = glCreateProgram(); | |
42 | |
43 // Compile the vertex shader | |
44 const char* vs_source = | |
45 "#version 150\n" | |
46 "out vec2 v_texcoord;\n" | |
47 "\n" | |
48 "void main()\n" | |
49 "{\n" | |
50 " const vec2 quad_positions[6] = vec2[6]\n" | |
51 " (\n" | |
52 " vec2(0.0f, 0.0f),\n" | |
53 " vec2(0.0f, 1.0f),\n" | |
54 " vec2(1.0f, 0.0f),\n" | |
55 "\n" | |
56 " vec2(0.0f, 1.0f),\n" | |
57 " vec2(1.0f, 0.0f),\n" | |
58 " vec2(1.0f, 1.0f)\n" | |
59 " );\n" | |
60 "\n" | |
61 " vec2 xy = vec2((quad_positions[gl_VertexID] * 2.0) - 1.0);\n" | |
62 " gl_Position = vec4(xy, 0.0, 1.0);\n" | |
63 " v_texcoord = quad_positions[gl_VertexID];\n" | |
64 "}\n"; | |
65 | |
66 GLuint vs = glCreateShader(GL_VERTEX_SHADER); | |
67 CompileShader(vs, vs_source); | |
68 glAttachShader(srgb_decoder_program_, vs); | |
69 glDeleteShader(vs); | |
70 | |
71 // Compile the fragment shader | |
72 // Sampling from a srgb texture and drawing to a linear color buffer, it will | |
73 // convert the srgb color space to linear color space automatically. | |
74 // However, sampling from a linear texture and drawing to a srgb color buffer, | |
75 // it will not convert linear to srgb automatically. | |
piman
2016/09/07 23:08:33
I don't think I understand the comment. The shader
yunchao
2016/09/08 18:32:49
I saw the some difference between these 2 situatio
piman
2016/09/08 19:39:18
For the output, the state of texture doesn't matte
yunchao
2016/09/08 23:16:49
(Maybe I am wrong here) I may have different opini
| |
76 const char* fs_source = | |
77 "#version 150\n" | |
78 "uniform sampler2D u_source_texture;\n" | |
79 "in vec2 v_texcoord;\n" | |
80 "out vec4 output_color;\n" | |
81 "\n" | |
82 /* "float decode(float color)\n" | |
83 "{\n" | |
84 " float decoded_color;\n" | |
85 " if (color <= 0.04045) {\n" | |
86 " decoded_color = color / 12.92;\n" | |
87 " } else {\n" | |
88 " decoded_color = (color + 0.055) / 1.055;\n" | |
89 " decoded_color = pow(decoded_color, 2.4);\n" | |
90 " }\n" | |
91 " return decoded_color;\n" | |
92 "}\n" | |
93 "\n" */ | |
piman
2016/09/07 23:08:32
nit: remove commented code.
yunchao
2016/09/08 18:32:49
I would like to keep the code here, which indicate
piman
2016/09/08 19:39:17
Please don't. It makes it confusing. The conversio
yunchao
2016/09/08 23:16:49
(Again, maybe I am wrong here) sampling from srgb
| |
94 "void main()\n" | |
95 "{\n" | |
96 " vec4 c = texture(u_source_texture, v_texcoord);\n" | |
97 //" output_color = vec4(decode(c.r), decode(c.g), decode(c.b), c.a);\n" | |
piman
2016/09/07 23:08:32
nit: remove commented code.
yunchao
2016/09/08 18:32:49
I'd like to keep the code here.
piman
2016/09/08 19:39:17
Please don't.
| |
98 " output_color = c;\n" | |
99 "}\n"; | |
100 | |
101 GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); | |
102 CompileShader(fs, fs_source); | |
103 glAttachShader(srgb_decoder_program_, fs); | |
104 glDeleteShader(fs); | |
105 | |
106 glLinkProgram(srgb_decoder_program_); | |
107 #ifndef NDEBUG | |
108 GLint linked = 0; | |
109 glGetProgramiv(srgb_decoder_program_, GL_LINK_STATUS, &linked); | |
110 if (!linked) { | |
111 DLOG(ERROR) << "BlitFramebuffer: program link failure."; | |
112 } | |
113 #endif | |
114 | |
115 GLuint texture_uniform = | |
116 glGetUniformLocation(srgb_decoder_program_, "u_source_texture"); | |
117 glUseProgram(srgb_decoder_program_); | |
118 glUniform1i(texture_uniform, 0); | |
119 | |
120 glGenTextures(srgb_decoder_textures_.size(), srgb_decoder_textures_.data()); | |
121 glActiveTexture(GL_TEXTURE0); | |
122 for (auto srgb_decoder_texture : srgb_decoder_textures_) { | |
123 glBindTexture(GL_TEXTURE_2D, srgb_decoder_texture); | |
124 | |
125 // Use nearest, non-mipmapped sampling with the srgb decoder texture | |
piman
2016/09/07 23:08:33
nit: you're using linear, not nearest. Fix comment
yunchao
2016/09/08 18:32:49
Done.
| |
126 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
130 } | |
131 | |
132 glGenFramebuffersEXT(1, &srgb_decoder_fbo_); | |
133 glGenVertexArraysOES(1, &srgb_decoder_vao_); | |
134 | |
135 decoder->RestoreTextureUnitBindings(0); | |
136 decoder->RestoreActiveTexture(); | |
137 decoder->RestoreProgramBindings(); | |
138 | |
139 srgb_decoder_initialized_ = true; | |
140 } | |
141 | |
142 void SRGBConverter::InitializeSRGBEncoder( | |
143 const gles2::GLES2Decoder* decoder) { | |
144 if (srgb_encoder_initialized_) { | |
145 return; | |
146 } | |
147 | |
148 srgb_encoder_program_ = glCreateProgram(); | |
149 | |
150 // Compile the vertex shader | |
151 const char* vs_source = | |
152 "#version 150\n" | |
153 "out vec2 v_texcoord;\n" | |
154 "\n" | |
155 "void main()\n" | |
156 "{\n" | |
157 " const vec2 quad_positions[6] = vec2[6]\n" | |
158 " (\n" | |
159 " vec2(0.0f, 0.0f),\n" | |
160 " vec2(0.0f, 1.0f),\n" | |
161 " vec2(1.0f, 0.0f),\n" | |
162 "\n" | |
163 " vec2(0.0f, 1.0f),\n" | |
164 " vec2(1.0f, 0.0f),\n" | |
165 " vec2(1.0f, 1.0f)\n" | |
166 " );\n" | |
167 "\n" | |
168 " vec2 xy = vec2((quad_positions[gl_VertexID] * 2.0) - 1.0);\n" | |
169 " gl_Position = vec4(xy, 0.0, 1.0);\n" | |
170 " v_texcoord = quad_positions[gl_VertexID];\n" | |
171 "}\n"; | |
piman
2016/09/07 23:08:32
This is the same VS as above for the decoder, can
yunchao
2016/09/08 18:32:49
That's true. Done.
| |
172 | |
173 GLuint vs = glCreateShader(GL_VERTEX_SHADER); | |
174 CompileShader(vs, vs_source); | |
175 glAttachShader(srgb_encoder_program_, vs); | |
176 glDeleteShader(vs); | |
177 | |
178 // Compile the fragment shader | |
179 const char* fs_source = | |
180 "#version 150\n" | |
181 "uniform sampler2D u_source_texture;\n" | |
182 "in vec2 v_texcoord;\n" | |
183 "out vec4 output_color;\n" | |
184 "\n" | |
185 "float encode(float color)\n" | |
piman
2016/09/07 23:08:33
If we're doing the linear->srgb conversion with a
yunchao
2016/09/08 18:32:49
Prior to OGL 4.4, it can not support FRAMEBUFFER_S
piman
2016/09/08 19:39:18
Why not? FRAMEBUFFER_SRGB is definitely supported
yunchao
2016/09/08 23:16:49
Sorry, I am wrong. FRAMEBUFFER_SRGB exists as long
| |
186 "{\n" | |
187 " float encoded_color;\n" | |
188 " if (color <= 0.0) {\n" | |
189 " return 0.0;\n" | |
190 " } else if (color < 0.0031308) {\n" | |
191 " return color * 12.92;\n" | |
192 " } else if (color < 1) {\n" | |
193 " return pow(color, 0.41666) * 1.055 - 0.055;\n" | |
194 " } else {\n" | |
195 " return 1.0;\n" | |
196 " }\n" | |
197 "}\n" | |
198 "\n" | |
199 "void main()\n" | |
200 "{\n" | |
201 " vec4 c = texture(u_source_texture, v_texcoord);\n" | |
202 " output_color = vec4(encode(c.r), encode(c.g), encode(c.b), c.a);\n" | |
203 "}\n"; | |
204 | |
205 GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); | |
206 CompileShader(fs, fs_source); | |
207 glAttachShader(srgb_encoder_program_, fs); | |
208 glDeleteShader(fs); | |
209 | |
210 glLinkProgram(srgb_encoder_program_); | |
211 #ifndef NDEBUG | |
212 GLint linked = 0; | |
213 glGetProgramiv(srgb_encoder_program_, GL_LINK_STATUS, &linked); | |
214 if (!linked) { | |
215 DLOG(ERROR) << "SRGB Encoder for BlitFramebuffer: program link failure."; | |
216 } | |
217 #endif | |
218 | |
219 GLuint texture_uniform = | |
220 glGetUniformLocation(srgb_encoder_program_, "u_source_texture"); | |
221 glUseProgram(srgb_encoder_program_); | |
222 glUniform1i(texture_uniform, 0); | |
223 | |
224 glGenTextures(srgb_encoder_textures_.size(), srgb_encoder_textures_.data()); | |
225 glActiveTexture(GL_TEXTURE0); | |
226 for (auto srgb_encoder_texture : srgb_encoder_textures_) { | |
227 glBindTexture(GL_TEXTURE_2D, srgb_encoder_texture); | |
228 | |
229 // Use nearest, non-mipmapped sampling with the srgb encoder texture | |
piman
2016/09/07 23:08:32
nit: ditto, nearest->linear
yunchao
2016/09/08 18:32:49
Done.
| |
230 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
231 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
232 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
234 } | |
235 | |
236 glGenFramebuffersEXT(1, &srgb_encoder_fbo_); | |
237 glGenVertexArraysOES(1, &srgb_encoder_vao_); | |
238 | |
239 decoder->RestoreTextureUnitBindings(0); | |
240 decoder->RestoreActiveTexture(); | |
241 decoder->RestoreProgramBindings(); | |
242 | |
243 srgb_encoder_initialized_ = true; | |
244 } | |
245 | |
246 void SRGBConverter::Destroy() { | |
247 if (srgb_decoder_initialized_) { | |
248 glDeleteProgram(srgb_decoder_program_); | |
249 srgb_decoder_program_ = 0; | |
250 | |
251 glDeleteTextures(srgb_decoder_textures_.size(), | |
252 srgb_decoder_textures_.data()); | |
253 srgb_decoder_textures_.fill(0); | |
254 | |
255 glDeleteFramebuffersEXT(1, &srgb_decoder_fbo_); | |
256 srgb_decoder_fbo_ = 0; | |
257 | |
258 glDeleteVertexArraysOES(1, &srgb_decoder_vao_); | |
259 srgb_decoder_vao_ = 0; | |
260 | |
261 srgb_decoder_initialized_ = false; | |
262 } | |
263 | |
264 if (srgb_encoder_initialized_) { | |
265 glDeleteProgram(srgb_encoder_program_); | |
266 srgb_encoder_program_ = 0; | |
267 | |
268 glDeleteTextures(srgb_encoder_textures_.size(), | |
269 srgb_encoder_textures_.data()); | |
270 srgb_encoder_textures_.fill(0); | |
271 | |
272 glDeleteFramebuffersEXT(1, &srgb_encoder_fbo_); | |
273 srgb_encoder_fbo_ = 0; | |
274 | |
275 glDeleteVertexArraysOES(1, &srgb_encoder_vao_); | |
276 srgb_encoder_vao_ = 0; | |
277 | |
278 srgb_encoder_initialized_ = false; | |
279 } | |
280 } | |
281 | |
282 void SRGBConverter::SRGBToLinear( | |
283 const gles2::GLES2Decoder* decoder, | |
284 GLint srcX0, | |
285 GLint srcY0, | |
286 GLint srcX1, | |
287 GLint srcY1, | |
288 GLint dstX0, | |
289 GLint dstY0, | |
290 GLint dstX1, | |
291 GLint dstY1, | |
292 GLbitfield mask, | |
293 GLenum filter, | |
294 const gfx::Size& framebuffer_size, | |
295 GLuint src_framebuffer, | |
296 GLenum src_framebuffer_internal_format, | |
297 GLuint dst_framebuffer, | |
298 GLenum dst_framebuffer_internal_format, | |
299 GLenum dst_framebuffer_format, | |
300 GLenum dst_framebuffer_type) { | |
piman
2016/09/07 23:08:33
This could use a high-level comment about what we'
yunchao
2016/09/08 18:32:49
Done.
yunchao
2016/09/08 18:32:49
Good suggestions! Done.
| |
301 | |
302 DCHECK(srgb_decoder_initialized_); | |
303 | |
304 // Copy the image from framebuffer to the first srgb decoder texture | |
305 // TODO(yunchao) If the read buffer is a fbo texture, we can sample | |
306 // directly from that texture. In this way, we can save gpu memory. | |
307 glBindFramebufferEXT(GL_FRAMEBUFFER, src_framebuffer); | |
308 glActiveTexture(GL_TEXTURE0); | |
309 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[0]); | |
310 | |
311 // We should not copy pixels outside of the read framebuffer. If we read | |
312 // these pixels, they would become in-bound during BlitFramebuffer. However, | |
313 // Out-of-bounds pixels will be initialized to 0 in CopyTexSubImage. But they | |
314 // should read as if the GL_CLAMP_TO_EDGE texture mapping mode were applied | |
315 // during BlitFramebuffer when the filter is GL_LINEAR. | |
316 GLuint x = srcX1 > srcX0 ? srcX0 : srcX1; | |
317 GLuint width = srcX1 > srcX0 ? srcX1 - srcX0 : srcX0 - srcX1; | |
318 GLuint y = srcY1 > srcY0 ? srcY0 : srcY1; | |
319 GLuint height = srcY1 > srcY0 ? srcY1 - srcY0 : srcY0 - srcY1; | |
320 gfx::Rect c(0, 0, framebuffer_size.width(), framebuffer_size.height()); | |
321 c.Intersect(gfx::Rect(x, y, width, height)); | |
322 GLuint xoffset = c.x() - x; | |
323 GLuint yoffset = c.y() - y; | |
324 glCopyTexImage2D(GL_TEXTURE_2D, 0, src_framebuffer_internal_format, | |
325 c.x(), c.y(), c.width(), c.height(), 0); | |
326 | |
327 // Make a temporary framebuffer using the second srgb decoder texture to | |
328 // render the converted (linear to srgb) result to. | |
piman
2016/09/07 23:08:32
nit: you're converting srgb to linear, not linear
yunchao
2016/09/08 18:32:49
Done.
| |
329 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); | |
330 | |
331 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[1]); | |
332 glTexImage2D(GL_TEXTURE_2D, 0, dst_framebuffer_internal_format, | |
333 c.width(), c.height(), | |
334 0, dst_framebuffer_format, dst_framebuffer_type, nullptr); | |
335 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_decoder_fbo_); | |
336 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
337 srgb_decoder_textures_[1], 0); | |
338 | |
339 // Render to the second srgb decoder texture, | |
340 // sampling from the first srgb decoder texture. | |
341 glUseProgram(srgb_decoder_program_); | |
342 glViewport(0, 0, width, height); | |
343 glDisable(GL_SCISSOR_TEST); | |
344 glDisable(GL_DEPTH_TEST); | |
345 glDisable(GL_STENCIL_TEST); | |
346 glDisable(GL_CULL_FACE); | |
347 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
348 glDepthMask(GL_FALSE); | |
349 glDisable(GL_BLEND); | |
350 glDisable(GL_DITHER); | |
351 | |
352 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[0]); | |
353 glBindVertexArrayOES(srgb_decoder_vao_); | |
354 | |
355 glDrawArrays(GL_TRIANGLES, 0, 6); | |
356 | |
357 // Finally, bind the temporary framebuffer as read framebuffer, | |
358 // blit the converted texture in temp fbo to the destination texture | |
359 // in destination framebuffer. | |
360 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_); | |
361 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, dst_framebuffer); | |
362 // Note that the source region has been changed in temp framebuffer. | |
363 // The xoffset/yoffset can make bliting clamp to the correct edge if | |
364 // CLAMP_TO_EDGE is necessary. | |
365 glBlitFramebuffer(srcX0 < srcX1 ? 0 - xoffset : width - xoffset, | |
366 srcY0 < srcY1 ? 0 - yoffset : height - yoffset, | |
367 srcX0 < srcX1 ? width - xoffset : 0 - xoffset, | |
368 srcY0 < srcY1 ? height - yoffset : 0 - yoffset, | |
Zhenyao Mo
2016/09/06 22:30:11
Can you also expand your new conformance test to c
yunchao
2016/09/07 03:46:26
Sure, see the patch at https://github.com/KhronosG
| |
369 dstX0, dstY0, dstX1, dstY1, mask, filter); | |
370 | |
371 // Restore state | |
372 decoder->RestoreAllAttributes(); | |
373 decoder->RestoreTextureUnitBindings(0); | |
374 decoder->RestoreActiveTexture(); | |
375 decoder->RestoreProgramBindings(); | |
376 decoder->RestoreBufferBindings(); | |
377 decoder->RestoreFramebufferBindings(); | |
378 decoder->RestoreGlobalState(); | |
379 } | |
380 | |
381 void SRGBConverter::LinearToSRGB( | |
382 const gles2::GLES2Decoder* decoder, | |
383 GLint srcX0, | |
384 GLint srcY0, | |
385 GLint srcX1, | |
386 GLint srcY1, | |
387 GLint dstX0, | |
388 GLint dstY0, | |
389 GLint dstX1, | |
390 GLint dstY1, | |
391 GLbitfield mask, | |
392 GLenum filter, | |
393 const gfx::Size& framebuffer_size, | |
394 GLuint src_framebuffer, | |
395 GLenum src_framebuffer_internal_format, | |
396 GLuint dst_framebuffer, | |
397 GLenum dst_framebuffer_internal_format, | |
398 GLenum dst_framebuffer_format, | |
399 GLenum dst_framebuffer_type) { | |
piman
2016/09/07 23:08:33
ditto, worth a high-level comment about what we do
yunchao
2016/09/08 18:32:49
Done.
| |
400 | |
401 DCHECK(srgb_encoder_initialized_); | |
402 | |
403 // Copy the framebuffer to the first srgb encoder texture | |
404 glBindFramebufferEXT(GL_FRAMEBUFFER, src_framebuffer); | |
405 glActiveTexture(GL_TEXTURE0); | |
406 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]); | |
407 | |
408 // We should not copy pixels outside of the read framebuffer. If we read | |
409 // these pixels, they would become in-bound during BlitFramebuffer. However, | |
410 // Out-of-bounds pixels will be initialized to 0 in CopyTexSubImage. But they | |
411 // should read as if the GL_CLAMP_TO_EDGE texture mapping mode were applied | |
412 // during BlitFramebuffer when the filter is GL_LINEAR. | |
413 GLuint x = srcX1 > srcX0 ? srcX0 : srcX1; | |
414 GLuint width = srcX1 > srcX0 ? srcX1 - srcX0 : srcX0 - srcX1; | |
415 GLuint y = srcY1 > srcY0 ? srcY0 : srcY1; | |
416 GLuint height = srcY1 > srcY0 ? srcY1 - srcY0 : srcY0 - srcY1; | |
417 gfx::Rect c(0, 0, framebuffer_size.width(), framebuffer_size.height()); | |
418 c.Intersect(gfx::Rect(x, y, width, height)); | |
419 GLuint xoffset = c.x() - x; | |
420 GLuint yoffset = c.y() - y; | |
421 glCopyTexImage2D(GL_TEXTURE_2D, 0, src_framebuffer_internal_format, | |
422 c.x(), c.y(), c.width(), c.height(), 0); | |
423 | |
424 // Make a temporary framebuffer using the second srgb encoder texture to | |
425 // render the converted (linear to srgb) result to. | |
426 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); | |
427 | |
428 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[1]); | |
429 glTexImage2D(GL_TEXTURE_2D, 0, dst_framebuffer_internal_format, | |
430 c.width(), c.height(), | |
431 0, dst_framebuffer_format, dst_framebuffer_type, nullptr); | |
432 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_encoder_fbo_); | |
433 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
434 srgb_encoder_textures_[1], 0); | |
435 | |
436 // Render to the second srgb encoder texture, | |
437 // sampling from the first srgb encoder texture. | |
438 glUseProgram(srgb_encoder_program_); | |
439 glViewport(0, 0, width, height); | |
440 glDisable(GL_SCISSOR_TEST); | |
441 glDisable(GL_DEPTH_TEST); | |
442 glDisable(GL_STENCIL_TEST); | |
443 glDisable(GL_CULL_FACE); | |
444 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
445 glDepthMask(GL_FALSE); | |
446 glDisable(GL_BLEND); | |
447 glDisable(GL_DITHER); | |
448 | |
449 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]); | |
450 glBindVertexArrayOES(srgb_encoder_vao_); | |
451 | |
452 glDrawArrays(GL_TRIANGLES, 0, 6); | |
453 | |
454 // Finally, bind the temporary framebuffer as read framebuffer, | |
455 // blit the converted texture in temp fbo to the destination texture | |
456 // in destination framebuffer. | |
457 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_encoder_fbo_); | |
458 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, dst_framebuffer); | |
459 // Note that the source region has been changed in temp framebuffer. | |
460 // The xoffset/yoffset can make bliting clamp to the correct edge if | |
461 // CLAMP_TO_EDGE is necessary. | |
462 glBlitFramebuffer(srcX0 < srcX1 ? 0 - xoffset : width - xoffset, | |
piman
2016/09/07 23:08:32
If we don't trust glBlitFramebuffer to correctly h
yunchao
2016/09/08 18:32:49
You are correct. My implementation is wrong for en
| |
463 srcY0 < srcY1 ? 0 - yoffset : height - yoffset, | |
464 srcX0 < srcX1 ? width - xoffset : 0 - xoffset, | |
465 srcY0 < srcY1 ? height - yoffset : 0 - yoffset, | |
466 dstX0, dstY0, dstX1, dstY1, mask, filter); | |
467 | |
468 // Restore state | |
469 decoder->RestoreAllAttributes(); | |
470 decoder->RestoreTextureUnitBindings(0); | |
471 decoder->RestoreActiveTexture(); | |
472 decoder->RestoreProgramBindings(); | |
473 decoder->RestoreBufferBindings(); | |
474 decoder->RestoreFramebufferBindings(); | |
475 decoder->RestoreGlobalState(); | |
476 } | |
477 | |
478 } // namespace gles2. | |
479 } // namespace gpu | |
OLD | NEW |