Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "gpu/command_buffer/service/gles2_cmd_srgb_converter.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_srgb_converter.h" |
| 6 | 6 |
| 7 #include "gpu/command_buffer/service/texture_manager.h" | 7 #include "gpu/command_buffer/service/texture_manager.h" |
| 8 #include "ui/gl/gl_version_info.h" | 8 #include "ui/gl/gl_version_info.h" |
| 9 | 9 |
| 10 namespace { | 10 namespace { |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 // Restore state | 315 // Restore state |
| 316 decoder->RestoreAllAttributes(); | 316 decoder->RestoreAllAttributes(); |
| 317 decoder->RestoreTextureUnitBindings(0); | 317 decoder->RestoreTextureUnitBindings(0); |
| 318 decoder->RestoreActiveTexture(); | 318 decoder->RestoreActiveTexture(); |
| 319 decoder->RestoreProgramBindings(); | 319 decoder->RestoreProgramBindings(); |
| 320 decoder->RestoreBufferBindings(); | 320 decoder->RestoreBufferBindings(); |
| 321 decoder->RestoreFramebufferBindings(); | 321 decoder->RestoreFramebufferBindings(); |
| 322 decoder->RestoreGlobalState(); | 322 decoder->RestoreGlobalState(); |
| 323 } | 323 } |
| 324 | 324 |
| 325 void SRGBConverter::InitializeSRGBEncoder(const gles2::GLES2Decoder* decoder) { | |
| 326 if (srgb_encoder_initialized_) { | |
| 327 return; | |
| 328 } | |
| 329 | |
| 330 GLuint srgb_encoder_program_ = 0; | |
| 331 | |
| 332 std::array<GLuint, 1> srgb_encoder_textures_ = {{0}}; | |
| 333 GLuint srgb_encoder_fbo_ = 0; | |
| 334 GLuint srgb_encoder_vao_ = 0; | |
| 335 | |
| 336 srgb_encoder_program_ = glCreateProgram(); | |
| 337 | |
| 338 const char* vs_source = | |
| 339 "#version 150\n" | |
| 340 "out vec2 v_texcoord;\n" | |
| 341 "\n" | |
| 342 "void main()\n" | |
| 343 "{\n" | |
| 344 " const vec2 quad_positions[6] = vec2[6]\n" | |
| 345 " (\n" | |
| 346 " vec2(0.0f, 0.0f),\n" | |
| 347 " vec2(0.0f, 1.0f),\n" | |
| 348 " vec2(1.0f, 0.0f),\n" | |
| 349 "\n" | |
| 350 " vec2(0.0f, 1.0f),\n" | |
| 351 " vec2(1.0f, 0.0f),\n" | |
| 352 " vec2(1.0f, 1.0f)\n" | |
| 353 " );\n" | |
| 354 "\n" | |
| 355 " vec2 xy = vec2((quad_positions[gl_VertexID] * 2.0) - 1.0);\n" | |
| 356 " gl_Position = vec4(xy, 0.0, 1.0);\n" | |
| 357 " v_texcoord = quad_positions[gl_VertexID];\n" | |
| 358 "}\n"; | |
| 359 | |
| 360 // Compile the vertex shader | |
| 361 GLuint vs = glCreateShader(GL_VERTEX_SHADER); | |
| 362 CompileShader(vs, vs_source); | |
| 363 glAttachShader(srgb_encoder_program_, vs); | |
| 364 glDeleteShader(vs); | |
| 365 | |
| 366 // Compile the fragment shader | |
| 367 | |
| 368 // Sampling texels from a srgb texture to a linear image, it will convert | |
| 369 // the srgb color space to linear color space automatically as a part of | |
| 370 // filtering. See the section <sRGB Texture Color Conversion> in GLES and | |
| 371 // OpenGL spec. So in decoder, we don't need to decode again. | |
| 372 // However, sampling texels from a linear texture to a srgb image, it will | |
| 373 // not convert linear to srgb automatically. Shader should always operates | |
| 374 // in linear space. So in encoder, we need to encode explicitly in shader. | |
| 375 const char* fs_source = | |
| 376 "#version 150\n" | |
| 377 "uniform sampler2D u_source_texture;\n" | |
| 378 "in vec2 v_texcoord;\n" | |
| 379 "out vec4 output_color;\n" | |
| 380 "\n" | |
| 381 "float encode(float color)\n" | |
| 382 "{\n" | |
| 383 " float encoded_color;\n" | |
| 384 " if (color <= 0.0) {\n" | |
| 385 " return 0.0;\n" | |
| 386 " } else if (color < 0.0031308) {\n" | |
| 387 " return color * 12.92;\n" | |
| 388 " } else if (color < 1) {\n" | |
| 389 " return pow(color, 0.41666) * 1.055 - 0.055;\n" | |
| 390 " } else {\n" | |
| 391 " return 1.0;\n" | |
| 392 " }\n" | |
| 393 "}\n" | |
| 394 "\n" | |
| 395 "void main()\n" | |
| 396 "{\n" | |
| 397 " vec4 c = texture(u_source_texture, v_texcoord);\n" | |
| 398 " output_color = vec4(encode(c.r), encode(c.g), encode(c.b), c.a);\n" | |
| 399 "}\n"; | |
| 400 /* const char* fs_source = | |
| 401 "#version 150\n" | |
| 402 "uniform sampler2D u_source_texture;\n" | |
| 403 "in vec2 v_texcoord;\n" | |
| 404 "out vec4 output_color;\n" | |
| 405 "\n" | |
| 406 "void main()\n" | |
| 407 "{\n" | |
| 408 " vec4 c = texture(u_source_texture, v_texcoord);\n" | |
| 409 " output_color = c;\n" | |
| 410 "}\n";*/ | |
| 411 | |
| 412 GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); | |
| 413 CompileShader(fs, fs_source); | |
| 414 glAttachShader(srgb_encoder_program_, fs); | |
| 415 glDeleteShader(fs); | |
| 416 | |
| 417 glLinkProgram(srgb_encoder_program_); | |
| 418 #ifndef NDEBUG | |
| 419 GLint linked = 0; | |
| 420 glGetProgramiv(srgb_encoder_program_, GL_LINK_STATUS, &linked); | |
| 421 if (!linked) { | |
| 422 DLOG(ERROR) << "SRGB Encoder for BlitFramebuffer: program link failure."; | |
| 423 } | |
| 424 #endif | |
| 425 | |
| 426 GLuint texture_uniform = | |
| 427 glGetUniformLocation(srgb_encoder_program_, "u_source_texture"); | |
| 428 glUseProgram(srgb_encoder_program_); | |
| 429 glUniform1i(texture_uniform, 0); | |
| 430 | |
| 431 glGenTextures(srgb_encoder_textures_.size(), srgb_encoder_textures_.data()); | |
| 432 glActiveTexture(GL_TEXTURE0); | |
| 433 for (auto srgb_encoder_texture : srgb_encoder_textures_) { | |
| 434 glBindTexture(GL_TEXTURE_2D, srgb_encoder_texture); | |
| 435 | |
| 436 // Use linear, non-mipmapped sampling with the srgb encoder texture | |
| 437 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 438 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 439 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 441 } | |
| 442 | |
| 443 glGenFramebuffersEXT(1, &srgb_encoder_fbo_); | |
| 444 glGenVertexArraysOES(1, &srgb_encoder_vao_); | |
| 445 | |
| 446 decoder->RestoreTextureUnitBindings(0); | |
| 447 decoder->RestoreActiveTexture(); | |
| 448 decoder->RestoreProgramBindings(); | |
| 449 | |
| 450 srgb_encoder_initialized_ = true; | |
| 451 } | |
|
yunchao
2016/09/19 15:25:48
Please remove this function above, Yizhou.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 452 | |
| 453 void SRGBConverter::SRGBGenerateMipmap(const gles2::GLES2Decoder* decoder, | |
| 454 Texture* tex, | |
| 455 GLenum target) { | |
| 456 DCHECK(srgb_converter_initialized_); | |
| 457 | |
| 458 GLsizei width; | |
| 459 GLsizei height; | |
| 460 GLsizei depth; | |
| 461 GLenum type = 0; | |
| 462 GLenum internal_format = 0; | |
| 463 GLsizei base_level = tex->base_level(); | |
| 464 tex->GetLevelSize(target, base_level, &width, &height, &depth); | |
| 465 tex->GetLevelType(target, 0, &type, &internal_format); | |
| 466 const GLint mipmap_level = | |
| 467 TextureManager::ComputeMipMapCount(target, width, height, depth); | |
| 468 | |
| 469 // copy tex to srgb_decoder_textures_[0] with srgb format | |
| 470 glBindTexture(target, tex->service_id()); | |
| 471 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_); | |
| 472 glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
| 473 GL_TEXTURE_2D, tex->service_id(), 0); | |
| 474 | |
| 475 GLenum error = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER); | |
| 476 error = glGetError(); | |
|
yunchao
2016/09/19 15:25:48
please remove the debugging code.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 477 | |
| 478 glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[0]); | |
| 479 glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, GL_SRGB, | |
| 480 GL_UNSIGNED_BYTE, nullptr); | |
|
yunchao
2016/09/19 15:25:48
This is not necessary, copyTexImage2D will allocat
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 481 glCopyTexImage2D(GL_TEXTURE_2D, 0, internal_format, 0, 0, width, height, 0); | |
| 482 error = glGetError(); | |
| 483 unsigned char bytes3[width * height * 4]; | |
| 484 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes3); | |
|
yunchao
2016/09/19 15:25:48
please remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 485 | |
| 486 // bind srgb_decoder_textures_[1] to draw framebuffer | |
| 487 glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[1]); | |
| 488 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, | |
| 489 GL_UNSIGNED_BYTE, nullptr); | |
| 490 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, srgb_decoder_fbo_); | |
| 491 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
| 492 GL_TEXTURE_2D, srgb_converter_textures_[1], 0); | |
| 493 | |
| 494 error = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER); | |
| 495 error = glGetError(); | |
| 496 unsigned char bytes2[width * height * 4]; | |
| 497 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes2); | |
|
yunchao
2016/09/19 15:25:47
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 498 | |
| 499 // bind texture with srgb format and render with srgb_decoder_program_ | |
| 500 glUseProgram(srgb_converter_program_); | |
| 501 glViewport(0, 0, width, height); | |
| 502 glDisable(GL_SCISSOR_TEST); | |
| 503 glDisable(GL_DEPTH_TEST); | |
| 504 glDisable(GL_STENCIL_TEST); | |
| 505 glDisable(GL_CULL_FACE); | |
| 506 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
| 507 glDepthMask(GL_FALSE); | |
| 508 glEnable(GL_BLEND); | |
|
yunchao
2016/09/19 15:25:48
glDisable blend
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 509 glDisable(GL_DITHER); | |
| 510 | |
| 511 glBindVertexArrayOES(srgb_converter_vao_); | |
| 512 glActiveTexture(GL_TEXTURE0); | |
| 513 glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[0]); | |
| 514 | |
| 515 error = glGetError(); | |
|
yunchao
2016/09/19 15:25:48
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 516 | |
| 517 glDrawArrays(GL_TRIANGLES, 0, 6); | |
| 518 | |
| 519 error = glGetError(); | |
| 520 unsigned char bytes1[width * height * 4]; | |
| 521 glBindFramebufferEXT(GL_READ_FRAMEBUFFER, srgb_decoder_fbo_); | |
| 522 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes1); | |
|
yunchao
2016/09/19 15:25:47
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 523 | |
| 524 // generateMipmap for tex and srgb_decoder_textures_[1] | |
| 525 glBindTexture(GL_TEXTURE_2D, tex->service_id()); | |
| 526 glGenerateMipmapEXT(GL_TEXTURE_2D); | |
| 527 glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[1]); | |
| 528 glGenerateMipmapEXT(GL_TEXTURE_2D); | |
| 529 | |
| 530 error = glGetError(); | |
|
yunchao
2016/09/19 15:25:47
remove debug code
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 531 | |
| 532 // bind tex with rgba format and render with srgb_encoder_program_ | |
| 533 | |
| 534 glClearColor(0, 0, 0, 255); | |
|
yunchao
2016/09/19 15:25:47
It is not necessary to set clear color.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 535 glBindTexture(GL_TEXTURE_2D, tex->service_id()); | |
| 536 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_encoder_fbo_); | |
| 537 | |
| 538 //InitializeSRGBEncoder(decoder); | |
| 539 //glUseProgram(srgb_encoder_program_); | |
| 540 | |
| 541 /*glDeleteProgram(srgb_converter_program_); | |
| 542 srgb_converter_program_ = 0; | |
| 543 srgb_converter_initialized_ = false; | |
| 544 InitializeSRGBConverterProgram(); | |
| 545 */ | |
|
yunchao
2016/09/19 15:25:47
remove debug code.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 546 glUseProgram(srgb_converter_program_); | |
| 547 | |
| 548 glBindVertexArrayOES(srgb_converter_vao_); | |
|
yunchao
2016/09/19 15:25:48
These two lines are not necessary, you have called
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 549 | |
| 550 for (GLint level = base_level; level < mipmap_level; level++) { | |
| 551 glBindTexture(GL_TEXTURE_2D, tex->service_id()); | |
|
yunchao
2016/09/19 15:25:47
This is not necessary.
yizhou.jiang
2016/09/20 07:00:26
Done.
| |
| 552 glBindFramebufferEXT(GL_FRAMEBUFFER, srgb_encoder_fbo_); | |
|
yunchao
2016/09/19 15:25:48
move this outside the for loop.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 553 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
| 554 GL_TEXTURE_2D, tex->service_id(), level); | |
| 555 | |
| 556 error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); | |
| 557 error = glGetError(); | |
| 558 unsigned char bytes2[width * height * 4]; | |
| 559 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes2); | |
|
yunchao
2016/09/19 15:25:48
remove debug code.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 560 | |
| 561 glActiveTexture(GL_TEXTURE0); | |
|
yunchao
2016/09/19 15:25:48
This is not necessary.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 562 glBindTexture(GL_TEXTURE_2D, srgb_converter_textures_[1]); | |
| 563 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level); | |
|
yunchao
2016/09/19 15:25:48
move these two lines outside the for loop.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 564 glViewport(0, 0, width, height); | |
| 565 glDrawArrays(GL_TRIANGLES, 0, 6); | |
| 566 | |
| 567 error = glGetError(); | |
| 568 unsigned char bytes[width * height * 4]; | |
| 569 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bytes); | |
|
yunchao
2016/09/19 15:25:48
remove the debug code.
yizhou.jiang
2016/09/20 07:00:27
Done.
| |
| 570 | |
| 571 width /= 2; | |
| 572 height /= 2; | |
| 573 } | |
| 574 | |
| 575 // Restore state | |
| 576 decoder->RestoreAllAttributes(); | |
| 577 decoder->RestoreTextureUnitBindings(0); | |
| 578 decoder->RestoreActiveTexture(); | |
| 579 decoder->RestoreProgramBindings(); | |
| 580 decoder->RestoreBufferBindings(); | |
| 581 decoder->RestoreFramebufferBindings(); | |
| 582 decoder->RestoreGlobalState(); | |
| 583 } | |
| 584 | |
| 325 } // namespace gles2. | 585 } // namespace gles2. |
| 326 } // namespace gpu | 586 } // namespace gpu |
| OLD | NEW |