Home | History | Annotate | Download | only in layers
      1 // Copyright 2012 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/layers/io_surface_layer_impl.h"
      6 
      7 #include "base/strings/stringprintf.h"
      8 #include "cc/layers/quad_sink.h"
      9 #include "cc/output/gl_renderer.h"  // For the GLC() macro.
     10 #include "cc/output/output_surface.h"
     11 #include "cc/quads/io_surface_draw_quad.h"
     12 #include "cc/trees/layer_tree_impl.h"
     13 #include "gpu/GLES2/gl2extchromium.h"
     14 #include "gpu/command_buffer/client/gles2_interface.h"
     15 #include "third_party/khronos/GLES2/gl2.h"
     16 #include "third_party/khronos/GLES2/gl2ext.h"
     17 
     18 namespace cc {
     19 
     20 IOSurfaceLayerImpl::IOSurfaceLayerImpl(LayerTreeImpl* tree_impl, int id)
     21     : LayerImpl(tree_impl, id),
     22       io_surface_id_(0),
     23       io_surface_changed_(false),
     24       io_surface_texture_id_(0),
     25       io_surface_resource_id_(0) {}
     26 
     27 IOSurfaceLayerImpl::~IOSurfaceLayerImpl() {
     28   if (!io_surface_texture_id_)
     29     return;
     30 
     31   DestroyTexture();
     32 }
     33 
     34 void IOSurfaceLayerImpl::DestroyTexture() {
     35   if (io_surface_resource_id_) {
     36     ResourceProvider* resource_provider =
     37         layer_tree_impl()->resource_provider();
     38     resource_provider->DeleteResource(io_surface_resource_id_);
     39     io_surface_resource_id_ = 0;
     40   }
     41 
     42   if (io_surface_texture_id_) {
     43     ContextProvider* context_provider =
     44         layer_tree_impl()->output_surface()->context_provider().get();
     45     // TODO(skaslev): Implement this path for software compositing.
     46     if (context_provider)
     47       context_provider->ContextGL()->DeleteTextures(1, &io_surface_texture_id_);
     48     io_surface_texture_id_ = 0;
     49   }
     50 }
     51 
     52 scoped_ptr<LayerImpl> IOSurfaceLayerImpl::CreateLayerImpl(
     53     LayerTreeImpl* tree_impl) {
     54   return IOSurfaceLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
     55 }
     56 
     57 void IOSurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) {
     58   LayerImpl::PushPropertiesTo(layer);
     59 
     60   IOSurfaceLayerImpl* io_surface_layer =
     61       static_cast<IOSurfaceLayerImpl*>(layer);
     62   io_surface_layer->SetIOSurfaceProperties(io_surface_id_, io_surface_size_);
     63 }
     64 
     65 bool IOSurfaceLayerImpl::WillDraw(DrawMode draw_mode,
     66                                   ResourceProvider* resource_provider) {
     67   if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
     68     return false;
     69 
     70   if (io_surface_changed_) {
     71     ContextProvider* context_provider =
     72         layer_tree_impl()->output_surface()->context_provider().get();
     73     if (!context_provider) {
     74       // TODO(skaslev): Implement this path for software compositing.
     75       return false;
     76     }
     77 
     78     gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
     79 
     80     // TODO(ernstm): Do this in a way that we can track memory usage.
     81     if (!io_surface_texture_id_) {
     82       gl->GenTextures(1, &io_surface_texture_id_);
     83       io_surface_resource_id_ =
     84           resource_provider->CreateResourceFromExternalTexture(
     85               GL_TEXTURE_RECTANGLE_ARB,
     86               io_surface_texture_id_);
     87     }
     88 
     89     GLC(gl, gl->BindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_id_));
     90     gl->TexImageIOSurface2DCHROMIUM(GL_TEXTURE_RECTANGLE_ARB,
     91                                     io_surface_size_.width(),
     92                                     io_surface_size_.height(),
     93                                     io_surface_id_,
     94                                     0);
     95     // Do not check for error conditions. texImageIOSurface2DCHROMIUM() is
     96     // supposed to hold on to the last good IOSurface if the new one is already
     97     // closed. This is only a possibility during live resizing of plugins.
     98     // However, it seems that this is not sufficient to completely guard against
     99     // garbage being drawn. If this is found to be a significant issue, it may
    100     // be necessary to explicitly tell the embedder when to free the surfaces it
    101     // has allocated.
    102     io_surface_changed_ = false;
    103   }
    104 
    105   return LayerImpl::WillDraw(draw_mode, resource_provider);
    106 }
    107 
    108 void IOSurfaceLayerImpl::AppendQuads(QuadSink* quad_sink,
    109                                      AppendQuadsData* append_quads_data) {
    110   SharedQuadState* shared_quad_state =
    111       quad_sink->UseSharedQuadState(CreateSharedQuadState());
    112   AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
    113 
    114   gfx::Rect quad_rect(content_bounds());
    115   gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
    116   scoped_ptr<IOSurfaceDrawQuad> quad = IOSurfaceDrawQuad::Create();
    117   quad->SetNew(shared_quad_state,
    118                quad_rect,
    119                opaque_rect,
    120                io_surface_size_,
    121                io_surface_resource_id_,
    122                IOSurfaceDrawQuad::FLIPPED);
    123   quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
    124 }
    125 
    126 void IOSurfaceLayerImpl::DidLoseOutputSurface() {
    127   // We don't have a valid texture ID in the new context; however,
    128   // the IOSurface is still valid.
    129   DestroyTexture();
    130   io_surface_changed_ = true;
    131 }
    132 
    133 void IOSurfaceLayerImpl::SetIOSurfaceProperties(unsigned io_surface_id,
    134                                                 gfx::Size size) {
    135   if (io_surface_id_ != io_surface_id)
    136     io_surface_changed_ = true;
    137 
    138   io_surface_id_ = io_surface_id;
    139   io_surface_size_ = size;
    140 }
    141 
    142 const char* IOSurfaceLayerImpl::LayerTypeAsString() const {
    143   return "cc::IOSurfaceLayerImpl";
    144 }
    145 
    146 }  // namespace cc
    147