io_surface_layer_impl.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
18namespace cc {
19
20IOSurfaceLayerImpl::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
27IOSurfaceLayerImpl::~IOSurfaceLayerImpl() {
28  if (!io_surface_texture_id_)
29    return;
30
31  DestroyTexture();
32}
33
34void 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
52scoped_ptr<LayerImpl> IOSurfaceLayerImpl::CreateLayerImpl(
53    LayerTreeImpl* tree_impl) {
54  return IOSurfaceLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
55}
56
57void 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
65bool 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
108void 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
126void IOSurfaceLayerImpl::ReleaseResources() {
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
133void IOSurfaceLayerImpl::SetIOSurfaceProperties(unsigned io_surface_id,
134                                                const 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
142const char* IOSurfaceLayerImpl::LayerTypeAsString() const {
143  return "cc::IOSurfaceLayerImpl";
144}
145
146}  // namespace cc
147