1 // Copyright 2010 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 "cc/output/gl_renderer.h" 6 7 #include <algorithm> 8 #include <limits> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/debug/trace_event.h" 14 #include "base/logging.h" 15 #include "base/strings/string_split.h" 16 #include "base/strings/string_util.h" 17 #include "base/strings/stringprintf.h" 18 #include "build/build_config.h" 19 #include "cc/base/math_util.h" 20 #include "cc/layers/video_layer_impl.h" 21 #include "cc/output/compositor_frame.h" 22 #include "cc/output/compositor_frame_metadata.h" 23 #include "cc/output/context_provider.h" 24 #include "cc/output/copy_output_request.h" 25 #include "cc/output/geometry_binding.h" 26 #include "cc/output/gl_frame_data.h" 27 #include "cc/output/output_surface.h" 28 #include "cc/output/render_surface_filters.h" 29 #include "cc/quads/picture_draw_quad.h" 30 #include "cc/quads/render_pass.h" 31 #include "cc/quads/stream_video_draw_quad.h" 32 #include "cc/quads/texture_draw_quad.h" 33 #include "cc/resources/layer_quad.h" 34 #include "cc/resources/scoped_resource.h" 35 #include "cc/resources/texture_mailbox_deleter.h" 36 #include "cc/trees/damage_tracker.h" 37 #include "cc/trees/proxy.h" 38 #include "cc/trees/single_thread_proxy.h" 39 #include "gpu/GLES2/gl2extchromium.h" 40 #include "gpu/command_buffer/client/context_support.h" 41 #include "gpu/command_buffer/client/gles2_interface.h" 42 #include "gpu/command_buffer/common/gpu_memory_allocation.h" 43 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 44 #include "third_party/khronos/GLES2/gl2.h" 45 #include "third_party/khronos/GLES2/gl2ext.h" 46 #include "third_party/skia/include/core/SkBitmap.h" 47 #include "third_party/skia/include/core/SkColor.h" 48 #include "third_party/skia/include/core/SkColorFilter.h" 49 #include "third_party/skia/include/core/SkSurface.h" 50 #include "third_party/skia/include/gpu/GrContext.h" 51 #include "third_party/skia/include/gpu/GrTexture.h" 52 #include "third_party/skia/include/gpu/SkGpuDevice.h" 53 #include "third_party/skia/include/gpu/SkGrTexturePixelRef.h" 54 #include "third_party/skia/include/gpu/gl/GrGLInterface.h" 55 #include "ui/gfx/quad_f.h" 56 #include "ui/gfx/rect_conversions.h" 57 58 using blink::WebGraphicsContext3D; 59 using gpu::gles2::GLES2Interface; 60 61 namespace cc { 62 63 namespace { 64 65 // TODO(epenner): This should probably be moved to output surface. 66 // 67 // This implements a simple fence based on client side swaps. 68 // This is to isolate the ResourceProvider from 'frames' which 69 // it shouldn't need to care about, while still allowing us to 70 // enforce good texture recycling behavior strictly throughout 71 // the compositor (don't recycle a texture while it's in use). 72 class SimpleSwapFence : public ResourceProvider::Fence { 73 public: 74 SimpleSwapFence() : has_passed_(false) {} 75 virtual bool HasPassed() OVERRIDE { return has_passed_; } 76 void SetHasPassed() { has_passed_ = true; } 77 78 private: 79 virtual ~SimpleSwapFence() {} 80 bool has_passed_; 81 }; 82 83 bool NeedsIOSurfaceReadbackWorkaround() { 84 #if defined(OS_MACOSX) 85 // This isn't strictly required in DumpRenderTree-mode when Mesa is used, 86 // but it doesn't seem to hurt. 87 return true; 88 #else 89 return false; 90 #endif 91 } 92 93 Float4 UVTransform(const TextureDrawQuad* quad) { 94 gfx::PointF uv0 = quad->uv_top_left; 95 gfx::PointF uv1 = quad->uv_bottom_right; 96 Float4 xform = {{uv0.x(), uv0.y(), uv1.x() - uv0.x(), uv1.y() - uv0.y()}}; 97 if (quad->flipped) { 98 xform.data[1] = 1.0f - xform.data[1]; 99 xform.data[3] = -xform.data[3]; 100 } 101 return xform; 102 } 103 104 Float4 PremultipliedColor(SkColor color) { 105 const float factor = 1.0f / 255.0f; 106 const float alpha = SkColorGetA(color) * factor; 107 108 Float4 result = { 109 {SkColorGetR(color) * factor * alpha, SkColorGetG(color) * factor * alpha, 110 SkColorGetB(color) * factor * alpha, alpha}}; 111 return result; 112 } 113 114 SamplerType SamplerTypeFromTextureTarget(GLenum target) { 115 switch (target) { 116 case GL_TEXTURE_2D: 117 return SamplerType2D; 118 case GL_TEXTURE_RECTANGLE_ARB: 119 return SamplerType2DRect; 120 case GL_TEXTURE_EXTERNAL_OES: 121 return SamplerTypeExternalOES; 122 default: 123 NOTREACHED(); 124 return SamplerType2D; 125 } 126 } 127 128 // Smallest unit that impact anti-aliasing output. We use this to 129 // determine when anti-aliasing is unnecessary. 130 const float kAntiAliasingEpsilon = 1.0f / 1024.0f; 131 132 } // anonymous namespace 133 134 struct GLRenderer::PendingAsyncReadPixels { 135 PendingAsyncReadPixels() : buffer(0) {} 136 137 scoped_ptr<CopyOutputRequest> copy_request; 138 base::CancelableClosure finished_read_pixels_callback; 139 unsigned buffer; 140 141 private: 142 DISALLOW_COPY_AND_ASSIGN(PendingAsyncReadPixels); 143 }; 144 145 scoped_ptr<GLRenderer> GLRenderer::Create( 146 RendererClient* client, 147 const LayerTreeSettings* settings, 148 OutputSurface* output_surface, 149 ResourceProvider* resource_provider, 150 TextureMailboxDeleter* texture_mailbox_deleter, 151 int highp_threshold_min) { 152 return make_scoped_ptr(new GLRenderer(client, 153 settings, 154 output_surface, 155 resource_provider, 156 texture_mailbox_deleter, 157 highp_threshold_min)); 158 } 159 160 GLRenderer::GLRenderer(RendererClient* client, 161 const LayerTreeSettings* settings, 162 OutputSurface* output_surface, 163 ResourceProvider* resource_provider, 164 TextureMailboxDeleter* texture_mailbox_deleter, 165 int highp_threshold_min) 166 : DirectRenderer(client, settings, output_surface, resource_provider), 167 offscreen_framebuffer_id_(0), 168 shared_geometry_quad_(gfx::RectF(-0.5f, -0.5f, 1.0f, 1.0f)), 169 context_(output_surface->context_provider()->Context3d()), 170 gl_(output_surface->context_provider()->ContextGL()), 171 context_support_(output_surface->context_provider()->ContextSupport()), 172 texture_mailbox_deleter_(texture_mailbox_deleter), 173 is_backbuffer_discarded_(false), 174 visible_(true), 175 is_scissor_enabled_(false), 176 scissor_rect_needs_reset_(true), 177 stencil_shadow_(false), 178 blend_shadow_(false), 179 highp_threshold_min_(highp_threshold_min), 180 highp_threshold_cache_(0), 181 on_demand_tile_raster_resource_id_(0) { 182 DCHECK(context_); 183 DCHECK(context_support_); 184 185 ContextProvider::Capabilities context_caps = 186 output_surface_->context_provider()->ContextCapabilities(); 187 188 capabilities_.using_partial_swap = 189 settings_->partial_swap_enabled && context_caps.post_sub_buffer; 190 191 DCHECK(!context_caps.iosurface || context_caps.texture_rectangle); 192 193 capabilities_.using_egl_image = context_caps.egl_image_external; 194 195 capabilities_.max_texture_size = resource_provider_->max_texture_size(); 196 capabilities_.best_texture_format = resource_provider_->best_texture_format(); 197 198 // The updater can access textures while the GLRenderer is using them. 199 capabilities_.allow_partial_texture_updates = true; 200 201 // Check for texture fast paths. Currently we always use MO8 textures, 202 // so we only need to avoid POT textures if we have an NPOT fast-path. 203 capabilities_.avoid_pow2_textures = context_caps.fast_npot_mo8_textures; 204 205 capabilities_.using_offscreen_context3d = true; 206 207 capabilities_.using_map_image = 208 settings_->use_map_image && context_caps.map_image; 209 210 capabilities_.using_discard_framebuffer = context_caps.discard_framebuffer; 211 212 InitializeSharedObjects(); 213 } 214 215 GLRenderer::~GLRenderer() { 216 while (!pending_async_read_pixels_.empty()) { 217 PendingAsyncReadPixels* pending_read = pending_async_read_pixels_.back(); 218 pending_read->finished_read_pixels_callback.Cancel(); 219 pending_async_read_pixels_.pop_back(); 220 } 221 222 CleanupSharedObjects(); 223 } 224 225 const RendererCapabilitiesImpl& GLRenderer::Capabilities() const { 226 return capabilities_; 227 } 228 229 WebGraphicsContext3D* GLRenderer::Context() { return context_; } 230 231 void GLRenderer::DebugGLCall(GLES2Interface* gl, 232 const char* command, 233 const char* file, 234 int line) { 235 GLuint error = gl->GetError(); 236 if (error != GL_NO_ERROR) 237 LOG(ERROR) << "GL command failed: File: " << file << "\n\tLine " << line 238 << "\n\tcommand: " << command << ", error " 239 << static_cast<int>(error) << "\n"; 240 } 241 242 void GLRenderer::SetVisible(bool visible) { 243 if (visible_ == visible) 244 return; 245 visible_ = visible; 246 247 EnforceMemoryPolicy(); 248 249 context_support_->SetSurfaceVisible(visible); 250 } 251 252 void GLRenderer::SendManagedMemoryStats(size_t bytes_visible, 253 size_t bytes_visible_and_nearby, 254 size_t bytes_allocated) { 255 gpu::ManagedMemoryStats stats; 256 stats.bytes_required = bytes_visible; 257 stats.bytes_nice_to_have = bytes_visible_and_nearby; 258 stats.bytes_allocated = bytes_allocated; 259 stats.backbuffer_requested = !is_backbuffer_discarded_; 260 context_support_->SendManagedMemoryStats(stats); 261 } 262 263 void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); } 264 265 void GLRenderer::DiscardPixels(bool has_external_stencil_test, 266 bool draw_rect_covers_full_surface) { 267 if (has_external_stencil_test || !draw_rect_covers_full_surface || 268 !capabilities_.using_discard_framebuffer) 269 return; 270 bool using_default_framebuffer = 271 !current_framebuffer_lock_ && 272 output_surface_->capabilities().uses_default_gl_framebuffer; 273 GLenum attachments[] = {static_cast<GLenum>( 274 using_default_framebuffer ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0_EXT)}; 275 gl_->DiscardFramebufferEXT( 276 GL_FRAMEBUFFER, arraysize(attachments), attachments); 277 } 278 279 void GLRenderer::ClearFramebuffer(DrawingFrame* frame, 280 bool has_external_stencil_test) { 281 // It's unsafe to clear when we have a stencil test because glClear ignores 282 // stencil. 283 if (has_external_stencil_test) { 284 DCHECK(!frame->current_render_pass->has_transparent_background); 285 return; 286 } 287 288 // On DEBUG builds, opaque render passes are cleared to blue to easily see 289 // regions that were not drawn on the screen. 290 if (frame->current_render_pass->has_transparent_background) 291 GLC(gl_, gl_->ClearColor(0, 0, 0, 0)); 292 else 293 GLC(gl_, gl_->ClearColor(0, 0, 1, 1)); 294 295 bool always_clear = false; 296 #ifndef NDEBUG 297 always_clear = true; 298 #endif 299 if (always_clear || frame->current_render_pass->has_transparent_background) { 300 GLbitfield clear_bits = GL_COLOR_BUFFER_BIT; 301 if (always_clear) 302 clear_bits |= GL_STENCIL_BUFFER_BIT; 303 gl_->Clear(clear_bits); 304 } 305 } 306 307 void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) { 308 if (frame->device_viewport_rect.IsEmpty()) 309 return; 310 311 TRACE_EVENT0("cc", "GLRenderer::BeginDrawingFrame"); 312 313 // TODO(enne): Do we need to reinitialize all of this state per frame? 314 ReinitializeGLState(); 315 } 316 317 void GLRenderer::DoNoOp() { 318 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, 0)); 319 GLC(gl_, gl_->Flush()); 320 } 321 322 void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { 323 DCHECK(quad->rect.Contains(quad->visible_rect)); 324 if (quad->material != DrawQuad::TEXTURE_CONTENT) { 325 FlushTextureQuadCache(); 326 } 327 328 switch (quad->material) { 329 case DrawQuad::INVALID: 330 NOTREACHED(); 331 break; 332 case DrawQuad::CHECKERBOARD: 333 DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad)); 334 break; 335 case DrawQuad::DEBUG_BORDER: 336 DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad)); 337 break; 338 case DrawQuad::IO_SURFACE_CONTENT: 339 DrawIOSurfaceQuad(frame, IOSurfaceDrawQuad::MaterialCast(quad)); 340 break; 341 case DrawQuad::PICTURE_CONTENT: 342 DrawPictureQuad(frame, PictureDrawQuad::MaterialCast(quad)); 343 break; 344 case DrawQuad::RENDER_PASS: 345 DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad)); 346 break; 347 case DrawQuad::SOLID_COLOR: 348 DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad)); 349 break; 350 case DrawQuad::STREAM_VIDEO_CONTENT: 351 DrawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad)); 352 break; 353 case DrawQuad::TEXTURE_CONTENT: 354 EnqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad)); 355 break; 356 case DrawQuad::TILED_CONTENT: 357 DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad)); 358 break; 359 case DrawQuad::YUV_VIDEO_CONTENT: 360 DrawYUVVideoQuad(frame, YUVVideoDrawQuad::MaterialCast(quad)); 361 break; 362 } 363 } 364 365 void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame, 366 const CheckerboardDrawQuad* quad) { 367 SetBlendEnabled(quad->ShouldDrawWithBlending()); 368 369 const TileCheckerboardProgram* program = GetTileCheckerboardProgram(); 370 DCHECK(program && (program->initialized() || IsContextLost())); 371 SetUseProgram(program->program()); 372 373 SkColor color = quad->color; 374 GLC(gl_, 375 gl_->Uniform4f(program->fragment_shader().color_location(), 376 SkColorGetR(color) * (1.0f / 255.0f), 377 SkColorGetG(color) * (1.0f / 255.0f), 378 SkColorGetB(color) * (1.0f / 255.0f), 379 1)); 380 381 const int checkerboard_width = 16; 382 float frequency = 1.0f / checkerboard_width; 383 384 gfx::Rect tile_rect = quad->rect; 385 float tex_offset_x = tile_rect.x() % checkerboard_width; 386 float tex_offset_y = tile_rect.y() % checkerboard_width; 387 float tex_scale_x = tile_rect.width(); 388 float tex_scale_y = tile_rect.height(); 389 GLC(gl_, 390 gl_->Uniform4f(program->fragment_shader().tex_transform_location(), 391 tex_offset_x, 392 tex_offset_y, 393 tex_scale_x, 394 tex_scale_y)); 395 396 GLC(gl_, 397 gl_->Uniform1f(program->fragment_shader().frequency_location(), 398 frequency)); 399 400 SetShaderOpacity(quad->opacity(), 401 program->fragment_shader().alpha_location()); 402 DrawQuadGeometry(frame, 403 quad->quadTransform(), 404 quad->rect, 405 program->vertex_shader().matrix_location()); 406 } 407 408 void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, 409 const DebugBorderDrawQuad* quad) { 410 SetBlendEnabled(quad->ShouldDrawWithBlending()); 411 412 static float gl_matrix[16]; 413 const DebugBorderProgram* program = GetDebugBorderProgram(); 414 DCHECK(program && (program->initialized() || IsContextLost())); 415 SetUseProgram(program->program()); 416 417 // Use the full quad_rect for debug quads to not move the edges based on 418 // partial swaps. 419 gfx::Rect layer_rect = quad->rect; 420 gfx::Transform render_matrix = quad->quadTransform(); 421 render_matrix.Translate(0.5f * layer_rect.width() + layer_rect.x(), 422 0.5f * layer_rect.height() + layer_rect.y()); 423 render_matrix.Scale(layer_rect.width(), layer_rect.height()); 424 GLRenderer::ToGLMatrix(&gl_matrix[0], 425 frame->projection_matrix * render_matrix); 426 GLC(gl_, 427 gl_->UniformMatrix4fv( 428 program->vertex_shader().matrix_location(), 1, false, &gl_matrix[0])); 429 430 SkColor color = quad->color; 431 float alpha = SkColorGetA(color) * (1.0f / 255.0f); 432 433 GLC(gl_, 434 gl_->Uniform4f(program->fragment_shader().color_location(), 435 (SkColorGetR(color) * (1.0f / 255.0f)) * alpha, 436 (SkColorGetG(color) * (1.0f / 255.0f)) * alpha, 437 (SkColorGetB(color) * (1.0f / 255.0f)) * alpha, 438 alpha)); 439 440 GLC(gl_, gl_->LineWidth(quad->width)); 441 442 // The indices for the line are stored in the same array as the triangle 443 // indices. 444 GLC(gl_, gl_->DrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0)); 445 } 446 447 static SkBitmap ApplyImageFilter(GLRenderer* renderer, 448 ContextProvider* offscreen_contexts, 449 gfx::Point origin, 450 SkImageFilter* filter, 451 ScopedResource* source_texture_resource) { 452 if (!filter) 453 return SkBitmap(); 454 455 if (!offscreen_contexts || !offscreen_contexts->GrContext()) 456 return SkBitmap(); 457 458 ResourceProvider::ScopedWriteLockGL lock(renderer->resource_provider(), 459 source_texture_resource->id()); 460 461 // Flush the compositor context to ensure that textures there are available 462 // in the shared context. Do this after locking/creating the compositor 463 // texture. 464 renderer->resource_provider()->Flush(); 465 466 // Make sure skia uses the correct GL context. 467 offscreen_contexts->MakeGrContextCurrent(); 468 469 // Wrap the source texture in a Ganesh platform texture. 470 GrBackendTextureDesc backend_texture_description; 471 backend_texture_description.fWidth = source_texture_resource->size().width(); 472 backend_texture_description.fHeight = 473 source_texture_resource->size().height(); 474 backend_texture_description.fConfig = kSkia8888_GrPixelConfig; 475 backend_texture_description.fTextureHandle = lock.texture_id(); 476 backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin; 477 skia::RefPtr<GrTexture> texture = 478 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( 479 backend_texture_description)); 480 481 SkImageInfo info = { 482 source_texture_resource->size().width(), 483 source_texture_resource->size().height(), 484 kPMColor_SkColorType, 485 kPremul_SkAlphaType 486 }; 487 // Place the platform texture inside an SkBitmap. 488 SkBitmap source; 489 source.setConfig(info); 490 skia::RefPtr<SkGrPixelRef> pixel_ref = 491 skia::AdoptRef(new SkGrPixelRef(info, texture.get())); 492 source.setPixelRef(pixel_ref.get()); 493 494 // Create a scratch texture for backing store. 495 GrTextureDesc desc; 496 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 497 desc.fSampleCnt = 0; 498 desc.fWidth = source.width(); 499 desc.fHeight = source.height(); 500 desc.fConfig = kSkia8888_GrPixelConfig; 501 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; 502 GrAutoScratchTexture scratch_texture( 503 offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch); 504 skia::RefPtr<GrTexture> backing_store = 505 skia::AdoptRef(scratch_texture.detach()); 506 507 // Create a device and canvas using that backing store. 508 SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get()); 509 SkCanvas canvas(&device); 510 511 // Draw the source bitmap through the filter to the canvas. 512 SkPaint paint; 513 paint.setImageFilter(filter); 514 canvas.clear(SK_ColorTRANSPARENT); 515 516 // TODO(senorblanco): in addition to the origin translation here, the canvas 517 // should also be scaled to accomodate device pixel ratio and pinch zoom. See 518 // crbug.com/281516 and crbug.com/281518. 519 canvas.translate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y())); 520 canvas.drawSprite(source, 0, 0, &paint); 521 522 // Flush skia context so that all the rendered stuff appears on the 523 // texture. 524 offscreen_contexts->GrContext()->flush(); 525 526 // Flush the GL context so rendering results from this context are 527 // visible in the compositor's context. 528 offscreen_contexts->Context3d()->flush(); 529 530 return device.accessBitmap(false); 531 } 532 533 static SkBitmap ApplyBlendModeWithBackdrop( 534 GLRenderer* renderer, 535 ContextProvider* offscreen_contexts, 536 SkBitmap source_bitmap_with_filters, 537 ScopedResource* source_texture_resource, 538 ScopedResource* background_texture_resource, 539 SkXfermode::Mode blend_mode) { 540 if (!offscreen_contexts || !offscreen_contexts->GrContext()) 541 return source_bitmap_with_filters; 542 543 DCHECK(background_texture_resource); 544 DCHECK(source_texture_resource); 545 546 gfx::Size source_size = source_texture_resource->size(); 547 gfx::Size background_size = background_texture_resource->size(); 548 549 DCHECK_LE(background_size.width(), source_size.width()); 550 DCHECK_LE(background_size.height(), source_size.height()); 551 552 int source_texture_with_filters_id; 553 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; 554 if (source_bitmap_with_filters.getTexture()) { 555 DCHECK_EQ(source_size.width(), source_bitmap_with_filters.width()); 556 DCHECK_EQ(source_size.height(), source_bitmap_with_filters.height()); 557 GrTexture* texture = 558 reinterpret_cast<GrTexture*>(source_bitmap_with_filters.getTexture()); 559 source_texture_with_filters_id = texture->getTextureHandle(); 560 } else { 561 lock.reset(new ResourceProvider::ScopedReadLockGL( 562 renderer->resource_provider(), source_texture_resource->id())); 563 source_texture_with_filters_id = lock->texture_id(); 564 } 565 566 ResourceProvider::ScopedReadLockGL lock_background( 567 renderer->resource_provider(), background_texture_resource->id()); 568 569 // Flush the compositor context to ensure that textures there are available 570 // in the shared context. Do this after locking/creating the compositor 571 // texture. 572 renderer->resource_provider()->Flush(); 573 574 // Make sure skia uses the correct GL context. 575 offscreen_contexts->MakeGrContextCurrent(); 576 577 // Wrap the source texture in a Ganesh platform texture. 578 GrBackendTextureDesc backend_texture_description; 579 backend_texture_description.fConfig = kSkia8888_GrPixelConfig; 580 backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin; 581 582 backend_texture_description.fWidth = source_size.width(); 583 backend_texture_description.fHeight = source_size.height(); 584 backend_texture_description.fTextureHandle = source_texture_with_filters_id; 585 skia::RefPtr<GrTexture> source_texture = 586 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( 587 backend_texture_description)); 588 589 backend_texture_description.fWidth = background_size.width(); 590 backend_texture_description.fHeight = background_size.height(); 591 backend_texture_description.fTextureHandle = lock_background.texture_id(); 592 skia::RefPtr<GrTexture> background_texture = 593 skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture( 594 backend_texture_description)); 595 596 SkImageInfo source_info = { 597 source_size.width(), 598 source_size.height(), 599 kPMColor_SkColorType, 600 kPremul_SkAlphaType 601 }; 602 // Place the platform texture inside an SkBitmap. 603 SkBitmap source; 604 source.setConfig(source_info); 605 skia::RefPtr<SkGrPixelRef> source_pixel_ref = 606 skia::AdoptRef(new SkGrPixelRef(source_info, source_texture.get())); 607 source.setPixelRef(source_pixel_ref.get()); 608 609 SkImageInfo background_info = { 610 background_size.width(), 611 background_size.height(), 612 kPMColor_SkColorType, 613 kPremul_SkAlphaType 614 }; 615 616 SkBitmap background; 617 background.setConfig(background_info); 618 skia::RefPtr<SkGrPixelRef> background_pixel_ref = 619 skia::AdoptRef(new SkGrPixelRef( 620 background_info, background_texture.get())); 621 background.setPixelRef(background_pixel_ref.get()); 622 623 // Create a scratch texture for backing store. 624 GrTextureDesc desc; 625 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 626 desc.fSampleCnt = 0; 627 desc.fWidth = source.width(); 628 desc.fHeight = source.height(); 629 desc.fConfig = kSkia8888_GrPixelConfig; 630 desc.fOrigin = kBottomLeft_GrSurfaceOrigin; 631 GrAutoScratchTexture scratch_texture( 632 offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch); 633 skia::RefPtr<GrTexture> backing_store = 634 skia::AdoptRef(scratch_texture.detach()); 635 636 // Create a device and canvas using that backing store. 637 SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get()); 638 SkCanvas canvas(&device); 639 640 // Draw the source bitmap through the filter to the canvas. 641 canvas.clear(SK_ColorTRANSPARENT); 642 canvas.drawSprite(background, 0, 0); 643 SkPaint paint; 644 paint.setXfermodeMode(blend_mode); 645 canvas.drawSprite(source, 0, 0, &paint); 646 647 // Flush skia context so that all the rendered stuff appears on the 648 // texture. 649 offscreen_contexts->GrContext()->flush(); 650 651 // Flush the GL context so rendering results from this context are 652 // visible in the compositor's context. 653 offscreen_contexts->Context3d()->flush(); 654 655 return device.accessBitmap(false); 656 } 657 658 scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( 659 DrawingFrame* frame, 660 const RenderPassDrawQuad* quad, 661 const gfx::Transform& contents_device_transform, 662 const gfx::Transform& contents_device_transform_inverse, 663 bool* background_changed) { 664 // This method draws a background filter, which applies a filter to any pixels 665 // behind the quad and seen through its background. The algorithm works as 666 // follows: 667 // 1. Compute a bounding box around the pixels that will be visible through 668 // the quad. 669 // 2. Read the pixels in the bounding box into a buffer R. 670 // 3. Apply the background filter to R, so that it is applied in the pixels' 671 // coordinate space. 672 // 4. Apply the quad's inverse transform to map the pixels in R into the 673 // quad's content space. This implicitly clips R by the content bounds of the 674 // quad since the destination texture has bounds matching the quad's content. 675 // 5. Draw the background texture for the contents using the same transform as 676 // used to draw the contents itself. This is done without blending to replace 677 // the current background pixels with the new filtered background. 678 // 6. Draw the contents of the quad over drop of the new background with 679 // blending, as per usual. The filtered background pixels will show through 680 // any non-opaque pixels in this draws. 681 // 682 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. 683 684 // TODO(danakj): When this algorithm changes, update 685 // LayerTreeHost::PrioritizeTextures() accordingly. 686 687 // TODO(danakj): We only allow background filters on an opaque render surface 688 // because other surfaces may contain translucent pixels, and the contents 689 // behind those translucent pixels wouldn't have the filter applied. 690 bool apply_background_filters = 691 !frame->current_render_pass->has_transparent_background; 692 DCHECK(!frame->current_texture); 693 694 // TODO(ajuma): Add support for reference filters once 695 // FilterOperations::GetOutsets supports reference filters. 696 if (apply_background_filters && quad->background_filters.HasReferenceFilter()) 697 apply_background_filters = false; 698 699 // TODO(danakj): Do a single readback for both the surface and replica and 700 // cache the filtered results (once filter textures are not reused). 701 gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( 702 contents_device_transform, SharedGeometryQuad().BoundingBox())); 703 704 int top, right, bottom, left; 705 quad->background_filters.GetOutsets(&top, &right, &bottom, &left); 706 window_rect.Inset(-left, -top, -right, -bottom); 707 708 window_rect.Intersect( 709 MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); 710 711 scoped_ptr<ScopedResource> device_background_texture = 712 ScopedResource::Create(resource_provider_); 713 // The TextureUsageFramebuffer hint makes ResourceProvider avoid immutable 714 // storage allocation (texStorage2DEXT) for this texture. copyTexImage2D fails 715 // when called on a texture having immutable storage. 716 device_background_texture->Allocate( 717 window_rect.size(), ResourceProvider::TextureUsageFramebuffer, RGBA_8888); 718 { 719 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, 720 device_background_texture->id()); 721 GetFramebufferTexture( 722 lock.texture_id(), device_background_texture->format(), window_rect); 723 } 724 725 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( 726 quad->background_filters, device_background_texture->size()); 727 728 SkBitmap filtered_device_background; 729 if (apply_background_filters) { 730 filtered_device_background = 731 ApplyImageFilter(this, 732 frame->offscreen_context_provider, 733 quad->rect.origin(), 734 filter.get(), 735 device_background_texture.get()); 736 } 737 *background_changed = (filtered_device_background.getTexture() != NULL); 738 739 int filtered_device_background_texture_id = 0; 740 scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; 741 if (filtered_device_background.getTexture()) { 742 GrTexture* texture = 743 reinterpret_cast<GrTexture*>(filtered_device_background.getTexture()); 744 filtered_device_background_texture_id = texture->getTextureHandle(); 745 } else { 746 lock.reset(new ResourceProvider::ScopedReadLockGL( 747 resource_provider_, device_background_texture->id())); 748 filtered_device_background_texture_id = lock->texture_id(); 749 } 750 751 scoped_ptr<ScopedResource> background_texture = 752 ScopedResource::Create(resource_provider_); 753 background_texture->Allocate( 754 quad->rect.size(), ResourceProvider::TextureUsageFramebuffer, RGBA_8888); 755 756 const RenderPass* target_render_pass = frame->current_render_pass; 757 bool using_background_texture = 758 UseScopedTexture(frame, background_texture.get(), quad->rect); 759 760 if (using_background_texture) { 761 // Copy the readback pixels from device to the background texture for the 762 // surface. 763 gfx::Transform device_to_framebuffer_transform; 764 device_to_framebuffer_transform.Translate( 765 quad->rect.width() * 0.5f + quad->rect.x(), 766 quad->rect.height() * 0.5f + quad->rect.y()); 767 device_to_framebuffer_transform.Scale(quad->rect.width(), 768 quad->rect.height()); 769 device_to_framebuffer_transform.PreconcatTransform( 770 contents_device_transform_inverse); 771 772 #ifndef NDEBUG 773 GLC(gl_, gl_->ClearColor(0, 0, 1, 1)); 774 gl_->Clear(GL_COLOR_BUFFER_BIT); 775 #endif 776 777 // The filtered_deveice_background_texture is oriented the same as the frame 778 // buffer. The transform we are copying with has a vertical flip, as well as 779 // the |device_to_framebuffer_transform|, which cancel each other out. So do 780 // not flip the contents in the shader to maintain orientation. 781 bool flip_vertically = false; 782 783 CopyTextureToFramebuffer(frame, 784 filtered_device_background_texture_id, 785 window_rect, 786 device_to_framebuffer_transform, 787 flip_vertically); 788 } 789 790 UseRenderPass(frame, target_render_pass); 791 792 if (!using_background_texture) 793 return scoped_ptr<ScopedResource>(); 794 return background_texture.Pass(); 795 } 796 797 void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, 798 const RenderPassDrawQuad* quad) { 799 SetBlendEnabled(quad->ShouldDrawWithBlending()); 800 801 ScopedResource* contents_texture = 802 render_pass_textures_.get(quad->render_pass_id); 803 if (!contents_texture || !contents_texture->id()) 804 return; 805 806 gfx::Transform quad_rect_matrix; 807 QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); 808 gfx::Transform contents_device_transform = 809 frame->window_matrix * frame->projection_matrix * quad_rect_matrix; 810 contents_device_transform.FlattenTo2d(); 811 812 // Can only draw surface if device matrix is invertible. 813 gfx::Transform contents_device_transform_inverse( 814 gfx::Transform::kSkipInitialization); 815 if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) 816 return; 817 818 bool need_background_texture = 819 quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode || 820 !quad->background_filters.IsEmpty(); 821 bool background_changed = false; 822 scoped_ptr<ScopedResource> background_texture; 823 if (need_background_texture) { 824 // The pixels from the filtered background should completely replace the 825 // current pixel values. 826 bool disable_blending = blend_enabled(); 827 if (disable_blending) 828 SetBlendEnabled(false); 829 830 background_texture = 831 GetBackgroundWithFilters(frame, 832 quad, 833 contents_device_transform, 834 contents_device_transform_inverse, 835 &background_changed); 836 837 if (disable_blending) 838 SetBlendEnabled(true); 839 } 840 841 // TODO(senorblanco): Cache this value so that we don't have to do it for both 842 // the surface and its replica. Apply filters to the contents texture. 843 SkBitmap filter_bitmap; 844 SkScalar color_matrix[20]; 845 bool use_color_matrix = false; 846 // TODO(ajuma): Always use RenderSurfaceFilters::BuildImageFilter, not just 847 // when we have a reference filter. 848 if (!quad->filters.IsEmpty()) { 849 skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( 850 quad->filters, contents_texture->size()); 851 if (filter) { 852 skia::RefPtr<SkColorFilter> cf; 853 854 { 855 SkColorFilter* colorfilter_rawptr = NULL; 856 filter->asColorFilter(&colorfilter_rawptr); 857 cf = skia::AdoptRef(colorfilter_rawptr); 858 } 859 860 if (cf && cf->asColorMatrix(color_matrix) && !filter->getInput(0)) { 861 // We have a single color matrix as a filter; apply it locally 862 // in the compositor. 863 use_color_matrix = true; 864 } else { 865 filter_bitmap = ApplyImageFilter(this, 866 frame->offscreen_context_provider, 867 quad->rect.origin(), 868 filter.get(), 869 contents_texture); 870 } 871 } 872 } 873 874 if (quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode && 875 background_texture) { 876 filter_bitmap = 877 ApplyBlendModeWithBackdrop(this, 878 frame->offscreen_context_provider, 879 filter_bitmap, 880 contents_texture, 881 background_texture.get(), 882 quad->shared_quad_state->blend_mode); 883 } 884 885 // Draw the background texture if it has some filters applied. 886 if (background_texture && background_changed) { 887 DCHECK(background_texture->size() == quad->rect.size()); 888 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 889 background_texture->id()); 890 891 // The background_texture is oriented the same as the frame buffer. The 892 // transform we are copying with has a vertical flip, so flip the contents 893 // in the shader to maintain orientation 894 bool flip_vertically = true; 895 896 CopyTextureToFramebuffer(frame, 897 lock.texture_id(), 898 quad->rect, 899 quad->quadTransform(), 900 flip_vertically); 901 } 902 903 bool clipped = false; 904 gfx::QuadF device_quad = MathUtil::MapQuad( 905 contents_device_transform, SharedGeometryQuad(), &clipped); 906 LayerQuad device_layer_bounds(gfx::QuadF(device_quad.BoundingBox())); 907 LayerQuad device_layer_edges(device_quad); 908 909 // Use anti-aliasing programs only when necessary. 910 bool use_aa = 911 !clipped && (!device_quad.IsRectilinear() || 912 !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(), 913 kAntiAliasingEpsilon)); 914 if (use_aa) { 915 device_layer_bounds.InflateAntiAliasingDistance(); 916 device_layer_edges.InflateAntiAliasingDistance(); 917 } 918 919 scoped_ptr<ResourceProvider::ScopedReadLockGL> mask_resource_lock; 920 unsigned mask_texture_id = 0; 921 if (quad->mask_resource_id) { 922 mask_resource_lock.reset(new ResourceProvider::ScopedReadLockGL( 923 resource_provider_, quad->mask_resource_id)); 924 mask_texture_id = mask_resource_lock->texture_id(); 925 } 926 927 // TODO(danakj): use the background_texture and blend the background in with 928 // this draw instead of having a separate copy of the background texture. 929 930 scoped_ptr<ResourceProvider::ScopedSamplerGL> contents_resource_lock; 931 if (filter_bitmap.getTexture()) { 932 GrTexture* texture = 933 reinterpret_cast<GrTexture*>(filter_bitmap.getTexture()); 934 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 935 gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle()); 936 } else { 937 contents_resource_lock = 938 make_scoped_ptr(new ResourceProvider::ScopedSamplerGL( 939 resource_provider_, contents_texture->id(), GL_LINEAR)); 940 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), 941 contents_resource_lock->target()); 942 } 943 944 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 945 gl_, 946 &highp_threshold_cache_, 947 highp_threshold_min_, 948 quad->shared_quad_state->visible_content_rect.bottom_right()); 949 950 int shader_quad_location = -1; 951 int shader_edge_location = -1; 952 int shader_viewport_location = -1; 953 int shader_mask_sampler_location = -1; 954 int shader_mask_tex_coord_scale_location = -1; 955 int shader_mask_tex_coord_offset_location = -1; 956 int shader_matrix_location = -1; 957 int shader_alpha_location = -1; 958 int shader_color_matrix_location = -1; 959 int shader_color_offset_location = -1; 960 int shader_tex_transform_location = -1; 961 962 if (use_aa && mask_texture_id && !use_color_matrix) { 963 const RenderPassMaskProgramAA* program = 964 GetRenderPassMaskProgramAA(tex_coord_precision); 965 SetUseProgram(program->program()); 966 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 967 968 shader_quad_location = program->vertex_shader().quad_location(); 969 shader_edge_location = program->vertex_shader().edge_location(); 970 shader_viewport_location = program->vertex_shader().viewport_location(); 971 shader_mask_sampler_location = 972 program->fragment_shader().mask_sampler_location(); 973 shader_mask_tex_coord_scale_location = 974 program->fragment_shader().mask_tex_coord_scale_location(); 975 shader_mask_tex_coord_offset_location = 976 program->fragment_shader().mask_tex_coord_offset_location(); 977 shader_matrix_location = program->vertex_shader().matrix_location(); 978 shader_alpha_location = program->fragment_shader().alpha_location(); 979 shader_tex_transform_location = 980 program->vertex_shader().tex_transform_location(); 981 } else if (!use_aa && mask_texture_id && !use_color_matrix) { 982 const RenderPassMaskProgram* program = 983 GetRenderPassMaskProgram(tex_coord_precision); 984 SetUseProgram(program->program()); 985 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 986 987 shader_mask_sampler_location = 988 program->fragment_shader().mask_sampler_location(); 989 shader_mask_tex_coord_scale_location = 990 program->fragment_shader().mask_tex_coord_scale_location(); 991 shader_mask_tex_coord_offset_location = 992 program->fragment_shader().mask_tex_coord_offset_location(); 993 shader_matrix_location = program->vertex_shader().matrix_location(); 994 shader_alpha_location = program->fragment_shader().alpha_location(); 995 shader_tex_transform_location = 996 program->vertex_shader().tex_transform_location(); 997 } else if (use_aa && !mask_texture_id && !use_color_matrix) { 998 const RenderPassProgramAA* program = 999 GetRenderPassProgramAA(tex_coord_precision); 1000 SetUseProgram(program->program()); 1001 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1002 1003 shader_quad_location = program->vertex_shader().quad_location(); 1004 shader_edge_location = program->vertex_shader().edge_location(); 1005 shader_viewport_location = program->vertex_shader().viewport_location(); 1006 shader_matrix_location = program->vertex_shader().matrix_location(); 1007 shader_alpha_location = program->fragment_shader().alpha_location(); 1008 shader_tex_transform_location = 1009 program->vertex_shader().tex_transform_location(); 1010 } else if (use_aa && mask_texture_id && use_color_matrix) { 1011 const RenderPassMaskColorMatrixProgramAA* program = 1012 GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision); 1013 SetUseProgram(program->program()); 1014 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1015 1016 shader_matrix_location = program->vertex_shader().matrix_location(); 1017 shader_quad_location = program->vertex_shader().quad_location(); 1018 shader_tex_transform_location = 1019 program->vertex_shader().tex_transform_location(); 1020 shader_edge_location = program->vertex_shader().edge_location(); 1021 shader_viewport_location = program->vertex_shader().viewport_location(); 1022 shader_alpha_location = program->fragment_shader().alpha_location(); 1023 shader_mask_sampler_location = 1024 program->fragment_shader().mask_sampler_location(); 1025 shader_mask_tex_coord_scale_location = 1026 program->fragment_shader().mask_tex_coord_scale_location(); 1027 shader_mask_tex_coord_offset_location = 1028 program->fragment_shader().mask_tex_coord_offset_location(); 1029 shader_color_matrix_location = 1030 program->fragment_shader().color_matrix_location(); 1031 shader_color_offset_location = 1032 program->fragment_shader().color_offset_location(); 1033 } else if (use_aa && !mask_texture_id && use_color_matrix) { 1034 const RenderPassColorMatrixProgramAA* program = 1035 GetRenderPassColorMatrixProgramAA(tex_coord_precision); 1036 SetUseProgram(program->program()); 1037 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1038 1039 shader_matrix_location = program->vertex_shader().matrix_location(); 1040 shader_quad_location = program->vertex_shader().quad_location(); 1041 shader_tex_transform_location = 1042 program->vertex_shader().tex_transform_location(); 1043 shader_edge_location = program->vertex_shader().edge_location(); 1044 shader_viewport_location = program->vertex_shader().viewport_location(); 1045 shader_alpha_location = program->fragment_shader().alpha_location(); 1046 shader_color_matrix_location = 1047 program->fragment_shader().color_matrix_location(); 1048 shader_color_offset_location = 1049 program->fragment_shader().color_offset_location(); 1050 } else if (!use_aa && mask_texture_id && use_color_matrix) { 1051 const RenderPassMaskColorMatrixProgram* program = 1052 GetRenderPassMaskColorMatrixProgram(tex_coord_precision); 1053 SetUseProgram(program->program()); 1054 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1055 1056 shader_matrix_location = program->vertex_shader().matrix_location(); 1057 shader_tex_transform_location = 1058 program->vertex_shader().tex_transform_location(); 1059 shader_mask_sampler_location = 1060 program->fragment_shader().mask_sampler_location(); 1061 shader_mask_tex_coord_scale_location = 1062 program->fragment_shader().mask_tex_coord_scale_location(); 1063 shader_mask_tex_coord_offset_location = 1064 program->fragment_shader().mask_tex_coord_offset_location(); 1065 shader_alpha_location = program->fragment_shader().alpha_location(); 1066 shader_color_matrix_location = 1067 program->fragment_shader().color_matrix_location(); 1068 shader_color_offset_location = 1069 program->fragment_shader().color_offset_location(); 1070 } else if (!use_aa && !mask_texture_id && use_color_matrix) { 1071 const RenderPassColorMatrixProgram* program = 1072 GetRenderPassColorMatrixProgram(tex_coord_precision); 1073 SetUseProgram(program->program()); 1074 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1075 1076 shader_matrix_location = program->vertex_shader().matrix_location(); 1077 shader_tex_transform_location = 1078 program->vertex_shader().tex_transform_location(); 1079 shader_alpha_location = program->fragment_shader().alpha_location(); 1080 shader_color_matrix_location = 1081 program->fragment_shader().color_matrix_location(); 1082 shader_color_offset_location = 1083 program->fragment_shader().color_offset_location(); 1084 } else { 1085 const RenderPassProgram* program = 1086 GetRenderPassProgram(tex_coord_precision); 1087 SetUseProgram(program->program()); 1088 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1089 1090 shader_matrix_location = program->vertex_shader().matrix_location(); 1091 shader_alpha_location = program->fragment_shader().alpha_location(); 1092 shader_tex_transform_location = 1093 program->vertex_shader().tex_transform_location(); 1094 } 1095 float tex_scale_x = 1096 quad->rect.width() / static_cast<float>(contents_texture->size().width()); 1097 float tex_scale_y = quad->rect.height() / 1098 static_cast<float>(contents_texture->size().height()); 1099 DCHECK_LE(tex_scale_x, 1.0f); 1100 DCHECK_LE(tex_scale_y, 1.0f); 1101 1102 DCHECK(shader_tex_transform_location != -1 || IsContextLost()); 1103 // Flip the content vertically in the shader, as the RenderPass input 1104 // texture is already oriented the same way as the framebuffer, but the 1105 // projection transform does a flip. 1106 GLC(gl_, 1107 gl_->Uniform4f(shader_tex_transform_location, 1108 0.0f, 1109 tex_scale_y, 1110 tex_scale_x, 1111 -tex_scale_y)); 1112 1113 scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_mask_sampler_lock; 1114 if (shader_mask_sampler_location != -1) { 1115 DCHECK_NE(shader_mask_tex_coord_scale_location, 1); 1116 DCHECK_NE(shader_mask_tex_coord_offset_location, 1); 1117 GLC(gl_, gl_->Uniform1i(shader_mask_sampler_location, 1)); 1118 1119 float mask_tex_scale_x = quad->mask_uv_rect.width() / tex_scale_x; 1120 float mask_tex_scale_y = quad->mask_uv_rect.height() / tex_scale_y; 1121 1122 // Mask textures are oriented vertically flipped relative to the framebuffer 1123 // and the RenderPass contents texture, so we flip the tex coords from the 1124 // RenderPass texture to find the mask texture coords. 1125 GLC(gl_, 1126 gl_->Uniform2f(shader_mask_tex_coord_offset_location, 1127 quad->mask_uv_rect.x(), 1128 quad->mask_uv_rect.y() + quad->mask_uv_rect.height())); 1129 GLC(gl_, 1130 gl_->Uniform2f(shader_mask_tex_coord_scale_location, 1131 mask_tex_scale_x, 1132 -mask_tex_scale_y)); 1133 shader_mask_sampler_lock = make_scoped_ptr( 1134 new ResourceProvider::ScopedSamplerGL(resource_provider_, 1135 quad->mask_resource_id, 1136 GL_TEXTURE1, 1137 GL_LINEAR)); 1138 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), 1139 shader_mask_sampler_lock->target()); 1140 } 1141 1142 if (shader_edge_location != -1) { 1143 float edge[24]; 1144 device_layer_edges.ToFloatArray(edge); 1145 device_layer_bounds.ToFloatArray(&edge[12]); 1146 GLC(gl_, gl_->Uniform3fv(shader_edge_location, 8, edge)); 1147 } 1148 1149 if (shader_viewport_location != -1) { 1150 float viewport[4] = {static_cast<float>(viewport_.x()), 1151 static_cast<float>(viewport_.y()), 1152 static_cast<float>(viewport_.width()), 1153 static_cast<float>(viewport_.height()), }; 1154 GLC(gl_, gl_->Uniform4fv(shader_viewport_location, 1, viewport)); 1155 } 1156 1157 if (shader_color_matrix_location != -1) { 1158 float matrix[16]; 1159 for (int i = 0; i < 4; ++i) { 1160 for (int j = 0; j < 4; ++j) 1161 matrix[i * 4 + j] = SkScalarToFloat(color_matrix[j * 5 + i]); 1162 } 1163 GLC(gl_, 1164 gl_->UniformMatrix4fv(shader_color_matrix_location, 1, false, matrix)); 1165 } 1166 static const float kScale = 1.0f / 255.0f; 1167 if (shader_color_offset_location != -1) { 1168 float offset[4]; 1169 for (int i = 0; i < 4; ++i) 1170 offset[i] = SkScalarToFloat(color_matrix[i * 5 + 4]) * kScale; 1171 1172 GLC(gl_, gl_->Uniform4fv(shader_color_offset_location, 1, offset)); 1173 } 1174 1175 // Map device space quad to surface space. contents_device_transform has no 3d 1176 // component since it was flattened, so we don't need to project. 1177 gfx::QuadF surface_quad = MathUtil::MapQuad(contents_device_transform_inverse, 1178 device_layer_edges.ToQuadF(), 1179 &clipped); 1180 1181 SetShaderOpacity(quad->opacity(), shader_alpha_location); 1182 SetShaderQuadF(surface_quad, shader_quad_location); 1183 DrawQuadGeometry( 1184 frame, quad->quadTransform(), quad->rect, shader_matrix_location); 1185 1186 // Flush the compositor context before the filter bitmap goes out of 1187 // scope, so the draw gets processed before the filter texture gets deleted. 1188 if (filter_bitmap.getTexture()) 1189 GLC(gl_, gl_->Flush()); 1190 } 1191 1192 struct SolidColorProgramUniforms { 1193 unsigned program; 1194 unsigned matrix_location; 1195 unsigned viewport_location; 1196 unsigned quad_location; 1197 unsigned edge_location; 1198 unsigned color_location; 1199 }; 1200 1201 template <class T> 1202 static void SolidColorUniformLocation(T program, 1203 SolidColorProgramUniforms* uniforms) { 1204 uniforms->program = program->program(); 1205 uniforms->matrix_location = program->vertex_shader().matrix_location(); 1206 uniforms->viewport_location = program->vertex_shader().viewport_location(); 1207 uniforms->quad_location = program->vertex_shader().quad_location(); 1208 uniforms->edge_location = program->vertex_shader().edge_location(); 1209 uniforms->color_location = program->fragment_shader().color_location(); 1210 } 1211 1212 // static 1213 bool GLRenderer::SetupQuadForAntialiasing( 1214 const gfx::Transform& device_transform, 1215 const DrawQuad* quad, 1216 gfx::QuadF* local_quad, 1217 float edge[24]) { 1218 gfx::Rect tile_rect = quad->visible_rect; 1219 1220 bool clipped = false; 1221 gfx::QuadF device_layer_quad = MathUtil::MapQuad( 1222 device_transform, gfx::QuadF(quad->visibleContentRect()), &clipped); 1223 1224 bool is_axis_aligned_in_target = device_layer_quad.IsRectilinear(); 1225 bool is_nearest_rect_within_epsilon = 1226 is_axis_aligned_in_target && 1227 gfx::IsNearestRectWithinDistance(device_layer_quad.BoundingBox(), 1228 kAntiAliasingEpsilon); 1229 // AAing clipped quads is not supported by the code yet. 1230 bool use_aa = !clipped && !is_nearest_rect_within_epsilon && quad->IsEdge(); 1231 if (!use_aa) 1232 return false; 1233 1234 LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox())); 1235 device_layer_bounds.InflateAntiAliasingDistance(); 1236 1237 LayerQuad device_layer_edges(device_layer_quad); 1238 device_layer_edges.InflateAntiAliasingDistance(); 1239 1240 device_layer_edges.ToFloatArray(edge); 1241 device_layer_bounds.ToFloatArray(&edge[12]); 1242 1243 gfx::PointF bottom_right = tile_rect.bottom_right(); 1244 gfx::PointF bottom_left = tile_rect.bottom_left(); 1245 gfx::PointF top_left = tile_rect.origin(); 1246 gfx::PointF top_right = tile_rect.top_right(); 1247 1248 // Map points to device space. 1249 bottom_right = MathUtil::MapPoint(device_transform, bottom_right, &clipped); 1250 DCHECK(!clipped); 1251 bottom_left = MathUtil::MapPoint(device_transform, bottom_left, &clipped); 1252 DCHECK(!clipped); 1253 top_left = MathUtil::MapPoint(device_transform, top_left, &clipped); 1254 DCHECK(!clipped); 1255 top_right = MathUtil::MapPoint(device_transform, top_right, &clipped); 1256 DCHECK(!clipped); 1257 1258 LayerQuad::Edge bottom_edge(bottom_right, bottom_left); 1259 LayerQuad::Edge left_edge(bottom_left, top_left); 1260 LayerQuad::Edge top_edge(top_left, top_right); 1261 LayerQuad::Edge right_edge(top_right, bottom_right); 1262 1263 // Only apply anti-aliasing to edges not clipped by culling or scissoring. 1264 if (quad->IsTopEdge() && tile_rect.y() == quad->rect.y()) 1265 top_edge = device_layer_edges.top(); 1266 if (quad->IsLeftEdge() && tile_rect.x() == quad->rect.x()) 1267 left_edge = device_layer_edges.left(); 1268 if (quad->IsRightEdge() && tile_rect.right() == quad->rect.right()) 1269 right_edge = device_layer_edges.right(); 1270 if (quad->IsBottomEdge() && tile_rect.bottom() == quad->rect.bottom()) 1271 bottom_edge = device_layer_edges.bottom(); 1272 1273 float sign = gfx::QuadF(tile_rect).IsCounterClockwise() ? -1 : 1; 1274 bottom_edge.scale(sign); 1275 left_edge.scale(sign); 1276 top_edge.scale(sign); 1277 right_edge.scale(sign); 1278 1279 // Create device space quad. 1280 LayerQuad device_quad(left_edge, top_edge, right_edge, bottom_edge); 1281 1282 // Map device space quad to local space. device_transform has no 3d 1283 // component since it was flattened, so we don't need to project. We should 1284 // have already checked that the transform was uninvertible above. 1285 gfx::Transform inverse_device_transform(gfx::Transform::kSkipInitialization); 1286 bool did_invert = device_transform.GetInverse(&inverse_device_transform); 1287 DCHECK(did_invert); 1288 *local_quad = MathUtil::MapQuad( 1289 inverse_device_transform, device_quad.ToQuadF(), &clipped); 1290 // We should not DCHECK(!clipped) here, because anti-aliasing inflation may 1291 // cause device_quad to become clipped. To our knowledge this scenario does 1292 // not need to be handled differently than the unclipped case. 1293 1294 return true; 1295 } 1296 1297 void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame, 1298 const SolidColorDrawQuad* quad) { 1299 gfx::Rect tile_rect = quad->visible_rect; 1300 1301 SkColor color = quad->color; 1302 float opacity = quad->opacity(); 1303 float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; 1304 1305 // Early out if alpha is small enough that quad doesn't contribute to output. 1306 if (alpha < std::numeric_limits<float>::epsilon() && 1307 quad->ShouldDrawWithBlending()) 1308 return; 1309 1310 gfx::Transform device_transform = 1311 frame->window_matrix * frame->projection_matrix * quad->quadTransform(); 1312 device_transform.FlattenTo2d(); 1313 if (!device_transform.IsInvertible()) 1314 return; 1315 1316 gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); 1317 float edge[24]; 1318 bool use_aa = 1319 settings_->allow_antialiasing && !quad->force_anti_aliasing_off && 1320 SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge); 1321 1322 SolidColorProgramUniforms uniforms; 1323 if (use_aa) 1324 SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms); 1325 else 1326 SolidColorUniformLocation(GetSolidColorProgram(), &uniforms); 1327 SetUseProgram(uniforms.program); 1328 1329 GLC(gl_, 1330 gl_->Uniform4f(uniforms.color_location, 1331 (SkColorGetR(color) * (1.0f / 255.0f)) * alpha, 1332 (SkColorGetG(color) * (1.0f / 255.0f)) * alpha, 1333 (SkColorGetB(color) * (1.0f / 255.0f)) * alpha, 1334 alpha)); 1335 if (use_aa) { 1336 float viewport[4] = {static_cast<float>(viewport_.x()), 1337 static_cast<float>(viewport_.y()), 1338 static_cast<float>(viewport_.width()), 1339 static_cast<float>(viewport_.height()), }; 1340 GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport)); 1341 GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge)); 1342 } 1343 1344 // Enable blending when the quad properties require it or if we decided 1345 // to use antialiasing. 1346 SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa); 1347 1348 // Normalize to tile_rect. 1349 local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); 1350 1351 SetShaderQuadF(local_quad, uniforms.quad_location); 1352 1353 // The transform and vertex data are used to figure out the extents that the 1354 // un-antialiased quad should have and which vertex this is and the float 1355 // quad passed in via uniform is the actual geometry that gets used to draw 1356 // it. This is why this centered rect is used and not the original quad_rect. 1357 gfx::RectF centered_rect( 1358 gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()), 1359 tile_rect.size()); 1360 DrawQuadGeometry( 1361 frame, quad->quadTransform(), centered_rect, uniforms.matrix_location); 1362 } 1363 1364 struct TileProgramUniforms { 1365 unsigned program; 1366 unsigned matrix_location; 1367 unsigned viewport_location; 1368 unsigned quad_location; 1369 unsigned edge_location; 1370 unsigned vertex_tex_transform_location; 1371 unsigned sampler_location; 1372 unsigned fragment_tex_transform_location; 1373 unsigned alpha_location; 1374 }; 1375 1376 template <class T> 1377 static void TileUniformLocation(T program, TileProgramUniforms* uniforms) { 1378 uniforms->program = program->program(); 1379 uniforms->matrix_location = program->vertex_shader().matrix_location(); 1380 uniforms->viewport_location = program->vertex_shader().viewport_location(); 1381 uniforms->quad_location = program->vertex_shader().quad_location(); 1382 uniforms->edge_location = program->vertex_shader().edge_location(); 1383 uniforms->vertex_tex_transform_location = 1384 program->vertex_shader().vertex_tex_transform_location(); 1385 1386 uniforms->sampler_location = program->fragment_shader().sampler_location(); 1387 uniforms->alpha_location = program->fragment_shader().alpha_location(); 1388 uniforms->fragment_tex_transform_location = 1389 program->fragment_shader().fragment_tex_transform_location(); 1390 } 1391 1392 void GLRenderer::DrawTileQuad(const DrawingFrame* frame, 1393 const TileDrawQuad* quad) { 1394 DrawContentQuad(frame, quad, quad->resource_id); 1395 } 1396 1397 void GLRenderer::DrawContentQuad(const DrawingFrame* frame, 1398 const ContentDrawQuadBase* quad, 1399 ResourceProvider::ResourceId resource_id) { 1400 gfx::Rect tile_rect = quad->visible_rect; 1401 1402 gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional( 1403 quad->tex_coord_rect, quad->rect, tile_rect); 1404 float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width(); 1405 float tex_to_geom_scale_y = 1406 quad->rect.height() / quad->tex_coord_rect.height(); 1407 1408 gfx::RectF clamp_geom_rect(tile_rect); 1409 gfx::RectF clamp_tex_rect(tex_coord_rect); 1410 // Clamp texture coordinates to avoid sampling outside the layer 1411 // by deflating the tile region half a texel or half a texel 1412 // minus epsilon for one pixel layers. The resulting clamp region 1413 // is mapped to the unit square by the vertex shader and mapped 1414 // back to normalized texture coordinates by the fragment shader 1415 // after being clamped to 0-1 range. 1416 float tex_clamp_x = 1417 std::min(0.5f, 0.5f * clamp_tex_rect.width() - kAntiAliasingEpsilon); 1418 float tex_clamp_y = 1419 std::min(0.5f, 0.5f * clamp_tex_rect.height() - kAntiAliasingEpsilon); 1420 float geom_clamp_x = 1421 std::min(tex_clamp_x * tex_to_geom_scale_x, 1422 0.5f * clamp_geom_rect.width() - kAntiAliasingEpsilon); 1423 float geom_clamp_y = 1424 std::min(tex_clamp_y * tex_to_geom_scale_y, 1425 0.5f * clamp_geom_rect.height() - kAntiAliasingEpsilon); 1426 clamp_geom_rect.Inset(geom_clamp_x, geom_clamp_y, geom_clamp_x, geom_clamp_y); 1427 clamp_tex_rect.Inset(tex_clamp_x, tex_clamp_y, tex_clamp_x, tex_clamp_y); 1428 1429 // Map clamping rectangle to unit square. 1430 float vertex_tex_translate_x = -clamp_geom_rect.x() / clamp_geom_rect.width(); 1431 float vertex_tex_translate_y = 1432 -clamp_geom_rect.y() / clamp_geom_rect.height(); 1433 float vertex_tex_scale_x = tile_rect.width() / clamp_geom_rect.width(); 1434 float vertex_tex_scale_y = tile_rect.height() / clamp_geom_rect.height(); 1435 1436 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1437 gl_, &highp_threshold_cache_, highp_threshold_min_, quad->texture_size); 1438 1439 gfx::Transform device_transform = 1440 frame->window_matrix * frame->projection_matrix * quad->quadTransform(); 1441 device_transform.FlattenTo2d(); 1442 if (!device_transform.IsInvertible()) 1443 return; 1444 1445 gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); 1446 float edge[24]; 1447 bool use_aa = 1448 settings_->allow_antialiasing && 1449 SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge); 1450 1451 bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f); 1452 GLenum filter = (use_aa || scaled || 1453 !quad->quadTransform().IsIdentityOrIntegerTranslation()) 1454 ? GL_LINEAR 1455 : GL_NEAREST; 1456 ResourceProvider::ScopedSamplerGL quad_resource_lock( 1457 resource_provider_, resource_id, filter); 1458 SamplerType sampler = 1459 SamplerTypeFromTextureTarget(quad_resource_lock.target()); 1460 1461 float fragment_tex_translate_x = clamp_tex_rect.x(); 1462 float fragment_tex_translate_y = clamp_tex_rect.y(); 1463 float fragment_tex_scale_x = clamp_tex_rect.width(); 1464 float fragment_tex_scale_y = clamp_tex_rect.height(); 1465 1466 // Map to normalized texture coordinates. 1467 if (sampler != SamplerType2DRect) { 1468 gfx::Size texture_size = quad->texture_size; 1469 DCHECK(!texture_size.IsEmpty()); 1470 fragment_tex_translate_x /= texture_size.width(); 1471 fragment_tex_translate_y /= texture_size.height(); 1472 fragment_tex_scale_x /= texture_size.width(); 1473 fragment_tex_scale_y /= texture_size.height(); 1474 } 1475 1476 TileProgramUniforms uniforms; 1477 if (use_aa) { 1478 if (quad->swizzle_contents) { 1479 TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision, sampler), 1480 &uniforms); 1481 } else { 1482 TileUniformLocation(GetTileProgramAA(tex_coord_precision, sampler), 1483 &uniforms); 1484 } 1485 } else { 1486 if (quad->ShouldDrawWithBlending()) { 1487 if (quad->swizzle_contents) { 1488 TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision, sampler), 1489 &uniforms); 1490 } else { 1491 TileUniformLocation(GetTileProgram(tex_coord_precision, sampler), 1492 &uniforms); 1493 } 1494 } else { 1495 if (quad->swizzle_contents) { 1496 TileUniformLocation( 1497 GetTileProgramSwizzleOpaque(tex_coord_precision, sampler), 1498 &uniforms); 1499 } else { 1500 TileUniformLocation(GetTileProgramOpaque(tex_coord_precision, sampler), 1501 &uniforms); 1502 } 1503 } 1504 } 1505 1506 SetUseProgram(uniforms.program); 1507 GLC(gl_, gl_->Uniform1i(uniforms.sampler_location, 0)); 1508 1509 if (use_aa) { 1510 float viewport[4] = {static_cast<float>(viewport_.x()), 1511 static_cast<float>(viewport_.y()), 1512 static_cast<float>(viewport_.width()), 1513 static_cast<float>(viewport_.height()), }; 1514 GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport)); 1515 GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge)); 1516 1517 GLC(gl_, 1518 gl_->Uniform4f(uniforms.vertex_tex_transform_location, 1519 vertex_tex_translate_x, 1520 vertex_tex_translate_y, 1521 vertex_tex_scale_x, 1522 vertex_tex_scale_y)); 1523 GLC(gl_, 1524 gl_->Uniform4f(uniforms.fragment_tex_transform_location, 1525 fragment_tex_translate_x, 1526 fragment_tex_translate_y, 1527 fragment_tex_scale_x, 1528 fragment_tex_scale_y)); 1529 } else { 1530 // Move fragment shader transform to vertex shader. We can do this while 1531 // still producing correct results as fragment_tex_transform_location 1532 // should always be non-negative when tiles are transformed in a way 1533 // that could result in sampling outside the layer. 1534 vertex_tex_scale_x *= fragment_tex_scale_x; 1535 vertex_tex_scale_y *= fragment_tex_scale_y; 1536 vertex_tex_translate_x *= fragment_tex_scale_x; 1537 vertex_tex_translate_y *= fragment_tex_scale_y; 1538 vertex_tex_translate_x += fragment_tex_translate_x; 1539 vertex_tex_translate_y += fragment_tex_translate_y; 1540 1541 GLC(gl_, 1542 gl_->Uniform4f(uniforms.vertex_tex_transform_location, 1543 vertex_tex_translate_x, 1544 vertex_tex_translate_y, 1545 vertex_tex_scale_x, 1546 vertex_tex_scale_y)); 1547 } 1548 1549 // Enable blending when the quad properties require it or if we decided 1550 // to use antialiasing. 1551 SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa); 1552 1553 // Normalize to tile_rect. 1554 local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); 1555 1556 SetShaderOpacity(quad->opacity(), uniforms.alpha_location); 1557 SetShaderQuadF(local_quad, uniforms.quad_location); 1558 1559 // The transform and vertex data are used to figure out the extents that the 1560 // un-antialiased quad should have and which vertex this is and the float 1561 // quad passed in via uniform is the actual geometry that gets used to draw 1562 // it. This is why this centered rect is used and not the original quad_rect. 1563 gfx::RectF centered_rect( 1564 gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()), 1565 tile_rect.size()); 1566 DrawQuadGeometry( 1567 frame, quad->quadTransform(), centered_rect, uniforms.matrix_location); 1568 } 1569 1570 void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, 1571 const YUVVideoDrawQuad* quad) { 1572 SetBlendEnabled(quad->ShouldDrawWithBlending()); 1573 1574 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1575 gl_, 1576 &highp_threshold_cache_, 1577 highp_threshold_min_, 1578 quad->shared_quad_state->visible_content_rect.bottom_right()); 1579 1580 bool use_alpha_plane = quad->a_plane_resource_id != 0; 1581 1582 ResourceProvider::ScopedSamplerGL y_plane_lock( 1583 resource_provider_, quad->y_plane_resource_id, GL_TEXTURE1, GL_LINEAR); 1584 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), y_plane_lock.target()); 1585 ResourceProvider::ScopedSamplerGL u_plane_lock( 1586 resource_provider_, quad->u_plane_resource_id, GL_TEXTURE2, GL_LINEAR); 1587 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), u_plane_lock.target()); 1588 ResourceProvider::ScopedSamplerGL v_plane_lock( 1589 resource_provider_, quad->v_plane_resource_id, GL_TEXTURE3, GL_LINEAR); 1590 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), v_plane_lock.target()); 1591 scoped_ptr<ResourceProvider::ScopedSamplerGL> a_plane_lock; 1592 if (use_alpha_plane) { 1593 a_plane_lock.reset(new ResourceProvider::ScopedSamplerGL( 1594 resource_provider_, quad->a_plane_resource_id, GL_TEXTURE4, GL_LINEAR)); 1595 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), a_plane_lock->target()); 1596 } 1597 1598 int tex_scale_location = -1; 1599 int matrix_location = -1; 1600 int y_texture_location = -1; 1601 int u_texture_location = -1; 1602 int v_texture_location = -1; 1603 int a_texture_location = -1; 1604 int yuv_matrix_location = -1; 1605 int yuv_adj_location = -1; 1606 int alpha_location = -1; 1607 if (use_alpha_plane) { 1608 const VideoYUVAProgram* program = GetVideoYUVAProgram(tex_coord_precision); 1609 DCHECK(program && (program->initialized() || IsContextLost())); 1610 SetUseProgram(program->program()); 1611 tex_scale_location = program->vertex_shader().tex_scale_location(); 1612 matrix_location = program->vertex_shader().matrix_location(); 1613 y_texture_location = program->fragment_shader().y_texture_location(); 1614 u_texture_location = program->fragment_shader().u_texture_location(); 1615 v_texture_location = program->fragment_shader().v_texture_location(); 1616 a_texture_location = program->fragment_shader().a_texture_location(); 1617 yuv_matrix_location = program->fragment_shader().yuv_matrix_location(); 1618 yuv_adj_location = program->fragment_shader().yuv_adj_location(); 1619 alpha_location = program->fragment_shader().alpha_location(); 1620 } else { 1621 const VideoYUVProgram* program = GetVideoYUVProgram(tex_coord_precision); 1622 DCHECK(program && (program->initialized() || IsContextLost())); 1623 SetUseProgram(program->program()); 1624 tex_scale_location = program->vertex_shader().tex_scale_location(); 1625 matrix_location = program->vertex_shader().matrix_location(); 1626 y_texture_location = program->fragment_shader().y_texture_location(); 1627 u_texture_location = program->fragment_shader().u_texture_location(); 1628 v_texture_location = program->fragment_shader().v_texture_location(); 1629 yuv_matrix_location = program->fragment_shader().yuv_matrix_location(); 1630 yuv_adj_location = program->fragment_shader().yuv_adj_location(); 1631 alpha_location = program->fragment_shader().alpha_location(); 1632 } 1633 1634 GLC(gl_, 1635 gl_->Uniform2f(tex_scale_location, 1636 quad->tex_scale.width(), 1637 quad->tex_scale.height())); 1638 GLC(gl_, gl_->Uniform1i(y_texture_location, 1)); 1639 GLC(gl_, gl_->Uniform1i(u_texture_location, 2)); 1640 GLC(gl_, gl_->Uniform1i(v_texture_location, 3)); 1641 if (use_alpha_plane) 1642 GLC(gl_, gl_->Uniform1i(a_texture_location, 4)); 1643 1644 // These values are magic numbers that are used in the transformation from YUV 1645 // to RGB color values. They are taken from the following webpage: 1646 // http://www.fourcc.org/fccyvrgb.php 1647 float yuv_to_rgb[9] = {1.164f, 1.164f, 1.164f, 0.0f, -.391f, 1648 2.018f, 1.596f, -.813f, 0.0f, }; 1649 GLC(gl_, gl_->UniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb)); 1650 1651 // These values map to 16, 128, and 128 respectively, and are computed 1652 // as a fraction over 256 (e.g. 16 / 256 = 0.0625). 1653 // They are used in the YUV to RGBA conversion formula: 1654 // Y - 16 : Gives 16 values of head and footroom for overshooting 1655 // U - 128 : Turns unsigned U into signed U [-128,127] 1656 // V - 128 : Turns unsigned V into signed V [-128,127] 1657 float yuv_adjust[3] = {-0.0625f, -0.5f, -0.5f, }; 1658 GLC(gl_, gl_->Uniform3fv(yuv_adj_location, 1, yuv_adjust)); 1659 1660 SetShaderOpacity(quad->opacity(), alpha_location); 1661 DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, matrix_location); 1662 } 1663 1664 void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame, 1665 const StreamVideoDrawQuad* quad) { 1666 SetBlendEnabled(quad->ShouldDrawWithBlending()); 1667 1668 static float gl_matrix[16]; 1669 1670 DCHECK(capabilities_.using_egl_image); 1671 1672 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1673 gl_, 1674 &highp_threshold_cache_, 1675 highp_threshold_min_, 1676 quad->shared_quad_state->visible_content_rect.bottom_right()); 1677 1678 const VideoStreamTextureProgram* program = 1679 GetVideoStreamTextureProgram(tex_coord_precision); 1680 SetUseProgram(program->program()); 1681 1682 ToGLMatrix(&gl_matrix[0], quad->matrix); 1683 GLC(gl_, 1684 gl_->UniformMatrix4fv( 1685 program->vertex_shader().tex_matrix_location(), 1, false, gl_matrix)); 1686 1687 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 1688 quad->resource_id); 1689 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 1690 GLC(gl_, gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id())); 1691 1692 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 1693 1694 SetShaderOpacity(quad->opacity(), 1695 program->fragment_shader().alpha_location()); 1696 DrawQuadGeometry(frame, 1697 quad->quadTransform(), 1698 quad->rect, 1699 program->vertex_shader().matrix_location()); 1700 } 1701 1702 void GLRenderer::DrawPictureQuad(const DrawingFrame* frame, 1703 const PictureDrawQuad* quad) { 1704 if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() || 1705 on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) { 1706 on_demand_tile_raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config, 1707 quad->texture_size.width(), 1708 quad->texture_size.height()); 1709 on_demand_tile_raster_bitmap_.allocPixels(); 1710 1711 if (on_demand_tile_raster_resource_id_) 1712 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); 1713 1714 on_demand_tile_raster_resource_id_ = 1715 resource_provider_->CreateGLTexture(quad->texture_size, 1716 GL_TEXTURE_2D, 1717 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM, 1718 GL_CLAMP_TO_EDGE, 1719 ResourceProvider::TextureUsageAny, 1720 quad->texture_format); 1721 } 1722 1723 SkBitmapDevice device(on_demand_tile_raster_bitmap_); 1724 SkCanvas canvas(&device); 1725 1726 quad->picture_pile->RasterToBitmap( 1727 &canvas, quad->content_rect, quad->contents_scale, NULL); 1728 1729 uint8_t* bitmap_pixels = NULL; 1730 SkBitmap on_demand_tile_raster_bitmap_dest; 1731 SkBitmap::Config config = SkBitmapConfig(quad->texture_format); 1732 if (on_demand_tile_raster_bitmap_.getConfig() != config) { 1733 on_demand_tile_raster_bitmap_.copyTo(&on_demand_tile_raster_bitmap_dest, 1734 config); 1735 // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the 1736 // bitmap data. This check will be removed once crbug.com/293728 is fixed. 1737 CHECK_EQ(0u, on_demand_tile_raster_bitmap_dest.rowBytes() % 4); 1738 bitmap_pixels = reinterpret_cast<uint8_t*>( 1739 on_demand_tile_raster_bitmap_dest.getPixels()); 1740 } else { 1741 bitmap_pixels = 1742 reinterpret_cast<uint8_t*>(on_demand_tile_raster_bitmap_.getPixels()); 1743 } 1744 1745 resource_provider_->SetPixels(on_demand_tile_raster_resource_id_, 1746 bitmap_pixels, 1747 gfx::Rect(quad->texture_size), 1748 gfx::Rect(quad->texture_size), 1749 gfx::Vector2d()); 1750 1751 DrawContentQuad(frame, quad, on_demand_tile_raster_resource_id_); 1752 } 1753 1754 struct TextureProgramBinding { 1755 template <class Program> 1756 void Set(Program* program) { 1757 DCHECK(program); 1758 program_id = program->program(); 1759 sampler_location = program->fragment_shader().sampler_location(); 1760 matrix_location = program->vertex_shader().matrix_location(); 1761 background_color_location = 1762 program->fragment_shader().background_color_location(); 1763 } 1764 int program_id; 1765 int sampler_location; 1766 int matrix_location; 1767 int background_color_location; 1768 }; 1769 1770 struct TexTransformTextureProgramBinding : TextureProgramBinding { 1771 template <class Program> 1772 void Set(Program* program) { 1773 TextureProgramBinding::Set(program); 1774 tex_transform_location = program->vertex_shader().tex_transform_location(); 1775 vertex_opacity_location = 1776 program->vertex_shader().vertex_opacity_location(); 1777 } 1778 int tex_transform_location; 1779 int vertex_opacity_location; 1780 }; 1781 1782 void GLRenderer::FlushTextureQuadCache() { 1783 // Check to see if we have anything to draw. 1784 if (draw_cache_.program_id == 0) 1785 return; 1786 1787 // Set the correct blending mode. 1788 SetBlendEnabled(draw_cache_.needs_blending); 1789 1790 // Bind the program to the GL state. 1791 SetUseProgram(draw_cache_.program_id); 1792 1793 // Bind the correct texture sampler location. 1794 GLC(gl_, gl_->Uniform1i(draw_cache_.sampler_location, 0)); 1795 1796 // Assume the current active textures is 0. 1797 ResourceProvider::ScopedReadLockGL locked_quad(resource_provider_, 1798 draw_cache_.resource_id); 1799 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 1800 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, locked_quad.texture_id())); 1801 1802 COMPILE_ASSERT(sizeof(Float4) == 4 * sizeof(float), // NOLINT(runtime/sizeof) 1803 struct_is_densely_packed); 1804 COMPILE_ASSERT( 1805 sizeof(Float16) == 16 * sizeof(float), // NOLINT(runtime/sizeof) 1806 struct_is_densely_packed); 1807 1808 // Upload the tranforms for both points and uvs. 1809 GLC(gl_, 1810 gl_->UniformMatrix4fv( 1811 static_cast<int>(draw_cache_.matrix_location), 1812 static_cast<int>(draw_cache_.matrix_data.size()), 1813 false, 1814 reinterpret_cast<float*>(&draw_cache_.matrix_data.front()))); 1815 GLC(gl_, 1816 gl_->Uniform4fv( 1817 static_cast<int>(draw_cache_.uv_xform_location), 1818 static_cast<int>(draw_cache_.uv_xform_data.size()), 1819 reinterpret_cast<float*>(&draw_cache_.uv_xform_data.front()))); 1820 1821 if (draw_cache_.background_color != SK_ColorTRANSPARENT) { 1822 Float4 background_color = PremultipliedColor(draw_cache_.background_color); 1823 GLC(gl_, 1824 gl_->Uniform4fv( 1825 draw_cache_.background_color_location, 1, background_color.data)); 1826 } 1827 1828 GLC(gl_, 1829 gl_->Uniform1fv( 1830 static_cast<int>(draw_cache_.vertex_opacity_location), 1831 static_cast<int>(draw_cache_.vertex_opacity_data.size()), 1832 static_cast<float*>(&draw_cache_.vertex_opacity_data.front()))); 1833 1834 // Draw the quads! 1835 GLC(gl_, 1836 gl_->DrawElements(GL_TRIANGLES, 1837 6 * draw_cache_.matrix_data.size(), 1838 GL_UNSIGNED_SHORT, 1839 0)); 1840 1841 // Clear the cache. 1842 draw_cache_.program_id = 0; 1843 draw_cache_.uv_xform_data.resize(0); 1844 draw_cache_.vertex_opacity_data.resize(0); 1845 draw_cache_.matrix_data.resize(0); 1846 } 1847 1848 void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, 1849 const TextureDrawQuad* quad) { 1850 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1851 gl_, 1852 &highp_threshold_cache_, 1853 highp_threshold_min_, 1854 quad->shared_quad_state->visible_content_rect.bottom_right()); 1855 1856 // Choose the correct texture program binding 1857 TexTransformTextureProgramBinding binding; 1858 if (quad->premultiplied_alpha) { 1859 if (quad->background_color == SK_ColorTRANSPARENT) { 1860 binding.Set(GetTextureProgram(tex_coord_precision)); 1861 } else { 1862 binding.Set(GetTextureBackgroundProgram(tex_coord_precision)); 1863 } 1864 } else { 1865 if (quad->background_color == SK_ColorTRANSPARENT) { 1866 binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision)); 1867 } else { 1868 binding.Set( 1869 GetNonPremultipliedTextureBackgroundProgram(tex_coord_precision)); 1870 } 1871 } 1872 1873 int resource_id = quad->resource_id; 1874 1875 if (draw_cache_.program_id != binding.program_id || 1876 draw_cache_.resource_id != resource_id || 1877 draw_cache_.needs_blending != quad->ShouldDrawWithBlending() || 1878 draw_cache_.background_color != quad->background_color || 1879 draw_cache_.matrix_data.size() >= 8) { 1880 FlushTextureQuadCache(); 1881 draw_cache_.program_id = binding.program_id; 1882 draw_cache_.resource_id = resource_id; 1883 draw_cache_.needs_blending = quad->ShouldDrawWithBlending(); 1884 draw_cache_.background_color = quad->background_color; 1885 1886 draw_cache_.uv_xform_location = binding.tex_transform_location; 1887 draw_cache_.background_color_location = binding.background_color_location; 1888 draw_cache_.vertex_opacity_location = binding.vertex_opacity_location; 1889 draw_cache_.matrix_location = binding.matrix_location; 1890 draw_cache_.sampler_location = binding.sampler_location; 1891 } 1892 1893 // Generate the uv-transform 1894 draw_cache_.uv_xform_data.push_back(UVTransform(quad)); 1895 1896 // Generate the vertex opacity 1897 const float opacity = quad->opacity(); 1898 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[0] * opacity); 1899 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[1] * opacity); 1900 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[2] * opacity); 1901 draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[3] * opacity); 1902 1903 // Generate the transform matrix 1904 gfx::Transform quad_rect_matrix; 1905 QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); 1906 quad_rect_matrix = frame->projection_matrix * quad_rect_matrix; 1907 1908 Float16 m; 1909 quad_rect_matrix.matrix().asColMajorf(m.data); 1910 draw_cache_.matrix_data.push_back(m); 1911 } 1912 1913 void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame, 1914 const IOSurfaceDrawQuad* quad) { 1915 SetBlendEnabled(quad->ShouldDrawWithBlending()); 1916 1917 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 1918 gl_, 1919 &highp_threshold_cache_, 1920 highp_threshold_min_, 1921 quad->shared_quad_state->visible_content_rect.bottom_right()); 1922 1923 TexTransformTextureProgramBinding binding; 1924 binding.Set(GetTextureIOSurfaceProgram(tex_coord_precision)); 1925 1926 SetUseProgram(binding.program_id); 1927 GLC(gl_, gl_->Uniform1i(binding.sampler_location, 0)); 1928 if (quad->orientation == IOSurfaceDrawQuad::FLIPPED) { 1929 GLC(gl_, 1930 gl_->Uniform4f(binding.tex_transform_location, 1931 0, 1932 quad->io_surface_size.height(), 1933 quad->io_surface_size.width(), 1934 quad->io_surface_size.height() * -1.0f)); 1935 } else { 1936 GLC(gl_, 1937 gl_->Uniform4f(binding.tex_transform_location, 1938 0, 1939 0, 1940 quad->io_surface_size.width(), 1941 quad->io_surface_size.height())); 1942 } 1943 1944 const float vertex_opacity[] = {quad->opacity(), quad->opacity(), 1945 quad->opacity(), quad->opacity()}; 1946 GLC(gl_, gl_->Uniform1fv(binding.vertex_opacity_location, 4, vertex_opacity)); 1947 1948 ResourceProvider::ScopedReadLockGL lock(resource_provider_, 1949 quad->io_surface_resource_id); 1950 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 1951 GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, lock.texture_id())); 1952 1953 DrawQuadGeometry( 1954 frame, quad->quadTransform(), quad->rect, binding.matrix_location); 1955 1956 GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, 0)); 1957 } 1958 1959 void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) { 1960 current_framebuffer_lock_.reset(); 1961 swap_buffer_rect_.Union(gfx::ToEnclosingRect(frame->root_damage_rect)); 1962 1963 GLC(gl_, gl_->Disable(GL_BLEND)); 1964 blend_shadow_ = false; 1965 } 1966 1967 void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); } 1968 1969 bool GLRenderer::FlippedFramebuffer() const { return true; } 1970 1971 void GLRenderer::EnsureScissorTestEnabled() { 1972 if (is_scissor_enabled_) 1973 return; 1974 1975 FlushTextureQuadCache(); 1976 GLC(gl_, gl_->Enable(GL_SCISSOR_TEST)); 1977 is_scissor_enabled_ = true; 1978 } 1979 1980 void GLRenderer::EnsureScissorTestDisabled() { 1981 if (!is_scissor_enabled_) 1982 return; 1983 1984 FlushTextureQuadCache(); 1985 GLC(gl_, gl_->Disable(GL_SCISSOR_TEST)); 1986 is_scissor_enabled_ = false; 1987 } 1988 1989 void GLRenderer::CopyCurrentRenderPassToBitmap( 1990 DrawingFrame* frame, 1991 scoped_ptr<CopyOutputRequest> request) { 1992 gfx::Rect copy_rect = frame->current_render_pass->output_rect; 1993 if (request->has_area()) 1994 copy_rect.Intersect(request->area()); 1995 GetFramebufferPixelsAsync(copy_rect, request.Pass()); 1996 } 1997 1998 void GLRenderer::ToGLMatrix(float* gl_matrix, const gfx::Transform& transform) { 1999 transform.matrix().asColMajorf(gl_matrix); 2000 } 2001 2002 void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad, int quad_location) { 2003 if (quad_location == -1) 2004 return; 2005 2006 float gl_quad[8]; 2007 gl_quad[0] = quad.p1().x(); 2008 gl_quad[1] = quad.p1().y(); 2009 gl_quad[2] = quad.p2().x(); 2010 gl_quad[3] = quad.p2().y(); 2011 gl_quad[4] = quad.p3().x(); 2012 gl_quad[5] = quad.p3().y(); 2013 gl_quad[6] = quad.p4().x(); 2014 gl_quad[7] = quad.p4().y(); 2015 GLC(gl_, gl_->Uniform2fv(quad_location, 4, gl_quad)); 2016 } 2017 2018 void GLRenderer::SetShaderOpacity(float opacity, int alpha_location) { 2019 if (alpha_location != -1) 2020 GLC(gl_, gl_->Uniform1f(alpha_location, opacity)); 2021 } 2022 2023 void GLRenderer::SetStencilEnabled(bool enabled) { 2024 if (enabled == stencil_shadow_) 2025 return; 2026 2027 if (enabled) 2028 GLC(gl_, gl_->Enable(GL_STENCIL_TEST)); 2029 else 2030 GLC(gl_, gl_->Disable(GL_STENCIL_TEST)); 2031 stencil_shadow_ = enabled; 2032 } 2033 2034 void GLRenderer::SetBlendEnabled(bool enabled) { 2035 if (enabled == blend_shadow_) 2036 return; 2037 2038 if (enabled) 2039 GLC(gl_, gl_->Enable(GL_BLEND)); 2040 else 2041 GLC(gl_, gl_->Disable(GL_BLEND)); 2042 blend_shadow_ = enabled; 2043 } 2044 2045 void GLRenderer::SetUseProgram(unsigned program) { 2046 if (program == program_shadow_) 2047 return; 2048 gl_->UseProgram(program); 2049 program_shadow_ = program; 2050 } 2051 2052 void GLRenderer::DrawQuadGeometry(const DrawingFrame* frame, 2053 const gfx::Transform& draw_transform, 2054 const gfx::RectF& quad_rect, 2055 int matrix_location) { 2056 gfx::Transform quad_rect_matrix; 2057 QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect); 2058 static float gl_matrix[16]; 2059 ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad_rect_matrix); 2060 GLC(gl_, gl_->UniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0])); 2061 2062 GLC(gl_, gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0)); 2063 } 2064 2065 void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame* frame, 2066 int texture_id, 2067 gfx::Rect rect, 2068 const gfx::Transform& draw_matrix, 2069 bool flip_vertically) { 2070 TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( 2071 gl_, &highp_threshold_cache_, highp_threshold_min_, rect.bottom_right()); 2072 2073 const RenderPassProgram* program = GetRenderPassProgram(tex_coord_precision); 2074 SetUseProgram(program->program()); 2075 2076 GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); 2077 2078 if (flip_vertically) { 2079 GLC(gl_, 2080 gl_->Uniform4f(program->vertex_shader().tex_transform_location(), 2081 0.f, 2082 1.f, 2083 1.f, 2084 -1.f)); 2085 } else { 2086 GLC(gl_, 2087 gl_->Uniform4f(program->vertex_shader().tex_transform_location(), 2088 0.f, 2089 0.f, 2090 1.f, 2091 1.f)); 2092 } 2093 2094 SetShaderOpacity(1.f, program->fragment_shader().alpha_location()); 2095 DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(gl_)); 2096 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id)); 2097 DrawQuadGeometry( 2098 frame, draw_matrix, rect, program->vertex_shader().matrix_location()); 2099 } 2100 2101 void GLRenderer::Finish() { 2102 TRACE_EVENT0("cc", "GLRenderer::Finish"); 2103 GLC(gl_, gl_->Finish()); 2104 } 2105 2106 void GLRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) { 2107 DCHECK(!is_backbuffer_discarded_); 2108 2109 TRACE_EVENT0("cc", "GLRenderer::SwapBuffers"); 2110 // We're done! Time to swapbuffers! 2111 2112 gfx::Size surface_size = output_surface_->SurfaceSize(); 2113 2114 CompositorFrame compositor_frame; 2115 compositor_frame.metadata = metadata; 2116 compositor_frame.gl_frame_data = make_scoped_ptr(new GLFrameData); 2117 compositor_frame.gl_frame_data->size = surface_size; 2118 if (capabilities_.using_partial_swap) { 2119 // If supported, we can save significant bandwidth by only swapping the 2120 // damaged/scissored region (clamped to the viewport). 2121 swap_buffer_rect_.Intersect(gfx::Rect(surface_size)); 2122 int flipped_y_pos_of_rect_bottom = surface_size.height() - 2123 swap_buffer_rect_.y() - 2124 swap_buffer_rect_.height(); 2125 compositor_frame.gl_frame_data->sub_buffer_rect = 2126 gfx::Rect(swap_buffer_rect_.x(), 2127 flipped_y_pos_of_rect_bottom, 2128 swap_buffer_rect_.width(), 2129 swap_buffer_rect_.height()); 2130 } else { 2131 compositor_frame.gl_frame_data->sub_buffer_rect = 2132 gfx::Rect(output_surface_->SurfaceSize()); 2133 } 2134 output_surface_->SwapBuffers(&compositor_frame); 2135 2136 swap_buffer_rect_ = gfx::Rect(); 2137 2138 // We don't have real fences, so we mark read fences as passed 2139 // assuming a double-buffered GPU pipeline. A texture can be 2140 // written to after one full frame has past since it was last read. 2141 if (last_swap_fence_.get()) 2142 static_cast<SimpleSwapFence*>(last_swap_fence_.get())->SetHasPassed(); 2143 last_swap_fence_ = resource_provider_->GetReadLockFence(); 2144 resource_provider_->SetReadLockFence(new SimpleSwapFence()); 2145 } 2146 2147 void GLRenderer::EnforceMemoryPolicy() { 2148 if (!visible_) { 2149 TRACE_EVENT0("cc", "GLRenderer::EnforceMemoryPolicy dropping resources"); 2150 ReleaseRenderPassTextures(); 2151 DiscardBackbuffer(); 2152 resource_provider_->ReleaseCachedData(); 2153 GLC(gl_, gl_->Flush()); 2154 } 2155 } 2156 2157 void GLRenderer::DiscardBackbuffer() { 2158 if (is_backbuffer_discarded_) 2159 return; 2160 2161 output_surface_->DiscardBackbuffer(); 2162 2163 is_backbuffer_discarded_ = true; 2164 2165 // Damage tracker needs a full reset every time framebuffer is discarded. 2166 client_->SetFullRootLayerDamage(); 2167 } 2168 2169 void GLRenderer::EnsureBackbuffer() { 2170 if (!is_backbuffer_discarded_) 2171 return; 2172 2173 output_surface_->EnsureBackbuffer(); 2174 is_backbuffer_discarded_ = false; 2175 } 2176 2177 void GLRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) { 2178 if (!pixels || rect.IsEmpty()) 2179 return; 2180 2181 // This function assumes that it is reading the root frame buffer. 2182 DCHECK(!current_framebuffer_lock_); 2183 2184 scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels); 2185 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), 2186 pending_read.Pass()); 2187 2188 // This is a syncronous call since the callback is null. 2189 gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect); 2190 DoGetFramebufferPixels(static_cast<uint8*>(pixels), 2191 window_rect, 2192 AsyncGetFramebufferPixelsCleanupCallback()); 2193 } 2194 2195 void GLRenderer::GetFramebufferPixelsAsync( 2196 gfx::Rect rect, 2197 scoped_ptr<CopyOutputRequest> request) { 2198 DCHECK(!request->IsEmpty()); 2199 if (request->IsEmpty()) 2200 return; 2201 if (rect.IsEmpty()) 2202 return; 2203 2204 gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect); 2205 2206 if (!request->force_bitmap_result()) { 2207 bool own_mailbox = !request->has_texture_mailbox(); 2208 2209 GLuint texture_id = 0; 2210 gl_->GenTextures(1, &texture_id); 2211 2212 gpu::Mailbox mailbox; 2213 if (own_mailbox) { 2214 GLC(gl_, gl_->GenMailboxCHROMIUM(mailbox.name)); 2215 if (mailbox.IsZero()) { 2216 gl_->DeleteTextures(1, &texture_id); 2217 request->SendEmptyResult(); 2218 return; 2219 } 2220 } else { 2221 mailbox = request->texture_mailbox().name(); 2222 DCHECK_EQ(static_cast<unsigned>(GL_TEXTURE_2D), 2223 request->texture_mailbox().target()); 2224 DCHECK(!mailbox.IsZero()); 2225 unsigned incoming_sync_point = request->texture_mailbox().sync_point(); 2226 if (incoming_sync_point) 2227 GLC(gl_, gl_->WaitSyncPointCHROMIUM(incoming_sync_point)); 2228 } 2229 2230 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id)); 2231 if (own_mailbox) { 2232 GLC(gl_, 2233 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2234 GLC(gl_, 2235 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2236 GLC(gl_, 2237 gl_->TexParameteri( 2238 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 2239 GLC(gl_, 2240 gl_->TexParameteri( 2241 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 2242 GLC(gl_, gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name)); 2243 } else { 2244 GLC(gl_, gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name)); 2245 } 2246 GetFramebufferTexture(texture_id, RGBA_8888, window_rect); 2247 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0)); 2248 2249 unsigned sync_point = gl_->InsertSyncPointCHROMIUM(); 2250 TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, sync_point); 2251 2252 scoped_ptr<SingleReleaseCallback> release_callback; 2253 if (own_mailbox) { 2254 release_callback = texture_mailbox_deleter_->GetReleaseCallback( 2255 output_surface_->context_provider(), texture_id); 2256 } else { 2257 gl_->DeleteTextures(1, &texture_id); 2258 } 2259 2260 request->SendTextureResult( 2261 window_rect.size(), texture_mailbox, release_callback.Pass()); 2262 return; 2263 } 2264 2265 DCHECK(request->force_bitmap_result()); 2266 2267 scoped_ptr<SkBitmap> bitmap(new SkBitmap); 2268 bitmap->setConfig( 2269 SkBitmap::kARGB_8888_Config, window_rect.width(), window_rect.height()); 2270 bitmap->allocPixels(); 2271 2272 scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap)); 2273 2274 // Save a pointer to the pixels, the bitmap is owned by the cleanup_callback. 2275 uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); 2276 2277 AsyncGetFramebufferPixelsCleanupCallback cleanup_callback = 2278 base::Bind(&GLRenderer::PassOnSkBitmap, 2279 base::Unretained(this), 2280 base::Passed(&bitmap), 2281 base::Passed(&lock)); 2282 2283 scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels); 2284 pending_read->copy_request = request.Pass(); 2285 pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(), 2286 pending_read.Pass()); 2287 2288 // This is an asyncronous call since the callback is not null. 2289 DoGetFramebufferPixels(pixels, window_rect, cleanup_callback); 2290 } 2291 2292 void GLRenderer::DoGetFramebufferPixels( 2293 uint8* dest_pixels, 2294 gfx::Rect window_rect, 2295 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback) { 2296 DCHECK_GE(window_rect.x(), 0); 2297 DCHECK_GE(window_rect.y(), 0); 2298 DCHECK_LE(window_rect.right(), current_surface_size_.width()); 2299 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); 2300 2301 bool is_async = !cleanup_callback.is_null(); 2302 2303 bool do_workaround = NeedsIOSurfaceReadbackWorkaround(); 2304 2305 unsigned temporary_texture = 0; 2306 unsigned temporary_fbo = 0; 2307 2308 if (do_workaround) { 2309 // On Mac OS X, calling glReadPixels() against an FBO whose color attachment 2310 // is an IOSurface-backed texture causes corruption of future glReadPixels() 2311 // calls, even those on different OpenGL contexts. It is believed that this 2312 // is the root cause of top crasher 2313 // http://crbug.com/99393. <rdar://problem/10949687> 2314 2315 gl_->GenTextures(1, &temporary_texture); 2316 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, temporary_texture)); 2317 GLC(gl_, 2318 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); 2319 GLC(gl_, 2320 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 2321 GLC(gl_, 2322 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); 2323 GLC(gl_, 2324 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); 2325 // Copy the contents of the current (IOSurface-backed) framebuffer into a 2326 // temporary texture. 2327 GetFramebufferTexture( 2328 temporary_texture, RGBA_8888, gfx::Rect(current_surface_size_)); 2329 gl_->GenFramebuffers(1, &temporary_fbo); 2330 // Attach this texture to an FBO, and perform the readback from that FBO. 2331 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, temporary_fbo)); 2332 GLC(gl_, 2333 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, 2334 GL_COLOR_ATTACHMENT0, 2335 GL_TEXTURE_2D, 2336 temporary_texture, 2337 0)); 2338 2339 DCHECK_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE), 2340 gl_->CheckFramebufferStatus(GL_FRAMEBUFFER)); 2341 } 2342 2343 GLuint buffer = 0; 2344 gl_->GenBuffers(1, &buffer); 2345 GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, buffer)); 2346 GLC(gl_, 2347 gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 2348 4 * window_rect.size().GetArea(), 2349 NULL, 2350 GL_STREAM_READ)); 2351 2352 GLuint query = 0; 2353 if (is_async) { 2354 gl_->GenQueriesEXT(1, &query); 2355 GLC(gl_, gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, query)); 2356 } 2357 2358 GLC(gl_, 2359 gl_->ReadPixels(window_rect.x(), 2360 window_rect.y(), 2361 window_rect.width(), 2362 window_rect.height(), 2363 GL_RGBA, 2364 GL_UNSIGNED_BYTE, 2365 NULL)); 2366 2367 GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0)); 2368 2369 if (do_workaround) { 2370 // Clean up. 2371 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, 0)); 2372 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0)); 2373 GLC(gl_, gl_->DeleteFramebuffers(1, &temporary_fbo)); 2374 GLC(gl_, gl_->DeleteTextures(1, &temporary_texture)); 2375 } 2376 2377 base::Closure finished_callback = base::Bind(&GLRenderer::FinishedReadback, 2378 base::Unretained(this), 2379 cleanup_callback, 2380 buffer, 2381 query, 2382 dest_pixels, 2383 window_rect.size()); 2384 // Save the finished_callback so it can be cancelled. 2385 pending_async_read_pixels_.front()->finished_read_pixels_callback.Reset( 2386 finished_callback); 2387 2388 // Save the buffer to verify the callbacks happen in the expected order. 2389 pending_async_read_pixels_.front()->buffer = buffer; 2390 2391 if (is_async) { 2392 GLC(gl_, gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM)); 2393 context_support_->SignalQuery(query, finished_callback); 2394 } else { 2395 resource_provider_->Finish(); 2396 finished_callback.Run(); 2397 } 2398 2399 EnforceMemoryPolicy(); 2400 } 2401 2402 void GLRenderer::FinishedReadback( 2403 const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback, 2404 unsigned source_buffer, 2405 unsigned query, 2406 uint8* dest_pixels, 2407 gfx::Size size) { 2408 DCHECK(!pending_async_read_pixels_.empty()); 2409 2410 if (query != 0) { 2411 GLC(gl_, gl_->DeleteQueriesEXT(1, &query)); 2412 } 2413 2414 PendingAsyncReadPixels* current_read = pending_async_read_pixels_.back(); 2415 // Make sure we service the readbacks in order. 2416 DCHECK_EQ(source_buffer, current_read->buffer); 2417 2418 uint8* src_pixels = NULL; 2419 2420 if (source_buffer != 0) { 2421 GLC(gl_, 2422 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, source_buffer)); 2423 src_pixels = static_cast<uint8*>(gl_->MapBufferCHROMIUM( 2424 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); 2425 2426 if (src_pixels) { 2427 size_t row_bytes = size.width() * 4; 2428 int num_rows = size.height(); 2429 size_t total_bytes = num_rows * row_bytes; 2430 for (size_t dest_y = 0; dest_y < total_bytes; dest_y += row_bytes) { 2431 // Flip Y axis. 2432 size_t src_y = total_bytes - dest_y - row_bytes; 2433 // Swizzle OpenGL -> Skia byte order. 2434 for (size_t x = 0; x < row_bytes; x += 4) { 2435 dest_pixels[dest_y + x + SK_R32_SHIFT / 8] = 2436 src_pixels[src_y + x + 0]; 2437 dest_pixels[dest_y + x + SK_G32_SHIFT / 8] = 2438 src_pixels[src_y + x + 1]; 2439 dest_pixels[dest_y + x + SK_B32_SHIFT / 8] = 2440 src_pixels[src_y + x + 2]; 2441 dest_pixels[dest_y + x + SK_A32_SHIFT / 8] = 2442 src_pixels[src_y + x + 3]; 2443 } 2444 } 2445 2446 GLC(gl_, 2447 gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM)); 2448 } 2449 GLC(gl_, gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0)); 2450 GLC(gl_, gl_->DeleteBuffers(1, &source_buffer)); 2451 } 2452 2453 // TODO(danakj): This can go away when synchronous readback is no more and its 2454 // contents can just move here. 2455 if (!cleanup_callback.is_null()) 2456 cleanup_callback.Run(current_read->copy_request.Pass(), src_pixels != NULL); 2457 2458 pending_async_read_pixels_.pop_back(); 2459 } 2460 2461 void GLRenderer::PassOnSkBitmap(scoped_ptr<SkBitmap> bitmap, 2462 scoped_ptr<SkAutoLockPixels> lock, 2463 scoped_ptr<CopyOutputRequest> request, 2464 bool success) { 2465 DCHECK(request->force_bitmap_result()); 2466 2467 lock.reset(); 2468 if (success) 2469 request->SendBitmapResult(bitmap.Pass()); 2470 } 2471 2472 void GLRenderer::GetFramebufferTexture(unsigned texture_id, 2473 ResourceFormat texture_format, 2474 gfx::Rect window_rect) { 2475 DCHECK(texture_id); 2476 DCHECK_GE(window_rect.x(), 0); 2477 DCHECK_GE(window_rect.y(), 0); 2478 DCHECK_LE(window_rect.right(), current_surface_size_.width()); 2479 DCHECK_LE(window_rect.bottom(), current_surface_size_.height()); 2480 2481 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, texture_id)); 2482 GLC(gl_, 2483 gl_->CopyTexImage2D(GL_TEXTURE_2D, 2484 0, 2485 GLDataFormat(texture_format), 2486 window_rect.x(), 2487 window_rect.y(), 2488 window_rect.width(), 2489 window_rect.height(), 2490 0)); 2491 GLC(gl_, gl_->BindTexture(GL_TEXTURE_2D, 0)); 2492 } 2493 2494 bool GLRenderer::UseScopedTexture(DrawingFrame* frame, 2495 const ScopedResource* texture, 2496 gfx::Rect viewport_rect) { 2497 DCHECK(texture->id()); 2498 frame->current_render_pass = NULL; 2499 frame->current_texture = texture; 2500 2501 return BindFramebufferToTexture(frame, texture, viewport_rect); 2502 } 2503 2504 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) { 2505 current_framebuffer_lock_.reset(); 2506 output_surface_->BindFramebuffer(); 2507 2508 if (output_surface_->HasExternalStencilTest()) { 2509 SetStencilEnabled(true); 2510 GLC(gl_, gl_->StencilFunc(GL_EQUAL, 1, 1)); 2511 } else { 2512 SetStencilEnabled(false); 2513 } 2514 } 2515 2516 bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame, 2517 const ScopedResource* texture, 2518 gfx::Rect target_rect) { 2519 DCHECK(texture->id()); 2520 2521 current_framebuffer_lock_.reset(); 2522 2523 SetStencilEnabled(false); 2524 GLC(gl_, gl_->BindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_)); 2525 current_framebuffer_lock_ = 2526 make_scoped_ptr(new ResourceProvider::ScopedWriteLockGL( 2527 resource_provider_, texture->id())); 2528 unsigned texture_id = current_framebuffer_lock_->texture_id(); 2529 GLC(gl_, 2530 gl_->FramebufferTexture2D( 2531 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0)); 2532 2533 DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) == 2534 GL_FRAMEBUFFER_COMPLETE || 2535 IsContextLost()); 2536 2537 InitializeViewport( 2538 frame, target_rect, gfx::Rect(target_rect.size()), target_rect.size()); 2539 return true; 2540 } 2541 2542 void GLRenderer::SetScissorTestRect(gfx::Rect scissor_rect) { 2543 EnsureScissorTestEnabled(); 2544 2545 // Don't unnecessarily ask the context to change the scissor, because it 2546 // may cause undesired GPU pipeline flushes. 2547 if (scissor_rect == scissor_rect_ && !scissor_rect_needs_reset_) 2548 return; 2549 2550 scissor_rect_ = scissor_rect; 2551 FlushTextureQuadCache(); 2552 GLC(gl_, 2553 gl_->Scissor(scissor_rect.x(), 2554 scissor_rect.y(), 2555 scissor_rect.width(), 2556 scissor_rect.height())); 2557 2558 scissor_rect_needs_reset_ = false; 2559 } 2560 2561 void GLRenderer::SetDrawViewport(gfx::Rect window_space_viewport) { 2562 viewport_ = window_space_viewport; 2563 GLC(gl_, 2564 gl_->Viewport(window_space_viewport.x(), 2565 window_space_viewport.y(), 2566 window_space_viewport.width(), 2567 window_space_viewport.height())); 2568 } 2569 2570 void GLRenderer::InitializeSharedObjects() { 2571 TRACE_EVENT0("cc", "GLRenderer::InitializeSharedObjects"); 2572 2573 // Create an FBO for doing offscreen rendering. 2574 GLC(gl_, gl_->GenFramebuffers(1, &offscreen_framebuffer_id_)); 2575 2576 shared_geometry_ = make_scoped_ptr( 2577 new GeometryBinding(gl_, QuadVertexRect())); 2578 } 2579 2580 const GLRenderer::TileCheckerboardProgram* 2581 GLRenderer::GetTileCheckerboardProgram() { 2582 if (!tile_checkerboard_program_.initialized()) { 2583 TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize"); 2584 tile_checkerboard_program_.Initialize(output_surface_->context_provider(), 2585 TexCoordPrecisionNA, 2586 SamplerTypeNA); 2587 } 2588 return &tile_checkerboard_program_; 2589 } 2590 2591 const GLRenderer::DebugBorderProgram* GLRenderer::GetDebugBorderProgram() { 2592 if (!debug_border_program_.initialized()) { 2593 TRACE_EVENT0("cc", "GLRenderer::debugBorderProgram::initialize"); 2594 debug_border_program_.Initialize(output_surface_->context_provider(), 2595 TexCoordPrecisionNA, 2596 SamplerTypeNA); 2597 } 2598 return &debug_border_program_; 2599 } 2600 2601 const GLRenderer::SolidColorProgram* GLRenderer::GetSolidColorProgram() { 2602 if (!solid_color_program_.initialized()) { 2603 TRACE_EVENT0("cc", "GLRenderer::solidColorProgram::initialize"); 2604 solid_color_program_.Initialize(output_surface_->context_provider(), 2605 TexCoordPrecisionNA, 2606 SamplerTypeNA); 2607 } 2608 return &solid_color_program_; 2609 } 2610 2611 const GLRenderer::SolidColorProgramAA* GLRenderer::GetSolidColorProgramAA() { 2612 if (!solid_color_program_aa_.initialized()) { 2613 TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize"); 2614 solid_color_program_aa_.Initialize(output_surface_->context_provider(), 2615 TexCoordPrecisionNA, 2616 SamplerTypeNA); 2617 } 2618 return &solid_color_program_aa_; 2619 } 2620 2621 const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram( 2622 TexCoordPrecision precision) { 2623 DCHECK_GE(precision, 0); 2624 DCHECK_LT(precision, NumTexCoordPrecisions); 2625 RenderPassProgram* program = &render_pass_program_[precision]; 2626 if (!program->initialized()) { 2627 TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize"); 2628 program->Initialize( 2629 output_surface_->context_provider(), precision, SamplerType2D); 2630 } 2631 return program; 2632 } 2633 2634 const GLRenderer::RenderPassProgramAA* GLRenderer::GetRenderPassProgramAA( 2635 TexCoordPrecision precision) { 2636 DCHECK_GE(precision, 0); 2637 DCHECK_LT(precision, NumTexCoordPrecisions); 2638 RenderPassProgramAA* program = &render_pass_program_aa_[precision]; 2639 if (!program->initialized()) { 2640 TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize"); 2641 program->Initialize( 2642 output_surface_->context_provider(), precision, SamplerType2D); 2643 } 2644 return program; 2645 } 2646 2647 const GLRenderer::RenderPassMaskProgram* GLRenderer::GetRenderPassMaskProgram( 2648 TexCoordPrecision precision) { 2649 DCHECK_GE(precision, 0); 2650 DCHECK_LT(precision, NumTexCoordPrecisions); 2651 RenderPassMaskProgram* program = &render_pass_mask_program_[precision]; 2652 if (!program->initialized()) { 2653 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize"); 2654 program->Initialize( 2655 output_surface_->context_provider(), precision, SamplerType2D); 2656 } 2657 return program; 2658 } 2659 2660 const GLRenderer::RenderPassMaskProgramAA* 2661 GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision) { 2662 DCHECK_GE(precision, 0); 2663 DCHECK_LT(precision, NumTexCoordPrecisions); 2664 RenderPassMaskProgramAA* program = &render_pass_mask_program_aa_[precision]; 2665 if (!program->initialized()) { 2666 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize"); 2667 program->Initialize( 2668 output_surface_->context_provider(), precision, SamplerType2D); 2669 } 2670 return program; 2671 } 2672 2673 const GLRenderer::RenderPassColorMatrixProgram* 2674 GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision) { 2675 DCHECK_GE(precision, 0); 2676 DCHECK_LT(precision, NumTexCoordPrecisions); 2677 RenderPassColorMatrixProgram* program = 2678 &render_pass_color_matrix_program_[precision]; 2679 if (!program->initialized()) { 2680 TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize"); 2681 program->Initialize( 2682 output_surface_->context_provider(), precision, SamplerType2D); 2683 } 2684 return program; 2685 } 2686 2687 const GLRenderer::RenderPassColorMatrixProgramAA* 2688 GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision) { 2689 DCHECK_GE(precision, 0); 2690 DCHECK_LT(precision, NumTexCoordPrecisions); 2691 RenderPassColorMatrixProgramAA* program = 2692 &render_pass_color_matrix_program_aa_[precision]; 2693 if (!program->initialized()) { 2694 TRACE_EVENT0("cc", 2695 "GLRenderer::renderPassColorMatrixProgramAA::initialize"); 2696 program->Initialize( 2697 output_surface_->context_provider(), precision, SamplerType2D); 2698 } 2699 return program; 2700 } 2701 2702 const GLRenderer::RenderPassMaskColorMatrixProgram* 2703 GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) { 2704 DCHECK_GE(precision, 0); 2705 DCHECK_LT(precision, NumTexCoordPrecisions); 2706 RenderPassMaskColorMatrixProgram* program = 2707 &render_pass_mask_color_matrix_program_[precision]; 2708 if (!program->initialized()) { 2709 TRACE_EVENT0("cc", 2710 "GLRenderer::renderPassMaskColorMatrixProgram::initialize"); 2711 program->Initialize( 2712 output_surface_->context_provider(), precision, SamplerType2D); 2713 } 2714 return program; 2715 } 2716 2717 const GLRenderer::RenderPassMaskColorMatrixProgramAA* 2718 GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) { 2719 DCHECK_GE(precision, 0); 2720 DCHECK_LT(precision, NumTexCoordPrecisions); 2721 RenderPassMaskColorMatrixProgramAA* program = 2722 &render_pass_mask_color_matrix_program_aa_[precision]; 2723 if (!program->initialized()) { 2724 TRACE_EVENT0("cc", 2725 "GLRenderer::renderPassMaskColorMatrixProgramAA::initialize"); 2726 program->Initialize( 2727 output_surface_->context_provider(), precision, SamplerType2D); 2728 } 2729 return program; 2730 } 2731 2732 const GLRenderer::TileProgram* GLRenderer::GetTileProgram( 2733 TexCoordPrecision precision, 2734 SamplerType sampler) { 2735 DCHECK_GE(precision, 0); 2736 DCHECK_LT(precision, NumTexCoordPrecisions); 2737 DCHECK_GE(sampler, 0); 2738 DCHECK_LT(sampler, NumSamplerTypes); 2739 TileProgram* program = &tile_program_[precision][sampler]; 2740 if (!program->initialized()) { 2741 TRACE_EVENT0("cc", "GLRenderer::tileProgram::initialize"); 2742 program->Initialize( 2743 output_surface_->context_provider(), precision, sampler); 2744 } 2745 return program; 2746 } 2747 2748 const GLRenderer::TileProgramOpaque* GLRenderer::GetTileProgramOpaque( 2749 TexCoordPrecision precision, 2750 SamplerType sampler) { 2751 DCHECK_GE(precision, 0); 2752 DCHECK_LT(precision, NumTexCoordPrecisions); 2753 DCHECK_GE(sampler, 0); 2754 DCHECK_LT(sampler, NumSamplerTypes); 2755 TileProgramOpaque* program = &tile_program_opaque_[precision][sampler]; 2756 if (!program->initialized()) { 2757 TRACE_EVENT0("cc", "GLRenderer::tileProgramOpaque::initialize"); 2758 program->Initialize( 2759 output_surface_->context_provider(), precision, sampler); 2760 } 2761 return program; 2762 } 2763 2764 const GLRenderer::TileProgramAA* GLRenderer::GetTileProgramAA( 2765 TexCoordPrecision precision, 2766 SamplerType sampler) { 2767 DCHECK_GE(precision, 0); 2768 DCHECK_LT(precision, NumTexCoordPrecisions); 2769 DCHECK_GE(sampler, 0); 2770 DCHECK_LT(sampler, NumSamplerTypes); 2771 TileProgramAA* program = &tile_program_aa_[precision][sampler]; 2772 if (!program->initialized()) { 2773 TRACE_EVENT0("cc", "GLRenderer::tileProgramAA::initialize"); 2774 program->Initialize( 2775 output_surface_->context_provider(), precision, sampler); 2776 } 2777 return program; 2778 } 2779 2780 const GLRenderer::TileProgramSwizzle* GLRenderer::GetTileProgramSwizzle( 2781 TexCoordPrecision precision, 2782 SamplerType sampler) { 2783 DCHECK_GE(precision, 0); 2784 DCHECK_LT(precision, NumTexCoordPrecisions); 2785 DCHECK_GE(sampler, 0); 2786 DCHECK_LT(sampler, NumSamplerTypes); 2787 TileProgramSwizzle* program = &tile_program_swizzle_[precision][sampler]; 2788 if (!program->initialized()) { 2789 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzle::initialize"); 2790 program->Initialize( 2791 output_surface_->context_provider(), precision, sampler); 2792 } 2793 return program; 2794 } 2795 2796 const GLRenderer::TileProgramSwizzleOpaque* 2797 GLRenderer::GetTileProgramSwizzleOpaque(TexCoordPrecision precision, 2798 SamplerType sampler) { 2799 DCHECK_GE(precision, 0); 2800 DCHECK_LT(precision, NumTexCoordPrecisions); 2801 DCHECK_GE(sampler, 0); 2802 DCHECK_LT(sampler, NumSamplerTypes); 2803 TileProgramSwizzleOpaque* program = 2804 &tile_program_swizzle_opaque_[precision][sampler]; 2805 if (!program->initialized()) { 2806 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleOpaque::initialize"); 2807 program->Initialize( 2808 output_surface_->context_provider(), precision, sampler); 2809 } 2810 return program; 2811 } 2812 2813 const GLRenderer::TileProgramSwizzleAA* GLRenderer::GetTileProgramSwizzleAA( 2814 TexCoordPrecision precision, 2815 SamplerType sampler) { 2816 DCHECK_GE(precision, 0); 2817 DCHECK_LT(precision, NumTexCoordPrecisions); 2818 DCHECK_GE(sampler, 0); 2819 DCHECK_LT(sampler, NumSamplerTypes); 2820 TileProgramSwizzleAA* program = &tile_program_swizzle_aa_[precision][sampler]; 2821 if (!program->initialized()) { 2822 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleAA::initialize"); 2823 program->Initialize( 2824 output_surface_->context_provider(), precision, sampler); 2825 } 2826 return program; 2827 } 2828 2829 const GLRenderer::TextureProgram* GLRenderer::GetTextureProgram( 2830 TexCoordPrecision precision) { 2831 DCHECK_GE(precision, 0); 2832 DCHECK_LT(precision, NumTexCoordPrecisions); 2833 TextureProgram* program = &texture_program_[precision]; 2834 if (!program->initialized()) { 2835 TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize"); 2836 program->Initialize( 2837 output_surface_->context_provider(), precision, SamplerType2D); 2838 } 2839 return program; 2840 } 2841 2842 const GLRenderer::NonPremultipliedTextureProgram* 2843 GLRenderer::GetNonPremultipliedTextureProgram(TexCoordPrecision precision) { 2844 DCHECK_GE(precision, 0); 2845 DCHECK_LT(precision, NumTexCoordPrecisions); 2846 NonPremultipliedTextureProgram* program = 2847 &nonpremultiplied_texture_program_[precision]; 2848 if (!program->initialized()) { 2849 TRACE_EVENT0("cc", 2850 "GLRenderer::NonPremultipliedTextureProgram::Initialize"); 2851 program->Initialize( 2852 output_surface_->context_provider(), precision, SamplerType2D); 2853 } 2854 return program; 2855 } 2856 2857 const GLRenderer::TextureBackgroundProgram* 2858 GLRenderer::GetTextureBackgroundProgram(TexCoordPrecision precision) { 2859 DCHECK_GE(precision, 0); 2860 DCHECK_LT(precision, NumTexCoordPrecisions); 2861 TextureBackgroundProgram* program = &texture_background_program_[precision]; 2862 if (!program->initialized()) { 2863 TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize"); 2864 program->Initialize( 2865 output_surface_->context_provider(), precision, SamplerType2D); 2866 } 2867 return program; 2868 } 2869 2870 const GLRenderer::NonPremultipliedTextureBackgroundProgram* 2871 GLRenderer::GetNonPremultipliedTextureBackgroundProgram( 2872 TexCoordPrecision precision) { 2873 DCHECK_GE(precision, 0); 2874 DCHECK_LT(precision, NumTexCoordPrecisions); 2875 NonPremultipliedTextureBackgroundProgram* program = 2876 &nonpremultiplied_texture_background_program_[precision]; 2877 if (!program->initialized()) { 2878 TRACE_EVENT0("cc", 2879 "GLRenderer::NonPremultipliedTextureProgram::Initialize"); 2880 program->Initialize( 2881 output_surface_->context_provider(), precision, SamplerType2D); 2882 } 2883 return program; 2884 } 2885 2886 const GLRenderer::TextureProgram* GLRenderer::GetTextureIOSurfaceProgram( 2887 TexCoordPrecision precision) { 2888 DCHECK_GE(precision, 0); 2889 DCHECK_LT(precision, NumTexCoordPrecisions); 2890 TextureProgram* program = &texture_io_surface_program_[precision]; 2891 if (!program->initialized()) { 2892 TRACE_EVENT0("cc", "GLRenderer::textureIOSurfaceProgram::initialize"); 2893 program->Initialize( 2894 output_surface_->context_provider(), precision, SamplerType2DRect); 2895 } 2896 return program; 2897 } 2898 2899 const GLRenderer::VideoYUVProgram* GLRenderer::GetVideoYUVProgram( 2900 TexCoordPrecision precision) { 2901 DCHECK_GE(precision, 0); 2902 DCHECK_LT(precision, NumTexCoordPrecisions); 2903 VideoYUVProgram* program = &video_yuv_program_[precision]; 2904 if (!program->initialized()) { 2905 TRACE_EVENT0("cc", "GLRenderer::videoYUVProgram::initialize"); 2906 program->Initialize( 2907 output_surface_->context_provider(), precision, SamplerType2D); 2908 } 2909 return program; 2910 } 2911 2912 const GLRenderer::VideoYUVAProgram* GLRenderer::GetVideoYUVAProgram( 2913 TexCoordPrecision precision) { 2914 DCHECK_GE(precision, 0); 2915 DCHECK_LT(precision, NumTexCoordPrecisions); 2916 VideoYUVAProgram* program = &video_yuva_program_[precision]; 2917 if (!program->initialized()) { 2918 TRACE_EVENT0("cc", "GLRenderer::videoYUVAProgram::initialize"); 2919 program->Initialize( 2920 output_surface_->context_provider(), precision, SamplerType2D); 2921 } 2922 return program; 2923 } 2924 2925 const GLRenderer::VideoStreamTextureProgram* 2926 GLRenderer::GetVideoStreamTextureProgram(TexCoordPrecision precision) { 2927 if (!Capabilities().using_egl_image) 2928 return NULL; 2929 DCHECK_GE(precision, 0); 2930 DCHECK_LT(precision, NumTexCoordPrecisions); 2931 VideoStreamTextureProgram* program = 2932 &video_stream_texture_program_[precision]; 2933 if (!program->initialized()) { 2934 TRACE_EVENT0("cc", "GLRenderer::streamTextureProgram::initialize"); 2935 program->Initialize( 2936 output_surface_->context_provider(), precision, SamplerTypeExternalOES); 2937 } 2938 return program; 2939 } 2940 2941 void GLRenderer::CleanupSharedObjects() { 2942 shared_geometry_.reset(); 2943 2944 for (int i = 0; i < NumTexCoordPrecisions; ++i) { 2945 for (int j = 0; j < NumSamplerTypes; ++j) { 2946 tile_program_[i][j].Cleanup(gl_); 2947 tile_program_opaque_[i][j].Cleanup(gl_); 2948 tile_program_swizzle_[i][j].Cleanup(gl_); 2949 tile_program_swizzle_opaque_[i][j].Cleanup(gl_); 2950 tile_program_aa_[i][j].Cleanup(gl_); 2951 tile_program_swizzle_aa_[i][j].Cleanup(gl_); 2952 } 2953 2954 render_pass_mask_program_[i].Cleanup(gl_); 2955 render_pass_program_[i].Cleanup(gl_); 2956 render_pass_mask_program_aa_[i].Cleanup(gl_); 2957 render_pass_program_aa_[i].Cleanup(gl_); 2958 render_pass_color_matrix_program_[i].Cleanup(gl_); 2959 render_pass_mask_color_matrix_program_aa_[i].Cleanup(gl_); 2960 render_pass_color_matrix_program_aa_[i].Cleanup(gl_); 2961 render_pass_mask_color_matrix_program_[i].Cleanup(gl_); 2962 2963 texture_program_[i].Cleanup(gl_); 2964 nonpremultiplied_texture_program_[i].Cleanup(gl_); 2965 texture_background_program_[i].Cleanup(gl_); 2966 nonpremultiplied_texture_background_program_[i].Cleanup(gl_); 2967 texture_io_surface_program_[i].Cleanup(gl_); 2968 2969 video_yuv_program_[i].Cleanup(gl_); 2970 video_yuva_program_[i].Cleanup(gl_); 2971 video_stream_texture_program_[i].Cleanup(gl_); 2972 } 2973 2974 tile_checkerboard_program_.Cleanup(gl_); 2975 2976 debug_border_program_.Cleanup(gl_); 2977 solid_color_program_.Cleanup(gl_); 2978 solid_color_program_aa_.Cleanup(gl_); 2979 2980 if (offscreen_framebuffer_id_) 2981 GLC(gl_, gl_->DeleteFramebuffers(1, &offscreen_framebuffer_id_)); 2982 2983 if (on_demand_tile_raster_resource_id_) 2984 resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_); 2985 2986 ReleaseRenderPassTextures(); 2987 } 2988 2989 void GLRenderer::ReinitializeGLState() { 2990 // Bind the common vertex attributes used for drawing all the layers. 2991 shared_geometry_->PrepareForDraw(); 2992 2993 GLC(gl_, gl_->Disable(GL_DEPTH_TEST)); 2994 GLC(gl_, gl_->Disable(GL_CULL_FACE)); 2995 GLC(gl_, gl_->ColorMask(true, true, true, true)); 2996 GLC(gl_, gl_->Disable(GL_STENCIL_TEST)); 2997 stencil_shadow_ = false; 2998 GLC(gl_, gl_->Enable(GL_BLEND)); 2999 blend_shadow_ = true; 3000 GLC(gl_, gl_->BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); 3001 GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0)); 3002 program_shadow_ = 0; 3003 3004 // Make sure scissoring starts as disabled. 3005 is_scissor_enabled_ = false; 3006 GLC(gl_, gl_->Disable(GL_SCISSOR_TEST)); 3007 scissor_rect_needs_reset_ = true; 3008 } 3009 3010 bool GLRenderer::IsContextLost() { 3011 return output_surface_->context_provider()->IsContextLost(); 3012 } 3013 3014 } // namespace cc 3015