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

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

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

Powered by Google App Engine
This is Rietveld 408576698