Don't add an aura tooltip to bubble close buttons on Windows.
[chromium-blink-merge.git] / gpu / command_buffer / service / texture_definition.cc
blobbb3c49de4e7a6c221c3df8b98795977f760a65d5
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 "gpu/command_buffer/service/texture_definition.h"
7 #include <list>
9 #include "base/memory/linked_ptr.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/synchronization/lock.h"
12 #include "gpu/command_buffer/service/texture_manager.h"
13 #include "ui/gl/gl_image.h"
14 #include "ui/gl/gl_implementation.h"
15 #include "ui/gl/scoped_binders.h"
17 #if !defined(OS_MACOSX)
18 #include "ui/gl/gl_surface_egl.h"
19 #endif
21 namespace gpu {
22 namespace gles2 {
24 namespace {
26 class GLImageSync : public gfx::GLImage {
27 public:
28 explicit GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer,
29 const gfx::Size& size);
31 // Implement GLImage.
32 void Destroy(bool have_context) override;
33 gfx::Size GetSize() override;
34 bool BindTexImage(unsigned target) override;
35 void ReleaseTexImage(unsigned target) override;
36 bool CopyTexImage(unsigned target) override;
37 void WillUseTexImage() override;
38 void WillModifyTexImage() override;
39 void DidModifyTexImage() override;
40 void DidUseTexImage() override;
41 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
42 int z_order,
43 gfx::OverlayTransform transform,
44 const gfx::Rect& bounds_rect,
45 const gfx::RectF& crop_rect) override;
47 protected:
48 ~GLImageSync() override;
50 private:
51 scoped_refptr<NativeImageBuffer> buffer_;
52 gfx::Size size_;
54 DISALLOW_COPY_AND_ASSIGN(GLImageSync);
57 GLImageSync::GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer,
58 const gfx::Size& size)
59 : buffer_(buffer), size_(size) {
60 if (buffer.get())
61 buffer->AddClient(this);
64 GLImageSync::~GLImageSync() {
65 if (buffer_.get())
66 buffer_->RemoveClient(this);
69 void GLImageSync::Destroy(bool have_context) {
72 gfx::Size GLImageSync::GetSize() {
73 return size_;
76 bool GLImageSync::BindTexImage(unsigned target) {
77 NOTREACHED();
78 return false;
81 void GLImageSync::ReleaseTexImage(unsigned target) {
82 NOTREACHED();
85 bool GLImageSync::CopyTexImage(unsigned target) {
86 return false;
89 void GLImageSync::WillUseTexImage() {
92 void GLImageSync::DidUseTexImage() {
95 void GLImageSync::WillModifyTexImage() {
98 void GLImageSync::DidModifyTexImage() {
101 bool GLImageSync::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
102 int z_order,
103 gfx::OverlayTransform transform,
104 const gfx::Rect& bounds_rect,
105 const gfx::RectF& crop_rect) {
106 NOTREACHED();
107 return false;
110 #if !defined(OS_MACOSX)
111 class NativeImageBufferEGL : public NativeImageBuffer {
112 public:
113 static scoped_refptr<NativeImageBufferEGL> Create(GLuint texture_id);
115 private:
116 NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image);
117 ~NativeImageBufferEGL() override;
118 void AddClient(gfx::GLImage* client) override;
119 void RemoveClient(gfx::GLImage* client) override;
120 bool IsClient(gfx::GLImage* client) override;
121 void BindToTexture(GLenum target) override;
123 EGLDisplay egl_display_;
124 EGLImageKHR egl_image_;
126 base::Lock lock_;
128 struct ClientInfo {
129 explicit ClientInfo(gfx::GLImage* client);
130 ~ClientInfo();
132 gfx::GLImage* client;
133 bool needs_wait_before_read;
135 std::list<ClientInfo> client_infos_;
136 gfx::GLImage* write_client_;
138 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL);
141 scoped_refptr<NativeImageBufferEGL> NativeImageBufferEGL::Create(
142 GLuint texture_id) {
143 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
144 EGLContext egl_context = eglGetCurrentContext();
146 DCHECK_NE(EGL_NO_CONTEXT, egl_context);
147 DCHECK_NE(EGL_NO_DISPLAY, egl_display);
148 DCHECK(glIsTexture(texture_id));
150 DCHECK(gfx::g_driver_egl.ext.b_EGL_KHR_image_base &&
151 gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image &&
152 gfx::g_driver_gl.ext.b_GL_OES_EGL_image);
154 const EGLint egl_attrib_list[] = {
155 EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
156 EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id);
157 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR;
159 EGLImageKHR egl_image = eglCreateImageKHR(
160 egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list);
162 if (egl_image == EGL_NO_IMAGE_KHR) {
163 LOG(ERROR) << "eglCreateImageKHR for cross-thread sharing failed: 0x"
164 << std::hex << eglGetError();
165 return NULL;
168 return new NativeImageBufferEGL(egl_display, egl_image);
171 NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client)
172 : client(client), needs_wait_before_read(true) {}
174 NativeImageBufferEGL::ClientInfo::~ClientInfo() {}
176 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display,
177 EGLImageKHR image)
178 : NativeImageBuffer(),
179 egl_display_(display),
180 egl_image_(image),
181 write_client_(NULL) {
182 DCHECK(egl_display_ != EGL_NO_DISPLAY);
183 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
186 NativeImageBufferEGL::~NativeImageBufferEGL() {
187 DCHECK(client_infos_.empty());
188 if (egl_image_ != EGL_NO_IMAGE_KHR)
189 eglDestroyImageKHR(egl_display_, egl_image_);
192 void NativeImageBufferEGL::AddClient(gfx::GLImage* client) {
193 base::AutoLock lock(lock_);
194 client_infos_.push_back(ClientInfo(client));
197 void NativeImageBufferEGL::RemoveClient(gfx::GLImage* client) {
198 base::AutoLock lock(lock_);
199 if (write_client_ == client)
200 write_client_ = NULL;
201 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
202 it != client_infos_.end();
203 it++) {
204 if (it->client == client) {
205 client_infos_.erase(it);
206 return;
209 NOTREACHED();
212 bool NativeImageBufferEGL::IsClient(gfx::GLImage* client) {
213 base::AutoLock lock(lock_);
214 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
215 it != client_infos_.end();
216 it++) {
217 if (it->client == client)
218 return true;
220 return false;
223 void NativeImageBufferEGL::BindToTexture(GLenum target) {
224 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
225 glEGLImageTargetTexture2DOES(target, egl_image_);
226 DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError());
227 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
230 #endif
232 class NativeImageBufferStub : public NativeImageBuffer {
233 public:
234 NativeImageBufferStub() : NativeImageBuffer() {}
236 private:
237 ~NativeImageBufferStub() override {}
238 void AddClient(gfx::GLImage* client) override {}
239 void RemoveClient(gfx::GLImage* client) override {}
240 bool IsClient(gfx::GLImage* client) override { return true; }
241 void BindToTexture(GLenum target) override {}
243 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub);
246 } // anonymous namespace
248 // static
249 scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) {
250 switch (gfx::GetGLImplementation()) {
251 #if !defined(OS_MACOSX)
252 case gfx::kGLImplementationEGLGLES2:
253 return NativeImageBufferEGL::Create(texture_id);
254 #endif
255 case gfx::kGLImplementationMockGL:
256 return new NativeImageBufferStub;
257 default:
258 NOTREACHED();
259 return NULL;
263 TextureDefinition::LevelInfo::LevelInfo()
264 : target(0),
265 internal_format(0),
266 width(0),
267 height(0),
268 depth(0),
269 border(0),
270 format(0),
271 type(0),
272 cleared(false) {
275 TextureDefinition::LevelInfo::LevelInfo(GLenum target,
276 GLenum internal_format,
277 GLsizei width,
278 GLsizei height,
279 GLsizei depth,
280 GLint border,
281 GLenum format,
282 GLenum type,
283 bool cleared)
284 : target(target),
285 internal_format(internal_format),
286 width(width),
287 height(height),
288 depth(depth),
289 border(border),
290 format(format),
291 type(type),
292 cleared(cleared) {}
294 TextureDefinition::LevelInfo::~LevelInfo() {}
296 TextureDefinition::TextureDefinition()
297 : version_(0),
298 target_(0),
299 min_filter_(0),
300 mag_filter_(0),
301 wrap_s_(0),
302 wrap_t_(0),
303 usage_(0),
304 immutable_(true) {
307 TextureDefinition::TextureDefinition(
308 Texture* texture,
309 unsigned int version,
310 const scoped_refptr<NativeImageBuffer>& image_buffer)
311 : version_(version),
312 target_(texture->target()),
313 image_buffer_(image_buffer),
314 min_filter_(texture->min_filter()),
315 mag_filter_(texture->mag_filter()),
316 wrap_s_(texture->wrap_s()),
317 wrap_t_(texture->wrap_t()),
318 usage_(texture->usage()),
319 immutable_(texture->IsImmutable()),
320 defined_(texture->IsDefined()) {
321 DCHECK_IMPLIES(image_buffer_.get(), defined_);
322 if (!image_buffer_.get() && defined_) {
323 image_buffer_ = NativeImageBuffer::Create(texture->service_id());
324 DCHECK(image_buffer_.get());
327 const Texture::FaceInfo& first_face = texture->face_infos_[0];
328 if (image_buffer_.get()) {
329 scoped_refptr<gfx::GLImage> gl_image(
330 new GLImageSync(image_buffer_,
331 gfx::Size(first_face.level_infos[0].width,
332 first_face.level_infos[0].height)));
333 texture->SetLevelImage(NULL, target_, 0, gl_image.get());
336 const Texture::LevelInfo& level = first_face.level_infos[0];
337 level_info_ = LevelInfo(level.target, level.internal_format, level.width,
338 level.height, level.depth, level.border, level.format,
339 level.type, level.cleared);
342 TextureDefinition::~TextureDefinition() {
345 Texture* TextureDefinition::CreateTexture() const {
346 GLuint texture_id;
347 glGenTextures(1, &texture_id);
349 Texture* texture(new Texture(texture_id));
350 UpdateTexture(texture);
352 return texture;
355 void TextureDefinition::UpdateTexture(Texture* texture) const {
356 gfx::ScopedTextureBinder texture_binder(target_, texture->service_id());
357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_);
358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_);
359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_);
360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_);
361 if (image_buffer_.get())
362 image_buffer_->BindToTexture(target_);
363 // We have to make sure the changes are visible to other clients in this share
364 // group. As far as the clients are concerned, the mailbox semantics only
365 // demand a single flush from the client after changes are first made,
366 // and it is not visible to them when another share group boundary is crossed.
367 // We could probably track this and be a bit smarter about when to flush
368 // though.
369 glFlush();
371 if (defined_) {
372 texture->face_infos_.resize(1);
373 texture->face_infos_[0].level_infos.resize(1);
374 texture->SetLevelInfo(NULL, level_info_.target, 0,
375 level_info_.internal_format, level_info_.width,
376 level_info_.height, level_info_.depth,
377 level_info_.border, level_info_.format,
378 level_info_.type, level_info_.cleared);
381 if (image_buffer_.get()) {
382 texture->SetLevelImage(
383 NULL,
384 target_,
386 new GLImageSync(
387 image_buffer_,
388 gfx::Size(level_info_.width, level_info_.height)));
391 texture->target_ = target_;
392 texture->SetImmutable(immutable_);
393 texture->min_filter_ = min_filter_;
394 texture->mag_filter_ = mag_filter_;
395 texture->wrap_s_ = wrap_s_;
396 texture->wrap_t_ = wrap_t_;
397 texture->usage_ = usage_;
400 bool TextureDefinition::Matches(const Texture* texture) const {
401 DCHECK(target_ == texture->target());
402 if (texture->min_filter_ != min_filter_ ||
403 texture->mag_filter_ != mag_filter_ ||
404 texture->wrap_s_ != wrap_s_ ||
405 texture->wrap_t_ != wrap_t_ ||
406 texture->SafeToRenderFrom() != SafeToRenderFrom()) {
407 return false;
410 // Texture became defined.
411 if (!image_buffer_.get() && texture->IsDefined())
412 return false;
414 // All structural changes should have orphaned the texture.
415 if (image_buffer_.get() && !texture->GetLevelImage(texture->target(), 0))
416 return false;
418 return true;
421 bool TextureDefinition::SafeToRenderFrom() const {
422 return level_info_.cleared;
425 } // namespace gles2
426 } // namespace gpu