1 // Copyright 2014 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.
5 #include "content/browser/compositor/buffer_queue.h"
7 #include "content/browser/compositor/image_transport_factory.h"
8 #include "content/common/gpu/client/context_provider_command_buffer.h"
9 #include "content/common/gpu/client/gl_helper.h"
10 #include "gpu/GLES2/gl2extchromium.h"
11 #include "gpu/command_buffer/client/gles2_interface.h"
12 #include "third_party/skia/include/core/SkRect.h"
13 #include "third_party/skia/include/core/SkRegion.h"
17 BufferQueue::BufferQueue(scoped_refptr
<cc::ContextProvider
> context_provider
,
18 unsigned int internalformat
)
19 : context_provider_(context_provider
),
22 internalformat_(internalformat
) {
25 BufferQueue::~BufferQueue() {
28 gpu::gles2::GLES2Interface
* gl
= context_provider_
->ContextGL();
30 gl
->DeleteFramebuffers(1, &fbo_
);
33 bool BufferQueue::Initialize() {
34 gpu::gles2::GLES2Interface
* gl
= context_provider_
->ContextGL();
35 gl
->GenFramebuffers(1, &fbo_
);
39 void BufferQueue::BindFramebuffer() {
40 gpu::gles2::GLES2Interface
* gl
= context_provider_
->ContextGL();
41 gl
->BindFramebuffer(GL_FRAMEBUFFER
, fbo_
);
43 if (!current_surface_
.texture
) {
44 current_surface_
= GetNextSurface();
45 gl
->FramebufferTexture2D(GL_FRAMEBUFFER
,
48 current_surface_
.texture
,
53 void BufferQueue::CopyBufferDamage(int texture
,
55 const gfx::Rect
& new_damage
,
56 const gfx::Rect
& old_damage
) {
57 ImageTransportFactory::GetInstance()->GetGLHelper()->CopySubBufferDamage(
60 SkRegion(SkIRect::MakeXYWH(new_damage
.x(),
63 new_damage
.height())),
64 SkRegion(SkIRect::MakeXYWH(old_damage
.x(),
67 old_damage
.height())));
70 void BufferQueue::UpdateBufferDamage(const gfx::Rect
& damage
) {
71 for (size_t i
= 0; i
< available_surfaces_
.size(); i
++)
72 available_surfaces_
[i
].damage
.Union(damage
);
73 for (std::deque
<AllocatedSurface
>::iterator it
=
74 in_flight_surfaces_
.begin();
75 it
!= in_flight_surfaces_
.end();
77 it
->damage
.Union(damage
);
80 void BufferQueue::SwapBuffers(const gfx::Rect
& damage
) {
81 if (damage
!= gfx::Rect(size_
)) {
82 // We must have a frame available to copy from.
83 DCHECK(!in_flight_surfaces_
.empty());
84 CopyBufferDamage(current_surface_
.texture
,
85 in_flight_surfaces_
.back().texture
,
87 current_surface_
.damage
);
89 UpdateBufferDamage(damage
);
90 current_surface_
.damage
= gfx::Rect();
91 in_flight_surfaces_
.push_back(current_surface_
);
92 current_surface_
.texture
= 0;
93 current_surface_
.image
= 0;
96 void BufferQueue::Reshape(const gfx::Size
& size
, float scale_factor
) {
97 DCHECK(!current_surface_
.texture
);
102 // TODO: add stencil buffer when needed.
103 gpu::gles2::GLES2Interface
* gl
= context_provider_
->ContextGL();
104 gl
->BindFramebuffer(GL_FRAMEBUFFER
, fbo_
);
105 gl
->FramebufferTexture2D(
106 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, 0, 0);
111 void BufferQueue::PageFlipComplete() {
112 if (in_flight_surfaces_
.size() > 1) {
113 available_surfaces_
.push_back(in_flight_surfaces_
.front());
114 in_flight_surfaces_
.pop_front();
118 void BufferQueue::FreeAllSurfaces() {
119 FreeSurface(¤t_surface_
);
120 while (!in_flight_surfaces_
.empty()) {
121 FreeSurface(&in_flight_surfaces_
.front());
122 in_flight_surfaces_
.pop_front();
124 for (size_t i
= 0; i
< available_surfaces_
.size(); i
++)
125 FreeSurface(&available_surfaces_
[i
]);
126 available_surfaces_
.clear();
129 void BufferQueue::FreeSurface(AllocatedSurface
* surface
) {
130 if (surface
->texture
) {
131 gpu::gles2::GLES2Interface
* gl
= context_provider_
->ContextGL();
132 gl
->BindTexture(GL_TEXTURE_2D
, surface
->texture
);
133 gl
->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, surface
->image
);
134 gl
->DeleteTextures(1, &surface
->texture
);
135 gl
->DestroyImageCHROMIUM(surface
->image
);
137 surface
->texture
= 0;
142 BufferQueue::AllocatedSurface
BufferQueue::GetNextSurface() {
143 if (!available_surfaces_
.empty()) {
144 AllocatedSurface surface
= available_surfaces_
.back();
145 available_surfaces_
.pop_back();
149 unsigned int texture
= 0;
150 gpu::gles2::GLES2Interface
* gl
= context_provider_
->ContextGL();
151 gl
->GenTextures(1, &texture
);
153 return AllocatedSurface();
155 // We don't want to allow anything more than triple buffering.
156 DCHECK_LT(allocated_count_
, 4U);
159 gl
->CreateGpuMemoryBufferImageCHROMIUM(size_
.width(),
162 GL_SCANOUT_CHROMIUM
);
164 LOG(ERROR
) << "Failed to allocate backing image surface";
165 gl
->DeleteTextures(1, &texture
);
166 return AllocatedSurface();
169 gl
->BindTexture(GL_TEXTURE_2D
, texture
);
170 gl
->BindTexImage2DCHROMIUM(GL_TEXTURE_2D
, id
);
171 return AllocatedSurface(texture
, id
, gfx::Rect(size_
));
174 } // namespace content