Chromium Code Reviews| 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 |