io_surface_layer_impl.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 "third_party/WebKit/public/platform/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      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->Context3d()->deleteTexture(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    blink::WebGraphicsContext3D* context3d = context_provider->Context3d();
79
80    // TODO(ernstm): Do this in a way that we can track memory usage.
81    if (!io_surface_texture_id_) {
82      io_surface_texture_id_ = context3d->createTexture();
83      io_surface_resource_id_ =
84          resource_provider->CreateResourceFromExternalTexture(
85              GL_TEXTURE_RECTANGLE_ARB,
86              io_surface_texture_id_);
87    }
88
89    GLC(context3d,
90        context3d->bindTexture(GL_TEXTURE_RECTANGLE_ARB,
91                               io_surface_texture_id_));
92    context3d->texImageIOSurface2DCHROMIUM(GL_TEXTURE_RECTANGLE_ARB,
93                                           io_surface_size_.width(),
94                                           io_surface_size_.height(),
95                                           io_surface_id_,
96                                           0);
97    // Do not check for error conditions. texImageIOSurface2DCHROMIUM() is
98    // supposed to hold on to the last good IOSurface if the new one is already
99    // closed. This is only a possibility during live resizing of plugins.
100    // However, it seems that this is not sufficient to completely guard against
101    // garbage being drawn. If this is found to be a significant issue, it may
102    // be necessary to explicitly tell the embedder when to free the surfaces it
103    // has allocated.
104    io_surface_changed_ = false;
105  }
106
107  return LayerImpl::WillDraw(draw_mode, resource_provider);
108}
109
110void IOSurfaceLayerImpl::AppendQuads(QuadSink* quad_sink,
111                                     AppendQuadsData* append_quads_data) {
112  SharedQuadState* shared_quad_state =
113      quad_sink->UseSharedQuadState(CreateSharedQuadState());
114  AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
115
116  gfx::Rect quad_rect(content_bounds());
117  gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
118  scoped_ptr<IOSurfaceDrawQuad> quad = IOSurfaceDrawQuad::Create();
119  quad->SetNew(shared_quad_state,
120               quad_rect,
121               opaque_rect,
122               io_surface_size_,
123               io_surface_resource_id_,
124               IOSurfaceDrawQuad::FLIPPED);
125  quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
126}
127
128void IOSurfaceLayerImpl::DidLoseOutputSurface() {
129  // We don't have a valid texture ID in the new context; however,
130  // the IOSurface is still valid.
131  DestroyTexture();
132  io_surface_changed_ = true;
133}
134
135void IOSurfaceLayerImpl::SetIOSurfaceProperties(unsigned io_surface_id,
136                                                gfx::Size size) {
137  if (io_surface_id_ != io_surface_id)
138    io_surface_changed_ = true;
139
140  io_surface_id_ = io_surface_id;
141  io_surface_size_ = size;
142}
143
144const char* IOSurfaceLayerImpl::LayerTypeAsString() const {
145  return "cc::IOSurfaceLayerImpl";
146}
147
148}  // namespace cc
149