io_surface_layer_impl.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/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 "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.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
26IOSurfaceLayerImpl::~IOSurfaceLayerImpl() {
27  if (!io_surface_texture_id_)
28    return;
29
30  DestroyTexture();
31}
32
33void IOSurfaceLayerImpl::DestroyTexture() {
34  if (io_surface_resource_id_) {
35    ResourceProvider* resource_provider =
36        layer_tree_impl()->resource_provider();
37    resource_provider->DeleteResource(io_surface_resource_id_);
38    io_surface_resource_id_ = 0;
39  }
40
41  if (io_surface_texture_id_) {
42    OutputSurface* output_surface = layer_tree_impl()->output_surface();
43    // FIXME: Implement this path for software compositing.
44    WebKit::WebGraphicsContext3D* context3d = output_surface->context3d();
45    if (context3d)
46      context3d->deleteTexture(io_surface_texture_id_);
47    io_surface_texture_id_ = 0;
48  }
49}
50
51scoped_ptr<LayerImpl> IOSurfaceLayerImpl::CreateLayerImpl(
52    LayerTreeImpl* tree_impl) {
53  return IOSurfaceLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
54}
55
56void IOSurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) {
57  LayerImpl::PushPropertiesTo(layer);
58
59  IOSurfaceLayerImpl* io_surface_layer =
60      static_cast<IOSurfaceLayerImpl*>(layer);
61  io_surface_layer->SetIOSurfaceProperties(io_surface_id_, io_surface_size_);
62}
63
64void IOSurfaceLayerImpl::WillDraw(ResourceProvider* resource_provider) {
65  LayerImpl::WillDraw(resource_provider);
66
67  if (io_surface_changed_) {
68    WebKit::WebGraphicsContext3D* context3d =
69        resource_provider->GraphicsContext3D();
70    if (!context3d) {
71      // FIXME: Implement this path for software compositing.
72      return;
73    }
74
75    // FIXME: Do this in a way that we can track memory usage.
76    if (!io_surface_texture_id_) {
77      io_surface_texture_id_ = context3d->createTexture();
78      io_surface_resource_id_ =
79          resource_provider->CreateResourceFromExternalTexture(
80              GL_TEXTURE_RECTANGLE_ARB,
81              io_surface_texture_id_);
82    }
83
84    GLC(context3d,
85        context3d->bindTexture(GL_TEXTURE_RECTANGLE_ARB,
86                               io_surface_texture_id_));
87    context3d->texImageIOSurface2DCHROMIUM(GL_TEXTURE_RECTANGLE_ARB,
88                                           io_surface_size_.width(),
89                                           io_surface_size_.height(),
90                                           io_surface_id_,
91                                           0);
92    // Do not check for error conditions. texImageIOSurface2DCHROMIUM() is
93    // supposed to hold on to the last good IOSurface if the new one is already
94    // closed. This is only a possibility during live resizing of plugins.
95    // However, it seems that this is not sufficient to completely guard against
96    // garbage being drawn. If this is found to be a significant issue, it may
97    // be necessary to explicitly tell the embedder when to free the surfaces it
98    // has allocated.
99    io_surface_changed_ = false;
100  }
101}
102
103void IOSurfaceLayerImpl::AppendQuads(QuadSink* quad_sink,
104                                     AppendQuadsData* append_quads_data) {
105  SharedQuadState* shared_quad_state =
106      quad_sink->UseSharedQuadState(CreateSharedQuadState());
107  AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
108
109  gfx::Rect quad_rect(content_bounds());
110  gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
111  scoped_ptr<IOSurfaceDrawQuad> quad = IOSurfaceDrawQuad::Create();
112  quad->SetNew(shared_quad_state,
113               quad_rect,
114               opaque_rect,
115               io_surface_size_,
116               io_surface_resource_id_,
117               IOSurfaceDrawQuad::FLIPPED);
118  quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
119}
120
121void IOSurfaceLayerImpl::DumpLayerProperties(std::string* str,
122                                             int indent) const {
123  str->append(IndentString(indent));
124  base::StringAppendF(str,
125                      "iosurface id: %u texture id: %u\n",
126                      io_surface_id_,
127                      io_surface_texture_id_);
128  LayerImpl::DumpLayerProperties(str, indent);
129}
130
131void IOSurfaceLayerImpl::DidLoseOutputSurface() {
132  // We don't have a valid texture ID in the new context; however,
133  // the IOSurface is still valid.
134  DestroyTexture();
135  io_surface_changed_ = true;
136}
137
138void IOSurfaceLayerImpl::SetIOSurfaceProperties(unsigned io_surface_id,
139                                                gfx::Size size) {
140  if (io_surface_id_ != io_surface_id)
141    io_surface_changed_ = true;
142
143  io_surface_id_ = io_surface_id;
144  io_surface_size_ = size;
145}
146
147const char* IOSurfaceLayerImpl::LayerTypeAsString() const {
148  return "IOSurfaceLayer";
149}
150
151}  // namespace cc
152