blob: 5992071ac18766e20fb07085aac3f337d51c4a6b [file] [log] [blame]
// Copyright 2015 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/gl/gl_surface_osmesa_x11.h"
#include <X11/Xlib.h>
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/trace_event/trace_event.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface_egl.h"
namespace gfx {
// static
bool GLSurface::InitializeOneOffInternal() {
if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) {
LOG(ERROR) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed.";
return false;
}
return true;
}
// static
bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
static bool initialized = false;
if (initialized)
return true;
if (!GetXDisplay()) {
LOG(ERROR) << "XOpenDisplay failed.";
return false;
}
initialized = true;
return true;
}
scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
gfx::AcceleratedWidget window,
const gfx::SurfaceConfiguration& requested_configuration) {
TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface");
scoped_refptr<GLSurface> surface(
new NativeViewGLSurfaceOSMesa(window, requested_configuration));
if (!surface->Initialize())
return NULL;
return surface;
}
scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
const gfx::Size& size,
const gfx::SurfaceConfiguration& requested_configuration) {
TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface");
scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(
OSMesaSurfaceFormatRGBA, size, requested_configuration));
if (!surface->Initialize())
return NULL;
return surface;
}
NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
AcceleratedWidget window,
const SurfaceConfiguration& requested_configuration)
: GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA,
Size(1, 1),
requested_configuration),
xdisplay_(GetXDisplay()),
window_graphics_context_(0),
window_(window),
pixmap_graphics_context_(0),
pixmap_(0) {
DCHECK(xdisplay_);
DCHECK(window_);
}
bool NativeViewGLSurfaceOSMesa::Initialize() {
if (!GLSurfaceOSMesa::Initialize())
return false;
window_graphics_context_ = XCreateGC(xdisplay_, window_, 0, NULL);
if (!window_graphics_context_) {
LOG(ERROR) << "XCreateGC failed.";
Destroy();
return false;
}
return true;
}
void NativeViewGLSurfaceOSMesa::Destroy() {
if (pixmap_graphics_context_) {
XFreeGC(xdisplay_, pixmap_graphics_context_);
pixmap_graphics_context_ = NULL;
}
if (pixmap_) {
XFreePixmap(xdisplay_, pixmap_);
pixmap_ = 0;
}
if (window_graphics_context_) {
XFreeGC(xdisplay_, window_graphics_context_);
window_graphics_context_ = NULL;
}
XSync(xdisplay_, False);
}
bool NativeViewGLSurfaceOSMesa::Resize(const Size& new_size) {
if (!GLSurfaceOSMesa::Resize(new_size))
return false;
XWindowAttributes attributes;
if (!XGetWindowAttributes(xdisplay_, window_, &attributes)) {
LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
return false;
}
// Destroy the previous pixmap and graphics context.
if (pixmap_graphics_context_) {
XFreeGC(xdisplay_, pixmap_graphics_context_);
pixmap_graphics_context_ = NULL;
}
if (pixmap_) {
XFreePixmap(xdisplay_, pixmap_);
pixmap_ = 0;
}
// Recreate a pixmap to hold the frame.
pixmap_ = XCreatePixmap(xdisplay_, window_, new_size.width(),
new_size.height(), attributes.depth);
if (!pixmap_) {
LOG(ERROR) << "XCreatePixmap failed.";
return false;
}
// Recreate a graphics context for the pixmap.
pixmap_graphics_context_ = XCreateGC(xdisplay_, pixmap_, 0, NULL);
if (!pixmap_graphics_context_) {
LOG(ERROR) << "XCreateGC failed";
return false;
}
return true;
}
bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
return false;
}
bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
TRACE_EVENT2("gpu", "NativeViewGLSurfaceOSMesa:RealSwapBuffers", "width",
GetSize().width(), "height", GetSize().height());
Size size = GetSize();
XWindowAttributes attributes;
if (!XGetWindowAttributes(xdisplay_, window_, &attributes)) {
LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
return false;
}
// Copy the frame into the pixmap.
PutARGBImage(xdisplay_, attributes.visual, attributes.depth, pixmap_,
pixmap_graphics_context_, static_cast<const uint8*>(GetHandle()),
size.width(), size.height());
// Copy the pixmap to the window.
XCopyArea(xdisplay_, pixmap_, window_, window_graphics_context_, 0, 0,
size.width(), size.height(), 0, 0);
return true;
}
bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() {
return true;
}
bool NativeViewGLSurfaceOSMesa::PostSubBuffer(int x,
int y,
int width,
int height) {
Size size = GetSize();
// Move (0,0) from lower-left to upper-left
y = size.height() - y - height;
XWindowAttributes attributes;
if (!XGetWindowAttributes(xdisplay_, window_, &attributes)) {
LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
return false;
}
// Copy the frame into the pixmap.
PutARGBImage(xdisplay_, attributes.visual, attributes.depth, pixmap_,
pixmap_graphics_context_, static_cast<const uint8*>(GetHandle()),
size.width(), size.height(), x, y, x, y, width, height);
// Copy the pixmap to the window.
XCopyArea(xdisplay_, pixmap_, window_, window_graphics_context_, x, y, width,
height, x, y);
return true;
}
NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
Destroy();
}
EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
return gfx::GetXDisplay();
}
}