Index: ui/ozone/platform/drm/gpu/gbm_surface.cc |
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface.cc b/ui/ozone/platform/drm/gpu/gbm_surface.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..566d0c7c0742a53455406317745a24bde950ddfa |
--- /dev/null |
+++ b/ui/ozone/platform/drm/gpu/gbm_surface.cc |
@@ -0,0 +1,148 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/ozone/platform/drm/gpu/gbm_surface.h" |
+ |
+#include <utility> |
+ |
+#include "base/logging.h" |
+#include "ui/gl/gl_surface_egl.h" |
+#include "ui/ozone/gl/gl_image_ozone_native_pixmap.h" |
+#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h" |
+#include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h" |
+#include "ui/ozone/public/native_pixmap.h" |
+ |
+namespace ui { |
+ |
+GbmSurface::GbmSurface(GbmSurfaceFactory* surface_factory, |
+ std::unique_ptr<DrmWindowProxy> window, |
+ gfx::AcceleratedWidget widget) |
+ : GbmSurfaceless(surface_factory, std::move(window), widget) { |
+ for (auto& texture : textures_) |
+ texture = 0; |
+} |
+ |
+unsigned int GbmSurface::GetBackingFrameBufferObject() { |
+ return fbo_; |
+} |
+ |
+bool GbmSurface::OnMakeCurrent(gl::GLContext* context) { |
+ DCHECK(!context_ || context == context_); |
+ context_ = context; |
+ if (!fbo_) { |
+ glGenFramebuffersEXT(1, &fbo_); |
+ if (!fbo_) |
+ return false; |
+ glGenTextures(arraysize(textures_), textures_); |
+ if (!CreatePixmaps()) |
+ return false; |
+ } |
+ BindFramebuffer(); |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_); |
+ return SurfacelessEGL::OnMakeCurrent(context); |
+} |
+ |
+bool GbmSurface::Resize(const gfx::Size& size, |
+ float scale_factor, |
+ bool has_alpha) { |
+ if (size == GetSize()) |
+ return true; |
+ // Alpha value isn't actually used in allocating buffers yet, so always use |
+ // true instead. |
+ return GbmSurfaceless::Resize(size, scale_factor, true) && CreatePixmaps(); |
+} |
+ |
+bool GbmSurface::SupportsPostSubBuffer() { |
+ return false; |
+} |
+ |
+void GbmSurface::SwapBuffersAsync(const SwapCompletionCallback& callback) { |
+ if (!images_[current_surface_]->ScheduleOverlayPlane( |
+ widget(), 0, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE, |
+ gfx::Rect(GetSize()), gfx::RectF(1, 1))) { |
+ callback.Run(gfx::SwapResult::SWAP_FAILED); |
+ return; |
+ } |
+ GbmSurfaceless::SwapBuffersAsync(callback); |
+ current_surface_ ^= 1; |
+ BindFramebuffer(); |
+} |
+ |
+void GbmSurface::Destroy() { |
+ if (!context_) |
+ return; |
+ scoped_refptr<gl::GLContext> previous_context = gl::GLContext::GetCurrent(); |
+ scoped_refptr<GLSurface> previous_surface; |
+ |
+ bool was_current = previous_context && previous_context->IsCurrent(nullptr) && |
+ GLSurface::GetCurrent() == this; |
+ if (!was_current) { |
+ // Only take a reference to previous surface if it's not |this| |
+ // because otherwise we can take a self reference from our own dtor. |
+ previous_surface = GLSurface::GetCurrent(); |
+ context_->MakeCurrent(this); |
+ } |
+ |
+ glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
+ if (fbo_) { |
+ glDeleteTextures(arraysize(textures_), textures_); |
+ for (auto& texture : textures_) |
+ texture = 0; |
+ glDeleteFramebuffersEXT(1, &fbo_); |
+ fbo_ = 0; |
+ } |
+ for (auto image : images_) { |
+ if (image) |
+ image->Destroy(true); |
+ } |
+ |
+ if (!was_current) { |
+ if (previous_context) { |
+ previous_context->MakeCurrent(previous_surface.get()); |
+ } else { |
+ context_->ReleaseCurrent(this); |
+ } |
+ } |
+} |
+ |
+bool GbmSurface::IsSurfaceless() const { |
+ return false; |
+} |
+ |
+GbmSurface::~GbmSurface() { |
+ Destroy(); |
+} |
+ |
+void GbmSurface::BindFramebuffer() { |
+ gl::ScopedFrameBufferBinder fb(fbo_); |
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, |
+ textures_[current_surface_], 0); |
+} |
+ |
+bool GbmSurface::CreatePixmaps() { |
+ if (!fbo_) |
+ return true; |
+ for (size_t i = 0; i < arraysize(textures_); i++) { |
+ scoped_refptr<NativePixmap> pixmap = surface_factory()->CreateNativePixmap( |
+ widget(), GetSize(), gfx::BufferFormat::BGRA_8888, |
+ gfx::BufferUsage::SCANOUT); |
+ if (!pixmap) |
+ return false; |
+ scoped_refptr<GLImageOzoneNativePixmap> image = |
+ new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT); |
+ if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888)) |
+ return false; |
+ // GLImage must have Destroy() called before destructor is called. |
+ if (images_[i]) |
+ images_[i]->Destroy(true); |
+ images_[i] = image; |
+ // Bind image to texture. |
+ gl::ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]); |
+ if (!images_[i]->BindTexImage(GL_TEXTURE_2D)) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+} // namespace ui |