blob: de741361750dcddb884ee858ad706e7e4d011b3c [file] [log] [blame]
revemanb195f41d2015-11-19 22:16:481// Copyright 2015 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 "components/exo/buffer.h"
6
7#include <GLES2/gl2.h>
8#include <GLES2/gl2ext.h>
9#include <GLES2/gl2extchromium.h>
avibc5337b2015-12-25 23:16:3310#include <stdint.h>
revemanb195f41d2015-11-19 22:16:4811#include <algorithm>
dcheng27f7483f2015-12-29 22:26:5612#include <utility>
revemanb195f41d2015-11-19 22:16:4813
revemanae3b7c852016-02-25 01:50:0314#include "base/callback_helpers.h"
revemanb195f41d2015-11-19 22:16:4815#include "base/logging.h"
avibc5337b2015-12-25 23:16:3316#include "base/macros.h"
revemanae3b7c852016-02-25 01:50:0317#include "base/memory/weak_ptr.h"
18#include "base/thread_task_runner_handle.h"
19#include "base/time/time.h"
revemanb195f41d2015-11-19 22:16:4820#include "base/trace_event/trace_event.h"
21#include "base/trace_event/trace_event_argument.h"
22#include "cc/output/context_provider.h"
23#include "cc/resources/single_release_callback.h"
24#include "cc/resources/texture_mailbox.h"
revemanc8623d5b2016-02-09 02:29:1025#include "gpu/command_buffer/client/context_support.h"
revemanb195f41d2015-11-19 22:16:4826#include "gpu/command_buffer/client/gles2_interface.h"
27#include "ui/aura/env.h"
28#include "ui/compositor/compositor.h"
29#include "ui/gfx/gpu_memory_buffer.h"
30
31namespace exo {
32namespace {
33
revemanae3b7c852016-02-25 01:50:0334// The amount of time before we wait for release queries using
35// GetQueryObjectuivEXT(GL_QUERY_RESULT_EXT).
36const int kWaitForReleaseDelayMs = 500;
37
revemanb195f41d2015-11-19 22:16:4838GLenum GLInternalFormat(gfx::BufferFormat format) {
39 const GLenum kGLInternalFormats[] = {
40 GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD, // ATC
41 GL_COMPRESSED_RGB_S3TC_DXT1_EXT, // ATCIA
42 GL_COMPRESSED_RGB_S3TC_DXT1_EXT, // DXT1
43 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, // DXT5
44 GL_ETC1_RGB8_OES, // ETC1
45 GL_R8_EXT, // R_8
46 GL_RGBA, // RGBA_4444
47 GL_RGB, // RGBX_8888
48 GL_RGBA, // RGBA_8888
49 GL_RGB, // BGRX_8888
50 GL_BGRA_EXT, // BGRA_8888
51 GL_RGB_YUV_420_CHROMIUM, // YUV_420
52 GL_INVALID_ENUM, // YUV_420_BIPLANAR
53 GL_RGB_YCBCR_422_CHROMIUM, // UYVY_422
54 };
55 static_assert(arraysize(kGLInternalFormats) ==
56 (static_cast<int>(gfx::BufferFormat::LAST) + 1),
57 "BufferFormat::LAST must be last value of kGLInternalFormats");
58
59 DCHECK(format <= gfx::BufferFormat::LAST);
60 return kGLInternalFormats[static_cast<int>(format)];
61}
62
revemanc8623d5b2016-02-09 02:29:1063unsigned CreateGLTexture(gpu::gles2::GLES2Interface* gles2, GLenum target) {
64 unsigned texture_id = 0;
65 gles2->GenTextures(1, &texture_id);
66 gles2->ActiveTexture(GL_TEXTURE0);
67 gles2->BindTexture(target, texture_id);
68 gles2->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
69 gles2->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
70 gles2->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
71 gles2->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
72 return texture_id;
73}
74
75void CreateGLTextureMailbox(gpu::gles2::GLES2Interface* gles2,
76 unsigned texture_id,
77 GLenum target,
78 gpu::Mailbox* mailbox) {
79 gles2->ActiveTexture(GL_TEXTURE0);
80 gles2->BindTexture(target, texture_id);
81 gles2->GenMailboxCHROMIUM(mailbox->name);
82 gles2->ProduceTextureCHROMIUM(target, mailbox->name);
83}
84
revemanb195f41d2015-11-19 22:16:4885} // namespace
86
87////////////////////////////////////////////////////////////////////////////////
revemanced21f862015-11-24 00:42:4988// Buffer::Texture
revemanb195f41d2015-11-19 22:16:4889
revemanced21f862015-11-24 00:42:4990// Encapsulates the state and logic needed to bind a buffer to a GLES2 texture.
91class Buffer::Texture {
92 public:
revemanc8623d5b2016-02-09 02:29:1093 explicit Texture(cc::ContextProvider* context_provider);
94 Texture(cc::ContextProvider* context_provider,
95 gfx::GpuMemoryBuffer* gpu_memory_buffer,
96 unsigned texture_target,
97 unsigned query_type);
revemanced21f862015-11-24 00:42:4998 ~Texture();
99
100 // Returns true if GLES2 resources for texture have been lost.
101 bool IsLost();
102
revemanc8623d5b2016-02-09 02:29:10103 // Allow texture to be reused after |sync_token| has passed and runs
104 // |callback|.
105 void Release(const base::Closure& callback,
106 const gpu::SyncToken& sync_token,
107 bool is_lost);
108
109 // Binds the contents referenced by |image_id_| to the texture returned by
110 // mailbox(). Returns a sync token that can be used when accessing texture
revemanced21f862015-11-24 00:42:49111 // from a different context.
112 gpu::SyncToken BindTexImage();
113
revemanc8623d5b2016-02-09 02:29:10114 // Releases the contents referenced by |image_id_| after |sync_token| has
115 // passed and runs |callback| when completed.
116 void ReleaseTexImage(const base::Closure& callback,
117 const gpu::SyncToken& sync_token,
118 bool is_lost);
119
120 // Copy the contents of texture to |destination| and runs |callback| when
121 // completed. Returns a sync token that can be used when accessing texture
122 // from a different context.
123 gpu::SyncToken CopyTexImage(Texture* destination,
124 const base::Closure& callback);
revemanced21f862015-11-24 00:42:49125
126 // Returns the mailbox for this texture.
127 gpu::Mailbox mailbox() const { return mailbox_; }
128
129 private:
revemanae3b7c852016-02-25 01:50:03130 void ReleaseWhenQueryResultIsAvailable(const base::Closure& callback);
131 void Released();
132 void ScheduleWaitForRelease(base::TimeDelta delay);
133 void WaitForRelease();
134
revemanced21f862015-11-24 00:42:49135 scoped_refptr<cc::ContextProvider> context_provider_;
136 const unsigned texture_target_;
revemanc8623d5b2016-02-09 02:29:10137 const unsigned query_type_;
138 const GLenum internalformat_;
revemanced21f862015-11-24 00:42:49139 unsigned image_id_;
revemanc8623d5b2016-02-09 02:29:10140 unsigned query_id_;
revemanced21f862015-11-24 00:42:49141 unsigned texture_id_;
142 gpu::Mailbox mailbox_;
revemanae3b7c852016-02-25 01:50:03143 base::Closure release_callback_;
144 base::TimeTicks wait_for_release_time_;
145 bool wait_for_release_pending_;
146 base::WeakPtrFactory<Texture> weak_ptr_factory_;
revemanced21f862015-11-24 00:42:49147
148 DISALLOW_COPY_AND_ASSIGN(Texture);
149};
150
revemanc8623d5b2016-02-09 02:29:10151Buffer::Texture::Texture(cc::ContextProvider* context_provider)
revemanced21f862015-11-24 00:42:49152 : context_provider_(context_provider),
revemanc8623d5b2016-02-09 02:29:10153 texture_target_(GL_TEXTURE_2D),
154 query_type_(GL_COMMANDS_COMPLETED_CHROMIUM),
155 internalformat_(GL_RGBA),
revemanced21f862015-11-24 00:42:49156 image_id_(0),
revemanc8623d5b2016-02-09 02:29:10157 query_id_(0),
revemanae3b7c852016-02-25 01:50:03158 texture_id_(0),
159 wait_for_release_pending_(false),
160 weak_ptr_factory_(this) {
revemanced21f862015-11-24 00:42:49161 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
revemanc8623d5b2016-02-09 02:29:10162 texture_id_ = CreateGLTexture(gles2, texture_target_);
revemanb195f41d2015-11-19 22:16:48163 // Generate a crypto-secure random mailbox name.
revemanc8623d5b2016-02-09 02:29:10164 CreateGLTextureMailbox(gles2, texture_id_, texture_target_, &mailbox_);
165}
166
167Buffer::Texture::Texture(cc::ContextProvider* context_provider,
168 gfx::GpuMemoryBuffer* gpu_memory_buffer,
169 unsigned texture_target,
170 unsigned query_type)
171 : context_provider_(context_provider),
172 texture_target_(texture_target),
173 query_type_(query_type),
174 internalformat_(GLInternalFormat(gpu_memory_buffer->GetFormat())),
175 image_id_(0),
176 query_id_(0),
revemanae3b7c852016-02-25 01:50:03177 texture_id_(0),
178 wait_for_release_pending_(false),
179 weak_ptr_factory_(this) {
revemanc8623d5b2016-02-09 02:29:10180 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
181 gfx::Size size = gpu_memory_buffer->GetSize();
182 image_id_ =
183 gles2->CreateImageCHROMIUM(gpu_memory_buffer->AsClientBuffer(),
184 size.width(), size.height(), internalformat_);
185 gles2->GenQueriesEXT(1, &query_id_);
186 texture_id_ = CreateGLTexture(gles2, texture_target_);
revemanb195f41d2015-11-19 22:16:48187}
188
revemanced21f862015-11-24 00:42:49189Buffer::Texture::~Texture() {
190 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
revemanced21f862015-11-24 00:42:49191 gles2->DeleteTextures(1, &texture_id_);
revemanc8623d5b2016-02-09 02:29:10192 if (query_id_)
193 gles2->DeleteQueriesEXT(1, &query_id_);
194 if (image_id_)
195 gles2->DestroyImageCHROMIUM(image_id_);
revemanb195f41d2015-11-19 22:16:48196}
197
revemanced21f862015-11-24 00:42:49198bool Buffer::Texture::IsLost() {
199 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
200 return gles2->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
201}
revemanb195f41d2015-11-19 22:16:48202
revemanc8623d5b2016-02-09 02:29:10203void Buffer::Texture::Release(const base::Closure& callback,
204 const gpu::SyncToken& sync_token,
205 bool is_lost) {
206 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
207 if (sync_token.HasData())
208 gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
209
210 // Run callback as texture can be reused immediately after waiting for sync
211 // token.
212 callback.Run();
213}
214
revemanced21f862015-11-24 00:42:49215gpu::SyncToken Buffer::Texture::BindTexImage() {
216 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
revemanb195f41d2015-11-19 22:16:48217 gles2->ActiveTexture(GL_TEXTURE0);
revemanced21f862015-11-24 00:42:49218 gles2->BindTexture(texture_target_, texture_id_);
revemanc8623d5b2016-02-09 02:29:10219 DCHECK_NE(image_id_, 0u);
revemanced21f862015-11-24 00:42:49220 gles2->BindTexImage2DCHROMIUM(texture_target_, image_id_);
revemanc8623d5b2016-02-09 02:29:10221 // Generate a crypto-secure random mailbox name if not already done.
222 if (mailbox_.IsZero())
223 CreateGLTextureMailbox(gles2, texture_id_, texture_target_, &mailbox_);
revemanced21f862015-11-24 00:42:49224 // Create and return a sync token that can be used to ensure that the
225 // BindTexImage2DCHROMIUM call is processed before issuing any commands
226 // that will read from the texture on a different context.
avibc5337b2015-12-25 23:16:33227 uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM();
revemanced21f862015-11-24 00:42:49228 gles2->OrderingBarrierCHROMIUM();
revemanb195f41d2015-11-19 22:16:48229 gpu::SyncToken sync_token;
230 gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
revemanced21f862015-11-24 00:42:49231 return sync_token;
232}
233
revemanc8623d5b2016-02-09 02:29:10234void Buffer::Texture::ReleaseTexImage(const base::Closure& callback,
235 const gpu::SyncToken& sync_token,
236 bool is_lost) {
revemanced21f862015-11-24 00:42:49237 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
238 if (sync_token.HasData())
239 gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
240 gles2->ActiveTexture(GL_TEXTURE0);
241 gles2->BindTexture(texture_target_, texture_id_);
revemanc8623d5b2016-02-09 02:29:10242 DCHECK_NE(query_id_, 0u);
243 gles2->BeginQueryEXT(query_type_, query_id_);
revemanced21f862015-11-24 00:42:49244 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, image_id_);
revemanc8623d5b2016-02-09 02:29:10245 gles2->EndQueryEXT(query_type_);
revemanae3b7c852016-02-25 01:50:03246 // Run callback when query result is available and ReleaseTexImage has been
247 // handled if sync token has data and buffer has been used. If buffer was
248 // never used then run the callback immediately.
revemanc8623d5b2016-02-09 02:29:10249 if (sync_token.HasData()) {
revemanae3b7c852016-02-25 01:50:03250 ReleaseWhenQueryResultIsAvailable(callback);
revemanc8623d5b2016-02-09 02:29:10251 } else {
252 callback.Run();
253 }
254}
255
256gpu::SyncToken Buffer::Texture::CopyTexImage(Texture* destination,
257 const base::Closure& callback) {
258 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
259 gles2->ActiveTexture(GL_TEXTURE0);
260 gles2->BindTexture(texture_target_, texture_id_);
261 DCHECK_NE(image_id_, 0u);
262 gles2->BindTexImage2DCHROMIUM(texture_target_, image_id_);
263 gles2->CopyTextureCHROMIUM(texture_id_, destination->texture_id_,
264 internalformat_, GL_UNSIGNED_BYTE, false, false,
265 false);
266 DCHECK_NE(query_id_, 0u);
267 gles2->BeginQueryEXT(query_type_, query_id_);
268 gles2->ReleaseTexImage2DCHROMIUM(texture_target_, image_id_);
269 gles2->EndQueryEXT(query_type_);
revemanae3b7c852016-02-25 01:50:03270 // Run callback when query result is available and ReleaseTexImage has been
271 // handled.
272 ReleaseWhenQueryResultIsAvailable(callback);
revemanc8623d5b2016-02-09 02:29:10273 // Create and return a sync token that can be used to ensure that the
274 // CopyTextureCHROMIUM call is processed before issuing any commands
275 // that will read from the target texture on a different context.
276 uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM();
277 gles2->OrderingBarrierCHROMIUM();
278 gpu::SyncToken sync_token;
279 gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
280 return sync_token;
revemanced21f862015-11-24 00:42:49281}
282
revemanae3b7c852016-02-25 01:50:03283void Buffer::Texture::ReleaseWhenQueryResultIsAvailable(
284 const base::Closure& callback) {
285 DCHECK(release_callback_.is_null());
286 release_callback_ = callback;
287 base::TimeDelta wait_for_release_delay =
288 base::TimeDelta::FromMilliseconds(kWaitForReleaseDelayMs);
289 wait_for_release_time_ = base::TimeTicks::Now() + wait_for_release_delay;
290 ScheduleWaitForRelease(wait_for_release_delay);
291 context_provider_->ContextSupport()->SignalQuery(
292 query_id_,
293 base::Bind(&Buffer::Texture::Released, weak_ptr_factory_.GetWeakPtr()));
294}
295
296void Buffer::Texture::Released() {
297 if (!release_callback_.is_null())
298 base::ResetAndReturn(&release_callback_).Run();
299}
300
301void Buffer::Texture::ScheduleWaitForRelease(base::TimeDelta delay) {
302 if (wait_for_release_pending_)
303 return;
304
305 wait_for_release_pending_ = true;
306 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
307 FROM_HERE, base::Bind(&Buffer::Texture::WaitForRelease,
308 weak_ptr_factory_.GetWeakPtr()),
309 delay);
310}
311
312void Buffer::Texture::WaitForRelease() {
313 DCHECK(wait_for_release_pending_);
314 wait_for_release_pending_ = false;
315
316 if (release_callback_.is_null())
317 return;
318
319 base::TimeTicks current_time = base::TimeTicks::Now();
320 if (current_time < wait_for_release_time_) {
321 ScheduleWaitForRelease(wait_for_release_time_ - current_time);
322 return;
323 }
324
325 base::Closure callback = base::ResetAndReturn(&release_callback_);
326
327 {
328 TRACE_EVENT0("exo", "Buffer::Texture::WaitForQueryResult");
329
330 // We need to wait for the result to be available. Getting the result of
331 // the query implies waiting for it to become available. The actual result
332 // is unimportant and also not well defined.
333 unsigned result = 0;
334 gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
335 gles2->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &result);
336 }
337
338 callback.Run();
339}
340
revemanced21f862015-11-24 00:42:49341////////////////////////////////////////////////////////////////////////////////
342// Buffer, public:
343
revemanc8623d5b2016-02-09 02:29:10344Buffer::Buffer(scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer)
345 : gpu_memory_buffer_(std::move(gpu_memory_buffer)),
346 texture_target_(GL_TEXTURE_2D),
347 query_type_(GL_COMMANDS_COMPLETED_CHROMIUM),
348 use_zero_copy_(true),
349 use_count_(0) {}
350
revemanced21f862015-11-24 00:42:49351Buffer::Buffer(scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer,
revemanc8623d5b2016-02-09 02:29:10352 unsigned texture_target,
353 unsigned query_type,
354 bool use_zero_copy)
dcheng27f7483f2015-12-29 22:26:56355 : gpu_memory_buffer_(std::move(gpu_memory_buffer)),
revemanced21f862015-11-24 00:42:49356 texture_target_(texture_target),
revemanc8623d5b2016-02-09 02:29:10357 query_type_(query_type),
358 use_zero_copy_(use_zero_copy),
revemanced21f862015-11-24 00:42:49359 use_count_(0) {}
360
361Buffer::~Buffer() {}
362
363scoped_ptr<cc::SingleReleaseCallback> Buffer::ProduceTextureMailbox(
revemanc8623d5b2016-02-09 02:29:10364 cc::TextureMailbox* texture_mailbox,
365 bool lost_context) {
revemanced21f862015-11-24 00:42:49366 DLOG_IF(WARNING, use_count_)
367 << "Producing a texture mailbox for a buffer that has not been released";
368
revemanc8623d5b2016-02-09 02:29:10369 // Some clients think that they can reuse a buffer before it's released by
370 // performing a fast blit into the buffer. This behavior is bad as it prevents
371 // the client from knowing when the buffer is actually released (e.g. the
372 // release notification for the previous use of buffer can arrive after the
373 // buffer has been reused). We stop running the release callback when this
374 // type of behavior is detected as having the buffer always be busy will
375 // result in fewer drawing artifacts.
376 if (use_count_ && !lost_context)
377 release_callback_.Reset();
378
revemanced21f862015-11-24 00:42:49379 // Increment the use count for this buffer.
380 ++use_count_;
381
revemanc8623d5b2016-02-09 02:29:10382 // If textures are lost, destroy them to ensure that we create new ones below.
383 if (contents_texture_ && contents_texture_->IsLost())
384 contents_texture_.reset();
385 if (texture_ && texture_->IsLost())
386 texture_.reset();
revemanced21f862015-11-24 00:42:49387
revemanc8623d5b2016-02-09 02:29:10388 // Note: This can fail if GPU acceleration has been disabled.
389 scoped_refptr<cc::ContextProvider> context_provider =
390 aura::Env::GetInstance()
391 ->context_factory()
392 ->SharedMainThreadContextProvider();
393 if (!context_provider) {
394 DLOG(WARNING) << "Failed to acquire a context provider";
395 Release(); // Decrements the use count
396 return nullptr;
revemanced21f862015-11-24 00:42:49397 }
398
revemanc8623d5b2016-02-09 02:29:10399 // Create a new image texture for |gpu_memory_buffer_| with |texture_target_|
400 // if one doesn't already exist. The contents of this buffer are copied to
401 // |texture| using a call to CopyTexImage.
402 if (!contents_texture_) {
403 contents_texture_ = make_scoped_ptr(
404 new Texture(context_provider.get(), gpu_memory_buffer_.get(),
405 texture_target_, query_type_));
406 }
revemanb195f41d2015-11-19 22:16:48407
revemanc8623d5b2016-02-09 02:29:10408 if (use_zero_copy_) {
409 // Zero-copy means using the contents texture directly.
410 Texture* texture = contents_texture_.get();
411
412 // This binds the latest contents of this buffer to |texture|.
413 gpu::SyncToken sync_token = texture->BindTexImage();
414
415 // TODO(reveman): Set to true when GMBs can be imported for SCANOUT.
416 bool is_overlay_candidate = false;
417 *texture_mailbox =
418 cc::TextureMailbox(texture->mailbox(), sync_token, texture_target_,
419 gpu_memory_buffer_->GetSize(), is_overlay_candidate);
420 // The contents texture will be released when no longer used by the
421 // compositor.
422 return cc::SingleReleaseCallback::Create(
423 base::Bind(&Buffer::Texture::ReleaseTexImage, base::Unretained(texture),
424 base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(),
425 base::Passed(&contents_texture_))));
426 }
427
428 // Create a mailbox texture that we copy the buffer contents to.
429 if (!texture_)
430 texture_ = make_scoped_ptr(new Texture(context_provider.get()));
431
reveman17fdee02016-02-10 04:26:47432 // Copy the contents of |contents_texture| to |texture| and produce a
433 // texture mailbox from the result in |texture|.
434 Texture* contents_texture = contents_texture_.get();
revemanc8623d5b2016-02-09 02:29:10435 Texture* texture = texture_.get();
436
437 // The contents texture will be released when copy has completed.
reveman17fdee02016-02-10 04:26:47438 gpu::SyncToken sync_token = contents_texture->CopyTexImage(
revemanc8623d5b2016-02-09 02:29:10439 texture, base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(),
440 base::Passed(&contents_texture_)));
441 *texture_mailbox = cc::TextureMailbox(
442 texture->mailbox(), sync_token, GL_TEXTURE_2D,
443 gpu_memory_buffer_->GetSize(), false /* is_overlay_candidate*/);
444 // The mailbox texture will be released when no longer used by the
445 // compositor.
revemanb195f41d2015-11-19 22:16:48446 return cc::SingleReleaseCallback::Create(
revemanc8623d5b2016-02-09 02:29:10447 base::Bind(&Buffer::Texture::Release, base::Unretained(texture),
448 base::Bind(&Buffer::ReleaseTexture, AsWeakPtr(),
449 base::Passed(&texture_))));
revemanb195f41d2015-11-19 22:16:48450}
451
452gfx::Size Buffer::GetSize() const {
453 return gpu_memory_buffer_->GetSize();
454}
455
456scoped_refptr<base::trace_event::TracedValue> Buffer::AsTracedValue() const {
457 scoped_refptr<base::trace_event::TracedValue> value =
458 new base::trace_event::TracedValue;
revemanced21f862015-11-24 00:42:49459 gfx::Size size = gpu_memory_buffer_->GetSize();
460 value->SetInteger("width", size.width());
461 value->SetInteger("height", size.height());
revemanb195f41d2015-11-19 22:16:48462 value->SetInteger("format",
463 static_cast<int>(gpu_memory_buffer_->GetFormat()));
464 return value;
465}
466
467////////////////////////////////////////////////////////////////////////////////
468// Buffer, private:
469
revemanced21f862015-11-24 00:42:49470void Buffer::Release() {
471 DCHECK_GT(use_count_, 0u);
472 if (--use_count_)
revemanb195f41d2015-11-19 22:16:48473 return;
revemanb195f41d2015-11-19 22:16:48474
revemanced21f862015-11-24 00:42:49475 // Run release callback to notify the client that buffer has been released.
476 if (!release_callback_.is_null())
477 release_callback_.Run();
478}
revemanb195f41d2015-11-19 22:16:48479
revemanc8623d5b2016-02-09 02:29:10480void Buffer::ReleaseTexture(scoped_ptr<Texture> texture) {
481 texture_ = std::move(texture);
482}
revemanced21f862015-11-24 00:42:49483
revemanc8623d5b2016-02-09 02:29:10484void Buffer::ReleaseContentsTexture(scoped_ptr<Texture> texture) {
485 TRACE_EVENT0("exo", "Buffer::ReleaseContentsTexture");
revemanced21f862015-11-24 00:42:49486
revemanc8623d5b2016-02-09 02:29:10487 contents_texture_ = std::move(texture);
488 Release();
revemanb195f41d2015-11-19 22:16:48489}
490
491} // namespace exo