// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define WAFFLE_API_VERSION 0x0106
#include <memory>
#include "base/logging.h"
#include "main.h"
#include "waffle_stuff.h"
#include <stdio.h>
GLint g_width = WINDOW_WIDTH;
GLint g_height = WINDOW_HEIGHT;
std::unique_ptr<GLInterface> g_main_gl_interface;
#ifdef USE_OPENGL
namespace gl {
#define F(fun, type) type fun = NULL;
LIST_PROC_FUNCTIONS(F)
#undef F
};
#define GL_API WAFFLE_CONTEXT_OPENGL
#else
#define GL_API WAFFLE_CONTEXT_OPENGL_ES2
#endif
#define ID_PLATFORM_GLX 1
#define ID_PLATFORM_X11_EGL 2
#define ID_PLATFORM_NULL 3
#define CONCAT(a,b) a ## b
#define PLATFORM_ID(x) CONCAT(ID_, x)
#define PLATFORM_ENUM(x) CONCAT(WAFFLE_, x)
#define THIS_IS(x) PLATFORM_ID(x) == PLATFORM_ID(PLATFORM)
#if THIS_IS(PLATFORM_GLX)
#include "waffle_glx.h"
#elif THIS_IS(PLATFORM_X11_EGL)
#include "waffle_x11_egl.h"
#elif THIS_IS(PLATFORM_NULL)
#include "waffle_null.h"
#else
#error "Compile with -DPLATFORM=PLATFORM_<x> where <x> is NULL, GLX or X11_EGL."
#endif
#define WAFFLE_CHECK_ERROR do { CHECK(WaffleOK()); } while (0)
GLInterface* GLInterface::Create() {
return new WaffleInterface;
}
static bool WaffleOK() {
const waffle_error_info *info = waffle_error_get_info();
if (info->code == WAFFLE_NO_ERROR)
return true;
printf("# Error: %s: %s\n",
waffle_error_to_string(info->code),
info->message);
return false;
}
void WaffleInterface::GetSurfaceSize(GLint *width, GLint *height) {
union waffle_native_window *nw = waffle_window_get_native(surface_);
#if THIS_IS(PLATFORM_NULL)
*width = nw->null->width;
*height = nw->null->height;
#elif THIS_IS(PLATFORM_GLX)
unsigned w, h;
#if 0
// doesn't work with mesa - https://bugs.freedesktop.org/show_bug.cgi?id=54080
glXQueryDrawable(nw->glx->xlib_display, nw->glx->xlib_window, GLX_WIDTH, &w);
glXQueryDrawable(nw->glx->xlib_display, nw->glx->xlib_window, GLX_HEIGHT, &h);
#else
Window root;
int x, y;
unsigned bd, depth;
XGetGeometry(nw->glx->xlib_display, nw->glx->xlib_window,
&root, &x, &y, &w, &h, &bd, &depth);
#endif
*width = w;
*height = h;
#elif THIS_IS(PLATFORM_X11_EGL)
EGLint w, h;
eglQuerySurface(nw->x11_egl->display.egl_display, nw->x11_egl->egl_surface,
EGL_WIDTH, &w);
eglQuerySurface(nw->x11_egl->display.egl_display, nw->x11_egl->egl_surface,
EGL_HEIGHT, &h);
*width = w;
*height = h;
#else
#error "Compile with -DPLATFORM=PLATFORM_<x> where <x> is NULL, GLX or X11_EGL."
#endif
free(nw);
}
void WaffleInterface::InitOnce() {
// Prevent multiple initializations.
if (surface_)
return;
int32_t initAttribs[] = {
WAFFLE_PLATFORM, PLATFORM_ENUM(PLATFORM),
0
};
waffle_init(initAttribs);
WAFFLE_CHECK_ERROR;
display_ = waffle_display_connect(NULL);
WAFFLE_CHECK_ERROR;
int32_t configAttribs[] = {
WAFFLE_CONTEXT_API, GL_API,
WAFFLE_RED_SIZE, 1,
WAFFLE_GREEN_SIZE, 1,
WAFFLE_BLUE_SIZE, 1,
WAFFLE_ALPHA_SIZE, 1,
WAFFLE_DEPTH_SIZE, 1,
WAFFLE_STENCIL_SIZE, 1,
WAFFLE_DOUBLE_BUFFERED, true,
0
};
config_ = waffle_config_choose(display_, configAttribs);
WAFFLE_CHECK_ERROR;
if (g_width == -1 && g_height == -1) {
const intptr_t attrib[] = {
WAFFLE_WINDOW_FULLSCREEN, 1,
0
};
surface_ = waffle_window_create2(config_, attrib);
GetSurfaceSize(&g_width, &g_height);
} else {
surface_ = waffle_window_create(config_, g_width, g_height);
}
WAFFLE_CHECK_ERROR;
waffle_window_show(surface_);
WAFFLE_CHECK_ERROR;
}
bool WaffleInterface::Init() {
InitOnce();
context_ = CreateContext();
CHECK(context_);
waffle_make_current(display_, surface_, context_);
WAFFLE_CHECK_ERROR;
#if defined(USE_OPENGL)
#define F(fun, type) fun = reinterpret_cast<type>(waffle_get_proc_address(#fun));
LIST_PROC_FUNCTIONS(F)
#undef F
#endif
return true;
}
void WaffleInterface::Cleanup() {
waffle_make_current(display_, NULL, NULL);
WAFFLE_CHECK_ERROR;
waffle_context_destroy(context_);
WAFFLE_CHECK_ERROR;
}
void WaffleInterface::SwapBuffers() {
waffle_window_swap_buffers(surface_);
WAFFLE_CHECK_ERROR;
}
bool WaffleInterface::SwapInterval(int interval) {
return false;
}
bool WaffleInterface::MakeCurrent(const GLContext& context) {
return waffle_make_current(display_, surface_, context);
}
const GLContext WaffleInterface::CreateContext() {
return waffle_context_create(config_, NULL);
}
void WaffleInterface::CheckError() {
}
void WaffleInterface::DeleteContext(const GLContext& context) {
waffle_context_destroy(context);
WAFFLE_CHECK_ERROR;
}