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