| 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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 DLOG(ERROR) << "CopyTextureCHROMIUM: Incomplete framebuffer."; | 255 DLOG(ERROR) << "CopyTextureCHROMIUM: Incomplete framebuffer."; |
| 279 return false; | 256 return false; |
| 280 } | 257 } |
| 281 #endif | 258 #endif |
| 282 return true; | 259 return true; |
| 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, |
| 265 GLenum dest_target, |
| 288 GLuint dest_id, | 266 GLuint dest_id, |
| 289 GLenum dest_internal_format, | 267 GLenum dest_internal_format, |
| 290 GLsizei width, | 268 GLsizei width, |
| 291 GLsizei height, | 269 GLsizei height, |
| 292 GLuint framebuffer) { | 270 GLuint framebuffer) { |
| 293 DCHECK(source_target == GL_TEXTURE_2D || | 271 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), source_target); |
| 294 source_target == GL_TEXTURE_RECTANGLE_ARB); | 272 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), dest_target); |
| 295 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { | 273 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { |
| 296 glBindTexture(GL_TEXTURE_2D, dest_id); | 274 glBindTexture(dest_target, dest_id); |
| 297 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 275 glTexParameterf(dest_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 298 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 276 glTexParameterf(dest_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 277 glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 278 glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 301 glCopyTexImage2D(GL_TEXTURE_2D, 0 /* level */, dest_internal_format, | 279 glCopyTexImage2D(dest_target, 0 /* level */, dest_internal_format, |
| 302 0 /* x */, 0 /* y */, width, height, 0 /* border */); | 280 0 /* x */, 0 /* y */, width, height, 0 /* border */); |
| 303 } | 281 } |
| 304 | 282 |
| 305 decoder->RestoreTextureState(source_id); | 283 decoder->RestoreTextureState(source_id); |
| 306 decoder->RestoreTextureState(dest_id); | 284 decoder->RestoreTextureState(dest_id); |
| 307 decoder->RestoreTextureUnitBindings(0); | 285 decoder->RestoreTextureUnitBindings(0); |
| 308 decoder->RestoreActiveTexture(); | 286 decoder->RestoreActiveTexture(); |
| 309 decoder->RestoreFramebufferBindings(); | 287 decoder->RestoreFramebufferBindings(); |
| 310 } | 288 } |
| 311 | 289 |
| 312 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, | 290 void DoCopyTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, |
| 313 GLenum source_target, | 291 GLenum source_target, |
| 314 GLuint source_id, | 292 GLuint source_id, |
| 293 GLenum dest_target, |
| 315 GLuint dest_id, | 294 GLuint dest_id, |
| 316 GLint xoffset, | 295 GLint xoffset, |
| 317 GLint yoffset, | 296 GLint yoffset, |
| 318 GLint source_x, | 297 GLint source_x, |
| 319 GLint source_y, | 298 GLint source_y, |
| 320 GLsizei source_width, | 299 GLsizei source_width, |
| 321 GLsizei source_height, | 300 GLsizei source_height, |
| 322 GLuint framebuffer) { | 301 GLuint framebuffer) { |
| 323 DCHECK(source_target == GL_TEXTURE_2D || | 302 DCHECK(source_target == GL_TEXTURE_2D || |
| 324 source_target == GL_TEXTURE_RECTANGLE_ARB); | 303 source_target == GL_TEXTURE_RECTANGLE_ARB); |
| 304 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), dest_target); |
| 325 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { | 305 if (BindFramebufferTexture2D(source_target, source_id, framebuffer)) { |
| 326 glBindTexture(GL_TEXTURE_2D, dest_id); | 306 glBindTexture(dest_target, dest_id); |
| 327 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 307 glTexParameterf(dest_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 328 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 308 glTexParameterf(dest_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 309 glTexParameteri(dest_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 310 glTexParameteri(dest_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 331 glCopyTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, xoffset, yoffset, | 311 glCopyTexSubImage2D(dest_target, 0 /* level */, xoffset, yoffset, |
| 332 source_x, source_y, source_width, source_height); | 312 source_x, source_y, source_width, source_height); |
| 333 } | 313 } |
| 334 | 314 |
| 335 decoder->RestoreTextureState(source_id); | 315 decoder->RestoreTextureState(source_id); |
| 336 decoder->RestoreTextureState(dest_id); | 316 decoder->RestoreTextureState(dest_id); |
| 337 decoder->RestoreTextureUnitBindings(0); | 317 decoder->RestoreTextureUnitBindings(0); |
| 338 decoder->RestoreActiveTexture(); | 318 decoder->RestoreActiveTexture(); |
| 339 decoder->RestoreFramebufferBindings(); | 319 decoder->RestoreFramebufferBindings(); |
| 340 } | 320 } |
| 341 | 321 |
| 342 } // namespace | 322 } // namespace |
| 343 | 323 |
| 344 namespace gpu { | 324 namespace gpu { |
| 345 | 325 |
| 346 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() | 326 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() |
| 347 : initialized_(false), | 327 : initialized_(false), |
| 348 vertex_shaders_(NUM_VERTEX_SHADERS, 0u), | 328 vertex_shader_(0u), |
| 349 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), | 329 fragment_shaders_(NUM_FRAGMENT_SHADERS, 0u), |
| 350 buffer_id_(0u), | 330 buffer_id_(0u), |
| 351 framebuffer_(0u) {} | 331 framebuffer_(0u) {} |
| 352 | 332 |
| 353 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() { | 333 CopyTextureCHROMIUMResourceManager::~CopyTextureCHROMIUMResourceManager() { |
| 354 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is | 334 // |buffer_id_| and |framebuffer_| can be not-null because when GPU context is |
| 355 // lost, this class can be deleted without releasing resources like | 335 // lost, this class can be deleted without releasing resources like |
| 356 // GLES2DecoderImpl. | 336 // GLES2DecoderImpl. |
| 357 } | 337 } |
| 358 | 338 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 382 initialized_ = true; | 362 initialized_ = true; |
| 383 } | 363 } |
| 384 | 364 |
| 385 void CopyTextureCHROMIUMResourceManager::Destroy() { | 365 void CopyTextureCHROMIUMResourceManager::Destroy() { |
| 386 if (!initialized_) | 366 if (!initialized_) |
| 387 return; | 367 return; |
| 388 | 368 |
| 389 glDeleteFramebuffersEXT(1, &framebuffer_); | 369 glDeleteFramebuffersEXT(1, &framebuffer_); |
| 390 framebuffer_ = 0; | 370 framebuffer_ = 0; |
| 391 | 371 |
| 392 std::for_each(vertex_shaders_.begin(), vertex_shaders_.end(), DeleteShader); | 372 DeleteShader(vertex_shader_); |
| 393 std::for_each( | 373 std::for_each( |
| 394 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); | 374 fragment_shaders_.begin(), fragment_shaders_.end(), DeleteShader); |
| 395 | 375 |
| 396 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); | 376 for (ProgramMap::const_iterator it = programs_.begin(); it != programs_.end(); |
| 397 ++it) { | 377 ++it) { |
| 398 const ProgramInfo& info = it->second; | 378 const ProgramInfo& info = it->second; |
| 399 glDeleteProgram(info.program); | 379 glDeleteProgram(info.program); |
| 400 } | 380 } |
| 401 | 381 |
| 402 glDeleteBuffersARB(1, &buffer_id_); | 382 glDeleteBuffersARB(1, &buffer_id_); |
| 403 buffer_id_ = 0; | 383 buffer_id_ = 0; |
| 404 } | 384 } |
| 405 | 385 |
| 406 void CopyTextureCHROMIUMResourceManager::DoCopyTexture( | 386 void CopyTextureCHROMIUMResourceManager::DoCopyTexture( |
| 407 const gles2::GLES2Decoder* decoder, | 387 const gles2::GLES2Decoder* decoder, |
| 408 GLenum source_target, | 388 GLenum source_target, |
| 409 GLuint source_id, | 389 GLuint source_id, |
| 410 GLenum source_internal_format, | 390 GLenum source_internal_format, |
| 391 GLenum dest_target, |
| 411 GLuint dest_id, | 392 GLuint dest_id, |
| 412 GLenum dest_internal_format, | 393 GLenum dest_internal_format, |
| 413 GLsizei width, | 394 GLsizei width, |
| 414 GLsizei height, | 395 GLsizei height, |
| 415 bool flip_y, | 396 bool flip_y, |
| 416 bool premultiply_alpha, | 397 bool premultiply_alpha, |
| 417 bool unpremultiply_alpha) { | 398 bool unpremultiply_alpha) { |
| 418 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; | 399 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; |
| 419 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's | 400 // 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 | 401 // format does not contain a superset of the components required by the base |
| 421 // format of internalformat. | 402 // format of internalformat. |
| 422 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml | 403 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml |
| 423 bool source_format_contain_superset_of_dest_format = | 404 bool source_format_contain_superset_of_dest_format = |
| 424 (source_internal_format == dest_internal_format && | 405 (source_internal_format == dest_internal_format && |
| 425 source_internal_format != GL_BGRA_EXT) || | 406 source_internal_format != GL_BGRA_EXT) || |
| 426 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); | 407 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); |
| 427 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, | 408 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, |
| 428 // so restrict this to GL_TEXTURE_2D. | 409 // so restrict this to GL_TEXTURE_2D. |
| 429 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && | 410 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D && |
| 411 !flip_y && !premultiply_alpha_change && |
| 430 source_format_contain_superset_of_dest_format) { | 412 source_format_contain_superset_of_dest_format) { |
| 431 DoCopyTexImage2D(decoder, | 413 DoCopyTexImage2D(decoder, |
| 432 source_target, | 414 source_target, |
| 433 source_id, | 415 source_id, |
| 416 dest_target, |
| 434 dest_id, | 417 dest_id, |
| 435 dest_internal_format, | 418 dest_internal_format, |
| 436 width, | 419 width, |
| 437 height, | 420 height, |
| 438 framebuffer_); | 421 framebuffer_); |
| 439 return; | 422 return; |
| 440 } | 423 } |
| 441 | 424 |
| 442 // Use kIdentityMatrix if no transform passed in. | 425 // Use kIdentityMatrix if no transform passed in. |
| 443 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_id, width, | 426 DoCopyTextureWithTransform(decoder, source_target, source_id, dest_target, |
| 444 height, flip_y, premultiply_alpha, | 427 dest_id, width, height, flip_y, premultiply_alpha, |
| 445 unpremultiply_alpha, kIdentityMatrix); | 428 unpremultiply_alpha, kIdentityMatrix); |
| 446 } | 429 } |
| 447 | 430 |
| 448 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( | 431 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( |
| 449 const gles2::GLES2Decoder* decoder, | 432 const gles2::GLES2Decoder* decoder, |
| 450 GLenum source_target, | 433 GLenum source_target, |
| 451 GLuint source_id, | 434 GLuint source_id, |
| 452 GLenum source_internal_format, | 435 GLenum source_internal_format, |
| 436 GLenum dest_target, |
| 453 GLuint dest_id, | 437 GLuint dest_id, |
| 454 GLenum dest_internal_format, | 438 GLenum dest_internal_format, |
| 455 GLint xoffset, | 439 GLint xoffset, |
| 456 GLint yoffset, | 440 GLint yoffset, |
| 457 GLint x, | 441 GLint x, |
| 458 GLint y, | 442 GLint y, |
| 459 GLsizei width, | 443 GLsizei width, |
| 460 GLsizei height, | 444 GLsizei height, |
| 461 GLsizei dest_width, | 445 GLsizei dest_width, |
| 462 GLsizei dest_height, | 446 GLsizei dest_height, |
| 463 GLsizei source_width, | 447 GLsizei source_width, |
| 464 GLsizei source_height, | 448 GLsizei source_height, |
| 465 bool flip_y, | 449 bool flip_y, |
| 466 bool premultiply_alpha, | 450 bool premultiply_alpha, |
| 467 bool unpremultiply_alpha) { | 451 bool unpremultiply_alpha) { |
| 468 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; | 452 bool premultiply_alpha_change = premultiply_alpha ^ unpremultiply_alpha; |
| 469 // GL_INVALID_OPERATION is generated if the currently bound framebuffer's | 453 // 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 | 454 // format does not contain a superset of the components required by the base |
| 471 // format of internalformat. | 455 // format of internalformat. |
| 472 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml | 456 // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glCopyTexImage2D.xml |
| 473 bool source_format_contain_superset_of_dest_format = | 457 bool source_format_contain_superset_of_dest_format = |
| 474 (source_internal_format == dest_internal_format && | 458 (source_internal_format == dest_internal_format && |
| 475 source_internal_format != GL_BGRA_EXT) || | 459 source_internal_format != GL_BGRA_EXT) || |
| 476 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); | 460 (source_internal_format == GL_RGBA && dest_internal_format == GL_RGB); |
| 477 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, | 461 // GL_TEXTURE_RECTANGLE_ARB on FBO is supported by OpenGL, not GLES2, |
| 478 // so restrict this to GL_TEXTURE_2D. | 462 // so restrict this to GL_TEXTURE_2D. |
| 479 if (source_target == GL_TEXTURE_2D && !flip_y && !premultiply_alpha_change && | 463 if (source_target == GL_TEXTURE_2D && dest_target == GL_TEXTURE_2D && |
| 464 !flip_y && !premultiply_alpha_change && |
| 480 source_format_contain_superset_of_dest_format) { | 465 source_format_contain_superset_of_dest_format) { |
| 481 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_id, xoffset, | 466 DoCopyTexSubImage2D(decoder, source_target, source_id, dest_target, dest_id, |
| 482 yoffset, x, y, width, height, framebuffer_); | 467 xoffset, yoffset, x, y, width, height, framebuffer_); |
| 483 return; | 468 return; |
| 484 } | 469 } |
| 485 | 470 |
| 486 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, xoffset, | 471 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id, |
| 487 yoffset, x, y, width, height, dest_width, dest_height, | 472 xoffset, yoffset, x, y, width, height, dest_width, dest_height, |
| 488 source_width, source_height, flip_y, premultiply_alpha, | 473 source_width, source_height, flip_y, premultiply_alpha, |
| 489 unpremultiply_alpha, kIdentityMatrix); | 474 unpremultiply_alpha, kIdentityMatrix); |
| 490 } | 475 } |
| 491 | 476 |
| 492 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( | 477 void CopyTextureCHROMIUMResourceManager::DoCopyTextureWithTransform( |
| 493 const gles2::GLES2Decoder* decoder, | 478 const gles2::GLES2Decoder* decoder, |
| 494 GLenum source_target, | 479 GLenum source_target, |
| 495 GLuint source_id, | 480 GLuint source_id, |
| 481 GLenum dest_target, |
| 496 GLuint dest_id, | 482 GLuint dest_id, |
| 497 GLsizei width, | 483 GLsizei width, |
| 498 GLsizei height, | 484 GLsizei height, |
| 499 bool flip_y, | 485 bool flip_y, |
| 500 bool premultiply_alpha, | 486 bool premultiply_alpha, |
| 501 bool unpremultiply_alpha, | 487 bool unpremultiply_alpha, |
| 502 const GLfloat transform_matrix[16]) { | 488 const GLfloat transform_matrix[16]) { |
| 503 GLsizei dest_width = width; | 489 GLsizei dest_width = width; |
| 504 GLsizei dest_height = height; | 490 GLsizei dest_height = height; |
| 505 DoCopyTextureInternal(decoder, source_target, source_id, dest_id, 0, 0, 0, 0, | 491 DoCopyTextureInternal(decoder, source_target, source_id, dest_target, dest_id, |
| 506 width, height, dest_width, dest_height, width, height, | 492 0, 0, 0, 0, width, height, dest_width, dest_height, |
| 507 flip_y, premultiply_alpha, unpremultiply_alpha, | 493 width, height, flip_y, premultiply_alpha, |
| 508 transform_matrix); | 494 unpremultiply_alpha, transform_matrix); |
| 509 } | 495 } |
| 510 | 496 |
| 511 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( | 497 void CopyTextureCHROMIUMResourceManager::DoCopyTextureInternal( |
| 512 const gles2::GLES2Decoder* decoder, | 498 const gles2::GLES2Decoder* decoder, |
| 513 GLenum source_target, | 499 GLenum source_target, |
| 514 GLuint source_id, | 500 GLuint source_id, |
| 501 GLenum dest_target, |
| 515 GLuint dest_id, | 502 GLuint dest_id, |
| 516 GLint xoffset, | 503 GLint xoffset, |
| 517 GLint yoffset, | 504 GLint yoffset, |
| 518 GLint x, | 505 GLint x, |
| 519 GLint y, | 506 GLint y, |
| 520 GLsizei width, | 507 GLsizei width, |
| 521 GLsizei height, | 508 GLsizei height, |
| 522 GLsizei dest_width, | 509 GLsizei dest_width, |
| 523 GLsizei dest_height, | 510 GLsizei dest_height, |
| 524 GLsizei source_width, | 511 GLsizei source_width, |
| 525 GLsizei source_height, | 512 GLsizei source_height, |
| 526 bool flip_y, | 513 bool flip_y, |
| 527 bool premultiply_alpha, | 514 bool premultiply_alpha, |
| 528 bool unpremultiply_alpha, | 515 bool unpremultiply_alpha, |
| 529 const GLfloat transform_matrix[16]) { | 516 const GLfloat transform_matrix[16]) { |
| 530 DCHECK(source_target == GL_TEXTURE_2D || | 517 DCHECK(source_target == GL_TEXTURE_2D || |
| 531 source_target == GL_TEXTURE_RECTANGLE_ARB || | 518 source_target == GL_TEXTURE_RECTANGLE_ARB || |
| 532 source_target == GL_TEXTURE_EXTERNAL_OES); | 519 source_target == GL_TEXTURE_EXTERNAL_OES); |
| 520 DCHECK(dest_target == GL_TEXTURE_2D || |
| 521 dest_target == GL_TEXTURE_RECTANGLE_ARB); |
| 533 DCHECK_GE(xoffset, 0); | 522 DCHECK_GE(xoffset, 0); |
| 534 DCHECK_LE(xoffset + width, dest_width); | 523 DCHECK_LE(xoffset + width, dest_width); |
| 535 DCHECK_GE(yoffset, 0); | 524 DCHECK_GE(yoffset, 0); |
| 536 DCHECK_LE(yoffset + height, dest_height); | 525 DCHECK_LE(yoffset + height, dest_height); |
| 526 if (dest_width == 0 || dest_height == 0 || source_width == 0 || |
| 527 source_height == 0) { |
| 528 return; |
| 529 } |
| 530 |
| 537 if (!initialized_) { | 531 if (!initialized_) { |
| 538 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; | 532 DLOG(ERROR) << "CopyTextureCHROMIUM: Uninitialized manager."; |
| 539 return; | 533 return; |
| 540 } | 534 } |
| 541 | 535 |
| 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( | 536 FragmentShaderId fragment_shader_id = GetFragmentShaderId( |
| 545 premultiply_alpha, unpremultiply_alpha, source_target); | 537 premultiply_alpha, unpremultiply_alpha, source_target); |
| 546 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); | 538 DCHECK_LT(static_cast<size_t>(fragment_shader_id), fragment_shaders_.size()); |
| 547 | 539 |
| 548 ProgramMapKey key(vertex_shader_id, fragment_shader_id); | 540 ProgramMapKey key(fragment_shader_id); |
| 549 ProgramInfo* info = &programs_[key]; | 541 ProgramInfo* info = &programs_[key]; |
| 550 // Create program if necessary. | 542 // Create program if necessary. |
| 551 if (!info->program) { | 543 if (!info->program) { |
| 552 info->program = glCreateProgram(); | 544 info->program = glCreateProgram(); |
| 553 GLuint* vertex_shader = &vertex_shaders_[vertex_shader_id]; | 545 if (!vertex_shader_) { |
| 554 if (!*vertex_shader) { | 546 vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); |
| 555 *vertex_shader = glCreateShader(GL_VERTEX_SHADER); | 547 std::string source = GetVertexShaderSource(); |
| 556 std::string source = GetVertexShaderSource(flip_y); | 548 CompileShader(vertex_shader_, source.c_str()); |
| 557 CompileShader(*vertex_shader, source.c_str()); | |
| 558 } | 549 } |
| 559 glAttachShader(info->program, *vertex_shader); | 550 glAttachShader(info->program, vertex_shader_); |
| 560 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; | 551 GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; |
| 561 if (!*fragment_shader) { | 552 if (!*fragment_shader) { |
| 562 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); | 553 *fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); |
| 563 std::string source = GetFragmentShaderSource( | 554 std::string source = GetFragmentShaderSource( |
| 564 premultiply_alpha, unpremultiply_alpha, source_target); | 555 premultiply_alpha, unpremultiply_alpha, source_target); |
| 565 CompileShader(*fragment_shader, source.c_str()); | 556 CompileShader(*fragment_shader, source.c_str()); |
| 566 } | 557 } |
| 567 glAttachShader(info->program, *fragment_shader); | 558 glAttachShader(info->program, *fragment_shader); |
| 568 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); | 559 glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position"); |
| 569 glLinkProgram(info->program); | 560 glLinkProgram(info->program); |
| 570 #ifndef NDEBUG | 561 #ifndef NDEBUG |
| 571 GLint linked; | 562 GLint linked; |
| 572 glGetProgramiv(info->program, GL_LINK_STATUS, &linked); | 563 glGetProgramiv(info->program, GL_LINK_STATUS, &linked); |
| 573 if (!linked) | 564 if (!linked) |
| 574 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; | 565 DLOG(ERROR) << "CopyTextureCHROMIUM: program link failure."; |
| 575 #endif | 566 #endif |
| 576 info->vertex_translate_handle = glGetUniformLocation(info->program, | 567 info->vertex_dest_mult_handle = |
| 577 "u_vertex_translate"); | 568 glGetUniformLocation(info->program, "u_vertex_dest_mult"); |
| 569 info->vertex_dest_add_handle = |
| 570 glGetUniformLocation(info->program, "u_vertex_dest_add"); |
| 571 info->vertex_source_mult_handle = |
| 572 glGetUniformLocation(info->program, "u_vertex_source_mult"); |
| 573 info->vertex_source_add_handle = |
| 574 glGetUniformLocation(info->program, "u_vertex_source_add"); |
| 575 |
| 578 info->tex_coord_transform_handle = | 576 info->tex_coord_transform_handle = |
| 579 glGetUniformLocation(info->program, "u_tex_coord_transform"); | 577 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"); | 578 info->sampler_handle = glGetUniformLocation(info->program, "u_sampler"); |
| 582 } | 579 } |
| 583 glUseProgram(info->program); | 580 glUseProgram(info->program); |
| 584 | 581 |
| 585 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, | 582 glUniformMatrix4fv(info->tex_coord_transform_handle, 1, GL_FALSE, |
| 586 transform_matrix); | 583 transform_matrix); |
| 587 | 584 |
| 588 GLint x_translate = xoffset - x; | 585 // Note: For simplicity, the calculations in this comment block use a single |
| 589 GLint y_translate = yoffset - y; | 586 // dimension. All calculations trivially extend to the x-y plane. |
| 590 if (!x_translate && !y_translate) { | 587 // The target subrange in the destination texture has coordinates |
| 591 glUniform2f(info->vertex_translate_handle, 0.0f, 0.0f); | 588 // [xoffset, xoffset + width]. The full destination texture has range |
| 592 } else { | 589 // [0, dest_width]. |
| 593 // transform offsets from ([0, dest_width], [0, dest_height]) coord. | 590 // |
| 594 // to ([-1, 1], [-1, 1]) coord. | 591 // We want to find A and B such that: |
| 595 GLfloat x_translate_on_vertex = ((2.f * x_translate) / dest_width); | 592 // A * X + B = Y |
| 596 GLfloat y_translate_on_vertex = ((2.f * y_translate) / dest_height); | 593 // C * Y + D = Z |
| 594 // |
| 595 // where X = [-1, 1], Z = [xoffset, xoffset + width] |
| 596 // and C, D satisfy the relationship C * [-1, 1] + D = [0, dest_width]. |
| 597 // |
| 598 // Math shows: |
| 599 // C = D = dest_width / 2 |
| 600 // Y = [(xoffset * 2 / dest_width) - 1, |
| 601 // (xoffset + width) * 2 / dest_width) - 1] |
| 602 // A = width / dest_width |
| 603 // B = (xoffset * 2 + width - dest_width) / dest_width |
| 604 glUniform2f(info->vertex_dest_mult_handle, width * 1.f / dest_width, |
| 605 height * 1.f / dest_height); |
| 606 glUniform2f(info->vertex_dest_add_handle, |
| 607 (xoffset * 2.f + width - dest_width) / dest_width, |
| 608 (yoffset * 2.f + height - dest_height) / dest_height); |
| 597 | 609 |
| 598 // Pass translation to the shader program. | 610 // Note: For simplicity, the calculations in this comment block use a single |
| 599 glUniform2f(info->vertex_translate_handle, x_translate_on_vertex, | 611 // dimension. All calculations trivially extend to the x-y plane. |
| 600 y_translate_on_vertex); | 612 // The target subrange in the source texture has coordinates [x, x + width]. |
| 601 } | 613 // The full source texture has range [0, source_width]. We need to transform |
| 602 if (source_target == GL_TEXTURE_RECTANGLE_ARB) | 614 // the subrange into texture space ([0, M]), assuming that [0, source_width] |
| 603 glUniform2f(info->half_size_handle, source_width / 2.0f, | 615 // gets mapped to [0, M]. If source_target == GL_TEXTURE_RECTANGLE_ARB, M = |
| 604 source_height / 2.0f); | 616 // source_width. Otherwise, M = 1. |
| 605 else | 617 // |
| 606 glUniform2f(info->half_size_handle, 0.5f, 0.5f); | 618 // We want to find A and B such that: |
| 619 // A * X + B = Y |
| 620 // C * Y + D = Z |
| 621 // |
| 622 // where X = [-1, 1], Z = [x, x + width] |
| 623 // and C, D satisfy the relationship C * [0, M] + D = [0, source_width]. |
| 624 // |
| 625 // Math shows: |
| 626 // D = 0 |
| 627 // C = source_width / M |
| 628 // Y = [x * M / source_width, (x + width) * M / source_width] |
| 629 // B = (x + w/2) * M / source_width |
| 630 // A = (w/2) * M / source_width |
| 631 // |
| 632 // When flip_y is true, we run the same calcluation, but with Z = [x + width, |
| 633 // x]. (I'm intentionally keeping the x-plane notation, although the |
| 634 // calculation only gets applied to the y-plane). |
| 635 // |
| 636 // Math shows: |
| 637 // D = 0 |
| 638 // C = source_width / M |
| 639 // Y = [(x + width) * M / source_width, x * M / source_width] |
| 640 // B = (x + w/2) * M / source_width |
| 641 // A = (-w/2) * M / source_width |
| 642 // |
| 643 // So everything is the same but the sign of A is flipped. |
| 644 GLfloat m_x = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_width : 1; |
| 645 GLfloat m_y = source_target == GL_TEXTURE_RECTANGLE_ARB ? source_height : 1; |
| 646 GLfloat sign_a = flip_y ? -1 : 1; |
| 647 glUniform2f(info->vertex_source_mult_handle, width / 2.f * m_x / source_width, |
| 648 height / 2.f * m_y / source_height * sign_a); |
| 649 glUniform2f(info->vertex_source_add_handle, |
| 650 (x + width / 2.f) * m_x / source_width, |
| 651 (y + height / 2.f) * m_y / source_height); |
| 607 | 652 |
| 608 if (BindFramebufferTexture2D(GL_TEXTURE_2D, dest_id, framebuffer_)) { | 653 if (BindFramebufferTexture2D(dest_target, dest_id, framebuffer_)) { |
| 609 #ifndef NDEBUG | 654 #ifndef NDEBUG |
| 610 // glValidateProgram of MACOSX validates FBO unlike other platforms, so | 655 // glValidateProgram of MACOSX validates FBO unlike other platforms, so |
| 611 // glValidateProgram must be called after FBO binding. crbug.com/463439 | 656 // glValidateProgram must be called after FBO binding. crbug.com/463439 |
| 612 glValidateProgram(info->program); | 657 glValidateProgram(info->program); |
| 613 GLint validation_status; | 658 GLint validation_status; |
| 614 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); | 659 glGetProgramiv(info->program, GL_VALIDATE_STATUS, &validation_status); |
| 615 if (GL_TRUE != validation_status) { | 660 if (GL_TRUE != validation_status) { |
| 616 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; | 661 DLOG(ERROR) << "CopyTextureCHROMIUM: Invalid shader."; |
| 617 return; | 662 return; |
| 618 } | 663 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 decoder->RestoreTextureState(dest_id); | 704 decoder->RestoreTextureState(dest_id); |
| 660 decoder->RestoreTextureUnitBindings(0); | 705 decoder->RestoreTextureUnitBindings(0); |
| 661 decoder->RestoreActiveTexture(); | 706 decoder->RestoreActiveTexture(); |
| 662 decoder->RestoreProgramBindings(); | 707 decoder->RestoreProgramBindings(); |
| 663 decoder->RestoreBufferBindings(); | 708 decoder->RestoreBufferBindings(); |
| 664 decoder->RestoreFramebufferBindings(); | 709 decoder->RestoreFramebufferBindings(); |
| 665 decoder->RestoreGlobalState(); | 710 decoder->RestoreGlobalState(); |
| 666 } | 711 } |
| 667 | 712 |
| 668 } // namespace gpu | 713 } // namespace gpu |
| OLD | NEW |