Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_copy_texture_chromium.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| 11 #include "gpu/command_buffer/service/gl_utils.h" | 11 #include "gpu/command_buffer/service/gl_utils.h" |
| 12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 13 #include "ui/gl/gl_implementation.h" | 13 #include "ui/gl/gl_implementation.h" |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, | 17 const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, |
| 18 0.0f, 1.0f, 0.0f, 0.0f, | 18 0.0f, 1.0f, 0.0f, 0.0f, |
| 19 0.0f, 0.0f, 1.0f, 0.0f, | 19 0.0f, 0.0f, 1.0f, 0.0f, |
| 20 0.0f, 0.0f, 0.0f, 1.0f}; | 20 0.0f, 0.0f, 0.0f, 1.0f}; |
| 21 | 21 |
| 22 enum VertexShaderId { | |
| 23 VERTEX_SHADER_COPY_TEXTURE, | |
| 24 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, | |
| 25 NUM_VERTEX_SHADERS, | |
| 26 }; | |
| 27 | |
| 28 enum FragmentShaderId { | 22 enum FragmentShaderId { |
| 29 FRAGMENT_SHADER_COPY_TEXTURE_2D, | 23 FRAGMENT_SHADER_COPY_TEXTURE_2D, |
| 30 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, | 24 FRAGMENT_SHADER_COPY_TEXTURE_RECTANGLE_ARB, |
| 31 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, | 25 FRAGMENT_SHADER_COPY_TEXTURE_EXTERNAL_OES, |
| 32 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, | 26 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_2D, |
| 33 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, | 27 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_RECTANGLE_ARB, |
| 34 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, | 28 FRAGMENT_SHADER_COPY_TEXTURE_PREMULTIPLY_ALPHA_EXTERNAL_OES, |
| 35 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, | 29 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_2D, |
| 36 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, | 30 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_RECTANGLE_ARB, |
| 37 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, | 31 FRAGMENT_SHADER_COPY_TEXTURE_UNPREMULTIPLY_ALPHA_EXTERNAL_OES, |
| 38 NUM_FRAGMENT_SHADERS, | 32 NUM_FRAGMENT_SHADERS, |
| 39 }; | 33 }; |
| 40 | 34 |
| 41 // Returns the correct vertex shader id to evaluate the copy operation for | |
| 42 // the CHROMIUM_flipy setting. | |
| 43 VertexShaderId GetVertexShaderId(bool flip_y) { | |
| 44 // bit 0: flip y | |
| 45 static VertexShaderId shader_ids[] = { | |
| 46 VERTEX_SHADER_COPY_TEXTURE, | |
| 47 VERTEX_SHADER_COPY_TEXTURE_FLIP_Y, | |
| 48 }; | |
| 49 | |
| 50 unsigned index = flip_y ? 1 : 0; | |
| 51 return shader_ids[index]; | |
| 52 } | |
| 53 | |
| 54 // Returns the correct fragment shader id to evaluate the copy operation for | 35 // Returns the correct fragment shader id to evaluate the copy operation for |
| 55 // the premultiply alpha pixel store settings and target. | 36 // the premultiply alpha pixel store settings and target. |
| 56 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha, | 37 FragmentShaderId GetFragmentShaderId(bool premultiply_alpha, |
| 57 bool unpremultiply_alpha, | 38 bool unpremultiply_alpha, |
| 58 GLenum target) { | 39 GLenum target) { |
| 59 // Only one alpha mode at a time makes sense. | 40 // Only one alpha mode at a time makes sense. |
| 60 DCHECK(!premultiply_alpha || !unpremultiply_alpha); | 41 DCHECK(!premultiply_alpha || !unpremultiply_alpha); |
| 61 | 42 |
| 62 enum { | 43 enum { |
| 63 SAMPLER_2D, | 44 SAMPLER_2D, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 } | 90 } |
| 110 | 91 |
| 111 const char* kShaderPrecisionPreamble = "\ | 92 const char* kShaderPrecisionPreamble = "\ |
| 112 #ifdef GL_ES\n\ | 93 #ifdef GL_ES\n\ |
| 113 precision mediump float;\n\ | 94 precision mediump float;\n\ |
| 114 #define TexCoordPrecision mediump\n\ | 95 #define TexCoordPrecision mediump\n\ |
| 115 #else\n\ | 96 #else\n\ |
| 116 #define TexCoordPrecision\n\ | 97 #define TexCoordPrecision\n\ |
| 117 #endif\n"; | 98 #endif\n"; |
| 118 | 99 |
| 119 std::string GetVertexShaderSource(bool flip_y) { | 100 std::string GetVertexShaderSource() { |
| 120 std::string source; | 101 std::string source; |
| 121 | 102 |
| 122 // Preamble for core and compatibility mode. | 103 // Preamble for core and compatibility mode. |
| 123 if (gfx::GetGLImplementation() == | 104 if (gfx::GetGLImplementation() == |
| 124 gfx::kGLImplementationDesktopGLCoreProfile) { | 105 gfx::kGLImplementationDesktopGLCoreProfile) { |
| 125 source += std::string("\ | 106 source += std::string("\ |
| 126 #version 150\n\ | 107 #version 150\n\ |
| 127 #define ATTRIBUTE in\n\ | 108 #define ATTRIBUTE in\n\ |
| 128 #define VARYING out\n"); | 109 #define VARYING out\n"); |
| 129 } else { | 110 } else { |
| 130 source += std::string("\ | 111 source += std::string("\ |
| 131 #define ATTRIBUTE attribute\n\ | 112 #define ATTRIBUTE attribute\n\ |
| 132 #define VARYING varying\n"); | 113 #define VARYING varying\n"); |
| 133 } | 114 } |
| 134 | 115 |
| 135 // Preamble for texture precision. | 116 // Preamble for texture precision. |
| 136 source += std::string(kShaderPrecisionPreamble); | 117 source += std::string(kShaderPrecisionPreamble); |
| 137 | 118 |
| 138 // Preamble to differentiate based on |flip_y|. | |
| 139 if (flip_y) { | |
| 140 source += std::string("#define SIGN -\n"); | |
| 141 } else { | |
| 142 source += std::string("#define SIGN\n"); | |
| 143 } | |
| 144 | |
| 145 // Main shader source. | 119 // Main shader source. |
| 146 source += std::string("\ | 120 source += std::string("\ |
| 147 uniform vec2 u_vertex_translate;\n\ | 121 uniform vec2 u_vertex_dest_mult;\n\ |
| 148 uniform vec2 u_half_size;\n\ | 122 uniform vec2 u_vertex_dest_add;\n\ |
| 123 uniform vec2 u_vertex_source_mult;\n\ | |
| 124 uniform vec2 u_vertex_source_add;\n\ | |
| 149 ATTRIBUTE vec4 a_position;\n\ | 125 ATTRIBUTE vec4 a_position;\n\ |
| 150 VARYING TexCoordPrecision vec2 v_uv;\n\ | 126 VARYING TexCoordPrecision vec2 v_uv;\n\ |
| 151 void main(void) {\n\ | 127 void main(void) {\n\ |
| 152 gl_Position = a_position + vec4(u_vertex_translate, 0.0, 0.0);\n\ | 128 gl_Position = a_position;\n\ |
| 153 v_uv = a_position.xy * vec2(u_half_size.s, SIGN u_half_size.t) +\n\ | 129 gl_Position.xy = a_position.xy * u_vertex_dest_mult + \ |
| 154 vec2(u_half_size.s, u_half_size.t);\n\ | 130 u_vertex_dest_add;\n\ |
| 131 v_uv = a_position.xy * u_vertex_source_mult + u_vertex_source_add;\n\ | |
| 155 }\n"); | 132 }\n"); |
| 156 | 133 |
| 157 return source; | 134 return source; |
| 158 } | 135 } |
| 159 | 136 |
| 160 std::string GetFragmentShaderSource(bool premultiply_alpha, | 137 std::string GetFragmentShaderSource(bool premultiply_alpha, |
| 161 bool unpremultiply_alpha, | 138 bool unpremultiply_alpha, |
| 162 GLenum target) { | 139 GLenum target) { |
| 163 // Only one alpha mode at a time makes sense. | 140 // Only one alpha mode at a time makes sense. |
| 164 DCHECK(!premultiply_alpha || !unpremultiply_alpha); | 141 DCHECK(!premultiply_alpha || !unpremultiply_alpha); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 } | 260 } |
| 284 | 261 |
| 285 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder, | 262 void DoCopyTexImage2D(const gpu::gles2::GLES2Decoder* decoder, |
| 286 GLenum source_target, | 263 GLenum source_target, |
| 287 GLuint source_id, | 264 GLuint source_id, |
| 288 GLuint dest_id, | 265 GLuint dest_id, |
| 289 GLenum dest_internal_format, | 266 GLenum dest_internal_format, |
| 290 GLsizei width, | 267 GLsizei width, |
| 291 GLsizei height, | 268 GLsizei height, |
| 292 GLuint framebuffer) { | 269 GLuint framebuffer) { |
| 293 DCHECK(source_target == GL_TEXTURE_2D || | 270 DCHECK(source_target == GL_TEXTURE_2D); |
|
Zhenyao Mo
2016/01/05 00:52:16
Can we also pass in dest_target and DCHECK it's TE
erikchen
2016/01/05 01:46:39
Done.
| |
| 294 source_target == GL_TEXTURE_RECTANGLE_ARB); | |
| 295 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { | 271 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { |
| 296 glBindTexture(GL_TEXTURE_2D, dest_id); | 272 glBindTexture(GL_TEXTURE_2D, dest_id); |
| 297 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 273 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 298 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 274 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 301 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format, | 277 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format, |
| 302 0 /* x */, 0 /* y */, width, height, 0 /* border */); | 278 0 /* x */, 0 /* y */, width, height, 0 /* border */); |
| 303 } | 279 } |
| 304 | 280 |
| 305 decoder->RestoreTextureState(source_id); | 281 decoder->RestoreTextureState(source_id); |
| 306 decoder->RestoreTextureState(dest_id); | 282 decoder->RestoreTextureState(dest_id); |
| 307 decoder->RestoreTextureUnitBindings(0); | 283 decoder->RestoreTextureUnitBindings(0); |
| 308 decoder->RestoreActiveTexture(); | 284 decoder->RestoreActiveTexture(); |
| 309 decoder->RestoreFramebufferBindings(); | 285 decoder->RestoreFramebufferBindings(); |
| 310 } | 286 } |
| 311 | 287 |
| 312 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, | 288 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, |
| 313 GLenum source_target, | 289 GLenum source_target, |
| 314 GLuint source_id, | 290 GLuint source_id, |
| 315 GLuint dest_id, | 291 GLuint dest_id, |
|
Zhenyao Mo
2016/01/05 00:52:16
Same here, can we also pass in dest_target and DCH
erikchen
2016/01/05 01:46:39
Done.
| |
| 316 GLint xoffset, | 292 GLint xoffset, |
| 317 GLint yoffset, | 293 GLint yoffset, |
| 318 GLint source_x, | 294 GLint source_x, |
| 319 GLint source_y, | 295 GLint source_y, |
| 320 GLsizei source_width, | 296 GLsizei source_width, |
| 321 GLsizei source_height, | 297 GLsizei source_height, |
| 322 GLuint framebuffer) { | 298 GLuint framebuffer) { |
| 323 DCHECK(source_target == GL_TEXTURE_2D || | 299 DCHECK(source_target == GL_TEXTURE_2D || |
| 324 source_target == GL_TEXTURE_RECTANGLE_ARB); | 300 source_target == GL_TEXTURE_RECTANGLE_ARB); |
| 325 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { | 301 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 338 decoder->RestoreActiveTexture(); | 314 decoder->RestoreActiveTexture(); |
| 339 decoder->RestoreFramebufferBindings(); | 315 decoder->RestoreFramebufferBindings(); |
| 340 } | 316 } |
| 341 | 317 |
| 342 } // namespace | 318 } // namespace |
| 343 | 319 |
| 344 namespace gpu { | 320 namespace gpu { |
| 345 | 321 |
| 346 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() | 322 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() |
| 347 : initialized_(false), | 323 : initialized_(false), |
| 348 vertex_shaders_(NUM_VERTEX_SHADERS, 0u), | 324 vertex_shader_(0u), |
| 349 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), | 325 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), |
| 350 buffer_id_(0u), | 326 buffer_id_(0u), |
| 351 framebuffer_(0u) {} | 327 framebuffer_(0u) {} |
| 352 | 328 |
| 353 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() { | 329 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() { |
| 354 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is | 330 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is |
| 355 // lost, this class can be deleted without releasing resources like | 331 // lost, this class can be deleted without releasing resources like |
| 356 // GLES2DecoderImpl. | 332 // GLES2DecoderImpl. |
| 357 } | 333 } |
| 358 | 334 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 382 initialized_ = true; | 358 initialized_ = true; |
| 383 } | 359 } |
| 384 | 360 |
| 385 void CopyTextureCHROMIUMResourceManager::Destroy() { | 361 void CopyTextureCHROMIUMResourceManager::Destroy() { |
| 386 if (!initialized_) | 362 if (!initialized_) |
| 387 return; | 363 return; |
| 388 | 364 |
| 389 glDeleteFramebuffersEXT(1, &framebuffer_); | 365 glDeleteFramebuffersEXT(1, &framebuffer_); |
| 390 framebuffer_ = 0; | 366 framebuffer_ = 0; |
| 391 | 367 |
| 392 std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader); | 368 DeleteShader(vertex_shader_); |
| 393 std::for_each( | 369 std::for_each( |
| 394 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); | 370 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); |
| 395 | 371 |
| 396 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); | 372 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); |
| 397 ++it) { | 373 ++it) { |
| 398 const ProgramInfo& info = it->second; | 374 const ProgramInfo& info = it->second; |
| 399 glDeleteProgram(info.program); | 375 glDeleteProgram(info.program); |
| 400 } | 376 } |
| 401 | 377 |
| 402 glDeleteBuffersARB(1, &buffer_id_); | 378 glDeleteBuffersARB(1, &buffer_id_); |
| 403 buffer_id_ = 0; | 379 buffer_id_ = 0; |
| 404 } | 380 } |
| 405 | 381 |
| 406 void CopyTextureCHROMIUMResourceManager::DoCopyTexture( | 382 void CopyTextureCHROMIUMResourceManager::DoCopyTexture( |
| 407 const gles2::GLES2Decoder* decoder, | 383 const gles2::GLES2Decoder* decoder, |
| 408 GLenum source_target, | 384 GLenum source_target, |
| 409 GLuint source_id, | 385 GLuint source_id, |
| 410 GLenum source_internal_format, | 386 GLenum source_internal_format, |
| 387 GLenum dest_target, | |
| 411 GLuint dest_id, | 388 GLuint dest_id, |
| 412 GLenum dest_internal_format, | 389 GLenum dest_internal_format, |
| 413 GLsizei width, | 390 GLsizei width, |
| 414 GLsizei height, | 391 GLsizei height, |
| 415 bool flip_y, | 392 bool flip_y, |
| 416 bool premultiply_alpha, | 393 bool premultiply_alpha, |
| 417 bool unpremultiply_alpha) { | 394 bool unpremultiply_alpha) { |
| 418 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; | 395 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; |
| 419 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's | 396 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's |
| 420 // format does not contain a superset of the components required by the base | 397 // format does not contain a superset of the components required by the base |
| 421 // format of internalformat. | 398 // format of internalformat. |
| 422 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml | 399 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml |
| 423 bool source_format_contain_superset_of_dest_format = | 400 bool source_format_contain_superset_of_dest_format = |
| 424 (source_internal_format == dest_internal_format && | 401 (source_internal_format == dest_internal_format && |
| 425 source_internal_format != GL_BGRA_EXT) || | 402 source_internal_format != GL_BGRA_EXT) || |
| 426 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); | 403 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); |
| 427 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, | 404 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, |
| 428 // so restrict this to GL_TEXTURE_2D. | 405 // so restrict this to GL_TEXTURE_2D. |
| 429 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && | 406 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D && |
| 407 !flip_y && !premultiply_alpha_change && | |
| 430 source_format_contain_superset_of_dest_format) { | 408 source_format_contain_superset_of_dest_format) { |
| 431 DoCopyTexImage2D(decoder, | 409 DoCopyTexImage2D(decoder, |
| 432 source_target, | 410 source_target, |
| 433 source_id, | 411 source_id, |
| 434 dest_id, | 412 dest_id, |
| 435 dest_internal_format, | 413 dest_internal_format, |
| 436 width, | 414 width, |
| 437 height, | 415 height, |
| 438 framebuffer_); | 416 framebuffer_); |
| 439 return; | 417 return; |
| 440 } | 418 } |
| 441 | 419 |
| 442 // Use kIdentityMatrix if no transform passed in. | 420 // Use kIdentityMatrix if no transform passed in. |
| 443 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width, | 421 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_target, |
| 444 height, flip_y, premultiply_alpha, | 422 dest_id, width, height, flip_y, premultiply_alpha, |
| 445 unpremultiply_alpha, kIdentityMatrix); | 423 unpremultiply_alpha, kIdentityMatrix); |
| 446 } | 424 } |
| 447 | 425 |
| 448 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( | 426 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( |
| 449 const gles2::GLES2Decoder* decoder, | 427 const gles2::GLES2Decoder* decoder, |
| 450 GLenum source_target, | 428 GLenum source_target, |
| 451 GLuint source_id, | 429 GLuint source_id, |
| 452 GLenum source_internal_format, | 430 GLenum source_internal_format, |
| 431 GLenum dest_target, | |
| 453 GLuint dest_id, | 432 GLuint dest_id, |
| 454 GLenum dest_internal_format, | 433 GLenum dest_internal_format, |
| 455 GLint xoffset, | 434 GLint xoffset, |
| 456 GLint yoffset, | 435 GLint yoffset, |
| 457 GLint x, | 436 GLint x, |
| 458 GLint y, | 437 GLint y, |
| 459 GLsizei width, | 438 GLsizei width, |
| 460 GLsizei height, | 439 GLsizei height, |
| 461 GLsizei dest_width, | 440 GLsizei dest_width, |
| 462 GLsizei dest_height, | 441 GLsizei dest_height, |
| 463 GLsizei source_width, | 442 GLsizei source_width, |
| 464 GLsizei source_height, | 443 GLsizei source_height, |
| 465 bool flip_y, | 444 bool flip_y, |
| 466 bool premultiply_alpha, | 445 bool premultiply_alpha, |
| 467 bool unpremultiply_alpha) { | 446 bool unpremultiply_alpha) { |
| 468 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; | 447 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; |
| 469 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's | 448 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's |
| 470 // format does not contain a superset of the components required by the base | 449 // format does not contain a superset of the components required by the base |
| 471 // format of internalformat. | 450 // format of internalformat. |
| 472 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml | 451 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml |
| 473 bool source_format_contain_superset_of_dest_format = | 452 bool source_format_contain_superset_of_dest_format = |
| 474 (source_internal_format == dest_internal_format && | 453 (source_internal_format == dest_internal_format && |
| 475 source_internal_format != GL_BGRA_EXT) || | 454 source_internal_format != GL_BGRA_EXT) || |
| 476 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); | 455 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); |
| 477 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, | 456 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, |
| 478 // so restrict this to GL_TEXTURE_2D. | 457 // so restrict this to GL_TEXTURE_2D. |
| 479 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && | 458 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D && |
| 459 !flip_y && !premultiply_alpha_change && | |
| 480 source_format_contain_superset_of_dest_format) { | 460 source_format_contain_superset_of_dest_format) { |
| 481 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset, | 461 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset, |
| 482 yoffset, x, y, width, height, framebuffer_); | 462 yoffset, x, y, width, height, framebuffer_); |
| 483 return; | 463 return; |
| 484 } | 464 } |
| 485 | 465 |
| 486 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset, | 466 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id, |
| 487 yoffset, x, y, width, height, dest_width, dest_height, | 467 xoffset, yoffset, x, y, width, height, dest_width, dest_height, |
| 488 source_width, source_height, flip_y, premultiply_alpha, | 468 source_width, source_height, flip_y, premultiply_alpha, |
| 489 unpremultiply_alpha, kIdentityMatrix); | 469 unpremultiply_alpha, kIdentityMatrix); |
| 490 } | 470 } |
| 491 | 471 |
| 492 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( | 472 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( |
| 493 const gles2::GLES2Decoder* decoder, | 473 const gles2::GLES2Decoder* decoder, |
| 494 GLenum source_target, | 474 GLenum source_target, |
| 495 GLuint source_id, | 475 GLuint source_id, |
| 476 GLenum dest_target, | |
| 496 GLuint dest_id, | 477 GLuint dest_id, |
| 497 GLsizei width, | 478 GLsizei width, |
| 498 GLsizei height, | 479 GLsizei height, |
| 499 bool flip_y, | 480 bool flip_y, |
| 500 bool premultiply_alpha, | 481 bool premultiply_alpha, |
| 501 bool unpremultiply_alpha, | 482 bool unpremultiply_alpha, |
| 502 const GLfloat transform_matrix[16]) { | 483 const GLfloat transform_matrix[16]) { |
| 503 GLsizei dest_width = width; | 484 GLsizei dest_width = width; |
| 504 GLsizei dest_height = height; | 485 GLsizei dest_height = height; |
| 505 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0, 0, 0, | 486 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id, |
| 506 width, height, dest_width, dest_height, width, height, | 487 0, 0, 0, 0, width, height, dest_width, dest_height, |
| 507 flip_y, premultiply_alpha, unpremultiply_alpha, | 488 width, height, flip_y, premultiply_alpha, |
| 508 transform_matrix); | 489 unpremultiply_alpha, transform_matrix); |
| 509 } | 490 } |
| 510 | 491 |
| 511 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( | 492 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( |
| 512 const gles2::GLES2Decoder* decoder, | 493 const gles2::GLES2Decoder* decoder, |
| 513 GLenum source_target, | 494 GLenum source_target, |
| 514 GLuint source_id, | 495 GLuint source_id, |
| 496 GLenum dest_target, | |
| 515 GLuint dest_id, | 497 GLuint dest_id, |
| 516 GLint xoffset, | 498 GLint xoffset, |
| 517 GLint yoffset, | 499 GLint yoffset, |
| 518 GLint x, | 500 GLint x, |
| 519 GLint y, | 501 GLint y, |
| 520 GLsizei width, | 502 GLsizei width, |
| 521 GLsizei height, | 503 GLsizei height, |
| 522 GLsizei dest_width, | 504 GLsizei dest_width, |
| 523 GLsizei dest_height, | 505 GLsizei dest_height, |
| 524 GLsizei source_width, | 506 GLsizei source_width, |
| 525 GLsizei source_height, | 507 GLsizei source_height, |
| 526 bool flip_y, | 508 bool flip_y, |
| 527 bool premultiply_alpha, | 509 bool premultiply_alpha, |
| 528 bool unpremultiply_alpha, | 510 bool unpremultiply_alpha, |
| 529 const GLfloat transform_matrix[16]) { | 511 const GLfloat transform_matrix[16]) { |
| 530 DCHECK(source_target == GL_TEXTURE_2D || | 512 DCHECK(source_target == GL_TEXTURE_2D || |
| 531 source_target == GL_TEXTURE_RECTANGLE_ARB || | 513 source_target == GL_TEXTURE_RECTANGLE_ARB || |
| 532 source_target == GL_TEXTURE_EXTERNAL_OES); | 514 source_target == GL_TEXTURE_EXTERNAL_OES); |
| 515 DCHECK(dest_target == GL_TEXTURE_2D || | |
| 516 dest_target == GL_TEXTURE_RECTANGLE_ARB); | |
| 533 DCHECK_GE(xoffset, 0); | 517 DCHECK_GE(xoffset, 0); |
| 534 DCHECK_LE(xoffset + width, dest_width); | 518 DCHECK_LE(xoffset + width, dest_width); |
| 535 DCHECK_GE(yoffset, 0); | 519 DCHECK_GE(yoffset, 0); |
| 536 DCHECK_LE(yoffset + height, dest_height); | 520 DCHECK_LE(yoffset + height, dest_height); |
| 521 if (dest_width == 0 || dest_height == 0 || source_width == 0 || | |
| 522 source_height == 0) { | |
| 523 return; | |
| 524 } | |
| 525 | |
| 537 if (!initialized_) { | 526 if (!initialized_) { |
| 538 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; | 527 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; |
| 539 return; | 528 return; |
| 540 } | 529 } |
| 541 | 530 |
| 542 VertexShaderId vertex_shader_id = GetVertexShaderId(flip_y); | |
| 543 DCHECK_LT(static_cast<size_t>(vertex_shader_id), vertex_shaders_.size()); | |
| 544 FragmentShaderId fragment_shader_id = GetFragmentShaderId( | 531 FragmentShaderId fragment_shader_id = GetFragmentShaderId( |
| 545 premultiply_alpha, unpremultiply_alpha, source_target); | 532 premultiply_alpha, unpremultiply_alpha, source_target); |
| 546 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); | 533 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); |
| 547 | 534 |
| 548 ProgramMapKey key(vertex_shader_id, fragment_shader_id); | 535 ProgramMapKey key(fragment_shader_id); |
| 549 ProgramInfo* info = &programs_[key]; | 536 ProgramInfo* info = &programs_[key]; |
| 550 // Create program if necessary. | 537 // Create program if necessary. |
| 551 if (!info->program) { | 538 if (!info->program) { |
| 552 info->program = glCreateProgram(); | 539 info->program = glCreateProgram(); |
| 553 GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id]; | 540 if (!vertex_shader_) { |
| 554 if (!*vertex_shader) { | 541 vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); |
| 555 *vertex_shader = glCreateShader(GL_VERTEX_SHADER); | 542 std::string source = GetVertexShaderSource(); |
| 556 std::string source = GetVertexShaderSource(flip_y); | 543 CompileShader(vertex_shader_, source.c_str()); |
| 557 CompileShader(*vertex_shader, source.c_str()); | |
| 558 } | 544 } |
| 559 glAttachShader(info->program, *vertex_shader); | 545 glAttachShader(info->program, vertex_shader_); |
| 560 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; | 546 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; |
| 561 if (!*fragment_shader) { | 547 if (!*fragment_shader) { |
| 562 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); | 548 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); |
| 563 std::string source = GetFragmentShaderSource( | 549 std::string source = GetFragmentShaderSource( |
| 564 premultiply_alpha, unpremultiply_alpha, source_target); | 550 premultiply_alpha, unpremultiply_alpha, source_target); |
| 565 CompileShader(*fragment_shader, source.c_str()); | 551 CompileShader(*fragment_shader, source.c_str()); |
| 566 } | 552 } |
| 567 glAttachShader(info->program, *fragment_shader); | 553 glAttachShader(info->program, *fragment_shader); |
| 568 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); | 554 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); |
| 569 glLinkProgram(info->program); | 555 glLinkProgram(info->program); |
| 570 #ifndef NDEBUG | 556 #ifndef NDEBUG |
| 571 GLint linked; | 557 GLint linked; |
| 572 glGetProgramiv(info->program, GL_LINK_STATUS, &linked); | 558 glGetProgramiv(info->program, GL_LINK_STATUS, &linked); |
| 573 if (!linked) | 559 if (!linked) |
| 574 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; | 560 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; |
| 575 #endif | 561 #endif |
| 576 info->vertex_translate_handle = glGetUniformLocation(info->program, | 562 info->vertex_dest_mult_handle = |
| 577 "u_vertex_translate"); | 563 glGetUniformLocation(info->program, "u_vertex_dest_mult"); |
| 564 info->vertex_dest_add_handle = | |
| 565 glGetUniformLocation(info->program, "u_vertex_dest_add"); | |
| 566 info->vertex_source_mult_handle = | |
| 567 glGetUniformLocation(info->program, "u_vertex_source_mult"); | |
| 568 info->vertex_source_add_handle = | |
| 569 glGetUniformLocation(info->program, "u_vertex_source_add"); | |
| 570 | |
| 578 info->tex_coord_transform_handle = | 571 info->tex_coord_transform_handle = |
| 579 glGetUniformLocation(info->program, "u_tex_coord_transform"); | 572 glGetUniformLocation(info->program, "u_tex_coord_transform"); |
| 580 info->half_size_handle = glGetUniformLocation(info->program, "u_half_size"); | |
| 581 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); | 573 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); |
| 582 } | 574 } |
| 583 glUseProgram(info->program); | 575 glUseProgram(info->program); |
| 584 | 576 |
| 585 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, | 577 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, |
| 586 transform_matrix); | 578 transform_matrix); |
| 587 | 579 |
| 588 GLint x_translate = xoffset - x; | 580 // Note: For simplicity, the calculations in this comment block use a single |
| 589 GLint y_translate = yoffset - y; | 581 // dimension. All calculations trivially extend to the x-y plane. |
| 590 if (!x_translate && !y_translate) { | 582 // The target subrange in the destination texture has coordinates |
| 591 glUniform2f(info->vertex_translate_handle, 0.0f, 0.0f); | 583 // [xoffset, xoffset + width]. The full destination texture has range |
| 592 } else { | 584 // [0, dest_width]. |
| 593 // transform offsets from ([0, dest_width], [0, dest_height]) coord. | 585 // |
| 594 // to ([-1, 1], [-1, 1]) coord. | 586 // We want to find A and B such that: |
| 595 GLfloat x_translate_on_vertex = ((2.f * x_translate) / dest_width); | 587 // A * X + B = Y |
| 596 GLfloat y_translate_on_vertex = ((2.f * y_translate) / dest_height); | 588 // C * Y + D = Z |
| 589 // | |
| 590 // where X = [-1, 1], Z = [xoffset, xoffset + width] | |
| 591 // and C, D satisfy the relationship C * [-1, 1] + D = [0, dest_width]. | |
| 592 // | |
| 593 // Math shows: | |
| 594 // C = D = dest_width / 2 | |
| 595 // Y = [(xoffset * 2 / dest_width) - 1, | |
| 596 // (xoffset + width) * 2 / dest_width) - 1] | |
| 597 // A = width / dest_width | |
| 598 // B = (xoffset * 2 + width - dest_width) / dest_width | |
| 599 glUniform2f(info->vertex_dest_mult_handle, width * 1.f / dest_width, | |
| 600 height * 1.f / dest_height); | |
| 601 glUniform2f(info->vertex_dest_add_handle, | |
| 602 (xoffset * 2.f + width - dest_width) / dest_width, | |
| 603 (yoffset * 2.f + height - dest_height) / dest_height); | |
| 597 | 604 |
| 598 // Pass translation to the shader program. | 605 // Note: For simplicity, the calculations in this comment block use a single |
| 599 glUniform2f(info->vertex_translate_handle, x_translate_on_vertex, | 606 // dimension. All calculations trivially extend to the x-y plane. |
| 600 y_translate_on_vertex); | 607 // The target subrange in the source texture has coordinates [x, x + width]. |
| 601 } | 608 // The full source texture has range [0, source_width]. We need to transform |
| 602 if (source_target == GL_TEXTURE_RECTANGLE_ARB) | 609 // the subrange into texture space ([0, M]), assuming that [0, source_width] |
| 603 glUniform2f(info->half_size_handle, source_width / 2.0f, | 610 // gets mapped to [0, M]. If source_target == GL_TEXTURE_RECTANGLE_ARB, M = |
| 604 source_height / 2.0f); | 611 // source_width. Otherwise, M = 1. |
| 605 else | 612 // |
| 606 glUniform2f(info->half_size_handle, 0.5f, 0.5f); | 613 // We want to find A and B such that: |
| 614 // A * X + B = Y | |
| 615 // C * Y + D = Z | |
| 616 // | |
| 617 // where X = [-1, 1], Z = [x, x + width] | |
| 618 // and C, D satisfy the relationship C * [0, M] + D = [0, source_width]. | |
| 619 // | |
| 620 // Math shows: | |
| 621 // D = 0 | |
| 622 // C = source_width / M | |
| 623 // Y = [x * M / source_width, (x + width) * M / source_width] | |
| 624 // B = (x + w/2) * M / source_width | |
| 625 // A = (w/2) * M / source_width | |
| 626 // | |
| 627 // When flip_y is true, we run the same calcluation, but with Z = [x + width, | |
| 628 // x]. (I'm intentionally keeping the x-plane notation, although the | |
| 629 // calculation only gets applied to the y-plane). | |
| 630 // | |
| 631 // Math shows: | |
| 632 // D = 0 | |
| 633 // C = source_width / M | |
| 634 // Y = [(x + width) * M / source_width, x * M / source_width] | |
| 635 // B = (x + w/2) * M / source_width | |
| 636 // A = (-w/2) * M / source_width | |
| 637 // | |
| 638 // So everything is the same but the sign of A is flipped. | |
| 639 GLfloat m_x = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_width : 1; | |
| 640 GLfloat m_y = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_height : 1; | |
| 641 GLfloat sign_a = flip_y ? -1 : 1; | |
| 642 glUniform2f(info->vertex_source_mult_handle, width / 2.f * m_x / source_width, | |
| 643 height / 2.f * m_y / source_height * sign_a); | |
| 644 glUniform2f(info->vertex_source_add_handle, | |
| 645 (x + width / 2.f) * m_x / source_width, | |
| 646 (y + height / 2.f) * m_y / source_height); | |
| 607 | 647 |
| 608 if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) { | 648 if (BindFramebufferTexture2D(dest_target, dest_id, framebuffer_)) { |
| 609 #ifndef NDEBUG | 649 #ifndef NDEBUG |
| 610 // glValidateProgram of MACOSX validates FBO unlike other platforms, so | 650 // glValidateProgram of MACOSX validates FBO unlike other platforms, so |
| 611 // glValidateProgram must be called after FBO binding. crbug.com/463439 | 651 // glValidateProgram must be called after FBO binding. crbug.com/463439 |
| 612 glValidateProgram(info->program); | 652 glValidateProgram(info->program); |
| 613 GLint validation_status; | 653 GLint validation_status; |
| 614 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); | 654 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); |
| 615 if (GL_TRUE != validation_status) { | 655 if (GL_TRUE != validation_status) { |
| 616 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; | 656 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; |
| 617 return; | 657 return; |
| 618 } | 658 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 659 decoder->RestoreTextureState(dest_id); | 699 decoder->RestoreTextureState(dest_id); |
| 660 decoder->RestoreTextureUnitBindings(0); | 700 decoder->RestoreTextureUnitBindings(0); |
| 661 decoder->RestoreActiveTexture(); | 701 decoder->RestoreActiveTexture(); |
| 662 decoder->RestoreProgramBindings(); | 702 decoder->RestoreProgramBindings(); |
| 663 decoder->RestoreBufferBindings(); | 703 decoder->RestoreBufferBindings(); |
| 664 decoder->RestoreFramebufferBindings(); | 704 decoder->RestoreFramebufferBindings(); |
| 665 decoder->RestoreGlobalState(); | 705 decoder->RestoreGlobalState(); |
| 666 } | 706 } |
| 667 | 707 |
| 668 } // namespace gpu | 708 } // namespace gpu |
| OLD | NEW |