Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: gpu/command_buffer/service/gles2_cmd_srgb_converter.cc

Issue 2286593002: [Command Buffer] emulate SRGB color format for BlitFramebuffer in OpenGL (Closed)
Patch Set: addressed piman's feedback: add support to blit from srgb read buffer to srgb draw buffer, and consider filtering srgb image Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 // Vertex shader, shared by both decoder program and encoder program
36 static const char* vs_source =
37 "#version 150\n"
38 "out vec2 v_texcoord;\n"
39 "\n"
40 "void main()\n"
41 "{\n"
42 " const vec2 quad_positions[6] = vec2[6]\n"
43 " (\n"
44 " vec2(0.0f, 0.0f),\n"
45 " vec2(0.0f, 1.0f),\n"
46 " vec2(1.0f, 0.0f),\n"
47 "\n"
48 " vec2(0.0f, 1.0f),\n"
49 " vec2(1.0f, 0.0f),\n"
50 " vec2(1.0f, 1.0f)\n"
51 " );\n"
52 "\n"
53 " vec2 xy = vec2((quad_positions[gl_VertexID] * 2.0) - 1.0);\n"
54 " gl_Position = vec4(xy, 0.0, 1.0);\n"
55 " v_texcoord = quad_positions[gl_VertexID];\n"
56 "}\n";
57
58 void SRGBConverter::InitializeSRGBDecoder(
59 const gles2::GLES2Decoder* decoder) {
60 if (srgb_decoder_initialized_) {
61 return;
62 }
63
64 srgb_decoder_program_ = glCreateProgram();
65
66 // Compile the vertex shader
67 GLuint vs = glCreateShader(GL_VERTEX_SHADER);
68 CompileShader(vs, vs_source);
69 glAttachShader(srgb_decoder_program_, vs);
70 glDeleteShader(vs);
71
72 // Compile the fragment shader
73
74 // Sampling texels from a srgb texture to a linear image, it will convert
75 // the srgb color space to linear color space automatically as a part of
76 // filtering. See the section <sRGB Texture Color Conversion> in GLES and
77 // OpenGL spec. So in decoder, we don't need to decode again.
78 // However, sampling texels from a linear texture to a srgb image, it will
79 // not convert linear to srgb automatically. Shader should always operates
80 // in linear space. So in encoder, we need to encode explicitly in shader.
81 const char* fs_source =
82 "#version 150\n"
83 "uniform sampler2D u_source_texture;\n"
84 "in vec2 v_texcoord;\n"
85 "out vec4 output_color;\n"
86 "\n"
87 "void main()\n"
88 "{\n"
89 " vec4 c = texture(u_source_texture, v_texcoord);\n"
90 " output_color = c;\n"
91 "}\n";
92
93 GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
94 CompileShader(fs, fs_source);
95 glAttachShader(srgb_decoder_program_, fs);
96 glDeleteShader(fs);
97
98 glLinkProgram(srgb_decoder_program_);
99 #ifndef NDEBUG
100 GLint linked = 0;
101 glGetProgramiv(srgb_decoder_program_, GL_LINK_STATUS, &linked);
102 if (!linked) {
103 DLOG(ERROR) << "BlitFramebuffer: program link failure.";
104 }
105 #endif
106
107 GLuint texture_uniform =
108 glGetUniformLocation(srgb_decoder_program_, "u_source_texture");
109 glUseProgram(srgb_decoder_program_);
110 glUniform1i(texture_uniform, 0);
111
112 glGenTextures(srgb_decoder_textures_.size(), srgb_decoder_textures_.data());
113 glActiveTexture(GL_TEXTURE0);
114 for (auto srgb_decoder_texture : srgb_decoder_textures_) {
115 glBindTexture(GL_TEXTURE_2D, srgb_decoder_texture);
116
117 // Use linear, non-mipmapped sampling with the srgb decoder texture
118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
120 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
122 }
123
124 glGenFramebuffersEXT(1, &srgb_decoder_fbo_);
125 glGenVertexArraysOES(1, &srgb_decoder_vao_);
126
127 decoder->RestoreTextureUnitBindings(0);
128 decoder->RestoreActiveTexture();
129 decoder->RestoreProgramBindings();
130
131 srgb_decoder_initialized_ = true;
132 }
133
134 void SRGBConverter::InitializeSRGBEncoder(
135 const gles2::GLES2Decoder* decoder) {
136 if (srgb_encoder_initialized_) {
137 return;
138 }
139
140 srgb_encoder_program_ = glCreateProgram();
141
142 // Compile the vertex shader
143 GLuint vs = glCreateShader(GL_VERTEX_SHADER);
144 CompileShader(vs, vs_source);
145 glAttachShader(srgb_encoder_program_, vs);
146 glDeleteShader(vs);
147
148 // Compile the fragment shader
149
150 // Sampling texels from a srgb texture to a linear image, it will convert
151 // the srgb color space to linear color space automatically as a part of
152 // filtering. See the section <sRGB Texture Color Conversion> in GLES and
153 // OpenGL spec. So in decoder, we don't need to decode again.
154 // However, sampling texels from a linear texture to a srgb image, it will
155 // not convert linear to srgb automatically. Shader should always operates
156 // in linear space. So in encoder, we need to encode explicitly in shader.
157 const char* fs_source =
158 "#version 150\n"
159 "uniform sampler2D u_source_texture;\n"
160 "in vec2 v_texcoord;\n"
161 "out vec4 output_color;\n"
162 "\n"
163 "float encode(float color)\n"
164 "{\n"
165 " float encoded_color;\n"
166 " if (color <= 0.0) {\n"
167 " return 0.0;\n"
168 " } else if (color < 0.0031308) {\n"
169 " return color * 12.92;\n"
170 " } else if (color < 1) {\n"
171 " return pow(color, 0.41666) * 1.055 - 0.055;\n"
172 " } else {\n"
173 " return 1.0;\n"
174 " }\n"
175 "}\n"
176 "\n"
177 "void main()\n"
178 "{\n"
179 " vec4 c = texture(u_source_texture, v_texcoord);\n"
180 " output_color = vec4(encode(c.r), encode(c.g), encode(c.b), c.a);\n"
181 "}\n";
182
183 GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
184 CompileShader(fs, fs_source);
185 glAttachShader(srgb_encoder_program_, fs);
186 glDeleteShader(fs);
187
188 glLinkProgram(srgb_encoder_program_);
189 #ifndef NDEBUG
190 GLint linked = 0;
191 glGetProgramiv(srgb_encoder_program_, GL_LINK_STATUS, &linked);
192 if (!linked) {
193 DLOG(ERROR) << "SRGB Encoder for BlitFramebuffer: program link failure.";
194 }
195 #endif
196
197 GLuint texture_uniform =
198 glGetUniformLocation(srgb_encoder_program_, "u_source_texture");
199 glUseProgram(srgb_encoder_program_);
200 glUniform1i(texture_uniform, 0);
201
202 glGenTextures(srgb_encoder_textures_.size(), srgb_encoder_textures_.data());
203 glActiveTexture(GL_TEXTURE0);
204 for (auto srgb_encoder_texture : srgb_encoder_textures_) {
205 glBindTexture(GL_TEXTURE_2D, srgb_encoder_texture);
206
207 // Use linear, non-mipmapped sampling with the srgb encoder texture
208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
212 }
213
214 glGenFramebuffersEXT(1, &srgb_encoder_fbo_);
215 glGenVertexArraysOES(1, &srgb_encoder_vao_);
216
217 decoder->RestoreTextureUnitBindings(0);
218 decoder->RestoreActiveTexture();
219 decoder->RestoreProgramBindings();
220
221 srgb_encoder_initialized_ = true;
222 }
223
224 void SRGBConverter::Destroy() {
225 if (srgb_decoder_initialized_) {
226 glDeleteProgram(srgb_decoder_program_);
227 srgb_decoder_program_ = 0;
228
229 glDeleteTextures(srgb_decoder_textures_.size(),
230 srgb_decoder_textures_.data());
231 srgb_decoder_textures_.fill(0);
232
233 glDeleteFramebuffersEXT(1, &srgb_decoder_fbo_);
234 srgb_decoder_fbo_ = 0;
235
236 glDeleteVertexArraysOES(1, &srgb_decoder_vao_);
237 srgb_decoder_vao_ = 0;
238
239 srgb_decoder_initialized_ = false;
240 }
241
242 if (srgb_encoder_initialized_) {
243 glDeleteProgram(srgb_encoder_program_);
244 srgb_encoder_program_ = 0;
245
246 glDeleteTextures(srgb_encoder_textures_.size(),
247 srgb_encoder_textures_.data());
248 srgb_encoder_textures_.fill(0);
249
250 glDeleteFramebuffersEXT(1, &srgb_encoder_fbo_);
251 srgb_encoder_fbo_ = 0;
252
253 glDeleteVertexArraysOES(1, &srgb_encoder_vao_);
254 srgb_encoder_vao_ = 0;
255
256 srgb_encoder_initialized_ = false;
257 }
258 }
259
260 void SRGBConverter::SRGBToLinear(
261 const gles2::GLES2Decoder* decoder,
262 GLint srcX0,
263 GLint srcY0,
264 GLint srcX1,
265 GLint srcY1,
266 GLint dstX0,
267 GLint dstY0,
268 GLint dstX1,
269 GLint dstY1,
270 GLbitfield mask,
271 GLenum filter,
272 const gfx::Size& framebuffer_size,
273 GLuint src_framebuffer,
274 GLenum src_framebuffer_internal_format,
275 GLuint dst_framebuffer) {
276 // This function blits srgb image in src fb to linear image in dst fb.
277 // The steps are:
278 // 1) Copy and crop pixels from source srgb image to the 1st texture(srgb).
279 // 2) Sampling from the 1st texture and drawing to the 2nd texture(linear).
280 // During this step, color space is converted from srgb to linear.
281 // 3) Finally, blit pixels from the 2nd texture to the target, which is
282 // also a linear image.
283 DCHECK(srgb_decoder_initialized_);
284
285 // Copy the image from read buffer to the decoder's 1st texture(srgb).
286 // TODO(yunchao) If the read buffer is a fbo texture, we can sample
287 // directly from that texture. In this way, we can save gpu memory.
288 glBindFramebufferEXT(GL_FRAMEBUFFER, src_framebuffer);
289 glActiveTexture(GL_TEXTURE0);
290 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[0]);
291
292 // We should not copy pixels outside of the read framebuffer. If we read
293 // these pixels, they would become in-bound during BlitFramebuffer. However,
294 // Out-of-bounds pixels will be initialized to 0 in CopyTexSubImage. But they
295 // should read as if the GL_CLAMP_TO_EDGE texture mapping mode were applied
296 // during BlitFramebuffer when the filter is GL_LINEAR.
297 GLuint x = srcX1 > srcX0 ? srcX0 : srcX1;
298 GLuint y = srcY1 > srcY0 ? srcY0 : srcY1;
299 GLuint width = srcX1 > srcX0 ? srcX1 - srcX0 : srcX0 - srcX1;
300 GLuint height = srcY1 > srcY0 ? srcY1 - srcY0 : srcY0 - srcY1;
301 gfx::Rect c(0, 0, framebuffer_size.width(), framebuffer_size.height());
302 c.Intersect(gfx::Rect(x, y, width, height));
303 GLuint xoffset = c.x() - x;
304 GLuint yoffset = c.y() - y;
305 glCopyTexImage2D(GL_TEXTURE_2D, 0, src_framebuffer_internal_format,
306 c.x(), c.y(), c.width(), c.height(), 0);
307
308 // Make a temporary linear texture as the decoder's 2nd texture, where we
309 // render the converted (srgb to linear) result to.
310 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
311
312 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[1]);
313 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
314 c.width(), c.height(),
315 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
316 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_decoder_fbo_);
317 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
318 GL_TEXTURE_2D, srgb_decoder_textures_[1], 0);
319
320 // Sampling from the decoder's first texture(srgb) and drawing to the
321 // decoder's 2nd texture(linear),
322 glUseProgram(srgb_decoder_program_);
323 glViewport(0, 0, width, height);
324 glDisable(GL_SCISSOR_TEST);
325 glDisable(GL_DEPTH_TEST);
326 glDisable(GL_STENCIL_TEST);
327 glDisable(GL_CULL_FACE);
328 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
329 glDepthMask(GL_FALSE);
330 glDisable(GL_BLEND);
331 glDisable(GL_DITHER);
332
333 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[0]);
334 glBindVertexArrayOES(srgb_decoder_vao_);
335
336 glDrawArrays(GL_TRIANGLES, 0, 6);
337
338 // Finally, bind the decoder framebuffer as read framebuffer,
339 // blit the converted texture in decoder fbo to the destination texture
340 // in destination framebuffer.
341 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_);
342 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, dst_framebuffer);
343 // Note that the source region has been changed in decoder framebuffer.
344 // The xoffset/yoffset can make bliting clamp to the correct edge if
345 // CLAMP_TO_EDGE is necessary.
346 glBlitFramebuffer(srcX0 < srcX1 ? 0 - xoffset : width - xoffset,
347 srcY0 < srcY1 ? 0 - yoffset : height - yoffset,
348 srcX0 < srcX1 ? width - xoffset : 0 - xoffset,
349 srcY0 < srcY1 ? height - yoffset : 0 - yoffset,
350 dstX0, dstY0, dstX1, dstY1, mask, filter);
351
352 // Restore state
353 decoder->RestoreAllAttributes();
354 decoder->RestoreTextureUnitBindings(0);
355 decoder->RestoreActiveTexture();
356 decoder->RestoreProgramBindings();
357 decoder->RestoreBufferBindings();
358 decoder->RestoreFramebufferBindings();
359 decoder->RestoreGlobalState();
360 }
361
362 void SRGBConverter::LinearToSRGB(
363 const gles2::GLES2Decoder* decoder,
364 GLint srcX0,
365 GLint srcY0,
366 GLint srcX1,
367 GLint srcY1,
368 GLint dstX0,
369 GLint dstY0,
370 GLint dstX1,
371 GLint dstY1,
372 GLbitfield mask,
373 GLenum filter,
374 GLuint src_framebuffer,
375 GLenum src_framebuffer_internal_format,
376 GLenum src_framebuffer_format,
377 GLenum src_framebuffer_type,
378 GLuint dst_framebuffer) {
379 // This function blits linear image in src fb to srgb image in dst fb.
380 // The steps are:
381 // 1) BlitFramebuffer from source linear image to a temp linear texture.
382 // 2) Sampling from the temp texture and drawing to the target srgb
383 // image. During this step, color space is converted from linear to srgb.
384
385 DCHECK(srgb_encoder_initialized_);
386
387 // Create a temp linear texture as draw buffer. Blit framebuffer from
388 // source linear image to the temp linear texture. Filtering is done
389 // during bliting. Note that the src and dst coordinates may be reversed.
390 glActiveTexture(GL_TEXTURE0);
391 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]);
392
393 GLuint width = dstX1 > dstX0 ? dstX1 - dstX0 : dstX0 - dstX1;
394 GLuint height = dstY1 > dstY0 ? dstY1 - dstY0 : dstY0 - dstY1;
395 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
396 glTexImage2D(GL_TEXTURE_2D, 0, src_framebuffer_internal_format,
397 width, height,
398 0, src_framebuffer_format, src_framebuffer_type, nullptr);
399
400 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, srgb_encoder_fbo_);
401 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
402 GL_TEXTURE_2D, srgb_encoder_textures_[0], 0);
403 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, src_framebuffer);
404 glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
405 dstX0 < dstX1 ? 0 : width,
406 dstY0 < dstY1 ? 0 : height,
407 dstX0 < dstX1 ? width : 0,
408 dstY0 < dstY1 ? height : 0,
409 mask, filter);
410
411 // Sampling from the linear texture and drawing to the target srgb image.
412 // During this step, color space is converted from linear to srgb. We should
413 // set appropriate viewport to draw to the correct location in target FB.
414 GLuint xstart = dstX0 < dstX1 ? dstX0 : dstX1;
415 GLuint ystart = dstY0 < dstY1 ? dstY0 : dstY1;
416 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, dst_framebuffer);
417 glUseProgram(srgb_encoder_program_);
418 glViewport(xstart, ystart, width, height);
419 glDisable(GL_SCISSOR_TEST);
420 glDisable(GL_DEPTH_TEST);
421 glDisable(GL_STENCIL_TEST);
422 glDisable(GL_CULL_FACE);
423 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
424 glDepthMask(GL_FALSE);
425 glDisable(GL_BLEND);
426 glDisable(GL_DITHER);
427
428 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]);
429 glBindVertexArrayOES(srgb_encoder_vao_);
430
431 glDrawArrays(GL_TRIANGLES, 0, 6);
432
433 // Restore state
434 decoder->RestoreAllAttributes();
435 decoder->RestoreTextureUnitBindings(0);
436 decoder->RestoreActiveTexture();
437 decoder->RestoreProgramBindings();
438 decoder->RestoreBufferBindings();
439 decoder->RestoreFramebufferBindings();
440 decoder->RestoreGlobalState();
441 }
442
443 void SRGBConverter::SRGBToSRGB(
444 const gles2::GLES2Decoder* decoder,
445 GLint srcX0,
446 GLint srcY0,
447 GLint srcX1,
448 GLint srcY1,
449 GLint dstX0,
450 GLint dstY0,
451 GLint dstX1,
452 GLint dstY1,
453 GLbitfield mask,
454 GLenum filter,
455 const gfx::Size& framebuffer_size,
456 GLuint src_framebuffer,
457 GLenum src_framebuffer_internal_format,
458 GLuint dst_framebuffer) {
459 // This function blits srgb image in src fb to srgb image in dst fb.
460 // It needs to use decoder's resource, as well as encoder's resources,
461 // for instance, decoder's and encoder's fbos, programs and textuers.
462 // The steps are:
463 // 1) Copy and crop pixels from source srgb image to the 1st texture(srgb).
464 // 2) Sampling from the 1st texture and drawing to the 2nd texture(linear).
465 // During this step, color space is converted from srgb to linear.
466 // 3) Blit pixels from the 2nd texture to the 3rd texture(linear).
467 // 4) Sampling from the 3rd texture and drawing to the dst image(srgb).
468 // During this step, color space is converted from linear to srgb.
469 DCHECK(srgb_decoder_initialized_ && srgb_encoder_initialized_);
470
471 // Copy the image from read buffer to the decoder's 1st texture(srgb).
472 // TODO(yunchao) If the read buffer is a fbo texture, we can sample
473 // directly from that texture. In this way, we can save gpu memory.
474 glBindFramebufferEXT(GL_FRAMEBUFFER, src_framebuffer);
475 glActiveTexture(GL_TEXTURE0);
476 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[0]);
477
478 // We should not copy pixels outside of the read framebuffer. If we read
479 // these pixels, they would become in-bound during BlitFramebuffer. However,
480 // Out-of-bounds pixels will be initialized to 0 in CopyTexSubImage. But they
481 // should read as if the GL_CLAMP_TO_EDGE texture mapping mode were applied
482 // during BlitFramebuffer when the filter is GL_LINEAR.
483 GLuint x = srcX1 > srcX0 ? srcX0 : srcX1;
484 GLuint y = srcY1 > srcY0 ? srcY0 : srcY1;
485 GLuint width_read = srcX1 > srcX0 ? srcX1 - srcX0 : srcX0 - srcX1;
486 GLuint height_read = srcY1 > srcY0 ? srcY1 - srcY0 : srcY0 - srcY1;
487 gfx::Rect c(0, 0, framebuffer_size.width(), framebuffer_size.height());
488 c.Intersect(gfx::Rect(x, y, width_read, height_read));
489 GLuint xoffset = c.x() - x;
490 GLuint yoffset = c.y() - y;
491 glCopyTexImage2D(GL_TEXTURE_2D, 0, src_framebuffer_internal_format,
492 c.x(), c.y(), c.width(), c.height(), 0);
493
494 // Make a temporary linear texture as the decoder's 2nd texture, where we
495 // render the converted (srgb to linear) result to.
496 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
497
498 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[1]);
499 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
500 c.width(), c.height(),
501 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
502 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_decoder_fbo_);
503 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
504 GL_TEXTURE_2D, srgb_decoder_textures_[1], 0);
505
506 // Sampling from the decoder's first texture(srgb) and drawing to the
507 // decoder's 2nd texture(linear),
508 glUseProgram(srgb_decoder_program_);
509 glViewport(0, 0, width_read, height_read);
510 glDisable(GL_SCISSOR_TEST);
511 glDisable(GL_DEPTH_TEST);
512 glDisable(GL_STENCIL_TEST);
513 glDisable(GL_CULL_FACE);
514 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
515 glDepthMask(GL_FALSE);
516 glDisable(GL_BLEND);
517 glDisable(GL_DITHER);
518
519 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[0]);
520 glBindVertexArrayOES(srgb_decoder_vao_);
521
522 glDrawArrays(GL_TRIANGLES, 0, 6);
523
524 // Create the 3rd texture(linear) as decoder's draw buffer. Blit framebuffer
525 // from the 2nd texture(linear) to the 3rd texture. Filtering is done
526 // during bliting. Note that the src and dst coordinates may be reversed.
527 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]);
528
529 GLuint width_draw = dstX1 > dstX0 ? dstX1 - dstX0 : dstX0 - dstX1;
530 GLuint height_draw = dstY1 > dstY0 ? dstY1 - dstY0 : dstY0 - dstY1;
531 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
532 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
533 width_draw, height_draw,
534 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
535
536 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, srgb_encoder_fbo_);
537 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
538 GL_TEXTURE_2D, srgb_encoder_textures_[0], 0);
539 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_);
540 glBlitFramebuffer(srcX0 < srcX1 ? 0 - xoffset : width_read - xoffset,
541 srcY0 < srcY1 ? 0 - yoffset : height_read - yoffset,
542 srcX0 < srcX1 ? width_read - xoffset : 0 - xoffset,
543 srcY0 < srcY1 ? height_read - yoffset : 0 - yoffset,
544 dstX0 < dstX1 ? 0 : width_draw,
545 dstY0 < dstY1 ? 0 : height_draw,
546 dstX0 < dstX1 ? width_draw : 0,
547 dstY0 < dstY1 ? height_draw : 0,
548 mask, filter);
549
550 // Sampling from the 3rd texture(linear) and drawing to the target srgb image.
551 // During this step, color space is converted from linear to srgb. We should
552 // set appropriate viewport to draw to the correct location in target FB.
553 GLuint xstart = dstX0 < dstX1 ? dstX0 : dstX1;
554 GLuint ystart = dstY0 < dstY1 ? dstY0 : dstY1;
555 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, dst_framebuffer);
556 glUseProgram(srgb_encoder_program_);
557 glViewport(xstart, ystart, width_draw, height_draw);
558
559 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]);
560 glBindVertexArrayOES(srgb_encoder_vao_);
561
562 glDrawArrays(GL_TRIANGLES, 0, 6);
563
564 // Restore state
565 decoder->RestoreAllAttributes();
566 decoder->RestoreTextureUnitBindings(0);
567 decoder->RestoreActiveTexture();
568 decoder->RestoreProgramBindings();
569 decoder->RestoreBufferBindings();
570 decoder->RestoreFramebufferBindings();
571 decoder->RestoreGlobalState();
572 }
573
574 } // namespace gles2.
575 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698