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. | |
| 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" */ | |
| 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" | |
| 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 | |
| 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"; | |
| 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" | |
| 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 | |
| 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) { | |
| 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 glCopyTexImage2D(GL_TEXTURE_2D, 0, src_framebuffer_internal_format, | |
| 323 c.x(), c.y(), c.width(), c.height(), 0); | |
| 324 | |
| 325 // Make a temporary framebuffer using the second srgb decoder texture to | |
| 326 // render the converted (linear to srgb) result to. | |
| 327 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); | |
| 328 | |
| 329 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[1]); | |
| 330 glTexImage2D(GL_TEXTURE_2D, 0, dst_framebuffer_internal_format, | |
| 331 c.width(), c.height(), | |
| 332 0, dst_framebuffer_format, dst_framebuffer_type, nullptr); | |
| 333 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_decoder_fbo_); | |
| 334 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
| 335 srgb_decoder_textures_[1], 0); | |
| 336 | |
| 337 // Render to the second srgb decoder texture, | |
| 338 // sampling from the first srgb decoder texture. | |
| 339 glUseProgram(srgb_decoder_program_); | |
| 340 glViewport(0, 0, width, height); | |
| 341 glDisable(GL_SCISSOR_TEST); | |
| 342 glDisable(GL_DEPTH_TEST); | |
| 343 glDisable(GL_STENCIL_TEST); | |
| 344 glDisable(GL_CULL_FACE); | |
| 345 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
| 346 glDepthMask(GL_FALSE); | |
| 347 glDisable(GL_BLEND); | |
| 348 glDisable(GL_DITHER); | |
| 349 | |
| 350 glBindTexture(GL_TEXTURE_2D, srgb_decoder_textures_[0]); | |
| 351 glBindVertexArrayOES(srgb_decoder_vao_); | |
| 352 | |
| 353 glDrawArrays(GL_TRIANGLES, 0, 6); | |
| 354 | |
| 355 // Finally, bind the temporary framebuffer as read framebuffer, | |
| 356 // blit the converted texture in temp fbo to the destination texture | |
| 357 // in destination framebuffer. | |
| 358 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_); | |
| 359 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, dst_framebuffer); | |
| 360 // Note that the source region has been changed in temp framebuffer | |
| 361 glBlitFramebuffer(srcX0 < srcX1 ? 0 : width, | |
| 362 srcY0 < srcY1 ? 0 : height, | |
| 363 srcX0 < srcX1 ? width : 0, | |
| 364 srcY0 < srcY1 ? height : 0, | |
| 365 dstX0, dstY0, dstX1, dstY1, mask, filter); | |
|
Zhenyao Mo
2016/09/01 19:28:33
I still think this is incorrect.
At glCopyTexImag
yunchao
2016/09/02 14:11:16
Got it. You are correct. This algorithm would make
| |
| 366 | |
| 367 // Restore state | |
| 368 decoder->RestoreAllAttributes(); | |
| 369 decoder->RestoreTextureUnitBindings(0); | |
| 370 decoder->RestoreActiveTexture(); | |
| 371 decoder->RestoreProgramBindings(); | |
| 372 decoder->RestoreBufferBindings(); | |
| 373 decoder->RestoreFramebufferBindings(); | |
| 374 decoder->RestoreGlobalState(); | |
| 375 } | |
| 376 | |
| 377 void SRGBConverter::LinearToSRGB( | |
| 378 const gles2::GLES2Decoder* decoder, | |
| 379 GLint srcX0, | |
| 380 GLint srcY0, | |
| 381 GLint srcX1, | |
| 382 GLint srcY1, | |
| 383 GLint dstX0, | |
| 384 GLint dstY0, | |
| 385 GLint dstX1, | |
| 386 GLint dstY1, | |
| 387 GLbitfield mask, | |
| 388 GLenum filter, | |
| 389 const gfx::Size& framebuffer_size, | |
| 390 GLuint src_framebuffer, | |
| 391 GLenum src_framebuffer_internal_format, | |
| 392 GLuint dst_framebuffer, | |
| 393 GLenum dst_framebuffer_internal_format, | |
| 394 GLenum dst_framebuffer_format, | |
| 395 GLenum dst_framebuffer_type) { | |
| 396 | |
| 397 DCHECK(srgb_encoder_initialized_); | |
| 398 | |
| 399 // Copy the framebuffer to the first srgb encoder texture | |
| 400 glBindFramebufferEXT(GL_FRAMEBUFFER, src_framebuffer); | |
| 401 glActiveTexture(GL_TEXTURE0); | |
| 402 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]); | |
| 403 | |
| 404 // We should not copy pixels outside of the read framebuffer. If we read | |
| 405 // these pixels, they would become in-bound during BlitFramebuffer. However, | |
| 406 // Out-of-bounds pixels will be initialized to 0 in CopyTexSubImage. But they | |
| 407 // should read as if the GL_CLAMP_TO_EDGE texture mapping mode were applied | |
| 408 // during BlitFramebuffer when the filter is GL_LINEAR. | |
| 409 GLuint x = srcX1 > srcX0 ? srcX0 : srcX1; | |
| 410 GLuint width = srcX1 > srcX0 ? srcX1 - srcX0 : srcX0 - srcX1; | |
| 411 GLuint y = srcY1 > srcY0 ? srcY0 : srcY1; | |
| 412 GLuint height = srcY1 > srcY0 ? srcY1 - srcY0 : srcY0 - srcY1; | |
| 413 gfx::Rect c(0, 0, framebuffer_size.width(), framebuffer_size.height()); | |
| 414 c.Intersect(gfx::Rect(x, y, width, height)); | |
| 415 glCopyTexImage2D(GL_TEXTURE_2D, 0, src_framebuffer_internal_format, | |
| 416 c.x(), c.y(), c.width(), c.height(), 0); | |
| 417 | |
| 418 // Make a temporary framebuffer using the second srgb encoder texture to | |
| 419 // render the converted (linear to srgb) result to. | |
| 420 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); | |
| 421 | |
| 422 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[1]); | |
| 423 glTexImage2D(GL_TEXTURE_2D, 0, dst_framebuffer_internal_format, | |
| 424 c.width(), c.height(), | |
| 425 0, dst_framebuffer_format, dst_framebuffer_type, nullptr); | |
| 426 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_encoder_fbo_); | |
| 427 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
| 428 srgb_encoder_textures_[1], 0); | |
| 429 | |
| 430 // Render to the second srgb encoder texture, | |
| 431 // sampling from the first srgb encoder texture. | |
| 432 glUseProgram(srgb_encoder_program_); | |
| 433 glViewport(0, 0, width, height); | |
| 434 glDisable(GL_SCISSOR_TEST); | |
| 435 glDisable(GL_DEPTH_TEST); | |
| 436 glDisable(GL_STENCIL_TEST); | |
| 437 glDisable(GL_CULL_FACE); | |
| 438 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
| 439 glDepthMask(GL_FALSE); | |
| 440 glDisable(GL_BLEND); | |
| 441 glDisable(GL_DITHER); | |
| 442 | |
| 443 glBindTexture(GL_TEXTURE_2D, srgb_encoder_textures_[0]); | |
| 444 glBindVertexArrayOES(srgb_encoder_vao_); | |
| 445 | |
| 446 glDrawArrays(GL_TRIANGLES, 0, 6); | |
| 447 | |
| 448 // Finally, bind the temporary framebuffer as read framebuffer, | |
| 449 // blit the converted texture in temp fbo to the destination texture | |
| 450 // in destination framebuffer. | |
| 451 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_encoder_fbo_); | |
| 452 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, dst_framebuffer); | |
| 453 // Note that the source region has been changed in temp framebuffer | |
| 454 glBlitFramebuffer(srcX0 < srcX1 ? 0 : width, | |
| 455 srcY0 < srcY1 ? 0 : height, | |
| 456 srcX0 < srcX1 ? width : 0, | |
| 457 srcY0 < srcY1 ? height : 0, | |
| 458 dstX0, dstY0, dstX1, dstY1, mask, filter); | |
|
Zhenyao Mo
2016/09/01 19:28:33
Same situation here.
yunchao
2016/09/02 14:11:16
Done.
| |
| 459 | |
| 460 // Restore state | |
| 461 decoder->RestoreAllAttributes(); | |
| 462 decoder->RestoreTextureUnitBindings(0); | |
| 463 decoder->RestoreActiveTexture(); | |
| 464 decoder->RestoreProgramBindings(); | |
| 465 decoder->RestoreBufferBindings(); | |
| 466 decoder->RestoreFramebufferBindings(); | |
| 467 decoder->RestoreGlobalState(); | |
| 468 } | |
| 469 | |
| 470 } // namespace gles2. | |
| 471 } // namespace gpu | |
| OLD | NEW |