st/egl: Remove.

Largely superseeded by src/egl, and
WGL/GLX_EXT_create_context_es_profile extensions.

Note this will break Android.mk with gallium drivers -- somebody
familiar with that build infrastructure will need to update it to use
gallium drivers through egl_dri2.

v2: Remove the _EGL_BUILT_IN_DRIVER_GALLIUM define from
src/egl/main/Android.mk; and update the src/egl/main/Sconscript to
create a SharedLibrary, add versioning, create symlink - copy the bits
from egl-static, per Emil Velikov.

Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>

v3: Disallow undefined symbols in libEGL.so.  Update release notes
This commit is contained in:
Jose Fonseca
2015-03-03 16:01:22 +00:00
parent 17b2825d76
commit 5564c361b5
63 changed files with 12 additions and 12965 deletions
+3 -26
View File
@@ -212,38 +212,15 @@ the X server directly using (XCB-)DRI2 protocol.</p>
</dd>
<dt><code>egl_gallium</code></dt>
<dd>
<p>This driver is based on Gallium3D. It supports all rendering APIs and
hardware supported by Gallium3D. It is the only driver that supports OpenVG.
The supported platforms are X11, DRM, FBDEV, and GDI.</p>
<p>This driver comes with its own hardware drivers
(<code>pipe_&lt;hw&gt;</code>) and client API modules
(<code>st_&lt;api&gt;</code>).</p>
</dd>
<h2>Packaging</h2>
<p>The ABI between the main library and its drivers are not stable. Nor is
there a plan to stabilize it at the moment. Of the EGL drivers,
<code>egl_gallium</code> has its own hardware drivers and client API modules.
They are considered internal to <code>egl_gallium</code> and there is also no
stable ABI between them. These should be kept in mind when packaging for
distribution.</p>
<p>Generally, <code>egl_dri2</code> is preferred over <code>egl_gallium</code>
when the system already has DRI drivers. As <code>egl_gallium</code> is loaded
before <code>egl_dri2</code> when both are available, <code>egl_gallium</code>
is disabled by default.</p>
there a plan to stabilize it at the moment.</p>
<h2>Developers</h2>
<p>The sources of the main library and the classic drivers can be found at
<code>src/egl/</code>. The sources of the <code>egl</code> state tracker can
be found at <code>src/gallium/state_trackers/egl/</code>.</p>
<p>The sources of the main library and drivers can be found at
<code>src/egl/</code>.</p>
<h3>Lifetime of Display Resources</h3>
+1
View File
@@ -60,6 +60,7 @@ TBD.
<ul>
<li>Removed classic Windows software rasterizer.</li>
<li>Removed egl_gallium EGL driver.</li>
</ul>
</div>
-1
View File
@@ -133,7 +133,6 @@ each directory.
<ul>
<li><b>clover</b> - OpenCL state tracker
<li><b>dri</b> - Meta state tracker for DRI drivers
<li><b>egl</b> - Meta state tracker for EGL drivers
<li><b>glx</b> - Meta state tracker for GLX
<li><b>vdpau</b> - VDPAU state tracker
<li><b>vega</b> - OpenVG 1.x state tracker
-2
View File
@@ -73,8 +73,6 @@ endif # MESA_BUILD_CLASSIC
ifeq ($(strip $(MESA_BUILD_GALLIUM)),true)
LOCAL_CFLAGS += -D_EGL_BUILT_IN_DRIVER_GALLIUM
gallium_DRIVERS :=
# swrast
+8 -4
View File
@@ -7,7 +7,6 @@ Import('*')
env = env.Clone()
env.Append(CPPDEFINES = [
'_EGL_BUILT_IN_DRIVER_GALLIUM',
'_EGL_DRIVER_SEARCH_DIR=\\"\\"',
])
@@ -38,6 +37,9 @@ else:
egl_dri2,
libloader,
])
# Disallow undefined symbols
if env['platform'] != 'darwin':
env.Append(SHLINKFLAGS = ['-Wl,-z,defs'])
env.Append(CPPPATH = [
'#/include',
@@ -47,9 +49,11 @@ env.Append(CPPPATH = [
# parse Makefile.sources
egl_sources = env.ParseSourceList('Makefile.sources', 'LIBEGL_C_FILES')
egl = env.ConvenienceLibrary(
target = 'egl',
egl = env.SharedLibrary(
target = 'EGL',
source = egl_sources,
)
Export('egl')
egl = env.InstallSharedLibrary(egl, version=(1, 0, 0))
env.Alias('egl', egl)
-3
View File
@@ -70,9 +70,6 @@ const struct {
const char *name;
_EGLMain_t main;
} _eglBuiltInDrivers[] = {
#ifdef _EGL_BUILT_IN_DRIVER_GALLIUM
{ "egl_gallium", _eglBuiltInDriverGALLIUM },
#endif
#ifdef _EGL_BUILT_IN_DRIVER_DRI2
{ "egl_dri2", _eglBuiltInDriverDRI2 },
#endif
-5
View File
@@ -79,10 +79,5 @@ ifneq ($(filter vmwgfx, $(MESA_GPU_DRIVERS)),)
SUBDIRS += winsys/svga/drm drivers/svga
endif
#
# Gallium state trackers and their users (targets)
#
SUBDIRS += state_trackers/egl targets/egl-static
mkfiles := $(patsubst %,$(GALLIUM_TOP)/%/Android.mk,$(SUBDIRS))
include $(mkfiles)
-2
View File
@@ -114,9 +114,7 @@ EXTRA_DIST = \
docs \
README.portability \
SConscript \
state_trackers/egl \
state_trackers/gbm \
targets/egl-static \
targets/gbm \
winsys/sw/gdi \
winsys/sw/hgl
-5
View File
@@ -62,11 +62,6 @@ SConscript([
if not env['embedded']:
SConscript('state_trackers/vega/SConscript')
if env['platform'] not in ('cygwin', 'darwin', 'freebsd', 'sunos'):
SConscript([
'state_trackers/egl/SConscript',
'targets/egl-static/SConscript',
])
if env['x11']:
SConscript([
-55
View File
@@ -1,55 +0,0 @@
# Mesa 3-D graphics library
#
# Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
# Copyright (C) 2010-2011 LunarG Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
LOCAL_PATH := $(call my-dir)
# get common_FILES, android_FILES
include $(LOCAL_PATH)/Makefile.sources
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(common_FILES) \
$(android_FILES)
LOCAL_CFLAGS := \
-DFEATURE_ES1=1 \
-DFEATURE_ES2=1 \
-DHAVE_ANDROID_BACKEND
LOCAL_C_INCLUDES := \
$(GALLIUM_TOP)/state_trackers/egl \
$(GALLIUM_TOP)/winsys \
$(MESA_TOP)/src/egl/main
# swrast only
ifeq ($(MESA_GPU_DRIVERS),swrast)
LOCAL_CFLAGS += -DANDROID_BACKEND_NO_DRM
else
LOCAL_C_INCLUDES += $(DRM_GRALLOC_TOP)
endif
LOCAL_MODULE := libmesa_st_egl
include $(GALLIUM_COMMON_MK)
include $(BUILD_STATIC_LIBRARY)
-111
View File
@@ -1,111 +0,0 @@
# Copyright © 2012 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
AUTOMAKE_OPTIONS = subdir-objects
include Makefile.sources
include $(top_srcdir)/src/gallium/Automake.inc
AM_CFLAGS = \
$(GALLIUM_CFLAGS) \
$(VISIBILITY_CFLAGS) \
$(MSVC2013_COMPAT_CFLAGS)
AM_CPPFLAGS = \
-I$(top_srcdir)/src/egl/main \
-I$(top_builddir)/src/egl/wayland/wayland-drm/ \
-I$(top_srcdir)/src/gallium/winsys
noinst_LTLIBRARIES = libegl.la
libegl_la_SOURCES = $(common_FILES)
if HAVE_EGL_PLATFORM_X11
libegl_la_SOURCES += $(x11_FILES) $(x11_drm_FILES)
AM_CFLAGS += \
$(X11_INCLUDES) \
$(LIBDRM_CFLAGS) \
$(DRI2PROTO_CFLAGS)
AM_CPPFLAGS += \
-I$(top_srcdir)/src/glx \
-I$(top_srcdir)/src/mapi \
-I$(top_srcdir)/src/mesa \
-DHAVE_X11_BACKEND
endif
if HAVE_EGL_PLATFORM_WAYLAND
libegl_la_SOURCES += $(wayland_FILES)
AM_CFLAGS += \
$(LIBDRM_CFLAGS) \
$(WAYLAND_CFLAGS)
AM_CPPFLAGS += \
-I$(top_srcdir)/src/egl/wayland/wayland-egl \
-I$(top_srcdir)/src/egl/wayland/wayland-drm \
-I$(top_builddir)/src/egl/wayland/wayland-drm \
-DHAVE_WAYLAND_BACKEND
endif
if HAVE_EGL_PLATFORM_DRM
libegl_la_SOURCES += $(drm_FILES)
AM_CFLAGS += \
$(LIBDRM_CFLAGS)
AM_CPPFLAGS += \
-I$(top_srcdir)/src/loader \
-I$(top_srcdir)/src/gbm/main \
-I$(top_srcdir)/src/gallium/state_trackers/gbm \
-DHAVE_DRM_BACKEND
endif
if HAVE_EGL_PLATFORM_FBDEV
libegl_la_SOURCES += $(fbdev_FILES)
AM_CPPFLAGS += \
-DHAVE_FBDEV_BACKEND
endif
if HAVE_EGL_PLATFORM_NULL
libegl_la_SOURCES += $(null_FILES)
AM_CPPFLAGS += \
-DHAVE_NULL_BACKEND
endif
if HAVE_OPENGL
AM_CPPFLAGS += \
-DFEATURE_GL=1
endif
if HAVE_OPENGL_ES1
AM_CPPFLAGS += \
-DFEATURE_ES1=1
endif
if HAVE_OPENGL_ES2
AM_CPPFLAGS += \
-DFEATURE_ES2=1
endif
if HAVE_OPENVG
AM_CPPFLAGS += \
-DFEATURE_VG=1
endif
EXTRA_DIST = \
SConscript \
$(android_FILES) $(gdi_FILES)
@@ -1,57 +0,0 @@
common_FILES := \
common/egl_g3d_api.c \
common/egl_g3d_api.h \
common/egl_g3d.c \
common/egl_g3d.h \
common/egl_g3d_image.c \
common/egl_g3d_image.h \
common/egl_g3d_loader.h \
common/egl_g3d_st.c \
common/egl_g3d_st.h \
common/egl_g3d_sync.c \
common/egl_g3d_sync.h \
common/native.h \
common/native_buffer.h \
common/native_helper.c \
common/native_helper.h \
common/native_modeset.h \
common/native_wayland_bufmgr.h \
common/native_wayland_drm_bufmgr.c \
common/native_wayland_drm_bufmgr.h
android_FILES := \
android/native_android.cpp
drm_FILES := \
drm/modeset.c \
drm/native_drm.c \
drm/native_drm.h
fbdev_FILES := \
fbdev/native_fbdev.c
gdi_FILES := \
gdi/native_gdi.c
null_FILES := \
null/native_null.c
wayland_FILES := \
wayland/native_drm.c \
wayland/native_shm.c \
wayland/native_wayland.c \
wayland/native_wayland.h
x11_FILES := \
x11/glcore.h \
x11/glxinit.c \
x11/glxinit.h \
x11/native_dri2.c \
x11/native_x11.c \
x11/native_x11.h \
x11/native_ximage.c
x11_drm_FILES := \
x11/dri2.c \
x11/x11_screen.c \
x11/x11_screen.h
-62
View File
@@ -1,62 +0,0 @@
#######################################################################
# SConscript for egl state_tracker
Import('*')
env = env.Clone()
env.Append(CPPPATH = [
'#/src/egl/main',
'#/src/gallium/winsys',
'#/src/gallium/winsys/sw',
'.',
])
sources = env.ParseSourceList('Makefile.sources', 'common_FILES')
# OpenGL ES and OpenGL
if env['gles']:
env.Append(CPPDEFINES = [
'FEATURE_GL=1',
'FEATURE_ES1=1',
'FEATURE_ES2=1'
])
# OpenVG
if True:
env.Append(CPPDEFINES = ['FEATURE_VG=1'])
if env['platform'] == 'windows':
env.Append(CPPDEFINES = ['HAVE_GDI_BACKEND'])
sources.append(env.ParseSourceList('Makefile.sources', 'gdi_FILES'))
else:
if env['drm']:
env.PkgUseModules('DRM')
if env['x11']:
env.Append(CPPDEFINES = ['HAVE_X11_BACKEND'])
env.Prepend(CPPPATH = [
'#/src/glx',
'#/src/mapi',
])
sources.append(env.ParseSourceList('Makefile.sources', 'x11_FILES'))
if env['drm']:
env.Append(CPPDEFINES = ['GLX_DIRECT_RENDERING'])
sources.append(env.ParseSourceList('Makefile.sources', 'x11_drm_FILES'))
if env['drm'] and False:
# XXX: Disabled as it depends on gbm, which is not yet built with scons
env.Append(CPPDEFINES = ['HAVE_DRM_BACKEND'])
env.Append(CPPPATH = [
'#/src/loader',
'#/src/gbm/main',
'#/src/gallium/state_trackers/gbm',
])
env.Prepend(LIBS = [
libloader
])
sources.append(env.ParseSourceList('Makefile.sources', 'drm_FILES'))
st_egl = env.ConvenienceLibrary(
target = 'st_egl',
source = sources,
)
Export('st_egl')
@@ -1,892 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
* Copyright (C) 2010-2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#define LOG_TAG "EGL-GALLIUM"
#if ANDROID_VERSION >= 0x0400
#if ANDROID_VERSION >= 0x0402
#include <sync/sync.h>
#endif
#include <stdlib.h>
#include <system/window.h>
#else /* ANDROID_VERSION >= 0x0400 */
#define android_native_buffer_t ANativeWindowBuffer
#include <ui/egl/android_natives.h>
#include <ui/android_native_buffer.h>
#endif /* ANDROID_VERSION >= 0x0400 */
#if ANDROID_VERSION < 0x0402
/* rename to old logging macros */
#define ALOGE(...) LOGE(__VA_ARGS__)
#define ALOGW(...) LOGW(__VA_ARGS__)
#define ALOGI(...) LOGI(__VA_ARGS__)
#define ALOGD(...) LOGD(__VA_ARGS__)
#endif
#include <hardware/gralloc.h>
#include <cutils/properties.h>
#include <cutils/log.h>
#include <utils/Errors.h>
extern "C" {
#include "egllog.h"
}
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_box.h"
#include "common/native.h"
#include "common/native_helper.h"
#include "state_tracker/drm_driver.h"
#include "sw/android/android_sw_winsys.h"
struct android_config;
struct android_display {
struct native_display base;
boolean use_drm;
const struct native_event_handler *event_handler;
struct android_config *configs;
int num_configs;
};
struct android_surface {
struct native_surface base;
struct android_display *adpy;
ANativeWindow *win;
/* staging color buffer for when buffer preserving is enabled */
struct pipe_resource *color_res;
uint stamp;
ANativeWindowBuffer *buf;
struct pipe_resource *buf_res;
/* cache the current back buffers */
struct {
int width;
int height;
int format;
} cache_key;
void *cache_handles[2];
struct pipe_resource *cache_resources[2];
};
struct android_config {
struct native_config base;
};
static INLINE struct android_display *
android_display(const struct native_display *ndpy)
{
return (struct android_display *) ndpy;
}
static INLINE struct android_surface *
android_surface(const struct native_surface *nsurf)
{
return (struct android_surface *) nsurf;
}
static INLINE struct android_config *
android_config(const struct native_config *nconf)
{
return (struct android_config *) nconf;
}
namespace android {
static enum pipe_format
get_pipe_format(int native)
{
enum pipe_format fmt;
switch (native) {
case HAL_PIXEL_FORMAT_RGBA_8888:
fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
break;
case HAL_PIXEL_FORMAT_RGBX_8888:
fmt = PIPE_FORMAT_R8G8B8X8_UNORM;
break;
case HAL_PIXEL_FORMAT_RGB_888:
fmt = PIPE_FORMAT_R8G8B8_UNORM;
break;
case HAL_PIXEL_FORMAT_RGB_565:
fmt = PIPE_FORMAT_B5G6R5_UNORM;
break;
case HAL_PIXEL_FORMAT_BGRA_8888:
fmt = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
default:
ALOGE("unsupported native format 0x%x", native);
fmt = PIPE_FORMAT_NONE;
break;
}
return fmt;
}
#ifndef ANDROID_BACKEND_NO_DRM
extern "C" {
#include <gralloc_drm.h>
}
static int
get_handle_name(buffer_handle_t handle)
{
return gralloc_drm_get_gem_handle(handle);
}
#else
static int
get_handle_name(buffer_handle_t handle)
{
return 0;
}
#endif /* ANDROID_BACKEND_NO_DRM */
/**
* Import an ANativeWindowBuffer allocated by the server.
*/
static struct pipe_resource *
import_buffer(struct android_display *adpy, const struct pipe_resource *templ,
ANativeWindowBuffer *abuf)
{
struct pipe_screen *screen = adpy->base.screen;
struct pipe_resource *res;
if (templ->bind & PIPE_BIND_RENDER_TARGET) {
if (!screen->is_format_supported(screen, templ->format,
templ->target, 0, PIPE_BIND_RENDER_TARGET))
ALOGW("importing unsupported buffer as render target");
}
if (templ->bind & PIPE_BIND_SAMPLER_VIEW) {
if (!screen->is_format_supported(screen, templ->format,
templ->target, 0, PIPE_BIND_SAMPLER_VIEW))
ALOGW("importing unsupported buffer as sampler view");
}
if (adpy->use_drm) {
struct winsys_handle handle;
memset(&handle, 0, sizeof(handle));
handle.type = DRM_API_HANDLE_TYPE_SHARED;
/* for DRM, we need the GEM name */
handle.handle = get_handle_name(abuf->handle);
if (!handle.handle) {
ALOGE("unable to import invalid buffer %p", abuf);
return NULL;
}
handle.stride =
abuf->stride * util_format_get_blocksize(templ->format);
res = screen->resource_from_handle(screen, templ, &handle);
}
else {
struct android_winsys_handle handle;
memset(&handle, 0, sizeof(handle));
handle.handle = abuf->handle;
handle.stride =
abuf->stride * util_format_get_blocksize(templ->format);
res = screen->resource_from_handle(screen,
templ, (struct winsys_handle *) &handle);
}
if (!res)
ALOGE("failed to import buffer %p", abuf);
return res;
}
static void
android_surface_clear_cache(struct native_surface *nsurf)
{
struct android_surface *asurf = android_surface(nsurf);
int i;
for (i = 0; i < Elements(asurf->cache_handles); i++) {
asurf->cache_handles[i] = NULL;
pipe_resource_reference(&asurf->cache_resources[i], NULL);
}
memset(&asurf->cache_key, 0, sizeof(asurf->cache_key));
}
static struct pipe_resource *
android_surface_add_cache(struct native_surface *nsurf,
ANativeWindowBuffer *abuf)
{
struct android_surface *asurf = android_surface(nsurf);
void *handle;
int idx;
/* how about abuf->usage? */
if (asurf->cache_key.width != abuf->width ||
asurf->cache_key.height != abuf->height ||
asurf->cache_key.format != abuf->format)
android_surface_clear_cache(&asurf->base);
if (asurf->adpy->use_drm)
handle = (void *) get_handle_name(abuf->handle);
else
handle = (void *) abuf->handle;
/* NULL is invalid */
if (!handle) {
ALOGE("invalid buffer native buffer %p", abuf);
return NULL;
}
/* find the slot to use */
for (idx = 0; idx < Elements(asurf->cache_handles); idx++) {
if (asurf->cache_handles[idx] == handle || !asurf->cache_handles[idx])
break;
}
if (idx == Elements(asurf->cache_handles)) {
ALOGW("cache full: buf %p, width %d, height %d, format %d, usage 0x%x",
abuf, abuf->width, abuf->height, abuf->format, abuf->usage);
android_surface_clear_cache(&asurf->base);
idx = 0;
}
if (idx == 0) {
asurf->cache_key.width = abuf->width;
asurf->cache_key.height = abuf->height;
asurf->cache_key.format = abuf->format;
}
if (!asurf->cache_handles[idx]) {
struct pipe_resource templ;
assert(!asurf->cache_resources[idx]);
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = get_pipe_format(asurf->buf->format);
templ.bind = PIPE_BIND_RENDER_TARGET;
if (!asurf->adpy->use_drm) {
templ.bind |= PIPE_BIND_TRANSFER_WRITE |
PIPE_BIND_TRANSFER_READ;
}
templ.width0 = asurf->buf->width;
templ.height0 = asurf->buf->height;
templ.depth0 = 1;
templ.array_size = 1;
if (templ.format != PIPE_FORMAT_NONE) {
asurf->cache_resources[idx] =
import_buffer(asurf->adpy, &templ, asurf->buf);
}
else {
asurf->cache_resources[idx] = NULL;
}
asurf->cache_handles[idx] = handle;
}
return asurf->cache_resources[idx];
}
/**
* Dequeue the next back buffer for rendering.
*/
static boolean
android_surface_dequeue_buffer(struct native_surface *nsurf)
{
struct android_surface *asurf = android_surface(nsurf);
struct pipe_resource *res;
#if ANDROID_VERSION >= 0x0402
int fence_fd;
if (asurf->win->dequeueBuffer(asurf->win, &asurf->buf, &fence_fd) != NO_ERROR) {
ALOGE("failed to dequeue window %p", asurf->win);
return FALSE;
}
if (fence_fd >= 0) {
sync_wait(fence_fd, -1);
close(fence_fd);
}
asurf->buf->common.incRef(&asurf->buf->common);
#else
if (asurf->win->dequeueBuffer(asurf->win, &asurf->buf) != NO_ERROR) {
ALOGE("failed to dequeue window %p", asurf->win);
return FALSE;
}
asurf->buf->common.incRef(&asurf->buf->common);
asurf->win->lockBuffer(asurf->win, asurf->buf);
#endif
res = android_surface_add_cache(&asurf->base, asurf->buf);
if (!res)
return FALSE;
pipe_resource_reference(&asurf->buf_res, res);
return TRUE;
}
/**
* Enqueue the back buffer. This will make it the next front buffer.
*/
static boolean
android_surface_enqueue_buffer(struct native_surface *nsurf)
{
struct android_surface *asurf = android_surface(nsurf);
pipe_resource_reference(&asurf->buf_res, NULL);
#if ANDROID_VERSION >= 0x0402
asurf->win->queueBuffer(asurf->win, asurf->buf, -1);
#else
asurf->win->queueBuffer(asurf->win, asurf->buf);
#endif
asurf->buf->common.decRef(&asurf->buf->common);
asurf->buf = NULL;
return TRUE;
}
static boolean
android_surface_swap_buffers(struct native_surface *nsurf)
{
struct android_surface *asurf = android_surface(nsurf);
struct android_display *adpy = asurf->adpy;
struct native_display *ndpy = &adpy->base;
struct pipe_context *pipe = ndpy_get_copy_context(ndpy);
/* flush buffer */
pipe->flush_resource(pipe, asurf->buf_res);
pipe->flush(pipe, NULL, 0);
android_surface_enqueue_buffer(&asurf->base);
asurf->stamp++;
adpy->event_handler->invalid_surface(&adpy->base,
&asurf->base, asurf->stamp);
return TRUE;
}
static void
copy_resources(struct native_display *ndpy,
struct pipe_resource *src,
struct pipe_resource *dst)
{
struct pipe_context *pipe;
struct pipe_box box;
pipe = ndpy_get_copy_context(ndpy);
if (!pipe)
return;
u_box_origin_2d(src->width0, src->height0, &box);
pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &box);
pipe->flush(pipe, NULL, 0);
}
static boolean
android_surface_present(struct native_surface *nsurf,
const native_present_control *ctrl)
{
struct android_surface *asurf = android_surface(nsurf);
struct android_display *adpy = asurf->adpy;
boolean ret;
if (ctrl->swap_interval || ctrl->natt != NATIVE_ATTACHMENT_BACK_LEFT)
return FALSE;
/* this happens when eglSwapBuffers is called more than once in a row */
if (!asurf->buf)
return TRUE;
/* we always render to color_res first when it exists */
if (asurf->color_res) {
copy_resources(&adpy->base, asurf->color_res, asurf->buf_res);
if (!ctrl->preserve)
pipe_resource_reference(&asurf->color_res, NULL);
}
else if (ctrl->preserve) {
struct pipe_resource templ;
memset(&templ, 0, sizeof(templ));
templ.target = asurf->buf_res->target;
templ.format = asurf->buf_res->format;
templ.bind = PIPE_BIND_RENDER_TARGET;
templ.width0 = asurf->buf_res->width0;
templ.height0 = asurf->buf_res->height0;
templ.depth0 = asurf->buf_res->depth0;
templ.array_size = asurf->buf_res->array_size;
asurf->color_res =
adpy->base.screen->resource_create(adpy->base.screen, &templ);
if (!asurf->color_res)
return FALSE;
/* preserve the contents */
copy_resources(&adpy->base, asurf->buf_res, asurf->color_res);
}
return android_surface_swap_buffers(nsurf);
}
static boolean
android_surface_validate(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height)
{
struct android_surface *asurf = android_surface(nsurf);
struct winsys_handle handle;
if (!asurf->buf) {
if (!android_surface_dequeue_buffer(&asurf->base))
return FALSE;
/* color_res must be compatible with buf_res */
if (asurf->color_res &&
(asurf->color_res->format != asurf->buf_res->format ||
asurf->color_res->width0 != asurf->buf_res->width0 ||
asurf->color_res->height0 != asurf->buf_res->height0))
pipe_resource_reference(&asurf->color_res, NULL);
}
if (textures) {
/* we have access to only the back buffer */
const enum native_attachment att = NATIVE_ATTACHMENT_BACK_LEFT;
if (native_attachment_mask_test(attachment_mask, att)) {
textures[att] = NULL;
pipe_resource_reference(&textures[att],
(asurf->color_res) ? asurf->color_res : asurf->buf_res);
}
}
if (seq_num)
*seq_num = asurf->stamp;
if (width)
*width = asurf->buf->width;
if (height)
*height = asurf->buf->height;
return TRUE;
}
static void
android_surface_wait(struct native_surface *nsurf)
{
}
static void
android_surface_destroy(struct native_surface *nsurf)
{
struct android_surface *asurf = android_surface(nsurf);
int i;
pipe_resource_reference(&asurf->color_res, NULL);
if (asurf->buf)
android_surface_enqueue_buffer(&asurf->base);
android_surface_clear_cache(&asurf->base);
asurf->win->common.decRef(&asurf->win->common);
FREE(asurf);
}
static struct native_surface *
android_display_create_window_surface(struct native_display *ndpy,
EGLNativeWindowType win,
const struct native_config *nconf)
{
struct android_display *adpy = android_display(ndpy);
struct android_config *aconf = android_config(nconf);
struct android_surface *asurf;
enum pipe_format format;
int val;
if (win->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
ALOGE("invalid native window with magic 0x%x", win->common.magic);
return NULL;
}
if (win->query(win, NATIVE_WINDOW_FORMAT, &val)) {
ALOGE("failed to query native window format");
return NULL;
}
format = get_pipe_format(val);
if (format != nconf->color_format) {
ALOGW("native window format 0x%x != config format 0x%x",
format, nconf->color_format);
if (!adpy->base.screen->is_format_supported(adpy->base.screen,
format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) {
ALOGE("and the native window cannot be used as a render target");
return NULL;
}
}
asurf = CALLOC_STRUCT(android_surface);
if (!asurf)
return NULL;
asurf->adpy = adpy;
asurf->win = win;
asurf->win->common.incRef(&asurf->win->common);
/* request buffers that are for CPU access */
if (!adpy->use_drm) {
native_window_set_usage(asurf->win,
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
}
asurf->base.destroy = android_surface_destroy;
asurf->base.present = android_surface_present;
asurf->base.validate = android_surface_validate;
asurf->base.wait = android_surface_wait;
return &asurf->base;
}
static boolean
android_display_init_configs(struct native_display *ndpy)
{
struct android_display *adpy = android_display(ndpy);
const int native_formats[] = {
HAL_PIXEL_FORMAT_RGBA_8888,
HAL_PIXEL_FORMAT_RGBX_8888,
HAL_PIXEL_FORMAT_RGB_888,
HAL_PIXEL_FORMAT_RGB_565,
HAL_PIXEL_FORMAT_BGRA_8888,
};
int i;
adpy->configs = (struct android_config *)
CALLOC(Elements(native_formats), sizeof(*adpy->configs));
if (!adpy->configs)
return FALSE;
for (i = 0; i < Elements(native_formats); i++) {
enum pipe_format color_format;
struct android_config *aconf;
color_format = get_pipe_format(native_formats[i]);
if (color_format == PIPE_FORMAT_NONE ||
!adpy->base.screen->is_format_supported(adpy->base.screen,
color_format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET)) {
ALOGI("skip unsupported native format 0x%x", native_formats[i]);
continue;
}
aconf = &adpy->configs[adpy->num_configs++];
/* only the back buffer */
aconf->base.buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT;
aconf->base.color_format = color_format;
aconf->base.window_bit = TRUE;
aconf->base.native_visual_id = native_formats[i];
aconf->base.native_visual_type = native_formats[i];
}
return TRUE;
}
static boolean
android_display_init_drm(struct native_display *ndpy)
{
struct android_display *adpy = android_display(ndpy);
const hw_module_t *mod;
int fd, err;
#ifndef ANDROID_BACKEND_NO_DRM
/* get the authorized fd from gralloc */
err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
if (!err) {
const gralloc_module_t *gr = (gralloc_module_t *) mod;
err = -EINVAL;
if (gr->perform)
err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
}
if (!err && fd >= 0) {
adpy->base.screen =
adpy->event_handler->new_drm_screen(&adpy->base, NULL, fd);
}
#endif
if (adpy->base.screen) {
ALOGI("using DRM screen");
return TRUE;
}
else {
ALOGW("failed to create DRM screen");
ALOGW("will fall back to other EGL drivers if any");
return FALSE;
}
}
static boolean
android_display_init_sw(struct native_display *ndpy)
{
struct android_display *adpy = android_display(ndpy);
struct sw_winsys *ws;
ws = android_create_sw_winsys();
if (ws) {
adpy->base.screen =
adpy->event_handler->new_sw_screen(&adpy->base, ws);
}
if (adpy->base.screen) {
ALOGI("using SW screen");
return TRUE;
}
else {
ALOGE("failed to create SW screen");
return FALSE;
}
}
static boolean
android_display_init_screen(struct native_display *ndpy)
{
struct android_display *adpy = android_display(ndpy);
if (adpy->use_drm)
android_display_init_drm(&adpy->base);
else
android_display_init_sw(&adpy->base);
if (!adpy->base.screen)
return FALSE;
if (!android_display_init_configs(&adpy->base)) {
adpy->base.screen->destroy(adpy->base.screen);
adpy->base.screen = NULL;
return FALSE;
}
return TRUE;
}
static void
android_display_destroy(struct native_display *ndpy)
{
struct android_display *adpy = android_display(ndpy);
FREE(adpy->configs);
if (adpy->base.screen)
adpy->base.screen->destroy(adpy->base.screen);
FREE(adpy);
}
static const struct native_config **
android_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct android_display *adpy = android_display(ndpy);
const struct native_config **configs;
int i;
configs = (const struct native_config **)
MALLOC(adpy->num_configs * sizeof(*configs));
if (configs) {
for (i = 0; i < adpy->num_configs; i++)
configs[i] = (const struct native_config *) &adpy->configs[i];
if (num_configs)
*num_configs = adpy->num_configs;
}
return configs;
}
static int
android_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
int val;
switch (param) {
case NATIVE_PARAM_PRESERVE_BUFFER:
val = 1;
break;
default:
val = 0;
break;
}
return val;
}
static struct pipe_resource *
android_display_import_buffer(struct native_display *ndpy,
struct native_buffer *nbuf)
{
struct android_display *adpy = android_display(ndpy);
ANativeWindowBuffer *abuf;
enum pipe_format format;
struct pipe_resource templ;
if (nbuf->type != NATIVE_BUFFER_ANDROID)
return NULL;
abuf = nbuf->u.android;
if (!abuf || abuf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
abuf->common.version != sizeof(*abuf)) {
ALOGE("invalid android native buffer");
return NULL;
}
format = get_pipe_format(abuf->format);
if (format == PIPE_FORMAT_NONE)
return NULL;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = format;
/* assume for texturing only */
templ.bind = PIPE_BIND_SAMPLER_VIEW;
templ.width0 = abuf->width;
templ.height0 = abuf->height;
templ.depth0 = 1;
templ.array_size = 1;
return import_buffer(adpy, &templ, abuf);
}
static boolean
android_display_export_buffer(struct native_display *ndpy,
struct pipe_resource *res,
struct native_buffer *nbuf)
{
return FALSE;
}
static struct native_display_buffer android_display_buffer = {
android_display_import_buffer,
android_display_export_buffer
};
static struct android_display *
android_display_create(const struct native_event_handler *event_handler,
boolean use_sw)
{
struct android_display *adpy;
char value[PROPERTY_VALUE_MAX];
boolean force_sw;
/* check if SW renderer is forced */
if (property_get("debug.mesa.software", value, NULL))
force_sw = (atoi(value) != 0);
else
force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
if (force_sw)
use_sw = TRUE;
adpy = CALLOC_STRUCT(android_display);
if (!adpy)
return NULL;
adpy->event_handler = event_handler;
adpy->use_drm = !use_sw;
adpy->base.init_screen = android_display_init_screen;
adpy->base.destroy = android_display_destroy;
adpy->base.get_param = android_display_get_param;
adpy->base.get_configs = android_display_get_configs;
adpy->base.create_window_surface = android_display_create_window_surface;
adpy->base.buffer = &android_display_buffer;
return adpy;
}
static const struct native_event_handler *android_event_handler;
static struct native_display *
native_create_display(void *dpy, boolean use_sw)
{
struct android_display *adpy;
adpy = android_display_create(android_event_handler, use_sw);
return (adpy) ? &adpy->base : NULL;
}
static const struct native_platform android_platform = {
"Android", /* name */
native_create_display
};
}; /* namespace android */
using namespace android;
static void
android_log(EGLint level, const char *msg)
{
switch (level) {
case _EGL_DEBUG:
ALOGD("%s", msg);
break;
case _EGL_INFO:
ALOGI("%s", msg);
break;
case _EGL_WARNING:
ALOGW("%s", msg);
break;
case _EGL_FATAL:
LOG_FATAL("%s", msg);
break;
default:
break;
}
}
const struct native_platform *
native_get_android_platform(const struct native_event_handler *event_handler)
{
android_event_handler = event_handler;
/* use Android logger */
_eglSetLogProc(android_log);
return &android_platform;
}
@@ -1,674 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "egldriver.h"
#include "eglcurrent.h"
#include "egllog.h"
#include "pipe/p_screen.h"
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_string.h"
#include "util/u_atomic.h"
#include "egl_g3d.h"
#include "egl_g3d_api.h"
#include "egl_g3d_st.h"
#include "egl_g3d_loader.h"
#include "native.h"
static void
egl_g3d_invalid_surface(struct native_display *ndpy,
struct native_surface *nsurf,
unsigned int seq_num)
{
/* XXX not thread safe? */
struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data);
if (gsurf && gsurf->stfbi)
p_atomic_inc(&gsurf->stfbi->stamp);
}
static struct pipe_screen *
egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
{
_EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
return gdpy->loader->create_drm_screen(name, fd);
}
static struct pipe_screen *
egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
{
_EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
return gdpy->loader->create_sw_screen(ws);
}
static struct pipe_resource *
egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image)
{
_EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct st_egl_image img;
struct pipe_resource *resource = NULL;
memset(&img, 0, sizeof(img));
if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img))
resource = img.texture;
return resource;
}
static const struct native_event_handler egl_g3d_native_event_handler = {
egl_g3d_invalid_surface,
egl_g3d_new_drm_screen,
egl_g3d_new_sw_screen,
egl_g3d_lookup_egl_image
};
/**
* Get the native platform.
*/
static const struct native_platform *
egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
if (!gdrv->platforms[plat]) {
const char *plat_name = NULL;
const struct native_platform *nplat = NULL;
switch (plat) {
case _EGL_PLATFORM_WINDOWS:
plat_name = "Windows";
#ifdef HAVE_GDI_BACKEND
nplat = native_get_gdi_platform(&egl_g3d_native_event_handler);
#endif
break;
case _EGL_PLATFORM_X11:
plat_name = "X11";
#ifdef HAVE_X11_BACKEND
nplat = native_get_x11_platform(&egl_g3d_native_event_handler);
#endif
break;
case _EGL_PLATFORM_WAYLAND:
plat_name = "wayland";
#ifdef HAVE_WAYLAND_BACKEND
nplat = native_get_wayland_platform(&egl_g3d_native_event_handler);
#endif
break;
case _EGL_PLATFORM_DRM:
plat_name = "DRM";
#ifdef HAVE_DRM_BACKEND
nplat = native_get_drm_platform(&egl_g3d_native_event_handler);
#endif
break;
case _EGL_PLATFORM_FBDEV:
plat_name = "FBDEV";
#ifdef HAVE_FBDEV_BACKEND
nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler);
#endif
break;
case _EGL_PLATFORM_NULL:
plat_name = "NULL";
#ifdef HAVE_NULL_BACKEND
nplat = native_get_null_platform(&egl_g3d_native_event_handler);
#endif
break;
case _EGL_PLATFORM_ANDROID:
plat_name = "Android";
#ifdef HAVE_ANDROID_BACKEND
nplat = native_get_android_platform(&egl_g3d_native_event_handler);
#endif
break;
default:
break;
}
if (!nplat)
_eglLog(_EGL_WARNING, "unsupported platform %s", plat_name);
gdrv->platforms[plat] = nplat;
}
return gdrv->platforms[plat];
}
#ifdef EGL_MESA_screen_surface
static void
egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
const struct native_connector **native_connectors;
EGLint num_connectors, i;
native_connectors =
gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL);
if (!num_connectors) {
FREE(native_connectors);
return;
}
for (i = 0; i < num_connectors; i++) {
const struct native_connector *nconn = native_connectors[i];
struct egl_g3d_screen *gscr;
const struct native_mode **native_modes;
EGLint num_modes, j;
/* TODO support for hotplug */
native_modes =
gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes);
if (!num_modes) {
FREE(native_modes);
continue;
}
gscr = CALLOC_STRUCT(egl_g3d_screen);
if (!gscr) {
FREE(native_modes);
continue;
}
_eglInitScreen(&gscr->base, dpy, num_modes);
for (j = 0; j < gscr->base.NumModes; j++) {
const struct native_mode *nmode = native_modes[j];
_EGLMode *mode = &gscr->base.Modes[j];
mode->Width = nmode->width;
mode->Height = nmode->height;
mode->RefreshRate = nmode->refresh_rate;
mode->Optimal = EGL_FALSE;
mode->Interlaced = EGL_FALSE;
/* no need to strdup() */
mode->Name = nmode->desc;
}
gscr->native = nconn;
gscr->native_modes = native_modes;
_eglLinkScreen(&gscr->base);
}
FREE(native_connectors);
}
#endif /* EGL_MESA_screen_surface */
/**
* Initialize and validate the EGL config attributes.
*/
static EGLBoolean
init_config_attributes(_EGLConfig *conf, const struct native_config *nconf,
EGLint api_mask, enum pipe_format depth_stencil_format,
EGLint preserve_buffer, EGLint max_swap_interval,
EGLBoolean pre_alpha)
{
uint rgba[4], depth_stencil[2], buffer_size;
EGLint surface_type;
EGLint i;
/* get the color and depth/stencil component sizes */
assert(nconf->color_format != PIPE_FORMAT_NONE);
buffer_size = 0;
for (i = 0; i < 4; i++) {
rgba[i] = util_format_get_component_bits(nconf->color_format,
UTIL_FORMAT_COLORSPACE_RGB, i);
buffer_size += rgba[i];
}
for (i = 0; i < 2; i++) {
if (depth_stencil_format != PIPE_FORMAT_NONE) {
depth_stencil[i] =
util_format_get_component_bits(depth_stencil_format,
UTIL_FORMAT_COLORSPACE_ZS, i);
}
else {
depth_stencil[i] = 0;
}
}
surface_type = 0x0;
/* pixmap surfaces should be EGL_SINGLE_BUFFER */
if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) {
if (nconf->pixmap_bit)
surface_type |= EGL_PIXMAP_BIT;
}
/* the others surfaces should be EGL_BACK_BUFFER (or settable) */
if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) {
if (nconf->window_bit)
surface_type |= EGL_WINDOW_BIT;
#ifdef EGL_MESA_screen_surface
if (nconf->scanout_bit)
surface_type |= EGL_SCREEN_BIT_MESA;
#endif
surface_type |= EGL_PBUFFER_BIT;
}
if (preserve_buffer)
surface_type |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
if (pre_alpha && rgba[3]) {
surface_type |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
/* st/vega does not support premultiplied alpha yet */
api_mask &= ~EGL_OPENVG_BIT;
}
conf->Conformant = api_mask;
conf->RenderableType = api_mask;
conf->RedSize = rgba[0];
conf->GreenSize = rgba[1];
conf->BlueSize = rgba[2];
conf->AlphaSize = rgba[3];
conf->BufferSize = buffer_size;
conf->DepthSize = depth_stencil[0];
conf->StencilSize = depth_stencil[1];
/* st/vega will allocate the mask on demand */
if (api_mask & EGL_OPENVG_BIT)
conf->AlphaMaskSize = 8;
conf->SurfaceType = surface_type;
conf->NativeRenderable = EGL_TRUE;
if (surface_type & EGL_WINDOW_BIT) {
conf->NativeVisualID = nconf->native_visual_id;
conf->NativeVisualType = nconf->native_visual_type;
}
if (surface_type & EGL_PBUFFER_BIT) {
conf->BindToTextureRGB = EGL_TRUE;
if (rgba[3])
conf->BindToTextureRGBA = EGL_TRUE;
conf->MaxPbufferWidth = 4096;
conf->MaxPbufferHeight = 4096;
conf->MaxPbufferPixels = 4096 * 4096;
}
conf->Level = nconf->level;
if (nconf->transparent_rgb) {
conf->TransparentType = EGL_TRANSPARENT_RGB;
conf->TransparentRedValue = nconf->transparent_rgb_values[0];
conf->TransparentGreenValue = nconf->transparent_rgb_values[1];
conf->TransparentBlueValue = nconf->transparent_rgb_values[2];
}
conf->MinSwapInterval = 0;
conf->MaxSwapInterval = max_swap_interval;
return _eglValidateConfig(conf, EGL_FALSE);
}
/**
* Initialize an EGL config from the native config.
*/
static EGLBoolean
egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLConfig *conf, const struct native_config *nconf,
enum pipe_format depth_stencil_format,
int preserve_buffer, int max_swap_interval,
int pre_alpha)
{
struct egl_g3d_config *gconf = egl_g3d_config(conf);
EGLint buffer_mask;
EGLBoolean valid;
buffer_mask = 0x0;
if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT))
buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT))
buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT))
buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT))
buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
gconf->stvis.buffer_mask = buffer_mask;
gconf->stvis.color_format = nconf->color_format;
gconf->stvis.depth_stencil_format = depth_stencil_format;
gconf->stvis.accum_format = PIPE_FORMAT_NONE;
gconf->stvis.samples = 0;
/* will be overridden per surface */
gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
valid = init_config_attributes(&gconf->base,
nconf, dpy->ClientAPIs, depth_stencil_format,
preserve_buffer, max_swap_interval, pre_alpha);
if (!valid) {
_eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id);
return EGL_FALSE;
}
gconf->native = nconf;
return EGL_TRUE;
}
/**
* Get all interested depth/stencil formats of a display.
*/
static EGLint
egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy,
enum pipe_format formats[8])
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct pipe_screen *screen = gdpy->native->screen;
const EGLint candidates[] = {
1, PIPE_FORMAT_Z16_UNORM,
1, PIPE_FORMAT_Z32_UNORM,
2, PIPE_FORMAT_Z24_UNORM_S8_UINT, PIPE_FORMAT_S8_UINT_Z24_UNORM,
2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM,
0
};
const EGLint *fmt = candidates;
EGLint count;
count = 0;
formats[count++] = PIPE_FORMAT_NONE;
while (*fmt) {
EGLint i, n = *fmt++;
/* pick the first supported format */
for (i = 0; i < n; i++) {
if (screen->is_format_supported(screen, fmt[i],
PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL)) {
formats[count++] = fmt[i];
break;
}
}
fmt += n;
}
return count;
}
/**
* Add configs to display and return the next config ID.
*/
static EGLint
egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
const struct native_config **native_configs;
enum pipe_format depth_stencil_formats[8];
int num_formats, num_configs, i, j;
int preserve_buffer, max_swap_interval, premultiplied_alpha;
native_configs = gdpy->native->get_configs(gdpy->native, &num_configs);
if (!num_configs) {
FREE(native_configs);
return id;
}
preserve_buffer =
gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER);
max_swap_interval =
gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL);
premultiplied_alpha =
gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PREMULTIPLIED_ALPHA);
num_formats = egl_g3d_fill_depth_stencil_formats(dpy,
depth_stencil_formats);
for (i = 0; i < num_configs; i++) {
for (j = 0; j < num_formats; j++) {
struct egl_g3d_config *gconf;
gconf = CALLOC_STRUCT(egl_g3d_config);
if (gconf) {
_eglInitConfig(&gconf->base, dpy, id);
if (!egl_g3d_init_config(drv, dpy, &gconf->base,
native_configs[i], depth_stencil_formats[j],
preserve_buffer, max_swap_interval,
premultiplied_alpha)) {
FREE(gconf);
break;
}
_eglLinkConfig(&gconf->base);
id++;
}
}
}
FREE(native_configs);
return id;
}
static void
egl_g3d_free_config(void *conf)
{
struct egl_g3d_config *gconf = egl_g3d_config((_EGLConfig *) conf);
FREE(gconf);
}
static void
egl_g3d_free_screen(void *scr)
{
#ifdef EGL_MESA_screen_surface
struct egl_g3d_screen *gscr = egl_g3d_screen((_EGLScreen *) scr);
FREE(gscr->native_modes);
FREE(gscr);
#endif
}
static EGLBoolean
egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
_eglReleaseDisplayResources(drv, dpy);
if (dpy->Configs) {
_eglDestroyArray(dpy->Configs, egl_g3d_free_config);
dpy->Configs = NULL;
}
if (dpy->Screens) {
_eglDestroyArray(dpy->Screens, egl_g3d_free_screen);
dpy->Screens = NULL;
}
_eglCleanupDisplay(dpy);
if (gdpy->smapi)
egl_g3d_destroy_st_manager(gdpy->smapi);
if (gdpy->native)
gdpy->native->destroy(gdpy->native);
FREE(gdpy);
dpy->DriverData = NULL;
return EGL_TRUE;
}
static EGLBoolean
egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
struct egl_g3d_display *gdpy;
const struct native_platform *nplat;
nplat = egl_g3d_get_platform(drv, dpy->Platform);
if (!nplat)
return EGL_FALSE;
if (dpy->Options.TestOnly)
return EGL_TRUE;
gdpy = CALLOC_STRUCT(egl_g3d_display);
if (!gdpy) {
_eglError(EGL_BAD_ALLOC, "eglInitialize");
goto fail;
}
gdpy->loader = gdrv->loader;
dpy->DriverData = gdpy;
_eglLog(_EGL_INFO, "use %s for display %p",
nplat->name, dpy->PlatformDisplay);
gdpy->native =
nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback);
if (!gdpy->native) {
_eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
goto fail;
}
gdpy->native->user_data = (void *) dpy;
if (!gdpy->native->init_screen(gdpy->native)) {
_eglError(EGL_NOT_INITIALIZED,
"eglInitialize(failed to initialize screen)");
goto fail;
}
#if FEATURE_GL
dpy->ClientAPIs |= EGL_OPENGL_BIT;
#endif
#if FEATURE_ES1
dpy->ClientAPIs |= EGL_OPENGL_ES_BIT;
#endif
#if FEATURE_ES2
dpy->ClientAPIs |= EGL_OPENGL_ES2_BIT;
#endif
#if FEATURE_VG
dpy->ClientAPIs |= EGL_OPENVG_BIT;
#endif
gdpy->smapi = egl_g3d_create_st_manager(dpy);
if (!gdpy->smapi) {
_eglError(EGL_NOT_INITIALIZED,
"eglInitialize(failed to create st manager)");
goto fail;
}
#ifdef EGL_MESA_screen_surface
/* enable MESA_screen_surface before adding (and validating) configs */
if (gdpy->native->modeset) {
dpy->Extensions.MESA_screen_surface = EGL_TRUE;
egl_g3d_add_screens(drv, dpy);
}
#endif
dpy->Extensions.KHR_image_base = EGL_TRUE;
if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER))
dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
dpy->Extensions.KHR_reusable_sync = EGL_TRUE;
dpy->Extensions.KHR_fence_sync = EGL_TRUE;
dpy->Extensions.KHR_surfaceless_context = EGL_TRUE;
if (dpy->Platform == _EGL_PLATFORM_DRM) {
dpy->Extensions.MESA_drm_display = EGL_TRUE;
if (gdpy->native->buffer)
dpy->Extensions.MESA_drm_image = EGL_TRUE;
}
if (dpy->Platform == _EGL_PLATFORM_WAYLAND && gdpy->native->buffer)
dpy->Extensions.MESA_drm_image = EGL_TRUE;
#ifdef EGL_ANDROID_image_native_buffer
if (dpy->Platform == _EGL_PLATFORM_ANDROID && gdpy->native->buffer)
dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
#endif
#ifdef EGL_WL_bind_wayland_display
if (gdpy->native->wayland_bufmgr)
dpy->Extensions.WL_bind_wayland_display = EGL_TRUE;
#endif
if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESENT_REGION) &&
gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER)) {
#ifdef EGL_NOK_swap_region
dpy->Extensions.NOK_swap_region = EGL_TRUE;
#endif
dpy->Extensions.NV_post_sub_buffer = EGL_TRUE;
}
if (egl_g3d_add_configs(drv, dpy, 1) == 1) {
_eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)");
goto fail;
}
dpy->VersionMajor = 1;
dpy->VersionMinor = 4;
return EGL_TRUE;
fail:
if (gdpy)
egl_g3d_terminate(drv, dpy);
return EGL_FALSE;
}
static _EGLProc
egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
struct st_api *stapi = NULL;
if (procname && procname[0] == 'v' && procname[1] == 'g')
stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
else if (procname && procname[0] == 'g' && procname[1] == 'l')
stapi = gdrv->loader->get_st_api(ST_API_OPENGL);
return (_EGLProc) ((stapi) ?
stapi->get_proc_address(stapi, procname) : NULL);
}
_EGLDriver *
egl_g3d_create_driver(const struct egl_g3d_loader *loader)
{
struct egl_g3d_driver *gdrv;
gdrv = CALLOC_STRUCT(egl_g3d_driver);
if (!gdrv)
return NULL;
gdrv->loader = loader;
egl_g3d_init_driver_api(&gdrv->base);
gdrv->base.API.Initialize = egl_g3d_initialize;
gdrv->base.API.Terminate = egl_g3d_terminate;
gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
/* to be filled by the caller */
gdrv->base.Name = NULL;
gdrv->base.Unload = NULL;
return &gdrv->base;
}
void
egl_g3d_destroy_driver(_EGLDriver *drv)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
FREE(gdrv);
}
@@ -1,132 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _EGL_G3D_H_
#define _EGL_G3D_H_
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_format.h"
#include "os/os_thread.h"
#include "egldriver.h"
#include "egldisplay.h"
#include "eglcontext.h"
#include "eglsurface.h"
#include "eglconfig.h"
#include "eglimage.h"
#include "eglsync.h"
#include "eglscreen.h"
#include "eglmode.h"
#include "native.h"
#include "egl_g3d_st.h"
#include "egl_g3d_loader.h"
struct egl_g3d_driver {
_EGLDriver base;
const struct egl_g3d_loader *loader;
const struct native_platform *platforms[_EGL_NUM_PLATFORMS];
};
struct egl_g3d_display {
struct native_display *native;
const struct egl_g3d_loader *loader;
struct st_manager *smapi;
};
struct egl_g3d_context {
_EGLContext base;
struct st_api *stapi;
struct st_context_iface *stctxi;
};
struct egl_g3d_surface {
_EGLSurface base;
struct st_visual stvis;
struct st_framebuffer_iface *stfbi;
/* the native surface; NULL for pbuffers */
struct native_surface *native;
struct pipe_resource *render_texture;
EGLenum client_buffer_type;
EGLClientBuffer client_buffer;
unsigned int sequence_number;
};
struct egl_g3d_config {
_EGLConfig base;
const struct native_config *native;
struct st_visual stvis;
};
struct egl_g3d_image {
_EGLImage base;
struct pipe_resource *texture;
unsigned level;
unsigned layer;
};
/* standard typecasts */
_EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d)
_EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj)
struct egl_g3d_sync {
_EGLSync base;
/* the mutex protects only the condvar, not the struct */
pipe_mutex mutex;
pipe_condvar condvar;
/* for fence sync */
struct pipe_fence_handle *fence;
};
_EGL_DRIVER_TYPECAST(egl_g3d_sync, _EGLSync, obj)
#ifdef EGL_MESA_screen_surface
struct egl_g3d_screen {
_EGLScreen base;
const struct native_connector *native;
const struct native_mode **native_modes;
};
_EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj)
#endif /* EGL_MESA_screen_surface */
static INLINE struct st_api *
egl_g3d_get_st_api(_EGLDriver *drv, enum st_api_type api)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
return gdrv->loader->get_st_api(api);
}
#endif /* _EGL_G3D_H_ */
@@ -1,952 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "egldriver.h"
#include "eglcurrent.h"
#include "egllog.h"
#include "pipe/p_screen.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_box.h"
#include "egl_g3d.h"
#include "egl_g3d_api.h"
#include "egl_g3d_image.h"
#include "egl_g3d_sync.h"
#include "egl_g3d_st.h"
#include "native.h"
/**
* Return the state tracker for the given context.
*/
static struct st_api *
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx,
enum st_profile_type *profile)
{
struct st_api *stapi;
EGLint api = -1;
*profile = ST_PROFILE_DEFAULT;
switch (ctx->ClientAPI) {
case EGL_OPENGL_ES_API:
switch (ctx->ClientMajorVersion) {
case 1:
api = ST_API_OPENGL;
*profile = ST_PROFILE_OPENGL_ES1;
break;
case 2:
api = ST_API_OPENGL;
*profile = ST_PROFILE_OPENGL_ES2;
break;
default:
_eglLog(_EGL_WARNING, "unknown client major version %d",
ctx->ClientMajorVersion);
break;
}
break;
case EGL_OPENVG_API:
api = ST_API_OPENVG;
break;
case EGL_OPENGL_API:
api = ST_API_OPENGL;
break;
default:
_eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
break;
}
stapi = egl_g3d_get_st_api(drv, api);
if (stapi && !(stapi->profile_mask & (1 << *profile)))
stapi = NULL;
return stapi;
}
struct egl_g3d_choose_config_data {
_EGLConfig criteria;
enum pipe_format format;
};
static int
egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2,
void *priv_data)
{
struct egl_g3d_choose_config_data *data =
(struct egl_g3d_choose_config_data *) priv_data;
const _EGLConfig *criteria = &data->criteria;;
/* EGL_NATIVE_VISUAL_TYPE ignored? */
return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE);
}
static EGLBoolean
egl_g3d_match_config(const _EGLConfig *conf, void *priv_data)
{
struct egl_g3d_choose_config_data *data =
(struct egl_g3d_choose_config_data *) priv_data;
struct egl_g3d_config *gconf = egl_g3d_config(conf);
if (data->format != PIPE_FORMAT_NONE &&
data->format != gconf->native->color_format)
return EGL_FALSE;
return _eglMatchConfig(conf, &data->criteria);
}
static EGLBoolean
egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs,
EGLConfig *configs, EGLint size, EGLint *num_configs)
{
struct egl_g3d_choose_config_data data;
if (!_eglParseConfigAttribList(&data.criteria, dpy, attribs))
return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
data.format = PIPE_FORMAT_NONE;
if (data.criteria.MatchNativePixmap != EGL_NONE &&
data.criteria.MatchNativePixmap != EGL_DONT_CARE) {
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
if (!gdpy->native->get_pixmap_format(gdpy->native,
(EGLNativePixmapType) data.criteria.MatchNativePixmap,
&data.format))
return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglChooseConfig");
}
return _eglFilterConfigArray(dpy->Configs, configs, size, num_configs,
egl_g3d_match_config, egl_g3d_compare_config, &data);
}
static _EGLContext *
egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
_EGLContext *share, const EGLint *attribs)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_context *gshare = egl_g3d_context(share);
struct egl_g3d_config *gconf = egl_g3d_config(conf);
struct egl_g3d_context *gctx;
struct st_context_attribs stattribs;
enum st_context_error ctx_err = 0;
gctx = CALLOC_STRUCT(egl_g3d_context);
if (!gctx) {
_eglError(EGL_BAD_ALLOC, "eglCreateContext");
return NULL;
}
if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) {
FREE(gctx);
return NULL;
}
memset(&stattribs, 0, sizeof(stattribs));
if (gconf)
stattribs.visual = gconf->stvis;
gctx->stapi = egl_g3d_choose_st(drv, &gctx->base, &stattribs.profile);
if (!gctx->stapi) {
FREE(gctx);
return NULL;
}
gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
&stattribs, &ctx_err, (gshare) ? gshare->stctxi : NULL);
if (!gctx->stctxi) {
FREE(gctx);
return NULL;
}
gctx->stctxi->st_manager_private = (void *) &gctx->base;
return &gctx->base;
}
/**
* Destroy a context.
*/
static void
destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
{
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
/* FIXME a context might live longer than its display */
if (!dpy->Initialized)
_eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
gctx->stctxi->destroy(gctx->stctxi);
FREE(gctx);
}
static EGLBoolean
egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
if (_eglPutContext(ctx))
destroy_context(dpy, ctx);
return EGL_TRUE;
}
struct egl_g3d_create_surface_arg {
EGLint type;
union {
EGLNativeWindowType win;
EGLNativePixmapType pix;
} u;
};
static _EGLSurface *
egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
struct egl_g3d_create_surface_arg *arg,
const EGLint *attribs)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_config *gconf = egl_g3d_config(conf);
struct egl_g3d_surface *gsurf;
struct native_surface *nsurf;
const char *err;
switch (arg->type) {
case EGL_WINDOW_BIT:
err = "eglCreateWindowSurface";
break;
case EGL_PIXMAP_BIT:
err = "eglCreatePixmapSurface";
break;
#ifdef EGL_MESA_screen_surface
case EGL_SCREEN_BIT_MESA:
err = "eglCreateScreenSurface";
break;
#endif
default:
err = "eglCreateUnknownSurface";
break;
}
gsurf = CALLOC_STRUCT(egl_g3d_surface);
if (!gsurf) {
_eglError(EGL_BAD_ALLOC, err);
return NULL;
}
if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) {
FREE(gsurf);
return NULL;
}
/* create the native surface */
switch (arg->type) {
case EGL_WINDOW_BIT:
nsurf = gdpy->native->create_window_surface(gdpy->native,
arg->u.win, gconf->native);
break;
case EGL_PIXMAP_BIT:
nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
arg->u.pix, gconf->native);
break;
#ifdef EGL_MESA_screen_surface
case EGL_SCREEN_BIT_MESA:
/* prefer back buffer (move to _eglInitSurface?) */
gsurf->base.RenderBuffer = EGL_BACK_BUFFER;
nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native,
gconf->native, gsurf->base.Width, gsurf->base.Height);
break;
#endif
default:
nsurf = NULL;
break;
}
if (!nsurf) {
FREE(gsurf);
return NULL;
}
/* initialize the geometry */
if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL,
&gsurf->base.Width, &gsurf->base.Height)) {
nsurf->destroy(nsurf);
FREE(gsurf);
return NULL;
}
gsurf->stvis = gconf->stvis;
if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER &&
gconf->stvis.buffer_mask & ST_ATTACHMENT_FRONT_LEFT_MASK)
gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT;
/* surfaces can always be posted when the display supports it */
if (dpy->Extensions.NV_post_sub_buffer)
gsurf->base.PostSubBufferSupportedNV = EGL_TRUE;
gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
if (!gsurf->stfbi) {
nsurf->destroy(nsurf);
FREE(gsurf);
return NULL;
}
nsurf->user_data = &gsurf->base;
gsurf->native = nsurf;
return &gsurf->base;
}
static _EGLSurface *
egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLConfig *conf, void *native_window,
const EGLint *attribs)
{
EGLNativeWindowType win;
struct egl_g3d_create_surface_arg arg;
STATIC_ASSERT(sizeof(EGLNativeWindowType) == sizeof(native_window));
win = (EGLNativeWindowType) native_window;
memset(&arg, 0, sizeof(arg));
arg.type = EGL_WINDOW_BIT;
arg.u.win = win;
return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
}
static _EGLSurface *
egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLConfig *conf, void *native_pixmap,
const EGLint *attribs)
{
EGLNativePixmapType pix;
struct egl_g3d_create_surface_arg arg;
STATIC_ASSERT(sizeof(EGLNativePixmapType) == sizeof(native_pixmap));
pix = (EGLNativePixmapType) native_pixmap;
memset(&arg, 0, sizeof(arg));
arg.type = EGL_PIXMAP_BIT;
arg.u.pix = pix;
return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
}
static struct egl_g3d_surface *
create_pbuffer_surface(_EGLDisplay *dpy, _EGLConfig *conf,
const EGLint *attribs, const char *func)
{
struct egl_g3d_config *gconf = egl_g3d_config(conf);
struct egl_g3d_surface *gsurf;
gsurf = CALLOC_STRUCT(egl_g3d_surface);
if (!gsurf) {
_eglError(EGL_BAD_ALLOC, func);
return NULL;
}
if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) {
FREE(gsurf);
return NULL;
}
gsurf->stvis = gconf->stvis;
gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
if (!gsurf->stfbi) {
FREE(gsurf);
return NULL;
}
return gsurf;
}
static _EGLSurface *
egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLConfig *conf, const EGLint *attribs)
{
struct egl_g3d_surface *gsurf;
gsurf = create_pbuffer_surface(dpy, conf, attribs,
"eglCreatePbufferSurface");
if (!gsurf)
return NULL;
gsurf->client_buffer_type = EGL_NONE;
return &gsurf->base;
}
static _EGLSurface *
egl_g3d_create_pbuffer_from_client_buffer(_EGLDriver *drv, _EGLDisplay *dpy,
EGLenum buftype,
EGLClientBuffer buffer,
_EGLConfig *conf,
const EGLint *attribs)
{
struct egl_g3d_surface *gsurf;
struct pipe_resource *ptex = NULL;
EGLint pbuffer_attribs[32];
EGLint count, i;
switch (buftype) {
case EGL_OPENVG_IMAGE:
break;
default:
_eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
return NULL;
break;
}
/* parse the attributes first */
count = 0;
for (i = 0; attribs && attribs[i] != EGL_NONE; i++) {
EGLint attr = attribs[i++];
EGLint val = attribs[i];
EGLint err = EGL_SUCCESS;
switch (attr) {
case EGL_TEXTURE_FORMAT:
case EGL_TEXTURE_TARGET:
case EGL_MIPMAP_TEXTURE:
pbuffer_attribs[count++] = attr;
pbuffer_attribs[count++] = val;
break;
default:
err = EGL_BAD_ATTRIBUTE;
break;
}
/* bail out */
if (err != EGL_SUCCESS) {
_eglError(err, "eglCreatePbufferFromClientBuffer");
return NULL;
}
}
pbuffer_attribs[count++] = EGL_NONE;
gsurf = create_pbuffer_surface(dpy, conf, pbuffer_attribs,
"eglCreatePbufferFromClientBuffer");
if (!gsurf)
return NULL;
gsurf->client_buffer_type = buftype;
gsurf->client_buffer = buffer;
/* validate now so that it fails if the client buffer is invalid */
if (!gsurf->stfbi->validate(NULL, gsurf->stfbi,
&gsurf->stvis.render_buffer, 1, &ptex)) {
egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
FREE(gsurf);
return NULL;
}
pipe_resource_reference(&ptex, NULL);
return &gsurf->base;
}
/**
* Destroy a surface.
*/
static void
destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
{
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
/* FIXME a surface might live longer than its display */
if (!dpy->Initialized)
_eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
pipe_resource_reference(&gsurf->render_texture, NULL);
egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
if (gsurf->native)
gsurf->native->destroy(gsurf->native);
FREE(gsurf);
}
static EGLBoolean
egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
{
if (_eglPutSurface(surf))
destroy_surface(dpy, surf);
return EGL_TRUE;
}
static EGLBoolean
egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
{
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
struct egl_g3d_surface *gread = egl_g3d_surface(read);
struct egl_g3d_context *old_gctx;
_EGLContext *old_ctx;
_EGLSurface *old_draw, *old_read;
EGLBoolean ok = EGL_TRUE;
/* make new bindings */
if (!_eglBindContext(ctx, draw, read, &old_ctx, &old_draw, &old_read))
return EGL_FALSE;
old_gctx = egl_g3d_context(old_ctx);
if (old_gctx) {
/* flush old context */
old_gctx->stctxi->flush(old_gctx->stctxi, ST_FLUSH_FRONT, NULL);
}
if (gctx) {
ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi,
(gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL);
if (ok) {
if (gdraw) {
if (gdraw->base.Type == EGL_WINDOW_BIT) {
gctx->base.WindowRenderBuffer =
(gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
}
}
}
}
else if (old_gctx) {
ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL);
if (ok)
old_gctx->base.WindowRenderBuffer = EGL_NONE;
}
if (ok) {
if (_eglPutContext(old_ctx))
destroy_context(dpy, old_ctx);
if (_eglPutSurface(old_draw))
destroy_surface(dpy, old_draw);
if (_eglPutSurface(old_read))
destroy_surface(dpy, old_read);
}
else {
/* undo the previous _eglBindContext */
_eglBindContext(old_ctx, old_draw, old_read, &ctx, &draw, &read);
assert(&gctx->base == ctx &&
&gdraw->base == draw &&
&gread->base == read);
_eglPutSurface(draw);
_eglPutSurface(read);
_eglPutContext(ctx);
_eglPutSurface(old_draw);
_eglPutSurface(old_read);
_eglPutContext(old_ctx);
}
return ok;
}
static EGLBoolean
swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
EGLint num_rects, const EGLint *rects, EGLBoolean preserve)
{
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
_EGLContext *ctx = _eglGetCurrentContext();
struct egl_g3d_context *gctx = NULL;
struct native_present_control ctrl;
/* no-op for pixmap or pbuffer surface */
if (gsurf->base.Type == EGL_PIXMAP_BIT ||
gsurf->base.Type == EGL_PBUFFER_BIT)
return EGL_TRUE;
/* or when the surface is single-buffered */
if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT)
return EGL_TRUE;
if (ctx && ctx->DrawSurface == surf)
gctx = egl_g3d_context(ctx);
/* flush if the surface is current */
if (gctx) {
gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
}
memset(&ctrl, 0, sizeof(ctrl));
ctrl.natt = NATIVE_ATTACHMENT_BACK_LEFT;
ctrl.preserve = preserve;
ctrl.swap_interval = gsurf->base.SwapInterval;
ctrl.premultiplied_alpha = (gsurf->base.VGAlphaFormat == EGL_VG_ALPHA_FORMAT_PRE);
ctrl.num_rects = num_rects;
ctrl.rects = rects;
return gsurf->native->present(gsurf->native, &ctrl);
}
static EGLBoolean
egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
{
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
return swap_buffers(drv, dpy, surf, 0, NULL,
(gsurf->base.SwapBehavior == EGL_BUFFER_PRESERVED));
}
#ifdef EGL_NOK_swap_region
static EGLBoolean
egl_g3d_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
EGLint num_rects, const EGLint *rects)
{
/* Note: y=0=top */
return swap_buffers(drv, dpy, surf, num_rects, rects, EGL_TRUE);
}
#endif /* EGL_NOK_swap_region */
static EGLBoolean
egl_g3d_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
EGLint x, EGLint y, EGLint width, EGLint height)
{
EGLint rect[4];
if (x < 0 || y < 0 || width < 0 || height < 0)
return _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV");
/* clamp */
if (x + width > surf->Width)
width = surf->Width - x;
if (y + height > surf->Height)
height = surf->Height - y;
if (width <= 0 || height <= 0)
return EGL_TRUE;
rect[0] = x;
/* Note: y=0=bottom */
rect[1] = surf->Height - y - height;
rect[2] = width;
rect[3] = height;
return swap_buffers(drv, dpy, surf, 1, rect, EGL_TRUE);
}
static EGLBoolean
egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
void *native_pixmap_target)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
_EGLContext *ctx = _eglGetCurrentContext();
EGLNativePixmapType target;
STATIC_ASSERT(sizeof(EGLNativePixmapType) == sizeof(native_pixmap_target));
target = (EGLNativePixmapType) native_pixmap_target;
if (!gsurf->render_texture)
return EGL_TRUE;
/* flush if the surface is current */
if (ctx && ctx->DrawSurface == &gsurf->base) {
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
}
return gdpy->native->copy_to_pixmap(gdpy->native,
target, gsurf->render_texture);
}
static EGLBoolean
egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
struct pipe_screen *screen = gdpy->native->screen;
struct pipe_fence_handle *fence = NULL;
gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, &fence);
if (fence) {
screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
screen->fence_reference(screen, &fence, NULL);
}
return EGL_TRUE;
}
static EGLBoolean
egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
{
_EGLContext *ctx = _eglGetCurrentContext();
if (engine != EGL_CORE_NATIVE_ENGINE)
return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
if (ctx && ctx->DrawSurface) {
struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface);
if (gsurf->native)
gsurf->native->wait(gsurf->native);
}
return EGL_TRUE;
}
static EGLBoolean
egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLSurface *surf, EGLint buffer)
{
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
_EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
struct egl_g3d_context *gctx;
enum pipe_format internal_format;
enum st_texture_type target;
if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
if (buffer != EGL_BACK_BUFFER)
return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
if (gsurf->base.BoundToTexture)
return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
switch (gsurf->base.TextureFormat) {
case EGL_TEXTURE_RGB:
internal_format = PIPE_FORMAT_R8G8B8_UNORM;
break;
case EGL_TEXTURE_RGBA:
internal_format = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
default:
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
}
switch (gsurf->base.TextureTarget) {
case EGL_TEXTURE_2D:
target = ST_TEXTURE_2D;
break;
default:
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
}
if (!es1)
return EGL_TRUE;
if (!gsurf->render_texture)
return EGL_FALSE;
/* flush properly if the surface is bound */
if (gsurf->base.CurrentContext) {
gctx = egl_g3d_context(gsurf->base.CurrentContext);
gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
}
gctx = egl_g3d_context(es1);
if (gctx->stctxi->teximage) {
if (!gctx->stctxi->teximage(gctx->stctxi, target,
gsurf->base.MipmapLevel, internal_format,
gsurf->render_texture, gsurf->base.MipmapTexture))
return EGL_FALSE;
gsurf->base.BoundToTexture = EGL_TRUE;
}
return EGL_TRUE;
}
static EGLBoolean
egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLSurface *surf, EGLint buffer)
{
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
!gsurf->base.BoundToTexture)
return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
if (buffer != EGL_BACK_BUFFER)
return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
if (gsurf->render_texture) {
_EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
/* what if the context the surface binds to is no longer current? */
if (gctx) {
gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D,
gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE);
}
}
gsurf->base.BoundToTexture = EGL_FALSE;
return EGL_TRUE;
}
#ifdef EGL_MESA_screen_surface
static _EGLSurface *
egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLConfig *conf, const EGLint *attribs)
{
struct egl_g3d_create_surface_arg arg;
memset(&arg, 0, sizeof(arg));
arg.type = EGL_SCREEN_BIT_MESA;
return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
}
static EGLBoolean
egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
_EGLScreen *scr, _EGLSurface *surf,
_EGLMode *mode)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
struct native_surface *nsurf;
const struct native_mode *nmode;
EGLBoolean changed;
if (gsurf) {
EGLint idx;
if (!mode)
return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
return _eglError(EGL_BAD_MATCH,
"eglShowSurfaceMESA(surface smaller than mode size)");
/* find the index of the mode */
for (idx = 0; idx < gscr->base.NumModes; idx++)
if (mode == &gscr->base.Modes[idx])
break;
if (idx >= gscr->base.NumModes) {
return _eglError(EGL_BAD_MODE_MESA,
"eglShowSurfaceMESA(unknown mode)");
}
nsurf = gsurf->native;
nmode = gscr->native_modes[idx];
}
else {
if (mode)
return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
/* disable the screen */
nsurf = NULL;
nmode = NULL;
}
/* TODO surface panning by CRTC choosing */
changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
if (changed) {
gscr->base.CurrentSurface = &gsurf->base;
gscr->base.CurrentMode = mode;
}
return changed;
}
#endif /* EGL_MESA_screen_surface */
#ifdef EGL_WL_bind_wayland_display
static EGLBoolean
egl_g3d_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *dpy,
struct wl_display *wl_dpy)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
if (!gdpy->native->wayland_bufmgr)
return EGL_FALSE;
return gdpy->native->wayland_bufmgr->bind_display(gdpy->native, wl_dpy);
}
static EGLBoolean
egl_g3d_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *dpy,
struct wl_display *wl_dpy)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
if (!gdpy->native->wayland_bufmgr)
return EGL_FALSE;
return gdpy->native->wayland_bufmgr->unbind_display(gdpy->native, wl_dpy);
}
static EGLBoolean
egl_g3d_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *dpy,
struct wl_resource *buffer,
EGLint attribute, EGLint *value)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
if (!gdpy->native->wayland_bufmgr)
return EGL_FALSE;
return gdpy->native->wayland_bufmgr->query_buffer(gdpy->native,
buffer, attribute, value);
}
#endif /* EGL_WL_bind_wayland_display */
void
egl_g3d_init_driver_api(_EGLDriver *drv)
{
_eglInitDriverFallbacks(drv);
drv->API.ChooseConfig = egl_g3d_choose_config;
drv->API.CreateContext = egl_g3d_create_context;
drv->API.DestroyContext = egl_g3d_destroy_context;
drv->API.CreateWindowSurface = egl_g3d_create_window_surface;
drv->API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
drv->API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
drv->API.CreatePbufferFromClientBuffer = egl_g3d_create_pbuffer_from_client_buffer;
drv->API.DestroySurface = egl_g3d_destroy_surface;
drv->API.MakeCurrent = egl_g3d_make_current;
drv->API.SwapBuffers = egl_g3d_swap_buffers;
drv->API.CopyBuffers = egl_g3d_copy_buffers;
drv->API.WaitClient = egl_g3d_wait_client;
drv->API.WaitNative = egl_g3d_wait_native;
drv->API.BindTexImage = egl_g3d_bind_tex_image;
drv->API.ReleaseTexImage = egl_g3d_release_tex_image;
drv->API.CreateImageKHR = egl_g3d_create_image;
drv->API.DestroyImageKHR = egl_g3d_destroy_image;
#ifdef EGL_MESA_drm_image
drv->API.CreateDRMImageMESA = egl_g3d_create_drm_image;
drv->API.ExportDRMImageMESA = egl_g3d_export_drm_image;
#endif
#ifdef EGL_WL_bind_wayland_display
drv->API.BindWaylandDisplayWL = egl_g3d_bind_wayland_display_wl;
drv->API.UnbindWaylandDisplayWL = egl_g3d_unbind_wayland_display_wl;
drv->API.QueryWaylandBufferWL = egl_g3d_query_wayland_buffer_wl;
#endif
drv->API.CreateSyncKHR = egl_g3d_create_sync;
drv->API.DestroySyncKHR = egl_g3d_destroy_sync;
drv->API.ClientWaitSyncKHR = egl_g3d_client_wait_sync;
drv->API.SignalSyncKHR = egl_g3d_signal_sync;
#ifdef EGL_MESA_screen_surface
drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
#endif
#ifdef EGL_NOK_swap_region
drv->API.SwapBuffersRegionNOK = egl_g3d_swap_buffers_region;
#endif
drv->API.PostSubBufferNV = egl_g3d_post_sub_buffer;
}
@@ -1,33 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _EGL_G3D_API_H_
#define _EGL_G3D_API_H_
#include "egl_g3d.h"
void
egl_g3d_init_driver_api(_EGLDriver *drv);
#endif /* _EGL_G3D_API_H_ */
@@ -1,372 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "pipe/p_screen.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_rect.h"
#include "util/u_inlines.h"
#include "eglcurrent.h"
#include "egllog.h"
#include "native.h"
#include "egl_g3d.h"
#include "egl_g3d_image.h"
/**
* Reference and return the front left buffer of the native pixmap.
*/
static struct pipe_resource *
egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct native_surface *nsurf;
struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
enum native_attachment natt;
nsurf = gdpy->native->create_pixmap_surface(gdpy->native, pix, NULL);
if (!nsurf)
return NULL;
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
if (!nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL))
textures[natt] = NULL;
nsurf->destroy(nsurf);
return textures[natt];
}
#ifdef EGL_MESA_drm_image
static struct pipe_resource *
egl_g3d_create_drm_buffer(_EGLDisplay *dpy, _EGLImage *img,
const EGLint *attribs)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct pipe_screen *screen = gdpy->native->screen;
struct pipe_resource templ;
_EGLImageAttribs attrs;
EGLint format, valid_use;
if (_eglParseImageAttribList(&attrs, dpy, attribs) != EGL_SUCCESS)
return NULL;
if (attrs.Width <= 0 || attrs.Height <= 0) {
_eglLog(_EGL_DEBUG, "bad width or height (%dx%d)",
attrs.Width, attrs.Height);
return NULL;
}
switch (attrs.DRMBufferFormatMESA) {
case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
format = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
default:
_eglLog(_EGL_DEBUG, "bad image format value 0x%04x",
attrs.DRMBufferFormatMESA);
return NULL;
break;
}
valid_use = EGL_DRM_BUFFER_USE_SCANOUT_MESA |
EGL_DRM_BUFFER_USE_SHARE_MESA |
EGL_DRM_BUFFER_USE_CURSOR_MESA;
if (attrs.DRMBufferUseMESA & ~valid_use) {
_eglLog(_EGL_DEBUG, "bad image use bit 0x%04x",
attrs.DRMBufferUseMESA);
return NULL;
}
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = format;
templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
templ.width0 = attrs.Width;
templ.height0 = attrs.Height;
templ.depth0 = 1;
templ.array_size = 1;
/*
* XXX fix apps (e.g. wayland) and pipe drivers (e.g. i915) and remove the
* size check
*/
if ((attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) &&
attrs.Width >= 640 && attrs.Height >= 480)
templ.bind |= PIPE_BIND_SCANOUT;
if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
templ.bind |= PIPE_BIND_SHARED;
if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) {
if (attrs.Width != 64 || attrs.Height != 64)
return NULL;
templ.bind |= PIPE_BIND_CURSOR;
}
return screen->resource_create(screen, &templ);
}
static struct pipe_resource *
egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name,
_EGLImage *img, const EGLint *attribs)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
_EGLImageAttribs attrs;
EGLint format;
struct native_buffer nbuf;
if (!dpy->Extensions.MESA_drm_image)
return NULL;
if (_eglParseImageAttribList(&attrs, dpy, attribs) != EGL_SUCCESS)
return NULL;
if (attrs.Width <= 0 || attrs.Height <= 0 ||
attrs.DRMBufferStrideMESA <= 0) {
_eglLog(_EGL_DEBUG, "bad width, height, or stride (%dx%dx%d)",
attrs.Width, attrs.Height, attrs.DRMBufferStrideMESA);
return NULL;
}
switch (attrs.DRMBufferFormatMESA) {
case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
format = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
default:
_eglLog(_EGL_DEBUG, "bad image format value 0x%04x",
attrs.DRMBufferFormatMESA);
return NULL;
break;
}
memset(&nbuf, 0, sizeof(nbuf));
nbuf.type = NATIVE_BUFFER_DRM;
nbuf.u.drm.templ.target = PIPE_TEXTURE_2D;
nbuf.u.drm.templ.format = format;
nbuf.u.drm.templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
nbuf.u.drm.templ.width0 = attrs.Width;
nbuf.u.drm.templ.height0 = attrs.Height;
nbuf.u.drm.templ.depth0 = 1;
nbuf.u.drm.templ.array_size = 1;
nbuf.u.drm.name = name;
nbuf.u.drm.stride =
attrs.DRMBufferStrideMESA * util_format_get_blocksize(format);
return gdpy->native->buffer->import_buffer(gdpy->native, &nbuf);
}
#endif /* EGL_MESA_drm_image */
#ifdef EGL_WL_bind_wayland_display
static struct pipe_resource *
egl_g3d_reference_wl_buffer(_EGLDisplay *dpy, struct wl_resource *buffer,
_EGLImage *img, const EGLint *attribs)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct pipe_resource *resource = NULL, *tmp = NULL;
if (!gdpy->native->wayland_bufmgr)
return NULL;
tmp = gdpy->native->wayland_bufmgr->buffer_get_resource(gdpy->native, buffer);
pipe_resource_reference(&resource, tmp);
return resource;
}
#endif /* EGL_WL_bind_wayland_display */
#ifdef EGL_ANDROID_image_native_buffer
static struct pipe_resource *
egl_g3d_reference_android_native_buffer(_EGLDisplay *dpy,
struct ANativeWindowBuffer *buf)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct native_buffer nbuf;
memset(&nbuf, 0, sizeof(nbuf));
nbuf.type = NATIVE_BUFFER_ANDROID;
nbuf.u.android = buf;
return gdpy->native->buffer->import_buffer(gdpy->native, &nbuf);
}
#endif /* EGL_ANDROID_image_native_buffer */
_EGLImage *
egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
EGLenum target, EGLClientBuffer buffer,
const EGLint *attribs)
{
struct pipe_resource *ptex;
struct egl_g3d_image *gimg;
unsigned level = 0, layer = 0;
gimg = CALLOC_STRUCT(egl_g3d_image);
if (!gimg) {
_eglError(EGL_BAD_ALLOC, "eglCreateEGLImageKHR");
return NULL;
}
if (!_eglInitImage(&gimg->base, dpy)) {
FREE(gimg);
return NULL;
}
switch (target) {
case EGL_NATIVE_PIXMAP_KHR:
ptex = egl_g3d_reference_native_pixmap(dpy,
(EGLNativePixmapType) buffer);
break;
#ifdef EGL_MESA_drm_image
case EGL_DRM_BUFFER_MESA:
ptex = egl_g3d_reference_drm_buffer(dpy,
(EGLint) pointer_to_intptr(buffer), &gimg->base, attribs);
break;
#endif
#ifdef EGL_WL_bind_wayland_display
case EGL_WAYLAND_BUFFER_WL:
ptex = egl_g3d_reference_wl_buffer(dpy,
(struct wl_resource *) buffer, &gimg->base, attribs);
break;
#endif
#ifdef EGL_ANDROID_image_native_buffer
case EGL_NATIVE_BUFFER_ANDROID:
ptex = egl_g3d_reference_android_native_buffer(dpy,
(struct ANativeWindowBuffer *) buffer);
break;
#endif
default:
ptex = NULL;
break;
}
if (!ptex) {
FREE(gimg);
return NULL;
}
if (level > ptex->last_level) {
_eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR");
pipe_resource_reference(&gimg->texture, NULL);
FREE(gimg);
return NULL;
}
if (layer >= (u_minify(ptex->depth0, level) + ptex->array_size - 1)) {
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
pipe_resource_reference(&gimg->texture, NULL);
FREE(gimg);
return NULL;
}
/* transfer the ownership to the image */
gimg->texture = ptex;
gimg->level = level;
gimg->layer = layer;
return &gimg->base;
}
EGLBoolean
egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
{
struct egl_g3d_image *gimg = egl_g3d_image(img);
pipe_resource_reference(&gimg->texture, NULL);
FREE(gimg);
return EGL_TRUE;
}
_EGLImage *
egl_g3d_create_drm_image(_EGLDriver *drv, _EGLDisplay *dpy,
const EGLint *attribs)
{
struct egl_g3d_image *gimg;
struct pipe_resource *ptex;
gimg = CALLOC_STRUCT(egl_g3d_image);
if (!gimg) {
_eglError(EGL_BAD_ALLOC, "eglCreateDRMImageKHR");
return NULL;
}
if (!_eglInitImage(&gimg->base, dpy)) {
FREE(gimg);
return NULL;
}
#ifdef EGL_MESA_drm_image
ptex = egl_g3d_create_drm_buffer(dpy, &gimg->base, attribs);
#else
ptex = NULL;
#endif
if (!ptex) {
FREE(gimg);
return NULL;
}
/* transfer the ownership to the image */
gimg->texture = ptex;
gimg->level = 0;
gimg->layer = 0;
return &gimg->base;
}
EGLBoolean
egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
EGLint *name, EGLint *handle, EGLint *stride)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_image *gimg = egl_g3d_image(img);
struct native_buffer nbuf;
if (!dpy->Extensions.MESA_drm_image)
return EGL_FALSE;
memset(&nbuf, 0, sizeof(nbuf));
nbuf.type = NATIVE_BUFFER_DRM;
if (name)
nbuf.u.drm.templ.bind |= PIPE_BIND_SHARED;
if (!gdpy->native->buffer->export_buffer(gdpy->native,
gimg->texture, &nbuf))
return EGL_FALSE;
if (name)
*name = nbuf.u.drm.name;
if (handle)
*handle = nbuf.u.drm.handle;
if (stride)
*stride = nbuf.u.drm.stride;
return EGL_TRUE;
}
@@ -1,49 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _EGL_G3D_IMAGE_H_
#define _EGL_G3D_IMAGE_H_
#include "egl_g3d.h"
_EGLImage *
egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
EGLenum target, EGLClientBuffer buffer,
const EGLint *attribs);
EGLBoolean
egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
_EGLImage *
egl_g3d_create_drm_image(_EGLDriver *drv, _EGLDisplay *dpy,
const EGLint *attribs);
EGLBoolean
egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
EGLint *name, EGLint *handle, EGLint *stride);
#endif /* _EGL_G3D_IMAGE_H_ */
@@ -1,51 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _EGL_G3D_LOADER_H_
#define _EGL_G3D_LOADER_H_
#include "pipe/p_compiler.h"
#include "state_tracker/st_api.h"
#include "egltypedefs.h"
struct pipe_screen;
struct sw_winsys;
struct egl_g3d_loader {
struct st_api *(*get_st_api)(enum st_api_type api);
struct pipe_screen *(*create_drm_screen)(const char *name, int fd);
struct pipe_screen *(*create_sw_screen)(struct sw_winsys *ws);
};
_EGLDriver *
egl_g3d_create_driver(const struct egl_g3d_loader *loader);
void
egl_g3d_destroy_driver(_EGLDriver *drv);
#endif /* _EGL_G3D_LOADER_H_ */
@@ -1,321 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "util/u_memory.h"
#include "util/u_string.h"
#include "util/u_inlines.h"
#include "util/u_pointer.h"
#include "util/u_dl.h"
#include "egldriver.h"
#include "eglimage.h"
#include "eglmutex.h"
#include "egl_g3d.h"
#include "egl_g3d_st.h"
struct egl_g3d_st_manager {
struct st_manager base;
_EGLDisplay *display;
};
static INLINE struct egl_g3d_st_manager *
egl_g3d_st_manager(struct st_manager *smapi)
{
return (struct egl_g3d_st_manager *) smapi;
}
static boolean
egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
void *egl_image,
struct st_egl_image *out)
{
struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
EGLImageKHR handle = (EGLImageKHR) egl_image;
_EGLImage *img;
struct egl_g3d_image *gimg;
/* this is called from state trackers */
_eglLockMutex(&gsmapi->display->Mutex);
img = _eglLookupImage(handle, gsmapi->display);
if (!img) {
_eglUnlockMutex(&gsmapi->display->Mutex);
return FALSE;
}
gimg = egl_g3d_image(img);
out->texture = NULL;
pipe_resource_reference(&out->texture, gimg->texture);
out->level = gimg->level;
out->layer = gimg->layer;
_eglUnlockMutex(&gsmapi->display->Mutex);
return TRUE;
}
static int
egl_g3d_st_manager_get_param(struct st_manager *smapi,
enum st_manager_param param)
{
return 0;
}
struct st_manager *
egl_g3d_create_st_manager(_EGLDisplay *dpy)
{
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct egl_g3d_st_manager *gsmapi;
gsmapi = CALLOC_STRUCT(egl_g3d_st_manager);
if (gsmapi) {
gsmapi->display = dpy;
gsmapi->base.screen = gdpy->native->screen;
gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image;
gsmapi->base.get_param = egl_g3d_st_manager_get_param;
}
return &gsmapi->base;;
}
void
egl_g3d_destroy_st_manager(struct st_manager *smapi)
{
struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi);
FREE(gsmapi);
}
static boolean
egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_context_iface *stctx,
struct st_framebuffer_iface *stfbi,
enum st_attachment_type statt)
{
return TRUE;
}
static void
pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf)
{
/* TODO */
}
static void
pbuffer_allocate_pbuffer_texture(struct egl_g3d_surface *gsurf)
{
struct egl_g3d_display *gdpy =
egl_g3d_display(gsurf->base.Resource.Display);
struct pipe_screen *screen = gdpy->native->screen;
struct pipe_resource templ, *ptex;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.last_level = 0;
templ.width0 = gsurf->base.Width;
templ.height0 = gsurf->base.Height;
templ.depth0 = 1;
templ.array_size = 1;
templ.format = gsurf->stvis.color_format;
/* for rendering and binding to texture */
templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
ptex = screen->resource_create(screen, &templ);
gsurf->render_texture = ptex;
}
static boolean
egl_g3d_st_framebuffer_validate_pbuffer(struct st_context_iface *stctx,
struct st_framebuffer_iface *stfbi,
const enum st_attachment_type *statts,
unsigned count,
struct pipe_resource **out)
{
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
unsigned i;
for (i = 0; i < count; i++) {
out[i] = NULL;
if (gsurf->stvis.render_buffer != statts[i])
continue;
if (!gsurf->render_texture) {
switch (gsurf->client_buffer_type) {
case EGL_NONE:
pbuffer_allocate_pbuffer_texture(gsurf);
break;
case EGL_OPENVG_IMAGE:
pbuffer_reference_openvg_image(gsurf);
break;
default:
break;
}
if (!gsurf->render_texture)
return FALSE;
}
pipe_resource_reference(&out[i], gsurf->render_texture);
}
return TRUE;
}
static boolean
egl_g3d_st_framebuffer_flush_front(struct st_context_iface *stctx,
struct st_framebuffer_iface *stfbi,
enum st_attachment_type statt)
{
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
struct native_present_control ctrl;
memset(&ctrl, 0, sizeof(ctrl));
ctrl.natt = NATIVE_ATTACHMENT_FRONT_LEFT;
return gsurf->native->present(gsurf->native, &ctrl);
}
static boolean
egl_g3d_st_framebuffer_validate(struct st_context_iface *stctx,
struct st_framebuffer_iface *stfbi,
const enum st_attachment_type *statts,
unsigned count,
struct pipe_resource **out)
{
_EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private;
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
uint attachment_mask = 0;
unsigned i;
for (i = 0; i < count; i++) {
int natt;
switch (statts[i]) {
case ST_ATTACHMENT_FRONT_LEFT:
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
break;
case ST_ATTACHMENT_BACK_LEFT:
natt = NATIVE_ATTACHMENT_BACK_LEFT;
break;
case ST_ATTACHMENT_FRONT_RIGHT:
natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
break;
case ST_ATTACHMENT_BACK_RIGHT:
natt = NATIVE_ATTACHMENT_BACK_RIGHT;
break;
default:
natt = -1;
break;
}
if (natt >= 0)
attachment_mask |= 1 << natt;
}
if (!gsurf->native->validate(gsurf->native, attachment_mask,
&gsurf->sequence_number, textures, &gsurf->base.Width,
&gsurf->base.Height))
return FALSE;
for (i = 0; i < count; i++) {
struct pipe_resource *tex;
int natt;
switch (statts[i]) {
case ST_ATTACHMENT_FRONT_LEFT:
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
break;
case ST_ATTACHMENT_BACK_LEFT:
natt = NATIVE_ATTACHMENT_BACK_LEFT;
break;
case ST_ATTACHMENT_FRONT_RIGHT:
natt = NATIVE_ATTACHMENT_FRONT_RIGHT;
break;
case ST_ATTACHMENT_BACK_RIGHT:
natt = NATIVE_ATTACHMENT_BACK_RIGHT;
break;
default:
natt = -1;
break;
}
if (natt >= 0) {
tex = textures[natt];
if (statts[i] == stfbi->visual->render_buffer)
pipe_resource_reference(&gsurf->render_texture, tex);
if (attachment_mask & (1 << natt)) {
/* transfer the ownership to the caller */
out[i] = tex;
attachment_mask &= ~(1 << natt);
}
else {
/* the attachment is listed more than once */
pipe_resource_reference(&out[i], tex);
}
}
}
return TRUE;
}
struct st_framebuffer_iface *
egl_g3d_create_st_framebuffer(_EGLSurface *surf)
{
struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
struct st_framebuffer_iface *stfbi;
stfbi = CALLOC_STRUCT(st_framebuffer_iface);
if (!stfbi)
return NULL;
stfbi->visual = &gsurf->stvis;
p_atomic_set(&stfbi->stamp, 1);
if (gsurf->base.Type != EGL_PBUFFER_BIT) {
stfbi->flush_front = egl_g3d_st_framebuffer_flush_front;
stfbi->validate = egl_g3d_st_framebuffer_validate;
}
else {
stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer;
stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer;
}
stfbi->st_manager_private = (void *) &gsurf->base;
return stfbi;
}
void
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
{
FREE(stfbi);
}
@@ -1,47 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _EGL_G3D_ST_H_
#define _EGL_G3D_ST_H_
#include "pipe/p_compiler.h"
#include "state_tracker/st_api.h"
#include "egltypedefs.h"
struct st_manager *
egl_g3d_create_st_manager(_EGLDisplay *dpy);
void
egl_g3d_destroy_st_manager(struct st_manager *smapi);
struct st_framebuffer_iface *
egl_g3d_create_st_framebuffer(_EGLSurface *surf);
void
egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
#endif /* _EGL_G3D_ST_H_ */
@@ -1,278 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "util/u_memory.h"
#include "util/u_atomic.h"
#include "os/os_thread.h"
#include "eglsync.h"
#include "eglcurrent.h"
#include "egl_g3d.h"
#include "egl_g3d_sync.h"
/**
* Wait for the conditional variable.
*/
static EGLint
egl_g3d_wait_sync_condvar(struct egl_g3d_sync *gsync, EGLTimeKHR timeout)
{
_EGLDisplay *dpy = gsync->base.Resource.Display;
pipe_mutex_lock(gsync->mutex);
/* unlock display lock just before waiting */
_eglUnlockMutex(&dpy->Mutex);
/* No timed wait. Always treat timeout as EGL_FOREVER_KHR */
pipe_condvar_wait(gsync->condvar, gsync->mutex);
_eglLockMutex(&dpy->Mutex);
pipe_mutex_unlock(gsync->mutex);
return EGL_CONDITION_SATISFIED_KHR;
}
/**
* Signal the conditional variable.
*/
static void
egl_g3d_signal_sync_condvar(struct egl_g3d_sync *gsync)
{
pipe_mutex_lock(gsync->mutex);
pipe_condvar_broadcast(gsync->condvar);
pipe_mutex_unlock(gsync->mutex);
}
/**
* Insert a fence command to the command stream of the current context.
*/
static EGLint
egl_g3d_insert_fence_sync(struct egl_g3d_sync *gsync)
{
_EGLContext *ctx = _eglGetCurrentContext();
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
/* already checked in egl_g3d_create_sync */
assert(gctx);
/* insert the fence command */
gctx->stctxi->flush(gctx->stctxi, 0x0, &gsync->fence);
if (!gsync->fence)
gsync->base.SyncStatus = EGL_SIGNALED_KHR;
return EGL_SUCCESS;
}
/**
* Wait for the fence sync to be signaled.
*/
static EGLint
egl_g3d_wait_fence_sync(struct egl_g3d_sync *gsync, EGLTimeKHR timeout)
{
EGLint ret;
if (gsync->fence) {
_EGLDisplay *dpy = gsync->base.Resource.Display;
struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
struct pipe_screen *screen = gdpy->native->screen;
struct pipe_fence_handle *fence = gsync->fence;
gsync->fence = NULL;
_eglUnlockMutex(&dpy->Mutex);
/* no timed finish? */
screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
ret = EGL_CONDITION_SATISFIED_KHR;
_eglLockMutex(&dpy->Mutex);
gsync->base.SyncStatus = EGL_SIGNALED_KHR;
screen->fence_reference(screen, &fence, NULL);
egl_g3d_signal_sync_condvar(gsync);
}
else {
ret = egl_g3d_wait_sync_condvar(gsync, timeout);
}
return ret;
}
static INLINE void
egl_g3d_ref_sync(struct egl_g3d_sync *gsync)
{
_eglGetSync(&gsync->base);
}
static INLINE void
egl_g3d_unref_sync(struct egl_g3d_sync *gsync)
{
if (_eglPutSync(&gsync->base)) {
pipe_condvar_destroy(gsync->condvar);
pipe_mutex_destroy(gsync->mutex);
if (gsync->fence) {
struct egl_g3d_display *gdpy =
egl_g3d_display(gsync->base.Resource.Display);
struct pipe_screen *screen = gdpy->native->screen;
screen->fence_reference(screen, &gsync->fence, NULL);
}
FREE(gsync);
}
}
_EGLSync *
egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
EGLenum type, const EGLint *attrib_list)
{
_EGLContext *ctx = _eglGetCurrentContext();
struct egl_g3d_sync *gsync;
EGLint err;
if (!ctx || ctx->Resource.Display != dpy) {
_eglError(EGL_BAD_MATCH, "eglCreateSyncKHR");
return NULL;
}
gsync = CALLOC_STRUCT(egl_g3d_sync);
if (!gsync) {
_eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR");
return NULL;
}
if (!_eglInitSync(&gsync->base, dpy, type, attrib_list)) {
FREE(gsync);
return NULL;
}
switch (type) {
case EGL_SYNC_REUSABLE_KHR:
err = EGL_SUCCESS;
break;
case EGL_SYNC_FENCE_KHR:
err = egl_g3d_insert_fence_sync(gsync);
break;
default:
err = EGL_BAD_ATTRIBUTE;
break;
}
if (err != EGL_SUCCESS) {
_eglError(err, "eglCreateSyncKHR");
FREE(gsync);
return NULL;
}
pipe_mutex_init(gsync->mutex);
pipe_condvar_init(gsync->condvar);
return &gsync->base;
}
EGLBoolean
egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
{
struct egl_g3d_sync *gsync = egl_g3d_sync(sync);
switch (gsync->base.Type) {
case EGL_SYNC_REUSABLE_KHR:
/* signal the waiters */
if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) {
gsync->base.SyncStatus = EGL_SIGNALED_KHR;
egl_g3d_signal_sync_condvar(gsync);
}
break;
default:
break;
}
egl_g3d_unref_sync(gsync);
return EGL_TRUE;
}
EGLint
egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
EGLint flags, EGLTimeKHR timeout)
{
struct egl_g3d_sync *gsync = egl_g3d_sync(sync);
EGLint ret = EGL_CONDITION_SATISFIED_KHR;
if (gsync->base.SyncStatus != EGL_SIGNALED_KHR) {
/* flush if there is a current context */
if (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) {
_EGLContext *ctx = _eglGetCurrentContext();
struct egl_g3d_context *gctx = egl_g3d_context(ctx);
if (gctx)
gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
}
if (timeout) {
/* reference the sync object in case it is destroyed while waiting */
egl_g3d_ref_sync(gsync);
switch (gsync->base.Type) {
case EGL_SYNC_REUSABLE_KHR:
ret = egl_g3d_wait_sync_condvar(gsync, timeout);
break;
case EGL_SYNC_FENCE_KHR:
ret = egl_g3d_wait_fence_sync(gsync, timeout);
default:
break;
}
egl_g3d_unref_sync(gsync);
}
else {
ret = EGL_TIMEOUT_EXPIRED_KHR;
}
}
return ret;
}
EGLBoolean
egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
EGLenum mode)
{
struct egl_g3d_sync *gsync = egl_g3d_sync(sync);
/* only for reusable sync */
if (sync->Type != EGL_SYNC_REUSABLE_KHR)
return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR");
if (gsync->base.SyncStatus != mode) {
gsync->base.SyncStatus = mode;
if (mode == EGL_SIGNALED_KHR)
egl_g3d_signal_sync_condvar(gsync);
}
return EGL_TRUE;
}
@@ -1,48 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _EGL_G3D_SYNC_H_
#define _EGL_G3D_SYNC_H_
#include "egl_g3d.h"
_EGLSync *
egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
EGLenum type, const EGLint *attrib_list);
EGLBoolean
egl_g3d_destroy_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
EGLint
egl_g3d_client_wait_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
EGLint flags, EGLTimeKHR timeout);
EGLBoolean
egl_g3d_signal_sync(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
EGLenum mode);
#endif /* _EGL_G3D_SYNC_H_ */
@@ -1,342 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _NATIVE_H_
#define _NATIVE_H_
#include "EGL/egl.h" /* for EGL native types */
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "state_tracker/sw_winsys.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "native_buffer.h"
#include "native_modeset.h"
#include "native_wayland_bufmgr.h"
/**
* Only color buffers are listed. The others are allocated privately through,
* for example, st_renderbuffer_alloc_storage().
*/
enum native_attachment {
NATIVE_ATTACHMENT_FRONT_LEFT,
NATIVE_ATTACHMENT_BACK_LEFT,
NATIVE_ATTACHMENT_FRONT_RIGHT,
NATIVE_ATTACHMENT_BACK_RIGHT,
NUM_NATIVE_ATTACHMENTS
};
enum native_param_type {
/*
* Return TRUE if window/pixmap surfaces use the buffers of the native
* types.
*/
NATIVE_PARAM_USE_NATIVE_BUFFER,
/**
* Return TRUE if native_surface::present can preserve the buffer.
*/
NATIVE_PARAM_PRESERVE_BUFFER,
/**
* Return the maximum supported swap interval.
*/
NATIVE_PARAM_MAX_SWAP_INTERVAL,
/**
* Return TRUE if the display supports premultiplied alpha, regardless of
* the surface color format.
*
* Note that returning TRUE for this parameter will make
* EGL_VG_ALPHA_FORMAT_PRE_BIT to be set for all EGLConfig's with non-zero
* EGL_ALPHA_SIZE. EGL_VG_ALPHA_FORMAT attribute of a surface will affect
* how the surface is presented.
*/
NATIVE_PARAM_PREMULTIPLIED_ALPHA,
/**
* Return TRUE if native_surface::present supports presenting a partial
* surface.
*/
NATIVE_PARAM_PRESENT_REGION
};
/**
* Control how a surface presentation should happen.
*/
struct native_present_control {
/**< the attachment to present */
enum native_attachment natt;
/**< the contents of the presented attachment should be preserved */
boolean preserve;
/**< wait until the given vsyncs has passed since the last presentation */
uint swap_interval;
/**< pixels use premultiplied alpha */
boolean premultiplied_alpha;
/**< The region to present. y=0=top.
If num_rects is 0, the whole surface is to be presented */
int num_rects;
const int *rects; /* x, y, width, height */
};
struct native_surface {
/**
* Available for caller's use.
*/
void *user_data;
void (*destroy)(struct native_surface *nsurf);
/**
* Present the given buffer to the native engine.
*/
boolean (*present)(struct native_surface *nsurf,
const struct native_present_control *ctrl);
/**
* Validate the buffers of the surface. textures, if not NULL, points to an
* array of size NUM_NATIVE_ATTACHMENTS and the returned textures are owned
* by the caller. A sequence number is also returned. The caller can use
* it to check if anything has changed since the last call. Any of the
* pointers may be NULL and it indicates the caller has no interest in those
* values.
*
* If this function is called multiple times with different attachment
* masks, those not listed in the latest call might be destroyed. This
* behavior might change in the future.
*/
boolean (*validate)(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height);
/**
* Wait until all native commands affecting the surface has been executed.
*/
void (*wait)(struct native_surface *nsurf);
};
/**
* Describe a native display config.
*/
struct native_config {
/* available buffers and their format */
uint buffer_mask;
enum pipe_format color_format;
/* supported surface types */
boolean window_bit;
boolean pixmap_bit;
boolean scanout_bit;
int native_visual_id;
int native_visual_type;
int level;
boolean transparent_rgb;
int transparent_rgb_values[3];
};
/**
* A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis
* hardware. A native display consists of a pipe winsys, a pipe screen, and
* the native display server.
*/
struct native_display {
/**
* The pipe screen of the native display.
*/
struct pipe_screen *screen;
/**
* Context used for copy operations.
*/
struct pipe_context *pipe;
/**
* Available for caller's use.
*/
void *user_data;
/**
* Initialize and create the pipe screen.
*/
boolean (*init_screen)(struct native_display *ndpy);
void (*destroy)(struct native_display *ndpy);
/**
* Query the parameters of the native display.
*
* The return value is defined by the parameter.
*/
int (*get_param)(struct native_display *ndpy,
enum native_param_type param);
/**
* Get the supported configs. The configs are owned by the display, but
* the returned array should be FREE()ed.
*/
const struct native_config **(*get_configs)(struct native_display *ndpy,
int *num_configs);
/**
* Get the color format of the pixmap. Required unless no config has
* pixmap_bit set.
*/
boolean (*get_pixmap_format)(struct native_display *ndpy,
EGLNativePixmapType pix,
enum pipe_format *format);
/**
* Copy the contents of the resource to the pixmap's front-left attachment.
* This is used to implement eglCopyBuffers. Required unless no config has
* pixmap_bit set.
*/
boolean (*copy_to_pixmap)(struct native_display *ndpy,
EGLNativePixmapType pix,
struct pipe_resource *src);
/**
* Create a window surface. Required unless no config has window_bit set.
*/
struct native_surface *(*create_window_surface)(struct native_display *ndpy,
EGLNativeWindowType win,
const struct native_config *nconf);
/**
* Create a pixmap surface. The native config may be NULL. In that case, a
* "best config" will be picked. Required unless no config has pixmap_bit
* set.
*/
struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy,
EGLNativePixmapType pix,
const struct native_config *nconf);
const struct native_display_buffer *buffer;
const struct native_display_modeset *modeset;
struct native_display_wayland_bufmgr *wayland_bufmgr;
};
/**
* The handler for events that a native display may generate. The events are
* generated asynchronously and the handler may be called by any thread at any
* time.
*/
struct native_event_handler {
/**
* This function is called when a surface needs to be validated.
*/
void (*invalid_surface)(struct native_display *ndpy,
struct native_surface *nsurf,
unsigned int seq_num);
struct pipe_screen *(*new_drm_screen)(struct native_display *ndpy,
const char *name, int fd);
struct pipe_screen *(*new_sw_screen)(struct native_display *ndpy,
struct sw_winsys *ws);
struct pipe_resource *(*lookup_egl_image)(struct native_display *ndpy,
void *egl_image);
};
/**
* Test whether an attachment is set in the mask.
*/
static INLINE boolean
native_attachment_mask_test(uint mask, enum native_attachment att)
{
return !!(mask & (1 << att));
}
/**
* Get the display copy context
*/
static INLINE struct pipe_context *
ndpy_get_copy_context(struct native_display *ndpy)
{
if (!ndpy->pipe)
ndpy->pipe = ndpy->screen->context_create(ndpy->screen, NULL);
return ndpy->pipe;
}
/**
* Free display screen and context resources
*/
static INLINE void
ndpy_uninit(struct native_display *ndpy)
{
if (ndpy->pipe)
ndpy->pipe->destroy(ndpy->pipe);
if (ndpy->screen)
ndpy->screen->destroy(ndpy->screen);
}
struct native_platform {
const char *name;
/**
* Create the native display and usually establish a connection to the
* display server.
*
* No event should be generated at this stage.
*/
struct native_display *(*create_display)(void *dpy, boolean use_sw);
};
const struct native_platform *
native_get_gdi_platform(const struct native_event_handler *event_handler);
const struct native_platform *
native_get_x11_platform(const struct native_event_handler *event_handler);
const struct native_platform *
native_get_wayland_platform(const struct native_event_handler *event_handler);
const struct native_platform *
native_get_drm_platform(const struct native_event_handler *event_handler);
const struct native_platform *
native_get_fbdev_platform(const struct native_event_handler *event_handler);
const struct native_platform *
native_get_null_platform(const struct native_event_handler *event_handler);
const struct native_platform *
native_get_android_platform(const struct native_event_handler *event_handler);
#ifdef __cplusplus
}
#endif
#endif /* _NATIVE_H_ */
@@ -1,75 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _NATIVE_BUFFER_H_
#define _NATIVE_BUFFER_H_
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
struct native_display;
struct ANativeWindowBuffer;
enum native_buffer_type {
NATIVE_BUFFER_DRM,
NATIVE_BUFFER_ANDROID,
NUM_NATIVE_BUFFERS
};
struct native_buffer {
enum native_buffer_type type;
union {
struct {
struct pipe_resource templ;
unsigned name; /**< the name of the GEM object */
unsigned handle; /**< the handle of the GEM object */
unsigned stride;
} drm;
struct ANativeWindowBuffer *android; /**< opaque native buffer */
} u;
};
/**
* Buffer interface of the native display. It allows native buffers to be
* imported and exported.
*/
struct native_display_buffer {
struct pipe_resource *(*import_buffer)(struct native_display *ndpy,
struct native_buffer *buf);
/**
* The resource must be creatred with PIPE_BIND_SHARED.
*/
boolean (*export_buffer)(struct native_display *ndpy,
struct pipe_resource *res,
struct native_buffer *nbuf);
};
#endif /* _NATIVE_BUFFER_H_ */
@@ -1,501 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
* Copyright (C) 2011 VMware Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
* Thomas Hellstrom <thellstrom@vmware.com>
*/
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "native_helper.h"
/**
* Number of swap fences and mask
*/
#define EGL_SWAP_FENCES_MAX 4
#define EGL_SWAP_FENCES_MASK 3
#define EGL_SWAP_FENCES_DEFAULT 1
struct resource_surface {
struct pipe_screen *screen;
enum pipe_format format;
uint bind;
struct pipe_resource *resources[NUM_NATIVE_ATTACHMENTS];
uint resource_mask;
uint width, height;
/**
* Swap fences.
*/
struct pipe_fence_handle *swap_fences[EGL_SWAP_FENCES_MAX];
unsigned int cur_fences;
unsigned int head;
unsigned int tail;
unsigned int desired_fences;
};
struct resource_surface *
resource_surface_create(struct pipe_screen *screen,
enum pipe_format format, uint bind)
{
struct resource_surface *rsurf = CALLOC_STRUCT(resource_surface);
char *swap_fences = getenv("EGL_THROTTLE_FENCES");
if (rsurf) {
rsurf->screen = screen;
rsurf->format = format;
rsurf->bind = bind;
rsurf->desired_fences = (swap_fences) ? atoi(swap_fences) :
EGL_SWAP_FENCES_DEFAULT;
if (rsurf->desired_fences > EGL_SWAP_FENCES_MAX)
rsurf->desired_fences = EGL_SWAP_FENCES_MAX;
}
return rsurf;
}
static void
resource_surface_free_resources(struct resource_surface *rsurf)
{
if (rsurf->resource_mask) {
int i;
for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
if (rsurf->resources[i])
pipe_resource_reference(&rsurf->resources[i], NULL);
}
rsurf->resource_mask = 0x0;
}
}
void
resource_surface_destroy(struct resource_surface *rsurf)
{
resource_surface_free_resources(rsurf);
FREE(rsurf);
}
boolean
resource_surface_set_size(struct resource_surface *rsurf,
uint width, uint height)
{
boolean changed = FALSE;
if (rsurf->width != width || rsurf->height != height) {
resource_surface_free_resources(rsurf);
rsurf->width = width;
rsurf->height = height;
changed = TRUE;
}
return changed;
}
void
resource_surface_get_size(struct resource_surface *rsurf,
uint *width, uint *height)
{
if (width)
*width = rsurf->width;
if (height)
*height = rsurf->height;
}
boolean
resource_surface_add_resources(struct resource_surface *rsurf,
uint resource_mask)
{
struct pipe_resource templ;
int i;
resource_mask &= ~rsurf->resource_mask;
if (!resource_mask)
return TRUE;
if (!rsurf->width || !rsurf->height)
return FALSE;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = rsurf->format;
templ.bind = rsurf->bind;
templ.width0 = rsurf->width;
templ.height0 = rsurf->height;
templ.depth0 = 1;
templ.array_size = 1;
for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
if (resource_mask & (1 <<i)) {
assert(!rsurf->resources[i]);
rsurf->resources[i] =
rsurf->screen->resource_create(rsurf->screen, &templ);
if (rsurf->resources[i])
rsurf->resource_mask |= 1 << i;
}
}
return ((rsurf->resource_mask & resource_mask) == resource_mask);
}
void
resource_surface_import_resource(struct resource_surface *rsurf,
enum native_attachment which,
struct pipe_resource *pres)
{
pipe_resource_reference(&rsurf->resources[which], pres);
rsurf->resource_mask |= 1 << which;
}
void
resource_surface_get_resources(struct resource_surface *rsurf,
struct pipe_resource **resources,
uint resource_mask)
{
int i;
for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
if (resource_mask & (1 << i)) {
resources[i] = NULL;
pipe_resource_reference(&resources[i], rsurf->resources[i]);
}
}
}
struct pipe_resource *
resource_surface_get_single_resource(struct resource_surface *rsurf,
enum native_attachment which)
{
struct pipe_resource *pres = NULL;
pipe_resource_reference(&pres, rsurf->resources[which]);
return pres;
}
static INLINE void
pointer_swap(const void **p1, const void **p2)
{
const void *tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void
resource_surface_swap_buffers(struct resource_surface *rsurf,
enum native_attachment buf1,
enum native_attachment buf2,
boolean only_if_exist)
{
const uint buf1_bit = 1 << buf1;
const uint buf2_bit = 1 << buf2;
uint mask;
if (only_if_exist && !(rsurf->resources[buf1] && rsurf->resources[buf2]))
return;
pointer_swap((const void **) &rsurf->resources[buf1],
(const void **) &rsurf->resources[buf2]);
/* swap mask bits */
mask = rsurf->resource_mask & ~(buf1_bit | buf2_bit);
if (rsurf->resource_mask & buf1_bit)
mask |= buf2_bit;
if (rsurf->resource_mask & buf2_bit)
mask |= buf1_bit;
rsurf->resource_mask = mask;
}
boolean
resource_surface_present(struct resource_surface *rsurf,
enum native_attachment which,
void *winsys_drawable_handle)
{
struct pipe_resource *pres = rsurf->resources[which];
if (!pres)
return TRUE;
rsurf->screen->flush_frontbuffer(rsurf->screen,
pres, 0, 0, winsys_drawable_handle, NULL);
return TRUE;
}
/**
* Schedule a copy swap from the back to the front buffer using the
* native display's copy context.
*/
boolean
resource_surface_copy_swap(struct resource_surface *rsurf,
struct native_display *ndpy)
{
struct pipe_resource *ftex;
struct pipe_resource *btex;
struct pipe_context *pipe;
struct pipe_box src_box;
boolean ret = FALSE;
pipe = ndpy_get_copy_context(ndpy);
if (!pipe)
return FALSE;
ftex = resource_surface_get_single_resource(rsurf,
NATIVE_ATTACHMENT_FRONT_LEFT);
if (!ftex)
goto out_no_ftex;
btex = resource_surface_get_single_resource(rsurf,
NATIVE_ATTACHMENT_BACK_LEFT);
if (!btex)
goto out_no_btex;
u_box_origin_2d(ftex->width0, ftex->height0, &src_box);
pipe->resource_copy_region(pipe, ftex, 0, 0, 0, 0,
btex, 0, &src_box);
ret = TRUE;
out_no_btex:
pipe_resource_reference(&btex, NULL);
out_no_ftex:
pipe_resource_reference(&ftex, NULL);
return ret;
}
static struct pipe_fence_handle *
swap_fences_pop_front(struct resource_surface *rsurf)
{
struct pipe_screen *screen = rsurf->screen;
struct pipe_fence_handle *fence = NULL;
if (rsurf->desired_fences == 0)
return NULL;
if (rsurf->cur_fences >= rsurf->desired_fences) {
screen->fence_reference(screen, &fence, rsurf->swap_fences[rsurf->tail]);
screen->fence_reference(screen, &rsurf->swap_fences[rsurf->tail++], NULL);
rsurf->tail &= EGL_SWAP_FENCES_MASK;
--rsurf->cur_fences;
}
return fence;
}
static void
swap_fences_push_back(struct resource_surface *rsurf,
struct pipe_fence_handle *fence)
{
struct pipe_screen *screen = rsurf->screen;
if (!fence || rsurf->desired_fences == 0)
return;
while(rsurf->cur_fences == rsurf->desired_fences)
swap_fences_pop_front(rsurf);
rsurf->cur_fences++;
screen->fence_reference(screen, &rsurf->swap_fences[rsurf->head++],
fence);
rsurf->head &= EGL_SWAP_FENCES_MASK;
}
boolean
resource_surface_throttle(struct resource_surface *rsurf)
{
struct pipe_screen *screen = rsurf->screen;
struct pipe_fence_handle *fence = swap_fences_pop_front(rsurf);
if (fence) {
(void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
screen->fence_reference(screen, &fence, NULL);
return TRUE;
}
return FALSE;
}
boolean
resource_surface_flush_resource(struct resource_surface *rsurf,
struct native_display *ndpy,
enum native_attachment which)
{
struct pipe_context *pipe = ndpy_get_copy_context(ndpy);
if (!pipe)
return FALSE;
pipe->flush_resource(pipe, rsurf->resources[which]);
return TRUE;
}
boolean
resource_surface_flush(struct resource_surface *rsurf,
struct native_display *ndpy)
{
struct pipe_fence_handle *fence = NULL;
struct pipe_screen *screen = rsurf->screen;
struct pipe_context *pipe= ndpy_get_copy_context(ndpy);
if (!pipe)
return FALSE;
pipe->flush(pipe, &fence, 0);
if (fence == NULL)
return FALSE;
swap_fences_push_back(rsurf, fence);
screen->fence_reference(screen, &fence, NULL);
return TRUE;
}
void
resource_surface_wait(struct resource_surface *rsurf)
{
while (resource_surface_throttle(rsurf));
}
boolean
native_display_copy_to_pixmap(struct native_display *ndpy,
EGLNativePixmapType pix,
struct pipe_resource *src)
{
struct pipe_context *pipe;
struct native_surface *nsurf;
struct pipe_resource *dst;
struct pipe_resource *tmp[NUM_NATIVE_ATTACHMENTS];
const enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
pipe = ndpy_get_copy_context(ndpy);
if (!pipe)
return FALSE;
nsurf = ndpy->create_pixmap_surface(ndpy, pix, NULL);
if (!nsurf)
return FALSE;
/* get the texutre */
tmp[natt] = NULL;
nsurf->validate(nsurf, 1 << natt, NULL, tmp, NULL, NULL);
dst = tmp[natt];
if (dst && dst->format == src->format) {
struct native_present_control ctrl;
struct pipe_box src_box;
u_box_origin_2d(src->width0, src->height0, &src_box);
pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &src_box);
pipe->flush(pipe, NULL, 0);
memset(&ctrl, 0, sizeof(ctrl));
ctrl.natt = natt;
nsurf->present(nsurf, &ctrl);
}
if (dst)
pipe_resource_reference(&dst, NULL);
nsurf->destroy(nsurf);
return TRUE;
}
#include "state_tracker/drm_driver.h"
struct pipe_resource *
drm_display_import_native_buffer(struct native_display *ndpy,
struct native_buffer *nbuf)
{
struct pipe_screen *screen = ndpy->screen;
struct pipe_resource *res = NULL;
switch (nbuf->type) {
case NATIVE_BUFFER_DRM:
{
struct winsys_handle wsh;
memset(&wsh, 0, sizeof(wsh));
wsh.handle = nbuf->u.drm.name;
wsh.type = DRM_API_HANDLE_TYPE_SHARED;
wsh.stride = nbuf->u.drm.stride;
res = screen->resource_from_handle(screen, &nbuf->u.drm.templ, &wsh);
}
break;
default:
break;
}
return res;
}
boolean
drm_display_export_native_buffer(struct native_display *ndpy,
struct pipe_resource *res,
struct native_buffer *nbuf)
{
struct pipe_screen *screen = ndpy->screen;
boolean ret = FALSE;
switch (nbuf->type) {
case NATIVE_BUFFER_DRM:
{
struct winsys_handle wsh;
if ((nbuf->u.drm.templ.bind & res->bind) != nbuf->u.drm.templ.bind)
break;
memset(&wsh, 0, sizeof(wsh));
wsh.type = DRM_API_HANDLE_TYPE_KMS;
if (!screen->resource_get_handle(screen, res, &wsh))
break;
nbuf->u.drm.handle = wsh.handle;
nbuf->u.drm.stride = wsh.stride;
/* get the name of the GEM object */
if (nbuf->u.drm.templ.bind & PIPE_BIND_SHARED) {
memset(&wsh, 0, sizeof(wsh));
wsh.type = DRM_API_HANDLE_TYPE_SHARED;
if (!screen->resource_get_handle(screen, res, &wsh))
break;
nbuf->u.drm.name = wsh.handle;
}
nbuf->u.drm.templ = *res;
ret = TRUE;
}
break;
default:
break;
}
return ret;
}
@@ -1,125 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
* Copyright (C) 2011 VMware Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
* Thomas Hellstrom <thellstrom@vmware.com>
*/
#include "native.h"
struct resource_surface;
struct sw_winsys;
struct resource_surface *
resource_surface_create(struct pipe_screen *screen,
enum pipe_format format, uint bind);
void
resource_surface_destroy(struct resource_surface *rsurf);
boolean
resource_surface_set_size(struct resource_surface *rsurf,
uint width, uint height);
void
resource_surface_get_size(struct resource_surface *rsurf,
uint *width, uint *height);
boolean
resource_surface_add_resources(struct resource_surface *rsurf,
uint resource_mask);
void
resource_surface_import_resource(struct resource_surface *rsurf,
enum native_attachment which,
struct pipe_resource *pres);
void
resource_surface_get_resources(struct resource_surface *rsurf,
struct pipe_resource **resources,
uint resource_mask);
struct pipe_resource *
resource_surface_get_single_resource(struct resource_surface *rsurf,
enum native_attachment which);
void
resource_surface_swap_buffers(struct resource_surface *rsurf,
enum native_attachment buf1,
enum native_attachment buf2,
boolean only_if_exist);
boolean
resource_surface_present(struct resource_surface *rsurf,
enum native_attachment which,
void *winsys_drawable_handle);
/**
* Perform a gallium copy blit between the back left and front left
* surfaces. Needs to be followed by a call to resource_surface_flush.
*/
boolean
resource_surface_copy_swap(struct resource_surface *rsurf,
struct native_display *ndpy);
/**
* Throttle on outstanding rendering using the copy context. For example
* copy swaps.
*/
boolean
resource_surface_throttle(struct resource_surface *rsurf);
boolean
resource_surface_flush_resource(struct resource_surface *rsurf,
struct native_display *ndpy,
enum native_attachment which);
/**
* Flush pending rendering using the copy context. This function saves a
* marker for upcoming throttles.
*/
boolean
resource_surface_flush(struct resource_surface *rsurf,
struct native_display *ndpy);
/**
* Wait for all rendering using the copy context to be complete. Frees all
* throttle markers saved using resource_surface_flush.
*/
void
resource_surface_wait(struct resource_surface *rsurf);
boolean
native_display_copy_to_pixmap(struct native_display *ndpy,
EGLNativePixmapType pix,
struct pipe_resource *src);
struct pipe_resource *
drm_display_import_native_buffer(struct native_display *ndpy,
struct native_buffer *nbuf);
boolean
drm_display_export_native_buffer(struct native_display *ndpy,
struct pipe_resource *res,
struct native_buffer *nbuf);
@@ -1,87 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _NATIVE_MODESET_H_
#define _NATIVE_MODESET_H_
#include "pipe/p_compiler.h"
struct native_display;
struct native_surface;
struct native_config;
struct native_connector {
int dummy;
};
struct native_mode {
const char *desc;
int width, height;
int refresh_rate; /* HZ * 1000 */
};
/**
* Mode setting interface of the native display. It exposes the mode setting
* capabilities of the underlying graphics hardware.
*/
struct native_display_modeset {
/**
* Get the available physical connectors and the number of CRTCs.
*/
const struct native_connector **(*get_connectors)(struct native_display *ndpy,
int *num_connectors,
int *num_crtcs);
/**
* Get the current supported modes of a connector. The returned modes may
* change every time this function is called and those from previous calls
* might become invalid.
*/
const struct native_mode **(*get_modes)(struct native_display *ndpy,
const struct native_connector *nconn,
int *num_modes);
/**
* Create a scan-out surface. Required unless no config has scanout_bit
* set.
*/
struct native_surface *(*create_scanout_surface)(struct native_display *ndpy,
const struct native_config *nconf,
uint width, uint height);
/**
* Program the CRTC to output the surface to the given connectors with the
* given mode. When surface is not given, the CRTC is disabled.
*
* This interface does not export a way to query capabilities of the CRTCs.
* The native display usually needs to dynamically map the index to a CRTC
* that supports the given connectors.
*/
boolean (*program)(struct native_display *ndpy, int crtc_idx,
struct native_surface *nsurf, uint x, uint y,
const struct native_connector **nconns, int num_nconns,
const struct native_mode *nmode);
};
#endif /* _NATIVE_MODESET_H_ */
@@ -1,49 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _NATIVE_WAYLAND_BUFMGR_H_
#define _NATIVE_WAYLAND_BUFMGR_H_
struct native_display;
struct wl_display;
struct wl_resource;
struct pipe_resource;
struct native_display_wayland_bufmgr {
boolean (*bind_display)(struct native_display *ndpy,
struct wl_display *wl_dpy);
boolean (*unbind_display)(struct native_display *ndpy,
struct wl_display *wl_dpy);
struct pipe_resource *(*buffer_get_resource)(struct native_display *ndpy,
struct wl_resource *buffer);
boolean (*query_buffer)(struct native_display *ndpy,
struct wl_resource *buffer,
int attribute, int *value);
};
#endif /* _NATIVE_WAYLAND_BUFMGR_H_ */
@@ -1,228 +0,0 @@
#include <stdint.h>
#include <string.h>
#include "native.h"
#include "util/u_inlines.h"
#include "state_tracker/drm_driver.h"
#ifdef HAVE_WAYLAND_BACKEND
#include <wayland-server.h>
#include <wayland-drm-server-protocol.h>
#include "native_wayland_drm_bufmgr.h"
#include "wayland-drm.h"
struct wayland_drm_bufmgr {
struct native_display_wayland_bufmgr base;
struct wl_drm *wl_server_drm;
char *device_name;
void *user_data;
wayland_drm_bufmgr_authenticate_func authenticate;
};
static INLINE struct wayland_drm_bufmgr *
wayland_drm_bufmgr(const struct native_display_wayland_bufmgr *base)
{
return (struct wayland_drm_bufmgr *) base;
}
static int
wayland_drm_bufmgr_authenticate(void *user_data, uint32_t magic)
{
struct native_display *ndpy = user_data;
struct wayland_drm_bufmgr *bufmgr;
bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
return bufmgr->authenticate(user_data, magic);
}
static void
wayland_drm_bufmgr_reference_buffer(void *user_data, uint32_t name, int fd,
struct wl_drm_buffer *buffer)
{
struct native_display *ndpy = user_data;
struct pipe_resource templ;
struct winsys_handle wsh;
enum pipe_format pf;
switch (buffer->format) {
case WL_DRM_FORMAT_ARGB8888:
pf = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
case WL_DRM_FORMAT_XRGB8888:
pf = PIPE_FORMAT_B8G8R8X8_UNORM;
break;
default:
pf = PIPE_FORMAT_NONE;
break;
}
if (pf == PIPE_FORMAT_NONE)
return;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = pf;
templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
templ.width0 = buffer->width;
templ.height0 = buffer->height;
templ.depth0 = 1;
templ.array_size = 1;
memset(&wsh, 0, sizeof(wsh));
wsh.handle = name;
wsh.stride = buffer->stride[0];
buffer->driver_buffer =
ndpy->screen->resource_from_handle(ndpy->screen, &templ, &wsh);
}
static void
wayland_drm_bufmgr_unreference_buffer(void *user_data,
struct wl_drm_buffer *buffer)
{
struct pipe_resource *resource = buffer->driver_buffer;
pipe_resource_reference(&resource, NULL);
}
static struct wayland_drm_callbacks wl_drm_callbacks = {
wayland_drm_bufmgr_authenticate,
wayland_drm_bufmgr_reference_buffer,
wayland_drm_bufmgr_unreference_buffer
};
static boolean
wayland_drm_bufmgr_bind_display(struct native_display *ndpy,
struct wl_display *wl_dpy)
{
struct wayland_drm_bufmgr *bufmgr;
bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
if (bufmgr->wl_server_drm)
return FALSE;
bufmgr->wl_server_drm = wayland_drm_init(wl_dpy, bufmgr->device_name,
&wl_drm_callbacks, ndpy, 0);
if (!bufmgr->wl_server_drm)
return FALSE;
return TRUE;
}
static boolean
wayland_drm_bufmgr_unbind_display(struct native_display *ndpy,
struct wl_display *wl_dpy)
{
struct wayland_drm_bufmgr *bufmgr;
bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
if (!bufmgr->wl_server_drm)
return FALSE;
wayland_drm_uninit(bufmgr->wl_server_drm);
bufmgr->wl_server_drm = NULL;
return TRUE;
}
static struct pipe_resource *
wayland_drm_bufmgr_wl_buffer_get_resource(struct native_display *ndpy,
struct wl_resource *buffer_resource)
{
struct wayland_drm_bufmgr *bufmgr;
struct wl_drm_buffer *buffer;
bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
buffer = wayland_drm_buffer_get(bufmgr->wl_server_drm, buffer_resource);
if (!buffer)
return NULL;
return wayland_drm_buffer_get_buffer(buffer);
}
static boolean
wayland_drm_bufmgr_query_buffer(struct native_display *ndpy,
struct wl_resource *buffer_resource,
int attribute, int *value)
{
struct wayland_drm_bufmgr *bufmgr;
struct wl_drm_buffer *buffer;
struct pipe_resource *resource;
bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
buffer = wayland_drm_buffer_get(bufmgr->wl_server_drm, buffer_resource);
if (!buffer)
return FALSE;
resource = buffer->driver_buffer;
switch (attribute) {
case EGL_TEXTURE_FORMAT:
switch (resource->format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
*value = EGL_TEXTURE_RGBA;
return TRUE;
case PIPE_FORMAT_B8G8R8X8_UNORM:
*value = EGL_TEXTURE_RGB;
return TRUE;
default:
return FALSE;
}
case EGL_WIDTH:
*value = buffer->width;
return TRUE;
case EGL_HEIGHT:
*value = buffer->height;
return TRUE;
default:
return FALSE;
}
}
struct native_display_wayland_bufmgr *
wayland_drm_bufmgr_create(wayland_drm_bufmgr_authenticate_func authenticate,
void *user_data, char *device_name)
{
struct wayland_drm_bufmgr *bufmgr;
bufmgr = calloc(1, sizeof *bufmgr);
if (!bufmgr)
return NULL;
bufmgr->user_data = user_data;
bufmgr->authenticate = authenticate;
bufmgr->device_name = strdup(device_name);
bufmgr->base.bind_display = wayland_drm_bufmgr_bind_display;
bufmgr->base.unbind_display = wayland_drm_bufmgr_unbind_display;
bufmgr->base.buffer_get_resource = wayland_drm_bufmgr_wl_buffer_get_resource;
bufmgr->base.query_buffer = wayland_drm_bufmgr_query_buffer;
return &bufmgr->base;
}
void
wayland_drm_bufmgr_destroy(struct native_display_wayland_bufmgr *_bufmgr)
{
struct wayland_drm_bufmgr *bufmgr = wayland_drm_bufmgr(_bufmgr);
if (!bufmgr)
return;
free(bufmgr->device_name);
free(bufmgr);
}
#endif
@@ -1,37 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _NATIVE_WAYLAND_DRM_BUFMGR_H_
#define _NATIVE_WAYLAND_DRM_BUFMGR_H_
typedef int (*wayland_drm_bufmgr_authenticate_func)(void *, uint32_t);
struct native_display_wayland_bufmgr *
wayland_drm_bufmgr_create(wayland_drm_bufmgr_authenticate_func authenticate,
void *user_data, char *device_name);
void
wayland_drm_bufmgr_destroy(struct native_display_wayland_bufmgr *bufmgr);
#endif /* _NATIVE_WAYLAND_DRM_BUFMGR_H_ */
@@ -1,707 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
* Copyright (C) 2011 VMware Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
* Thomas Hellstrom <thellstrom@vmware.com>
*/
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "egllog.h"
#include "native_drm.h"
static boolean
drm_surface_validate(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height)
{
struct drm_surface *drmsurf = drm_surface(nsurf);
if (!resource_surface_add_resources(drmsurf->rsurf, attachment_mask))
return FALSE;
if (textures)
resource_surface_get_resources(drmsurf->rsurf, textures, attachment_mask);
if (seq_num)
*seq_num = drmsurf->sequence_number;
if (width)
*width = drmsurf->width;
if (height)
*height = drmsurf->height;
return TRUE;
}
/**
* Add textures as DRM framebuffers.
*/
static boolean
drm_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
{
struct drm_surface *drmsurf = drm_surface(nsurf);
struct drm_display *drmdpy = drmsurf->drmdpy;
int num_framebuffers = (need_back) ? 2 : 1;
int i, err;
for (i = 0; i < num_framebuffers; i++) {
struct drm_framebuffer *fb;
enum native_attachment natt;
struct winsys_handle whandle;
uint block_bits;
if (i == 0) {
fb = &drmsurf->front_fb;
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
}
else {
fb = &drmsurf->back_fb;
natt = NATIVE_ATTACHMENT_BACK_LEFT;
}
if (!fb->texture) {
/* make sure the texture has been allocated */
resource_surface_add_resources(drmsurf->rsurf, 1 << natt);
fb->texture =
resource_surface_get_single_resource(drmsurf->rsurf, natt);
if (!fb->texture)
return FALSE;
}
/* already initialized */
if (fb->buffer_id)
continue;
/* TODO detect the real value */
fb->is_passive = TRUE;
memset(&whandle, 0, sizeof(whandle));
whandle.type = DRM_API_HANDLE_TYPE_KMS;
if (!drmdpy->base.screen->resource_get_handle(drmdpy->base.screen,
fb->texture, &whandle))
return FALSE;
block_bits = util_format_get_blocksizebits(drmsurf->color_format);
err = drmModeAddFB(drmdpy->fd, drmsurf->width, drmsurf->height,
block_bits, block_bits, whandle.stride, whandle.handle,
&fb->buffer_id);
if (err) {
fb->buffer_id = 0;
return FALSE;
}
}
return TRUE;
}
static boolean
drm_surface_flush_frontbuffer(struct native_surface *nsurf)
{
#ifdef DRM_MODE_FEATURE_DIRTYFB
struct drm_surface *drmsurf = drm_surface(nsurf);
struct drm_display *drmdpy = drmsurf->drmdpy;
if (drmsurf->front_fb.is_passive)
drmModeDirtyFB(drmdpy->fd, drmsurf->front_fb.buffer_id, NULL, 0);
#endif
return TRUE;
}
static boolean
drm_surface_copy_swap(struct native_surface *nsurf)
{
struct drm_surface *drmsurf = drm_surface(nsurf);
struct drm_display *drmdpy = drmsurf->drmdpy;
(void) resource_surface_throttle(drmsurf->rsurf);
if (!resource_surface_copy_swap(drmsurf->rsurf, &drmdpy->base))
return FALSE;
(void) resource_surface_flush(drmsurf->rsurf, &drmdpy->base);
if (!drm_surface_flush_frontbuffer(nsurf))
return FALSE;
drmsurf->sequence_number++;
return TRUE;
}
static boolean
drm_surface_swap_buffers(struct native_surface *nsurf)
{
struct drm_surface *drmsurf = drm_surface(nsurf);
struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
struct drm_display *drmdpy = drmsurf->drmdpy;
struct drm_framebuffer tmp_fb;
int err;
if (!drmsurf->have_pageflip)
return drm_surface_copy_swap(nsurf);
if (!drmsurf->back_fb.buffer_id) {
if (!drm_surface_init_framebuffers(&drmsurf->base, TRUE))
return FALSE;
}
if (drmsurf->is_shown && drmcrtc->crtc) {
err = drmModePageFlip(drmdpy->fd, drmcrtc->crtc->crtc_id,
drmsurf->back_fb.buffer_id, 0, NULL);
if (err) {
drmsurf->have_pageflip = FALSE;
return drm_surface_copy_swap(nsurf);
}
}
/* swap the buffers */
tmp_fb = drmsurf->front_fb;
drmsurf->front_fb = drmsurf->back_fb;
drmsurf->back_fb = tmp_fb;
resource_surface_swap_buffers(drmsurf->rsurf,
NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
/* the front/back textures are swapped */
drmsurf->sequence_number++;
drmdpy->event_handler->invalid_surface(&drmdpy->base,
&drmsurf->base, drmsurf->sequence_number);
return TRUE;
}
static boolean
drm_surface_present(struct native_surface *nsurf,
const struct native_present_control *ctrl)
{
boolean ret;
if (ctrl->swap_interval)
return FALSE;
switch (ctrl->natt) {
case NATIVE_ATTACHMENT_FRONT_LEFT:
ret = drm_surface_flush_frontbuffer(nsurf);
break;
case NATIVE_ATTACHMENT_BACK_LEFT:
if (ctrl->preserve)
ret = drm_surface_copy_swap(nsurf);
else
ret = drm_surface_swap_buffers(nsurf);
break;
default:
ret = FALSE;
break;
}
return ret;
}
static void
drm_surface_wait(struct native_surface *nsurf)
{
struct drm_surface *drmsurf = drm_surface(nsurf);
resource_surface_wait(drmsurf->rsurf);
}
static void
drm_surface_destroy(struct native_surface *nsurf)
{
struct drm_surface *drmsurf = drm_surface(nsurf);
resource_surface_wait(drmsurf->rsurf);
if (drmsurf->current_crtc.crtc)
drmModeFreeCrtc(drmsurf->current_crtc.crtc);
if (drmsurf->front_fb.buffer_id)
drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->front_fb.buffer_id);
pipe_resource_reference(&drmsurf->front_fb.texture, NULL);
if (drmsurf->back_fb.buffer_id)
drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->back_fb.buffer_id);
pipe_resource_reference(&drmsurf->back_fb.texture, NULL);
resource_surface_destroy(drmsurf->rsurf);
FREE(drmsurf);
}
static struct drm_surface *
drm_display_create_surface(struct native_display *ndpy,
const struct native_config *nconf,
uint width, uint height)
{
struct drm_display *drmdpy = drm_display(ndpy);
struct drm_config *drmconf = drm_config(nconf);
struct drm_surface *drmsurf;
drmsurf = CALLOC_STRUCT(drm_surface);
if (!drmsurf)
return NULL;
drmsurf->drmdpy = drmdpy;
drmsurf->color_format = drmconf->base.color_format;
drmsurf->width = width;
drmsurf->height = height;
drmsurf->have_pageflip = TRUE;
drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
drmsurf->color_format,
PIPE_BIND_RENDER_TARGET |
PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT);
if (!drmsurf->rsurf) {
FREE(drmsurf);
return NULL;
}
resource_surface_set_size(drmsurf->rsurf, drmsurf->width, drmsurf->height);
drmsurf->base.destroy = drm_surface_destroy;
drmsurf->base.present = drm_surface_present;
drmsurf->base.validate = drm_surface_validate;
drmsurf->base.wait = drm_surface_wait;
return drmsurf;
}
struct native_surface *
drm_display_create_surface_from_resource(struct native_display *ndpy,
struct pipe_resource *resource)
{
struct drm_display *drmdpy = drm_display(ndpy);
struct drm_surface *drmsurf;
enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
drmsurf = CALLOC_STRUCT(drm_surface);
if (!drmsurf)
return NULL;
drmsurf->drmdpy = drmdpy;
drmsurf->color_format = resource->format;
drmsurf->width = resource->width0;
drmsurf->height = resource->height0;
drmsurf->have_pageflip = FALSE;
drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
drmsurf->color_format,
PIPE_BIND_RENDER_TARGET |
PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT);
resource_surface_import_resource(drmsurf->rsurf, natt, resource);
drmsurf->base.destroy = drm_surface_destroy;
drmsurf->base.present = drm_surface_present;
drmsurf->base.validate = drm_surface_validate;
drmsurf->base.wait = drm_surface_wait;
return &drmsurf->base;
}
/**
* Choose a CRTC that supports all given connectors.
*/
static uint32_t
drm_display_choose_crtc(struct native_display *ndpy,
uint32_t *connectors, int num_connectors)
{
struct drm_display *drmdpy = drm_display(ndpy);
int idx;
for (idx = 0; idx < drmdpy->resources->count_crtcs; idx++) {
boolean found_crtc = TRUE;
int i, j;
for (i = 0; i < num_connectors; i++) {
drmModeConnectorPtr connector;
int encoder_idx = -1;
connector = drmModeGetConnector(drmdpy->fd, connectors[i]);
if (!connector) {
found_crtc = FALSE;
break;
}
/* find an encoder the CRTC supports */
for (j = 0; j < connector->count_encoders; j++) {
drmModeEncoderPtr encoder =
drmModeGetEncoder(drmdpy->fd, connector->encoders[j]);
if (encoder->possible_crtcs & (1 << idx)) {
encoder_idx = j;
break;
}
drmModeFreeEncoder(encoder);
}
drmModeFreeConnector(connector);
if (encoder_idx < 0) {
found_crtc = FALSE;
break;
}
}
if (found_crtc)
break;
}
if (idx >= drmdpy->resources->count_crtcs) {
_eglLog(_EGL_WARNING,
"failed to find a CRTC that supports the given %d connectors",
num_connectors);
return 0;
}
return drmdpy->resources->crtcs[idx];
}
/**
* Remember the original CRTC status and set the CRTC
*/
static boolean
drm_display_set_crtc(struct native_display *ndpy, int crtc_idx,
uint32_t buffer_id, uint32_t x, uint32_t y,
uint32_t *connectors, int num_connectors,
drmModeModeInfoPtr mode)
{
struct drm_display *drmdpy = drm_display(ndpy);
struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[crtc_idx];
uint32_t crtc_id;
int err;
if (drmcrtc->crtc) {
crtc_id = drmcrtc->crtc->crtc_id;
}
else {
int count = 0, i;
/*
* Choose the CRTC once. It could be more dynamic, but let's keep it
* simple for now.
*/
crtc_id = drm_display_choose_crtc(&drmdpy->base,
connectors, num_connectors);
/* save the original CRTC status */
drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
if (!drmcrtc->crtc)
return FALSE;
for (i = 0; i < drmdpy->num_connectors; i++) {
struct drm_connector *drmconn = &drmdpy->connectors[i];
drmModeConnectorPtr connector = drmconn->connector;
drmModeEncoderPtr encoder;
encoder = drmModeGetEncoder(drmdpy->fd, connector->encoder_id);
if (encoder) {
if (encoder->crtc_id == crtc_id) {
drmcrtc->connectors[count++] = connector->connector_id;
if (count >= Elements(drmcrtc->connectors))
break;
}
drmModeFreeEncoder(encoder);
}
}
drmcrtc->num_connectors = count;
}
err = drmModeSetCrtc(drmdpy->fd, crtc_id, buffer_id, x, y,
connectors, num_connectors, mode);
if (err) {
drmModeFreeCrtc(drmcrtc->crtc);
drmcrtc->crtc = NULL;
drmcrtc->num_connectors = 0;
return FALSE;
}
return TRUE;
}
static boolean
drm_display_program(struct native_display *ndpy, int crtc_idx,
struct native_surface *nsurf, uint x, uint y,
const struct native_connector **nconns, int num_nconns,
const struct native_mode *nmode)
{
struct drm_display *drmdpy = drm_display(ndpy);
struct drm_surface *drmsurf = drm_surface(nsurf);
const struct drm_mode *drmmode = drm_mode(nmode);
uint32_t connector_ids[32];
uint32_t buffer_id;
drmModeModeInfo mode_tmp, *mode;
int i;
if (num_nconns > Elements(connector_ids)) {
_eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
num_nconns = Elements(connector_ids);
}
if (drmsurf) {
if (!drm_surface_init_framebuffers(&drmsurf->base, FALSE))
return FALSE;
buffer_id = drmsurf->front_fb.buffer_id;
/* the mode argument of drmModeSetCrtc is not constified */
mode_tmp = drmmode->mode;
mode = &mode_tmp;
}
else {
/* disable the CRTC */
buffer_id = 0;
mode = NULL;
num_nconns = 0;
}
for (i = 0; i < num_nconns; i++) {
struct drm_connector *drmconn = drm_connector(nconns[i]);
connector_ids[i] = drmconn->connector->connector_id;
}
if (!drm_display_set_crtc(&drmdpy->base, crtc_idx, buffer_id, x, y,
connector_ids, num_nconns, mode)) {
_eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
return FALSE;
}
if (drmdpy->shown_surfaces[crtc_idx])
drmdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
drmdpy->shown_surfaces[crtc_idx] = drmsurf;
/* remember the settings for buffer swapping */
if (drmsurf) {
uint32_t crtc_id = drmdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
if (drmcrtc->crtc)
drmModeFreeCrtc(drmcrtc->crtc);
drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
assert(num_nconns < Elements(drmcrtc->connectors));
memcpy(drmcrtc->connectors, connector_ids,
sizeof(*connector_ids) * num_nconns);
drmcrtc->num_connectors = num_nconns;
drmsurf->is_shown = TRUE;
}
return TRUE;
}
static const struct native_mode **
drm_display_get_modes(struct native_display *ndpy,
const struct native_connector *nconn,
int *num_modes)
{
struct drm_display *drmdpy = drm_display(ndpy);
struct drm_connector *drmconn = drm_connector(nconn);
const struct native_mode **nmodes_return;
int count, i;
/* delete old data */
if (drmconn->connector) {
drmModeFreeConnector(drmconn->connector);
FREE(drmconn->drm_modes);
drmconn->connector = NULL;
drmconn->drm_modes = NULL;
drmconn->num_modes = 0;
}
/* detect again */
drmconn->connector = drmModeGetConnector(drmdpy->fd, drmconn->connector_id);
if (!drmconn->connector)
return NULL;
count = drmconn->connector->count_modes;
drmconn->drm_modes = CALLOC(count, sizeof(*drmconn->drm_modes));
if (!drmconn->drm_modes) {
drmModeFreeConnector(drmconn->connector);
drmconn->connector = NULL;
return NULL;
}
for (i = 0; i < count; i++) {
struct drm_mode *drmmode = &drmconn->drm_modes[i];
drmModeModeInfoPtr mode = &drmconn->connector->modes[i];
drmmode->mode = *mode;
drmmode->base.desc = drmmode->mode.name;
drmmode->base.width = drmmode->mode.hdisplay;
drmmode->base.height = drmmode->mode.vdisplay;
drmmode->base.refresh_rate = drmmode->mode.vrefresh;
/* not all kernels have vrefresh = refresh_rate * 1000 */
if (drmmode->base.refresh_rate < 1000)
drmmode->base.refresh_rate *= 1000;
}
nmodes_return = MALLOC(count * sizeof(*nmodes_return));
if (nmodes_return) {
for (i = 0; i < count; i++)
nmodes_return[i] = &drmconn->drm_modes[i].base;
if (num_modes)
*num_modes = count;
}
return nmodes_return;
}
static const struct native_connector **
drm_display_get_connectors(struct native_display *ndpy, int *num_connectors,
int *num_crtc)
{
struct drm_display *drmdpy = drm_display(ndpy);
const struct native_connector **connectors;
int i;
if (!drmdpy->connectors) {
drmdpy->connectors =
CALLOC(drmdpy->resources->count_connectors, sizeof(*drmdpy->connectors));
if (!drmdpy->connectors)
return NULL;
for (i = 0; i < drmdpy->resources->count_connectors; i++) {
struct drm_connector *drmconn = &drmdpy->connectors[i];
drmconn->connector_id = drmdpy->resources->connectors[i];
/* drmconn->connector is allocated when the modes are asked */
}
drmdpy->num_connectors = drmdpy->resources->count_connectors;
}
connectors = MALLOC(drmdpy->num_connectors * sizeof(*connectors));
if (connectors) {
for (i = 0; i < drmdpy->num_connectors; i++)
connectors[i] = &drmdpy->connectors[i].base;
if (num_connectors)
*num_connectors = drmdpy->num_connectors;
}
if (num_crtc)
*num_crtc = drmdpy->resources->count_crtcs;
return connectors;
}
static struct native_surface *
drm_display_create_scanout_surface(struct native_display *ndpy,
const struct native_config *nconf,
uint width, uint height)
{
struct drm_surface *drmsurf;
drmsurf = drm_display_create_surface(ndpy, nconf, width, height);
return &drmsurf->base;
}
static struct native_display_modeset drm_display_modeset = {
.get_connectors = drm_display_get_connectors,
.get_modes = drm_display_get_modes,
.create_scanout_surface = drm_display_create_scanout_surface,
.program = drm_display_program
};
void
drm_display_fini_modeset(struct native_display *ndpy)
{
struct drm_display *drmdpy = drm_display(ndpy);
int i;
if (drmdpy->connectors) {
for (i = 0; i < drmdpy->num_connectors; i++) {
struct drm_connector *drmconn = &drmdpy->connectors[i];
if (drmconn->connector) {
drmModeFreeConnector(drmconn->connector);
FREE(drmconn->drm_modes);
}
}
FREE(drmdpy->connectors);
}
FREE(drmdpy->shown_surfaces);
drmdpy->shown_surfaces = NULL;
if (drmdpy->saved_crtcs) {
for (i = 0; i < drmdpy->resources->count_crtcs; i++) {
struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[i];
if (drmcrtc->crtc) {
/* restore crtc */
drmModeSetCrtc(drmdpy->fd, drmcrtc->crtc->crtc_id,
drmcrtc->crtc->buffer_id, drmcrtc->crtc->x, drmcrtc->crtc->y,
drmcrtc->connectors, drmcrtc->num_connectors,
&drmcrtc->crtc->mode);
drmModeFreeCrtc(drmcrtc->crtc);
}
}
FREE(drmdpy->saved_crtcs);
}
if (drmdpy->resources) {
drmModeFreeResources(drmdpy->resources);
drmdpy->resources = NULL;
}
drmdpy->base.modeset = NULL;
}
boolean
drm_display_init_modeset(struct native_display *ndpy)
{
struct drm_display *drmdpy = drm_display(ndpy);
/* resources are fixed, unlike crtc, connector, or encoder */
drmdpy->resources = drmModeGetResources(drmdpy->fd);
if (!drmdpy->resources) {
_eglLog(_EGL_DEBUG, "Failed to get KMS resources. Disable modeset.");
return FALSE;
}
drmdpy->saved_crtcs =
CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->saved_crtcs));
if (!drmdpy->saved_crtcs) {
drm_display_fini_modeset(&drmdpy->base);
return FALSE;
}
drmdpy->shown_surfaces =
CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->shown_surfaces));
if (!drmdpy->shown_surfaces) {
drm_display_fini_modeset(&drmdpy->base);
return FALSE;
}
drmdpy->base.modeset = &drm_display_modeset;
return TRUE;
}
@@ -1,273 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "util/u_memory.h"
#include "egllog.h"
#include "loader.h"
#include "native_drm.h"
#include "gbm_gallium_drmint.h"
static boolean
drm_display_is_format_supported(struct native_display *ndpy,
enum pipe_format fmt, boolean is_color)
{
return ndpy->screen->is_format_supported(ndpy->screen,
fmt, PIPE_TEXTURE_2D, 0,
(is_color) ? PIPE_BIND_RENDER_TARGET :
PIPE_BIND_DEPTH_STENCIL);
}
static const struct native_config **
drm_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct drm_display *drmdpy = drm_display(ndpy);
const struct native_config **configs;
/* first time */
if (!drmdpy->config) {
struct native_config *nconf;
enum pipe_format format;
drmdpy->config = CALLOC(1, sizeof(*drmdpy->config));
if (!drmdpy->config)
return NULL;
nconf = &drmdpy->config->base;
nconf->buffer_mask =
(1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
format = PIPE_FORMAT_B8G8R8A8_UNORM;
if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE)) {
format = PIPE_FORMAT_A8R8G8B8_UNORM;
if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE))
format = PIPE_FORMAT_NONE;
}
if (format == PIPE_FORMAT_NONE) {
FREE(drmdpy->config);
drmdpy->config = NULL;
return NULL;
}
nconf->color_format = format;
/* support KMS */
if (drmdpy->resources)
nconf->scanout_bit = TRUE;
}
configs = MALLOC(sizeof(*configs));
if (configs) {
configs[0] = &drmdpy->config->base;
if (num_configs)
*num_configs = 1;
}
return configs;
}
static int
drm_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
int val;
switch (param) {
case NATIVE_PARAM_USE_NATIVE_BUFFER:
case NATIVE_PARAM_PRESERVE_BUFFER:
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
default:
val = 0;
break;
}
return val;
}
static void
drm_display_destroy(struct native_display *ndpy)
{
struct drm_display *drmdpy = drm_display(ndpy);
FREE(drmdpy->config);
drm_display_fini_modeset(&drmdpy->base);
/* gbm owns screen */
ndpy->screen = NULL;
ndpy_uninit(ndpy);
FREE(drmdpy->device_name);
#ifdef HAVE_WAYLAND_BACKEND
wayland_drm_bufmgr_destroy(ndpy->wayland_bufmgr);
#endif
if (drmdpy->own_gbm) {
gbm_device_destroy(&drmdpy->gbmdrm->base.base);
if (drmdpy->fd >= 0)
close(drmdpy->fd);
}
FREE(drmdpy);
}
static struct native_display_buffer drm_display_buffer = {
/* use the helpers */
drm_display_import_native_buffer,
drm_display_export_native_buffer
};
#ifdef HAVE_WAYLAND_BACKEND
static int
drm_display_authenticate(void *user_data, uint32_t magic)
{
struct native_display *ndpy = user_data;
struct drm_display *drmdpy = drm_display(ndpy);
return drmAuthMagic(drmdpy->fd, magic);
}
#endif /* HAVE_WAYLAND_BACKEND */
static struct native_surface *
drm_create_pixmap_surface(struct native_display *ndpy,
EGLNativePixmapType pix,
const struct native_config *nconf)
{
struct gbm_gallium_drm_bo *bo = (void *) pix;
return drm_display_create_surface_from_resource(ndpy, bo->resource);
}
static boolean
drm_display_init_screen(struct native_display *ndpy)
{
return TRUE;
}
static struct native_display *
drm_create_display(struct gbm_gallium_drm_device *gbmdrm, int own_gbm,
const struct native_event_handler *event_handler)
{
struct drm_display *drmdpy;
drmdpy = CALLOC_STRUCT(drm_display);
if (!drmdpy)
return NULL;
drmdpy->gbmdrm = gbmdrm;
drmdpy->own_gbm = own_gbm;
drmdpy->fd = gbmdrm->base.base.fd;
drmdpy->device_name = loader_get_device_name_for_fd(drmdpy->fd);
gbmdrm->lookup_egl_image = (struct pipe_resource *(*)(void *, void *))
event_handler->lookup_egl_image;
gbmdrm->lookup_egl_image_data = &drmdpy->base;
drmdpy->event_handler = event_handler;
drmdpy->base.screen = gbmdrm->screen;
drmdpy->base.init_screen = drm_display_init_screen;
drmdpy->base.destroy = drm_display_destroy;
drmdpy->base.get_param = drm_display_get_param;
drmdpy->base.get_configs = drm_display_get_configs;
drmdpy->base.create_pixmap_surface = drm_create_pixmap_surface;
drmdpy->base.buffer = &drm_display_buffer;
#ifdef HAVE_WAYLAND_BACKEND
if (drmdpy->device_name)
drmdpy->base.wayland_bufmgr = wayland_drm_bufmgr_create(
drm_display_authenticate, drmdpy, drmdpy->device_name);
#endif
drm_display_init_modeset(&drmdpy->base);
return &drmdpy->base;
}
static const struct native_event_handler *drm_event_handler;
static struct native_display *
native_create_display(void *dpy, boolean use_sw)
{
struct gbm_gallium_drm_device *gbm;
int fd;
int own_gbm = 0;
gbm = dpy;
if (gbm == NULL) {
const char *device_name="/dev/dri/card0";
#ifdef O_CLOEXEC
fd = open(device_name, O_RDWR | O_CLOEXEC);
if (fd == -1 && errno == EINVAL)
#endif
{
fd = open(device_name, O_RDWR);
if (fd != -1)
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
}
/* FIXME: Use an internal constructor to create a gbm
* device with gallium backend directly, without setenv */
setenv("GBM_BACKEND", "gbm_gallium_drm.so", 1);
gbm = gbm_gallium_drm_device(gbm_create_device(fd));
own_gbm = 1;
}
if (gbm == NULL)
return NULL;
if (strcmp(gbm_device_get_backend_name(&gbm->base.base), "drm") != 0 ||
gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM) {
if (own_gbm)
gbm_device_destroy(&gbm->base.base);
return NULL;
}
return drm_create_display(gbm, own_gbm, drm_event_handler);
}
static const struct native_platform drm_platform = {
"DRM", /* name */
native_create_display
};
const struct native_platform *
native_get_drm_platform(const struct native_event_handler *event_handler)
{
drm_event_handler = event_handler;
return &drm_platform;
}
@@ -1,160 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _NATIVE_DRM_H_
#define _NATIVE_DRM_H_
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "pipe/p_compiler.h"
#include "util/u_format.h"
#include "pipe/p_state.h"
#include "state_tracker/drm_driver.h"
#include "common/native.h"
#include "common/native_helper.h"
#ifdef HAVE_WAYLAND_BACKEND
#include "common/native_wayland_drm_bufmgr.h"
#endif
#include "gbm_gallium_drmint.h"
struct drm_config;
struct drm_crtc;
struct drm_connector;
struct drm_mode;
struct drm_surface;
struct drm_display {
struct native_display base;
const struct native_event_handler *event_handler;
struct gbm_gallium_drm_device *gbmdrm;
int own_gbm;
int fd;
char *device_name;
struct drm_config *config;
/* for modesetting */
drmModeResPtr resources;
struct drm_connector *connectors;
int num_connectors;
struct drm_surface **shown_surfaces;
/* save the original settings of the CRTCs */
struct drm_crtc *saved_crtcs;
};
struct drm_config {
struct native_config base;
};
struct drm_crtc {
drmModeCrtcPtr crtc;
uint32_t connectors[32];
int num_connectors;
};
struct drm_framebuffer {
struct pipe_resource *texture;
boolean is_passive;
uint32_t buffer_id;
};
struct drm_surface {
struct native_surface base;
struct drm_display *drmdpy;
struct resource_surface *rsurf;
enum pipe_format color_format;
int width, height;
unsigned int sequence_number;
struct drm_framebuffer front_fb, back_fb;
boolean is_shown;
struct drm_crtc current_crtc;
boolean have_pageflip;
};
struct drm_connector {
struct native_connector base;
uint32_t connector_id;
drmModeConnectorPtr connector;
struct drm_mode *drm_modes;
int num_modes;
};
struct drm_mode {
struct native_mode base;
drmModeModeInfo mode;
};
static INLINE struct drm_display *
drm_display(const struct native_display *ndpy)
{
return (struct drm_display *) ndpy;
}
static INLINE struct drm_config *
drm_config(const struct native_config *nconf)
{
return (struct drm_config *) nconf;
}
static INLINE struct drm_surface *
drm_surface(const struct native_surface *nsurf)
{
return (struct drm_surface *) nsurf;
}
static INLINE struct drm_connector *
drm_connector(const struct native_connector *nconn)
{
return (struct drm_connector *) nconn;
}
static INLINE struct drm_mode *
drm_mode(const struct native_mode *nmode)
{
return (struct drm_mode *) nmode;
}
boolean
drm_display_init_modeset(struct native_display *ndpy);
void
drm_display_fini_modeset(struct native_display *ndpy);
struct native_surface *
drm_display_create_surface_from_resource(struct native_display *ndpy,
struct pipe_resource *resource);
#endif /* _NATIVE_DRM_H_ */
@@ -1,552 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
/**
* Considering fbdev as an in-kernel window system,
*
* - opening a device opens a connection
* - there is only one window: the framebuffer
* - fb_var_screeninfo decides window position, size, and even color format
* - there is no pixmap
*
* Now EGL is built on top of this window system. So we should have
*
* - the fd as the handle of the native display
* - reject all but one native window: NULL
* - no pixmap support
*/
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include "pipe/p_screen.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_pointer.h"
#include "common/native.h"
#include "common/native_helper.h"
#include "sw/fbdev/fbdev_sw_winsys.h"
struct fbdev_display {
struct native_display base;
int fd;
const struct native_event_handler *event_handler;
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo config_vinfo;
struct native_config config;
boolean assume_fixed_vinfo;
};
struct fbdev_surface {
struct native_surface base;
struct fbdev_display *fbdpy;
struct resource_surface *rsurf;
int width, height;
unsigned int sequence_number;
struct fbdev_sw_drawable drawable;
};
static INLINE struct fbdev_display *
fbdev_display(const struct native_display *ndpy)
{
return (struct fbdev_display *) ndpy;
}
static INLINE struct fbdev_surface *
fbdev_surface(const struct native_surface *nsurf)
{
return (struct fbdev_surface *) nsurf;
}
static boolean
fbdev_surface_validate(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height)
{
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
if (!resource_surface_add_resources(fbsurf->rsurf, attachment_mask))
return FALSE;
if (textures)
resource_surface_get_resources(fbsurf->rsurf, textures, attachment_mask);
if (seq_num)
*seq_num = fbsurf->sequence_number;
if (width)
*width = fbsurf->width;
if (height)
*height = fbsurf->height;
return TRUE;
}
static enum pipe_format
vinfo_to_format(const struct fb_var_screeninfo *vinfo)
{
enum pipe_format format = PIPE_FORMAT_NONE;
/* should also check channel offsets... */
switch (vinfo->bits_per_pixel) {
case 32:
if (vinfo->red.length == 8 &&
vinfo->green.length == 8 &&
vinfo->blue.length == 8) {
format = (vinfo->transp.length == 8) ?
PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM;
}
break;
case 16:
if (vinfo->red.length == 5 &&
vinfo->green.length == 6 &&
vinfo->blue.length == 5 &&
vinfo->transp.length == 0)
format = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
break;
}
return format;
}
static boolean
fbdev_surface_update_drawable(struct native_surface *nsurf,
const struct fb_var_screeninfo *vinfo)
{
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
unsigned x, y, width, height;
x = vinfo->xoffset;
y = vinfo->yoffset;
width = MIN2(vinfo->xres, fbsurf->width);
height = MIN2(vinfo->yres, fbsurf->height);
/* sanitize the values */
if (x + width > vinfo->xres_virtual) {
if (x > vinfo->xres_virtual)
width = 0;
else
width = vinfo->xres_virtual - x;
}
if (y + height > vinfo->yres_virtual) {
if (y > vinfo->yres_virtual)
height = 0;
else
height = vinfo->yres_virtual - y;
}
fbsurf->drawable.format = vinfo_to_format(vinfo);
fbsurf->drawable.x = vinfo->xoffset;
fbsurf->drawable.y = vinfo->yoffset;
fbsurf->drawable.width = vinfo->xres;
fbsurf->drawable.height = vinfo->yres;
return (fbsurf->drawable.format != PIPE_FORMAT_NONE &&
fbsurf->drawable.width &&
fbsurf->drawable.height);
}
static boolean
fbdev_surface_present(struct native_surface *nsurf,
const struct native_present_control *ctrl)
{
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
struct fbdev_display *fbdpy = fbsurf->fbdpy;
boolean ret = FALSE;
if (ctrl->swap_interval)
return FALSE;
if (ctrl->natt != NATIVE_ATTACHMENT_BACK_LEFT)
return FALSE;
if (!fbdpy->assume_fixed_vinfo) {
struct fb_var_screeninfo vinfo;
memset(&vinfo, 0, sizeof(vinfo));
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo))
return FALSE;
/* present the surface */
if (fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) {
ret = resource_surface_present(fbsurf->rsurf,
ctrl->natt, (void *) &fbsurf->drawable);
}
fbsurf->width = vinfo.xres;
fbsurf->height = vinfo.yres;
if (resource_surface_set_size(fbsurf->rsurf,
fbsurf->width, fbsurf->height)) {
/* surface resized */
fbsurf->sequence_number++;
fbdpy->event_handler->invalid_surface(&fbdpy->base,
&fbsurf->base, fbsurf->sequence_number);
}
}
else {
/* the drawable never changes */
ret = resource_surface_present(fbsurf->rsurf,
ctrl->natt, (void *) &fbsurf->drawable);
}
return ret;
}
static void
fbdev_surface_wait(struct native_surface *nsurf)
{
/* no-op */
}
static void
fbdev_surface_destroy(struct native_surface *nsurf)
{
struct fbdev_surface *fbsurf = fbdev_surface(nsurf);
resource_surface_destroy(fbsurf->rsurf);
FREE(fbsurf);
}
static struct native_surface *
fbdev_display_create_window_surface(struct native_display *ndpy,
EGLNativeWindowType win,
const struct native_config *nconf)
{
struct fbdev_display *fbdpy = fbdev_display(ndpy);
struct fbdev_surface *fbsurf;
struct fb_var_screeninfo vinfo;
/* there is only one native window: NULL */
if (win)
return NULL;
fbsurf = CALLOC_STRUCT(fbdev_surface);
if (!fbsurf)
return NULL;
fbsurf->fbdpy = fbdpy;
/* get current vinfo */
if (fbdpy->assume_fixed_vinfo) {
vinfo = fbdpy->config_vinfo;
}
else {
memset(&vinfo, 0, sizeof(vinfo));
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo)) {
FREE(fbsurf);
return NULL;
}
}
fbsurf->width = vinfo.xres;
fbsurf->height = vinfo.yres;
if (!fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) {
FREE(fbsurf);
return NULL;
}
fbsurf->rsurf = resource_surface_create(fbdpy->base.screen,
nconf->color_format,
PIPE_BIND_RENDER_TARGET |
PIPE_BIND_DISPLAY_TARGET);
if (!fbsurf->rsurf) {
FREE(fbsurf);
return NULL;
}
resource_surface_set_size(fbsurf->rsurf, fbsurf->width, fbsurf->height);
fbsurf->base.destroy = fbdev_surface_destroy;
fbsurf->base.present = fbdev_surface_present;
fbsurf->base.validate = fbdev_surface_validate;
fbsurf->base.wait = fbdev_surface_wait;
return &fbsurf->base;
}
static struct native_surface *
fbdev_display_create_scanout_surface(struct native_display *ndpy,
const struct native_config *nconf,
uint width, uint height)
{
return fbdev_display_create_window_surface(ndpy,
(EGLNativeWindowType) NULL, nconf);
}
static boolean
fbdev_display_program(struct native_display *ndpy, int crtc_idx,
struct native_surface *nsurf, uint x, uint y,
const struct native_connector **nconns, int num_nconns,
const struct native_mode *nmode)
{
return TRUE;
}
static const struct native_mode **
fbdev_display_get_modes(struct native_display *ndpy,
const struct native_connector *nconn,
int *num_modes)
{
static struct native_mode mode;
const struct native_mode **modes;
if (!mode.desc) {
struct fbdev_display *fbdpy = fbdev_display(ndpy);
mode.desc = "Current Mode";
mode.width = fbdpy->config_vinfo.xres;
mode.height = fbdpy->config_vinfo.yres;
mode.refresh_rate = 60 * 1000; /* dummy */
}
modes = MALLOC(sizeof(*modes));
if (modes) {
modes[0] = &mode;
if (num_modes)
*num_modes = 1;
}
return modes;
}
static const struct native_connector **
fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors,
int *num_crtc)
{
static struct native_connector connector;
const struct native_connector **connectors;
connectors = MALLOC(sizeof(*connectors));
if (connectors) {
connectors[0] = &connector;
if (num_connectors)
*num_connectors = 1;
}
return connectors;
}
/* remove modeset support one day! */
static const struct native_display_modeset fbdev_display_modeset = {
.get_connectors = fbdev_display_get_connectors,
.get_modes = fbdev_display_get_modes,
.create_scanout_surface = fbdev_display_create_scanout_surface,
.program = fbdev_display_program
};
static const struct native_config **
fbdev_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct fbdev_display *fbdpy = fbdev_display(ndpy);
const struct native_config **configs;
configs = MALLOC(sizeof(*configs));
if (configs) {
configs[0] = &fbdpy->config;
if (num_configs)
*num_configs = 1;
}
return configs;
}
static int
fbdev_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
int val;
switch (param) {
case NATIVE_PARAM_PRESERVE_BUFFER:
val = 1;
break;
case NATIVE_PARAM_USE_NATIVE_BUFFER:
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
default:
val = 0;
break;
}
return val;
}
static void
fbdev_display_destroy(struct native_display *ndpy)
{
struct fbdev_display *fbdpy = fbdev_display(ndpy);
ndpy_uninit(&fbdpy->base);
close(fbdpy->fd);
FREE(fbdpy);
}
static boolean
fbdev_display_init_screen(struct native_display *ndpy)
{
struct fbdev_display *fbdpy = fbdev_display(ndpy);
struct sw_winsys *ws;
ws = fbdev_create_sw_winsys(fbdpy->fd);
if (!ws)
return FALSE;
fbdpy->base.screen = fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws);
if (!fbdpy->base.screen) {
if (ws->destroy)
ws->destroy(ws);
return FALSE;
}
if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen,
fbdpy->config.color_format, PIPE_TEXTURE_2D, 0,
PIPE_BIND_RENDER_TARGET)) {
fbdpy->base.screen->destroy(fbdpy->base.screen);
fbdpy->base.screen = NULL;
return FALSE;
}
return TRUE;
}
static boolean
fbdev_display_init_config(struct native_display *ndpy)
{
struct fbdev_display *fbdpy = fbdev_display(ndpy);
struct native_config *nconf = &fbdpy->config;
if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->config_vinfo))
return FALSE;
nconf->color_format = vinfo_to_format(&fbdpy->config_vinfo);
if (nconf->color_format == PIPE_FORMAT_NONE)
return FALSE;
nconf->buffer_mask = (1 << NATIVE_ATTACHMENT_BACK_LEFT);
nconf->window_bit = TRUE;
return TRUE;
}
static struct native_display *
fbdev_display_create(int fd, const struct native_event_handler *event_handler)
{
struct fbdev_display *fbdpy;
fbdpy = CALLOC_STRUCT(fbdev_display);
if (!fbdpy)
return NULL;
fbdpy->fd = fd;
fbdpy->event_handler = event_handler;
if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo))
goto fail;
if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR ||
fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS)
goto fail;
if (!fbdev_display_init_config(&fbdpy->base))
goto fail;
fbdpy->assume_fixed_vinfo = TRUE;
fbdpy->base.init_screen = fbdev_display_init_screen;
fbdpy->base.destroy = fbdev_display_destroy;
fbdpy->base.get_param = fbdev_display_get_param;
fbdpy->base.get_configs = fbdev_display_get_configs;
fbdpy->base.create_window_surface = fbdev_display_create_window_surface;
/* we'd like to remove modeset support one day */
fbdpy->config.scanout_bit = TRUE;
fbdpy->base.modeset = &fbdev_display_modeset;
return &fbdpy->base;
fail:
FREE(fbdpy);
return NULL;
}
static const struct native_event_handler *fbdev_event_handler;
static struct native_display *
native_create_display(void *dpy, boolean use_sw)
{
struct native_display *ndpy;
int fd;
/* well, this makes fd 0 being ignored */
if (!dpy) {
const char *device_name="/dev/fb0";
#ifdef O_CLOEXEC
fd = open(device_name, O_RDWR | O_CLOEXEC);
if (fd == -1 && errno == EINVAL)
#endif
{
fd = open(device_name, O_RDWR);
if (fd != -1)
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
}
}
else {
fd = dup((int) pointer_to_intptr(dpy));
}
if (fd < 0)
return NULL;
ndpy = fbdev_display_create(fd, fbdev_event_handler);
if (!ndpy)
close(fd);
return ndpy;
}
static const struct native_platform fbdev_platform = {
"FBDEV", /* name */
native_create_display
};
const struct native_platform *
native_get_fbdev_platform(const struct native_event_handler *event_handler)
{
fbdev_event_handler = event_handler;
return &fbdev_platform;
}
@@ -1,428 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include <windows.h>
#include "pipe/p_compiler.h"
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "common/native_helper.h"
#include "common/native.h"
#include "sw/gdi/gdi_sw_winsys.h"
struct gdi_display {
struct native_display base;
HDC hDC;
const struct native_event_handler *event_handler;
struct native_config *configs;
int num_configs;
};
struct gdi_surface {
struct native_surface base;
HWND hWnd;
enum pipe_format color_format;
struct gdi_display *gdpy;
unsigned int server_stamp;
unsigned int client_stamp;
struct resource_surface *rsurf;
};
static INLINE struct gdi_display *
gdi_display(const struct native_display *ndpy)
{
return (struct gdi_display *) ndpy;
}
static INLINE struct gdi_surface *
gdi_surface(const struct native_surface *nsurf)
{
return (struct gdi_surface *) nsurf;
}
/**
* Update the geometry of the surface. This is a slow functions.
*/
static void
gdi_surface_update_geometry(struct native_surface *nsurf)
{
struct gdi_surface *gsurf = gdi_surface(nsurf);
RECT rect;
uint w, h;
GetClientRect(gsurf->hWnd, &rect);
w = rect.right - rect.left;
h = rect.bottom - rect.top;
if (resource_surface_set_size(gsurf->rsurf, w, h))
gsurf->server_stamp++;
}
/**
* Update the buffers of the surface.
*/
static boolean
gdi_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
{
struct gdi_surface *gsurf = gdi_surface(nsurf);
if (gsurf->client_stamp != gsurf->server_stamp) {
gdi_surface_update_geometry(&gsurf->base);
gsurf->client_stamp = gsurf->server_stamp;
}
return resource_surface_add_resources(gsurf->rsurf, buffer_mask);
}
/**
* Emulate an invalidate event.
*/
static void
gdi_surface_invalidate(struct native_surface *nsurf)
{
struct gdi_surface *gsurf = gdi_surface(nsurf);
struct gdi_display *gdpy = gsurf->gdpy;
gsurf->server_stamp++;
gdpy->event_handler->invalid_surface(&gdpy->base,
&gsurf->base, gsurf->server_stamp);
}
static boolean
gdi_surface_flush_frontbuffer(struct native_surface *nsurf)
{
struct gdi_surface *gsurf = gdi_surface(nsurf);
HDC hDC;
boolean ret;
hDC = GetDC(gsurf->hWnd);
ret = resource_surface_present(gsurf->rsurf,
NATIVE_ATTACHMENT_FRONT_LEFT, (void *) hDC);
ReleaseDC(gsurf->hWnd, hDC);
/* force buffers to be updated in next validation call */
gdi_surface_invalidate(&gsurf->base);
return ret;
}
static boolean
gdi_surface_swap_buffers(struct native_surface *nsurf)
{
struct gdi_surface *gsurf = gdi_surface(nsurf);
HDC hDC;
boolean ret;
hDC = GetDC(gsurf->hWnd);
ret = resource_surface_present(gsurf->rsurf,
NATIVE_ATTACHMENT_BACK_LEFT, (void *) hDC);
ReleaseDC(gsurf->hWnd, hDC);
resource_surface_swap_buffers(gsurf->rsurf,
NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE);
/* the front/back buffers have been swapped */
gdi_surface_invalidate(&gsurf->base);
return ret;
}
static boolean
gdi_surface_present(struct native_surface *nsurf,
const struct native_present_control *ctrl)
{
boolean ret;
if (ctrl->preserve || ctrl->swap_interval)
return FALSE;
switch (ctrl->natt) {
case NATIVE_ATTACHMENT_FRONT_LEFT:
ret = gdi_surface_flush_frontbuffer(nsurf);
break;
case NATIVE_ATTACHMENT_BACK_LEFT:
ret = gdi_surface_swap_buffers(nsurf);
break;
default:
ret = FALSE;
break;
}
return ret;
}
static boolean
gdi_surface_validate(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height)
{
struct gdi_surface *gsurf = gdi_surface(nsurf);
uint w, h;
if (!gdi_surface_update_buffers(&gsurf->base, attachment_mask))
return FALSE;
if (seq_num)
*seq_num = gsurf->client_stamp;
if (textures)
resource_surface_get_resources(gsurf->rsurf, textures, attachment_mask);
resource_surface_get_size(gsurf->rsurf, &w, &h);
if (width)
*width = w;
if (height)
*height = h;
return TRUE;
}
static void
gdi_surface_wait(struct native_surface *nsurf)
{
/* no-op */
}
static void
gdi_surface_destroy(struct native_surface *nsurf)
{
struct gdi_surface *gsurf = gdi_surface(nsurf);
resource_surface_destroy(gsurf->rsurf);
FREE(gsurf);
}
static struct native_surface *
gdi_display_create_window_surface(struct native_display *ndpy,
EGLNativeWindowType win,
const struct native_config *nconf)
{
struct gdi_display *gdpy = gdi_display(ndpy);
struct gdi_surface *gsurf;
gsurf = CALLOC_STRUCT(gdi_surface);
if (!gsurf)
return NULL;
gsurf->gdpy = gdpy;
gsurf->color_format = nconf->color_format;
gsurf->hWnd = (HWND) win;
gsurf->rsurf = resource_surface_create(gdpy->base.screen,
gsurf->color_format,
PIPE_BIND_RENDER_TARGET |
PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT);
if (!gsurf->rsurf) {
FREE(gsurf);
return NULL;
}
/* initialize the geometry */
gdi_surface_update_geometry(&gsurf->base);
gsurf->base.destroy = gdi_surface_destroy;
gsurf->base.present = gdi_surface_present;
gsurf->base.validate = gdi_surface_validate;
gsurf->base.wait = gdi_surface_wait;
return &gsurf->base;
}
static int
fill_color_formats(struct native_display *ndpy, enum pipe_format formats[8])
{
struct pipe_screen *screen = ndpy->screen;
int i, count = 0;
enum pipe_format candidates[] = {
/* 32-bit */
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_A8R8G8B8_UNORM,
/* 24-bit */
PIPE_FORMAT_B8G8R8X8_UNORM,
PIPE_FORMAT_X8R8G8B8_UNORM,
/* 16-bit */
PIPE_FORMAT_B5G6R5_UNORM
};
assert(Elements(candidates) <= 8);
for (i = 0; i < Elements(candidates); i++) {
if (screen->is_format_supported(screen, candidates[i],
PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET))
formats[count++] = candidates[i];
}
return count;
}
static const struct native_config **
gdi_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct gdi_display *gdpy = gdi_display(ndpy);
const struct native_config **configs;
int i;
/* first time */
if (!gdpy->configs) {
enum pipe_format formats[8];
int i, count;
count = fill_color_formats(&gdpy->base, formats);
gdpy->configs = CALLOC(count, sizeof(*gdpy->configs));
if (!gdpy->configs)
return NULL;
for (i = 0; i < count; i++) {
struct native_config *nconf = &gdpy->configs[i];
nconf->buffer_mask =
(1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
nconf->color_format = formats[i];
nconf->window_bit = TRUE;
}
gdpy->num_configs = count;
}
configs = MALLOC(gdpy->num_configs * sizeof(*configs));
if (configs) {
for (i = 0; i < gdpy->num_configs; i++)
configs[i] = (const struct native_config *) &gdpy->configs[i];
if (num_configs)
*num_configs = gdpy->num_configs;
}
return configs;
}
static int
gdi_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
int val;
switch (param) {
case NATIVE_PARAM_USE_NATIVE_BUFFER:
/* private buffers are allocated */
val = FALSE;
break;
case NATIVE_PARAM_PRESERVE_BUFFER:
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
default:
val = 0;
break;
}
return val;
}
static void
gdi_display_destroy(struct native_display *ndpy)
{
struct gdi_display *gdpy = gdi_display(ndpy);
FREE(gdpy->configs);
ndpy_uninit(ndpy);
FREE(gdpy);
}
static boolean
gdi_display_init_screen(struct native_display *ndpy)
{
struct gdi_display *gdpy = gdi_display(ndpy);
struct sw_winsys *winsys;
winsys = gdi_create_sw_winsys();
if (!winsys)
return FALSE;
gdpy->base.screen = gdpy->event_handler->new_sw_screen(&gdpy->base, winsys);
if (!gdpy->base.screen) {
if (winsys->destroy)
winsys->destroy(winsys);
return FALSE;
}
return TRUE;
}
static struct native_display *
gdi_create_display(HDC hDC, const struct native_event_handler *event_handler)
{
struct gdi_display *gdpy;
gdpy = CALLOC_STRUCT(gdi_display);
if (!gdpy)
return NULL;
gdpy->hDC = hDC;
gdpy->event_handler = event_handler;
gdpy->base.init_screen = gdi_display_init_screen;
gdpy->base.destroy = gdi_display_destroy;
gdpy->base.get_param = gdi_display_get_param;
gdpy->base.get_configs = gdi_display_get_configs;
gdpy->base.create_window_surface = gdi_display_create_window_surface;
return &gdpy->base;
}
static const struct native_event_handler *gdi_event_handler;
static struct native_display *
native_create_display(void *dpy, boolean use_sw)
{
return gdi_create_display((HDC) dpy, gdi_event_handler);
}
static const struct native_platform gdi_platform = {
"GDI", /* name */
native_create_display
};
const struct native_platform *
native_get_gdi_platform(const struct native_event_handler *event_handler)
{
gdi_event_handler = event_handler;
return &gdi_platform;
}
@@ -1,189 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
/**
* For NULL window system,
*
* - the only valid native display is EGL_DEFAULT_DISPLAY
* - there is no window or pixmap
*/
#include "util/u_memory.h"
#include "common/native.h"
#include "sw/null/null_sw_winsys.h"
struct null_display {
struct native_display base;
const struct native_event_handler *event_handler;
struct native_config *configs;
int num_configs;
};
static INLINE struct null_display *
null_display(const struct native_display *ndpy)
{
return (struct null_display *) ndpy;
}
static const struct native_config **
null_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct null_display *null = null_display(ndpy);
const struct native_config **configs;
int i;
configs = MALLOC(sizeof(*configs) * null->num_configs);
if (configs) {
for (i = 0; i < null->num_configs; i++)
configs[i] = &null->configs[i];
if (num_configs)
*num_configs = null->num_configs;
}
return configs;
}
static int
null_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
return 0;
}
static void
null_display_destroy(struct native_display *ndpy)
{
struct null_display *null = null_display(ndpy);
FREE(null->configs);
ndpy_uninit(&null->base);
FREE(null);
}
static boolean
null_display_init_config(struct native_display *ndpy)
{
const enum pipe_format color_formats[] = {
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_B8G8R8X8_UNORM,
PIPE_FORMAT_B5G6R5_UNORM,
PIPE_FORMAT_NONE
};
struct null_display *null = null_display(ndpy);
int i;
null->configs = CALLOC(Elements(color_formats) - 1, sizeof(*null->configs));
if (!null->configs)
return FALSE;
/* add configs */
for (i = 0; color_formats[i] != PIPE_FORMAT_NONE; i++) {
if (null->base.screen->is_format_supported(null->base.screen,
color_formats[i], PIPE_TEXTURE_2D, 0,
PIPE_BIND_RENDER_TARGET)) {
struct native_config *nconf = &null->configs[null->num_configs];
nconf->color_format = color_formats[i];
nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_BACK_LEFT;
null->num_configs++;
}
}
return TRUE;
}
static boolean
null_display_init_screen(struct native_display *ndpy)
{
struct null_display *null = null_display(ndpy);
struct sw_winsys *ws;
ws = null_sw_create();
if (!ws)
return FALSE;
null->base.screen = null->event_handler->new_sw_screen(&null->base, ws);
if (!null->base.screen) {
if (ws->destroy)
ws->destroy(ws);
return FALSE;
}
if (!null_display_init_config(&null->base)) {
ndpy_uninit(&null->base);
return FALSE;
}
return TRUE;
}
static struct native_display *
null_display_create(const struct native_event_handler *event_handler)
{
struct null_display *null;
null = CALLOC_STRUCT(null_display);
if (!null)
return NULL;
null->event_handler = event_handler;
null->base.init_screen = null_display_init_screen;
null->base.destroy = null_display_destroy;
null->base.get_param = null_display_get_param;
null->base.get_configs = null_display_get_configs;
return &null->base;
}
static const struct native_event_handler *null_event_handler;
static struct native_display *
native_create_display(void *dpy, boolean use_sw)
{
struct native_display *ndpy = NULL;
/* the only valid display is NULL */
if (!dpy)
ndpy = null_display_create(null_event_handler);
return ndpy;
}
static const struct native_platform null_platform = {
"NULL", /* name */
native_create_display
};
const struct native_platform *
native_get_null_platform(const struct native_event_handler *event_handler)
{
null_event_handler = event_handler;
return &null_platform;
}
@@ -1,286 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "state_tracker/drm_driver.h"
#include "egllog.h"
#include <errno.h>
#include "native_wayland.h"
#include <wayland-client.h>
#include "wayland-drm-client-protocol.h"
#include "wayland-egl-priv.h"
#include "common/native_wayland_drm_bufmgr.h"
#include <xf86drm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct wayland_drm_display {
struct wayland_display base;
const struct native_event_handler *event_handler;
struct wl_drm *wl_drm;
int fd;
char *device_name;
boolean authenticated;
};
static INLINE struct wayland_drm_display *
wayland_drm_display(const struct native_display *ndpy)
{
return (struct wayland_drm_display *) ndpy;
}
static void
wayland_drm_display_destroy(struct native_display *ndpy)
{
struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
if (drmdpy->wl_drm)
wl_drm_destroy(drmdpy->wl_drm);
FREE(drmdpy->device_name);
FREE(drmdpy->base.configs);
if (drmdpy->base.own_dpy)
wl_display_disconnect(drmdpy->base.dpy);
wayland_drm_bufmgr_destroy(ndpy->wayland_bufmgr);
ndpy_uninit(ndpy);
if (drmdpy->fd)
close(drmdpy->fd);
FREE(drmdpy);
}
static struct wl_buffer *
wayland_create_drm_buffer(struct wayland_display *display,
struct wayland_surface *surface,
enum native_attachment attachment)
{
struct wayland_drm_display *drmdpy = (struct wayland_drm_display *) display;
struct pipe_screen *screen = drmdpy->base.base.screen;
struct pipe_resource *resource;
struct winsys_handle wsh;
uint width, height;
enum wl_drm_format format;
resource = resource_surface_get_single_resource(surface->rsurf, attachment);
resource_surface_get_size(surface->rsurf, &width, &height);
wsh.type = DRM_API_HANDLE_TYPE_SHARED;
screen->resource_get_handle(screen, resource, &wsh);
pipe_resource_reference(&resource, NULL);
switch (surface->color_format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
format = WL_DRM_FORMAT_ARGB8888;
break;
case PIPE_FORMAT_B8G8R8X8_UNORM:
format = WL_DRM_FORMAT_XRGB8888;
break;
default:
return NULL;
break;
}
return wl_drm_create_buffer(drmdpy->wl_drm, wsh.handle,
width, height, wsh.stride, format);
}
static void
drm_handle_device(void *data, struct wl_drm *drm, const char *device)
{
struct wayland_drm_display *drmdpy = data;
drm_magic_t magic;
drmdpy->device_name = strdup(device);
if (!drmdpy->device_name)
return;
#ifdef O_CLOEXEC
drmdpy->fd = open(drmdpy->device_name, O_RDWR | O_CLOEXEC);
if (drmdpy->fd == -1 && errno == EINVAL)
#endif
{
drmdpy->fd = open(drmdpy->device_name, O_RDWR);
if (drmdpy->fd != -1)
fcntl(drmdpy->fd, F_SETFD, fcntl(drmdpy->fd, F_GETFD) | FD_CLOEXEC);
}
if (drmdpy->fd == -1) {
_eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
drmdpy->device_name, strerror(errno));
return;
}
drmGetMagic(drmdpy->fd, &magic);
wl_drm_authenticate(drmdpy->wl_drm, magic);
}
static void
drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
{
struct wayland_drm_display *drmdpy = data;
switch (format) {
case WL_DRM_FORMAT_ARGB8888:
drmdpy->base.formats |= HAS_ARGB8888;
break;
case WL_DRM_FORMAT_XRGB8888:
drmdpy->base.formats |= HAS_XRGB8888;
break;
}
}
static void
drm_handle_authenticated(void *data, struct wl_drm *drm)
{
struct wayland_drm_display *drmdpy = data;
drmdpy->authenticated = true;
}
static const struct wl_drm_listener drm_listener = {
drm_handle_device,
drm_handle_format,
drm_handle_authenticated
};
static void
registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version)
{
struct wayland_drm_display *drmdpy = data;
if (strcmp(interface, "wl_drm") == 0) {
drmdpy->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface, 1);
wl_drm_add_listener(drmdpy->wl_drm, &drm_listener, drmdpy);
}
}
static const struct wl_registry_listener registry_listener = {
registry_handle_global
};
static int
wayland_drm_display_authenticate(void *user_data, uint32_t magic)
{
struct native_display *ndpy = user_data;
struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
boolean current_authenticate, authenticated;
current_authenticate = drmdpy->authenticated;
wl_drm_authenticate(drmdpy->wl_drm, magic);
wl_display_roundtrip(drmdpy->base.dpy);
authenticated = drmdpy->authenticated;
drmdpy->authenticated = current_authenticate;
return authenticated ? 0 : -1;
}
static boolean
wayland_drm_display_init_screen(struct native_display *ndpy)
{
struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
drmdpy->base.queue = wl_display_create_queue(drmdpy->base.dpy);
drmdpy->base.registry = wl_display_get_registry(drmdpy->base.dpy);
wl_proxy_set_queue((struct wl_proxy *) drmdpy->base.registry,
drmdpy->base.queue);
wl_registry_add_listener(drmdpy->base.registry, &registry_listener, drmdpy);
if (wayland_roundtrip(&drmdpy->base) < 0 || drmdpy->wl_drm == NULL)
return FALSE;
if (wayland_roundtrip(&drmdpy->base) < 0 || drmdpy->fd == -1)
return FALSE;
if (wayland_roundtrip(&drmdpy->base) < 0 || !drmdpy->authenticated)
return FALSE;
if (drmdpy->base.formats == 0)
return FALSE;
drmdpy->base.base.screen =
drmdpy->event_handler->new_drm_screen(&drmdpy->base.base,
NULL, drmdpy->fd);
if (!drmdpy->base.base.screen) {
_eglLog(_EGL_WARNING, "failed to create DRM screen");
return FALSE;
}
drmdpy->base.base.wayland_bufmgr = wayland_drm_bufmgr_create(
wayland_drm_display_authenticate, drmdpy, drmdpy->device_name);
return TRUE;
}
static struct native_display_buffer wayland_drm_display_buffer = {
/* use the helpers */
drm_display_import_native_buffer,
drm_display_export_native_buffer
};
struct wayland_display *
wayland_create_drm_display(struct wl_display *dpy,
const struct native_event_handler *event_handler)
{
struct wayland_drm_display *drmdpy;
drmdpy = CALLOC_STRUCT(wayland_drm_display);
if (!drmdpy)
return NULL;
drmdpy->event_handler = event_handler;
drmdpy->base.dpy = dpy;
if (!drmdpy->base.dpy) {
wayland_drm_display_destroy(&drmdpy->base.base);
return NULL;
}
drmdpy->base.base.init_screen = wayland_drm_display_init_screen;
drmdpy->base.base.destroy = wayland_drm_display_destroy;
drmdpy->base.base.buffer = &wayland_drm_display_buffer;
drmdpy->base.create_buffer = wayland_create_drm_buffer;
return &drmdpy->base;
}
/* vim: set sw=3 ts=8 sts=3 expandtab: */
@@ -1,209 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "sw/wayland/wayland_sw_winsys.h"
#include "egllog.h"
#include "native_wayland.h"
#include <wayland-client.h>
#include "wayland-egl-priv.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct wayland_shm_display {
struct wayland_display base;
const struct native_event_handler *event_handler;
struct wl_shm *wl_shm;
};
static INLINE struct wayland_shm_display *
wayland_shm_display(const struct native_display *ndpy)
{
return (struct wayland_shm_display *) ndpy;
}
static void
wayland_shm_display_destroy(struct native_display *ndpy)
{
struct wayland_shm_display *shmdpy = wayland_shm_display(ndpy);
FREE(shmdpy->base.configs);
if (shmdpy->base.own_dpy)
wl_display_disconnect(shmdpy->base.dpy);
ndpy_uninit(ndpy);
FREE(shmdpy);
}
static struct wl_buffer *
wayland_create_shm_buffer(struct wayland_display *display,
struct wayland_surface *surface,
enum native_attachment attachment)
{
struct wayland_shm_display *shmdpy = (struct wayland_shm_display *) display;
struct pipe_screen *screen = shmdpy->base.base.screen;
struct pipe_resource *resource;
struct winsys_handle wsh;
uint width, height;
enum wl_shm_format format;
struct wl_buffer *buffer;
struct wl_shm_pool *pool;
resource = resource_surface_get_single_resource(surface->rsurf, attachment);
resource_surface_get_size(surface->rsurf, &width, &height);
screen->resource_get_handle(screen, resource, &wsh);
pipe_resource_reference(&resource, NULL);
switch (surface->color_format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
format = WL_SHM_FORMAT_ARGB8888;
break;
case PIPE_FORMAT_B8G8R8X8_UNORM:
format = WL_SHM_FORMAT_XRGB8888;
break;
default:
return NULL;
break;
}
pool = wl_shm_create_pool(shmdpy->wl_shm, wsh.fd, wsh.size);
buffer = wl_shm_pool_create_buffer(pool, 0, width, height,
wsh.stride, format);
wl_shm_pool_destroy(pool);
return buffer;
}
static void
shm_handle_format(void *data, struct wl_shm *shm, uint32_t format)
{
struct wayland_shm_display *shmdpy = data;
switch (format) {
case WL_SHM_FORMAT_ARGB8888:
shmdpy->base.formats |= HAS_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
shmdpy->base.formats |= HAS_XRGB8888;
break;
}
}
static const struct wl_shm_listener shm_listener = {
shm_handle_format
};
static void
registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version)
{
struct wayland_shm_display *shmdpy = data;
if (strcmp(interface, "wl_shm") == 0) {
shmdpy->wl_shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
wl_shm_add_listener(shmdpy->wl_shm, &shm_listener, shmdpy);
}
}
static const struct wl_registry_listener registry_listener = {
registry_handle_global
};
static boolean
wayland_shm_display_init_screen(struct native_display *ndpy)
{
struct wayland_shm_display *shmdpy = wayland_shm_display(ndpy);
struct sw_winsys *winsys = NULL;
shmdpy->base.queue = wl_display_create_queue(shmdpy->base.dpy);
shmdpy->base.registry = wl_display_get_registry(shmdpy->base.dpy);
wl_proxy_set_queue((struct wl_proxy *) shmdpy->base.registry,
shmdpy->base.queue);
wl_registry_add_listener(shmdpy->base.registry, &registry_listener, shmdpy);
if (wayland_roundtrip(&shmdpy->base) < 0 || shmdpy->wl_shm == NULL)
return FALSE;
if (shmdpy->base.formats == 0)
wayland_roundtrip(&shmdpy->base);
if (shmdpy->base.formats == 0)
return FALSE;
winsys = wayland_create_sw_winsys(shmdpy->base.dpy);
if (!winsys)
return FALSE;
shmdpy->base.base.screen =
shmdpy->event_handler->new_sw_screen(&shmdpy->base.base, winsys);
if (!shmdpy->base.base.screen) {
_eglLog(_EGL_WARNING, "failed to create shm screen");
return FALSE;
}
return TRUE;
}
struct wayland_display *
wayland_create_shm_display(struct wl_display *dpy,
const struct native_event_handler *event_handler)
{
struct wayland_shm_display *shmdpy;
shmdpy = CALLOC_STRUCT(wayland_shm_display);
if (!shmdpy)
return NULL;
shmdpy->event_handler = event_handler;
shmdpy->base.dpy = dpy;
if (!shmdpy->base.dpy) {
wayland_shm_display_destroy(&shmdpy->base.base);
return NULL;
}
shmdpy->base.base.init_screen = wayland_shm_display_init_screen;
shmdpy->base.base.destroy = wayland_shm_display_destroy;
shmdpy->base.create_buffer = wayland_create_shm_buffer;
return &shmdpy->base;
}
/* vim: set sw=3 ts=8 sts=3 expandtab: */
@@ -1,465 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "state_tracker/drm_driver.h"
#include "egllog.h"
#include "native_wayland.h"
static void
sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
{
int *done = data;
*done = 1;
wl_callback_destroy(callback);
}
static const struct wl_callback_listener sync_listener = {
sync_callback
};
int
wayland_roundtrip(struct wayland_display *display)
{
struct wl_callback *callback;
int done = 0, ret = 0;
callback = wl_display_sync(display->dpy);
wl_callback_add_listener(callback, &sync_listener, &done);
wl_proxy_set_queue((struct wl_proxy *) callback, display->queue);
while (ret != -1 && !done)
ret = wl_display_dispatch_queue(display->dpy, display->queue);
if (!done)
wl_callback_destroy(callback);
return ret;
}
static const struct native_event_handler *wayland_event_handler;
const static struct {
enum pipe_format format;
enum wayland_format_flag flag;
} wayland_formats[] = {
{ PIPE_FORMAT_B8G8R8A8_UNORM, HAS_ARGB8888 },
{ PIPE_FORMAT_B8G8R8X8_UNORM, HAS_XRGB8888 },
};
static const struct native_config **
wayland_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct wayland_display *display = wayland_display(ndpy);
const struct native_config **configs;
int i;
if (!display->configs) {
struct native_config *nconf;
display->num_configs = 0;
display->configs = CALLOC(Elements(wayland_formats),
sizeof(*display->configs));
if (!display->configs)
return NULL;
for (i = 0; i < Elements(wayland_formats); ++i) {
if (!(display->formats & wayland_formats[i].flag))
continue;
nconf = &display->configs[display->num_configs].base;
nconf->buffer_mask =
(1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
nconf->window_bit = TRUE;
nconf->color_format = wayland_formats[i].format;
display->num_configs++;
}
}
configs = MALLOC(display->num_configs * sizeof(*configs));
if (configs) {
for (i = 0; i < display->num_configs; ++i)
configs[i] = &display->configs[i].base;
if (num_configs)
*num_configs = display->num_configs;
}
return configs;
}
static int
wayland_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
int val;
switch (param) {
case NATIVE_PARAM_PREMULTIPLIED_ALPHA:
val = 1;
break;
case NATIVE_PARAM_USE_NATIVE_BUFFER:
case NATIVE_PARAM_PRESERVE_BUFFER:
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
default:
val = 0;
break;
}
return val;
}
static void
wayland_release_pending_resource(void *data,
struct wl_callback *callback,
uint32_t time)
{
struct wayland_surface *surface = data;
wl_callback_destroy(callback);
/* FIXME: print internal error */
if (!surface->pending_resource)
return;
pipe_resource_reference(&surface->pending_resource, NULL);
}
static const struct wl_callback_listener release_buffer_listener = {
wayland_release_pending_resource
};
static void
wayland_window_surface_handle_resize(struct wayland_surface *surface)
{
struct wayland_display *display = surface->display;
struct pipe_resource *front_resource;
const enum native_attachment front_natt = NATIVE_ATTACHMENT_FRONT_LEFT;
int i;
front_resource = resource_surface_get_single_resource(surface->rsurf,
front_natt);
if (resource_surface_set_size(surface->rsurf,
surface->win->width, surface->win->height)) {
if (surface->pending_resource)
wayland_roundtrip(display);
if (front_resource) {
struct wl_callback *callback;
surface->pending_resource = front_resource;
front_resource = NULL;
callback = wl_display_sync(display->dpy);
wl_callback_add_listener(callback, &release_buffer_listener, surface);
wl_proxy_set_queue((struct wl_proxy *) callback, display->queue);
}
for (i = 0; i < WL_BUFFER_COUNT; ++i) {
if (surface->buffer[i])
wl_buffer_destroy(surface->buffer[i]);
surface->buffer[i] = NULL;
}
surface->dx = surface->win->dx;
surface->dy = surface->win->dy;
}
pipe_resource_reference(&front_resource, NULL);
}
static boolean
wayland_surface_validate(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height)
{
struct wayland_surface *surface = wayland_surface(nsurf);
if (surface->type == WL_WINDOW_SURFACE)
wayland_window_surface_handle_resize(surface);
if (!resource_surface_add_resources(surface->rsurf, attachment_mask |
surface->attachment_mask))
return FALSE;
if (textures)
resource_surface_get_resources(surface->rsurf, textures, attachment_mask);
if (seq_num)
*seq_num = surface->sequence_number;
resource_surface_get_size(surface->rsurf, (uint *) width, (uint *) height);
return TRUE;
}
static void
wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
{
struct wayland_surface *surface = data;
surface->frame_callback = NULL;
wl_callback_destroy(callback);
}
static const struct wl_callback_listener frame_listener = {
wayland_frame_callback
};
static INLINE void
wayland_buffers_swap(struct wl_buffer **buffer,
enum wayland_buffer_type buf1,
enum wayland_buffer_type buf2)
{
struct wl_buffer *tmp = buffer[buf1];
buffer[buf1] = buffer[buf2];
buffer[buf2] = tmp;
}
static boolean
wayland_surface_swap_buffers(struct native_surface *nsurf)
{
struct wayland_surface *surface = wayland_surface(nsurf);
struct wayland_display *display = surface->display;
int ret = 0;
while (surface->frame_callback && ret != -1)
ret = wl_display_dispatch_queue(display->dpy, display->queue);
if (ret == -1)
return EGL_FALSE;
(void) resource_surface_flush_resource(surface->rsurf, &display->base,
NATIVE_ATTACHMENT_BACK_LEFT);
(void) resource_surface_flush(surface->rsurf, &display->base);
surface->frame_callback = wl_surface_frame(surface->win->surface);
wl_callback_add_listener(surface->frame_callback, &frame_listener, surface);
wl_proxy_set_queue((struct wl_proxy *) surface->frame_callback,
display->queue);
if (surface->type == WL_WINDOW_SURFACE) {
resource_surface_swap_buffers(surface->rsurf,
NATIVE_ATTACHMENT_FRONT_LEFT,
NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
wayland_buffers_swap(surface->buffer, WL_BUFFER_FRONT, WL_BUFFER_BACK);
if (surface->buffer[WL_BUFFER_FRONT] == NULL)
surface->buffer[WL_BUFFER_FRONT] =
display->create_buffer(display, surface,
NATIVE_ATTACHMENT_FRONT_LEFT);
wl_surface_attach(surface->win->surface, surface->buffer[WL_BUFFER_FRONT],
surface->dx, surface->dy);
resource_surface_get_size(surface->rsurf,
(uint *) &surface->win->attached_width,
(uint *) &surface->win->attached_height);
surface->dx = 0;
surface->dy = 0;
}
surface->sequence_number++;
wayland_event_handler->invalid_surface(&display->base,
&surface->base,
surface->sequence_number);
return TRUE;
}
static boolean
wayland_surface_present(struct native_surface *nsurf,
const struct native_present_control *ctrl)
{
struct wayland_surface *surface = wayland_surface(nsurf);
uint width, height;
boolean ret;
if (ctrl->preserve || ctrl->swap_interval)
return FALSE;
/* force buffers to be re-created if they will be presented differently */
if (surface->premultiplied_alpha != ctrl->premultiplied_alpha) {
enum wayland_buffer_type buffer;
for (buffer = 0; buffer < WL_BUFFER_COUNT; ++buffer) {
if (surface->buffer[buffer]) {
wl_buffer_destroy(surface->buffer[buffer]);
surface->buffer[buffer] = NULL;
}
}
surface->premultiplied_alpha = ctrl->premultiplied_alpha;
}
switch (ctrl->natt) {
case NATIVE_ATTACHMENT_FRONT_LEFT:
ret = TRUE;
break;
case NATIVE_ATTACHMENT_BACK_LEFT:
ret = wayland_surface_swap_buffers(nsurf);
break;
default:
ret = FALSE;
break;
}
if (surface->type == WL_WINDOW_SURFACE) {
resource_surface_get_size(surface->rsurf, &width, &height);
wl_surface_damage(surface->win->surface, 0, 0, width, height);
wl_surface_commit(surface->win->surface);
}
return ret;
}
static void
wayland_surface_wait(struct native_surface *nsurf)
{
/* no-op */
}
static void
wayland_surface_destroy(struct native_surface *nsurf)
{
struct wayland_surface *surface = wayland_surface(nsurf);
enum wayland_buffer_type buffer;
for (buffer = 0; buffer < WL_BUFFER_COUNT; ++buffer) {
if (surface->buffer[buffer])
wl_buffer_destroy(surface->buffer[buffer]);
}
if (surface->frame_callback)
wl_callback_destroy(surface->frame_callback);
resource_surface_destroy(surface->rsurf);
FREE(surface);
}
static struct native_surface *
wayland_create_window_surface(struct native_display *ndpy,
EGLNativeWindowType win,
const struct native_config *nconf)
{
struct wayland_display *display = wayland_display(ndpy);
struct wayland_config *config = wayland_config(nconf);
struct wayland_surface *surface;
uint bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT;
surface = CALLOC_STRUCT(wayland_surface);
if (!surface)
return NULL;
surface->display = display;
surface->color_format = config->base.color_format;
surface->win = (struct wl_egl_window *) win;
surface->pending_resource = NULL;
surface->frame_callback = NULL;
surface->type = WL_WINDOW_SURFACE;
surface->buffer[WL_BUFFER_FRONT] = NULL;
surface->buffer[WL_BUFFER_BACK] = NULL;
surface->attachment_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
surface->rsurf = resource_surface_create(display->base.screen,
surface->color_format, bind);
if (!surface->rsurf) {
FREE(surface);
return NULL;
}
surface->base.destroy = wayland_surface_destroy;
surface->base.present = wayland_surface_present;
surface->base.validate = wayland_surface_validate;
surface->base.wait = wayland_surface_wait;
return &surface->base;
}
static struct native_display *
native_create_display(void *dpy, boolean use_sw)
{
struct wayland_display *display = NULL;
boolean own_dpy = FALSE;
use_sw = use_sw || debug_get_bool_option("EGL_SOFTWARE", FALSE);
if (dpy == NULL) {
dpy = wl_display_connect(NULL);
if (dpy == NULL)
return NULL;
own_dpy = TRUE;
}
if (use_sw) {
_eglLog(_EGL_INFO, "use software fallback");
display = wayland_create_shm_display((struct wl_display *) dpy,
wayland_event_handler);
} else {
display = wayland_create_drm_display((struct wl_display *) dpy,
wayland_event_handler);
}
if (!display)
return NULL;
display->base.get_param = wayland_display_get_param;
display->base.get_configs = wayland_display_get_configs;
display->base.create_window_surface = wayland_create_window_surface;
display->own_dpy = own_dpy;
return &display->base;
}
static const struct native_platform wayland_platform = {
"wayland", /* name */
native_create_display
};
const struct native_platform *
native_get_wayland_platform(const struct native_event_handler *event_handler)
{
wayland_event_handler = event_handler;
return &wayland_platform;
}
/* vim: set sw=3 ts=8 sts=3 expandtab: */
@@ -1,124 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _NATIVE_WAYLAND_H_
#define _NATIVE_WAYLAND_H_
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "common/native.h"
#include "common/native_helper.h"
#include "wayland-egl-priv.h"
struct wayland_surface;
enum wayland_format_flag {
HAS_ARGB8888 = (1 << 0),
HAS_XRGB8888 = (1 << 1)
};
struct wayland_display {
struct native_display base;
struct wl_display *dpy;
struct wl_event_queue *queue;
struct wl_registry *registry;
boolean own_dpy;
/* supported formats */
uint32_t formats;
struct wayland_config *configs;
int num_configs;
struct wl_buffer *(*create_buffer)(struct wayland_display *display,
struct wayland_surface *surface,
enum native_attachment attachment);
};
enum wayland_buffer_type {
WL_BUFFER_FRONT,
WL_BUFFER_BACK,
WL_BUFFER_COUNT
};
enum wayland_surface_type {
WL_WINDOW_SURFACE,
WL_PBUFFER_SURFACE
};
struct wayland_surface {
struct native_surface base;
struct wayland_display *display;
struct wl_egl_window *win;
enum wayland_surface_type type;
int dx, dy;
struct resource_surface *rsurf;
struct pipe_resource *pending_resource;
enum pipe_format color_format;
unsigned int sequence_number;
struct wl_buffer *buffer[WL_BUFFER_COUNT];
unsigned int attachment_mask;
struct wl_callback *frame_callback;
boolean premultiplied_alpha;
};
struct wayland_config {
struct native_config base;
};
static INLINE struct wayland_display *
wayland_display(const struct native_display *ndpy)
{
return (struct wayland_display *) ndpy;
}
static INLINE struct wayland_surface *
wayland_surface(const struct native_surface *nsurf)
{
return (struct wayland_surface *) nsurf;
}
static INLINE struct wayland_config *
wayland_config(const struct native_config *nconf)
{
return (struct wayland_config *) nconf;
}
struct wayland_display *
wayland_create_shm_display(struct wl_display *display,
const struct native_event_handler *event_handler);
struct wayland_display *
wayland_create_drm_display(struct wl_display *display,
const struct native_event_handler *event_handler);
int
wayland_roundtrip(struct wayland_display *drmdpy);
#endif /* _NATIVE_WAYLAND_H_ */
@@ -1 +0,0 @@
../../../../glx/dri2.c
-179
View File
@@ -1,179 +0,0 @@
#ifndef __gl_core_h_
#define __gl_core_h_
/*
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice including the dates of first publication and
* either this permission notice or a reference to
* http://oss.sgi.com/projects/FreeB/
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of Silicon Graphics, Inc.
* shall not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization from
* Silicon Graphics, Inc.
*/
#include <sys/types.h>
#define GL_CORE_SGI 1
#define GL_CORE_MESA 2
#define GL_CORE_APPLE 4
#define GL_CORE_WINDOWS 8
typedef struct __GLcontextRec __GLcontext;
/*
** This file defines the interface between the GL core and the surrounding
** "operating system" that supports it (currently the GLX or WGL extensions).
**
** Members (data and function pointers) are documented as imported or
** exported according to how they are used by the core rendering functions.
** Imported members are initialized by the "operating system" and used by
** the core functions. Exported members are initialized by the core functions
** and used by the "operating system".
*/
/**
* Mode and limit information for a context. This information is
* kept around in the context so that values can be used during
* command execution, and for returning information about the
* context to the application.
*
* Instances of this structure are shared by the driver and the loader. To
* maintain binary compatability, new fields \b must be added only to the
* end of the structure.
*
* \sa _gl_context_modes_create
*/
typedef struct __GLcontextModesRec {
struct __GLcontextModesRec * next;
GLboolean rgbMode;
GLboolean floatMode;
GLboolean colorIndexMode;
GLuint doubleBufferMode;
GLuint stereoMode;
GLboolean haveAccumBuffer;
GLboolean haveDepthBuffer;
GLboolean haveStencilBuffer;
GLint redBits, greenBits, blueBits, alphaBits; /* bits per comp */
GLuint redMask, greenMask, blueMask, alphaMask;
GLint rgbBits; /* total bits for rgb */
GLint indexBits; /* total bits for colorindex */
GLint accumRedBits, accumGreenBits, accumBlueBits, accumAlphaBits;
GLint depthBits;
GLint stencilBits;
GLint numAuxBuffers;
GLint level;
GLint pixmapMode;
/* GLX */
GLint visualID;
GLint visualType; /**< One of the GLX X visual types. (i.e.,
* \c GLX_TRUE_COLOR, etc.)
*/
/* EXT_visual_rating / GLX 1.2 */
GLint visualRating;
/* EXT_visual_info / GLX 1.2 */
GLint transparentPixel;
/* colors are floats scaled to ints */
GLint transparentRed, transparentGreen, transparentBlue, transparentAlpha;
GLint transparentIndex;
/* ARB_multisample / SGIS_multisample */
GLint sampleBuffers;
GLint samples;
/* SGIX_fbconfig / GLX 1.3 */
GLint drawableType;
GLint renderType;
GLint xRenderable;
GLint fbconfigID;
/* SGIX_pbuffer / GLX 1.3 */
GLint maxPbufferWidth;
GLint maxPbufferHeight;
GLint maxPbufferPixels;
GLint optimalPbufferWidth; /* Only for SGIX_pbuffer. */
GLint optimalPbufferHeight; /* Only for SGIX_pbuffer. */
/* SGIX_visual_select_group */
GLint visualSelectGroup;
/* OML_swap_method */
GLint swapMethod;
GLint screen;
/* EXT_texture_from_pixmap */
GLint bindToTextureRgb;
GLint bindToTextureRgba;
GLint bindToMipmapTexture;
GLint bindToTextureTargets;
GLint yInverted;
} __GLcontextModes;
/* Several fields of __GLcontextModes can take these as values. Since
* GLX header files may not be available everywhere they need to be used,
* redefine them here.
*/
#define GLX_NONE 0x8000
#define GLX_SLOW_CONFIG 0x8001
#define GLX_TRUE_COLOR 0x8002
#define GLX_DIRECT_COLOR 0x8003
#define GLX_PSEUDO_COLOR 0x8004
#define GLX_STATIC_COLOR 0x8005
#define GLX_GRAY_SCALE 0x8006
#define GLX_STATIC_GRAY 0x8007
#define GLX_TRANSPARENT_RGB 0x8008
#define GLX_TRANSPARENT_INDEX 0x8009
#define GLX_NON_CONFORMANT_CONFIG 0x800D
#define GLX_SWAP_EXCHANGE_OML 0x8061
#define GLX_SWAP_COPY_OML 0x8062
#define GLX_SWAP_UNDEFINED_OML 0x8063
#define GLX_DONT_CARE 0xFFFFFFFF
#define GLX_RGBA_BIT 0x00000001
#define GLX_COLOR_INDEX_BIT 0x00000002
#define GLX_WINDOW_BIT 0x00000001
#define GLX_PIXMAP_BIT 0x00000002
#define GLX_PBUFFER_BIT 0x00000004
#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
#define GLX_Y_INVERTED_EXT 0x20D4
#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
#endif /* __gl_core_h_ */
@@ -1,656 +0,0 @@
/**
* GLX initialization. Code based on glxext.c, glx_query.c, and
* glcontextmodes.c under src/glx/. The major difference is that DRI
* related code is stripped out.
*
* If the maintenance of this file takes too much time, we should consider
* refactoring glxext.c.
*/
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
#include <X11/Xlibint.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include <sys/time.h>
#include "GL/glxproto.h"
#include "GL/glxtokens.h"
#include "GL/gl.h" /* for GL types needed by __GLcontextModes */
#include "glcore.h" /* for __GLcontextModes */
#include "glxinit.h"
#ifdef GLX_DIRECT_RENDERING
typedef struct GLXGenericGetString
{
CARD8 reqType;
CARD8 glxCode;
CARD16 length B16;
CARD32 for_whom B32;
CARD32 name B32;
} xGLXGenericGetStringReq;
#define sz_xGLXGenericGetStringReq 12
#define X_GLXGenericGetString 0
/* Extension required boiler plate */
static char *__glXExtensionName = GLX_EXTENSION_NAME;
static XExtensionInfo *__glXExtensionInfo = NULL;
static int
__glXCloseDisplay(Display * dpy, XExtCodes * codes)
{
return XextRemoveDisplay(__glXExtensionInfo, dpy);
}
static /* const */ XExtensionHooks __glXExtensionHooks = {
NULL, /* create_gc */
NULL, /* copy_gc */
NULL, /* flush_gc */
NULL, /* free_gc */
NULL, /* create_font */
NULL, /* free_font */
__glXCloseDisplay, /* close_display */
NULL, /* wire_to_event */
NULL, /* event_to_wire */
NULL, /* error */
NULL, /* error_string */
};
static XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
__glXExtensionName, &__glXExtensionHooks,
__GLX_NUMBER_EVENTS, NULL)
static GLint
_gl_convert_from_x_visual_type(int visualType)
{
#define NUM_VISUAL_TYPES 6
static const int glx_visual_types[NUM_VISUAL_TYPES] = {
GLX_STATIC_GRAY, GLX_GRAY_SCALE,
GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
GLX_TRUE_COLOR, GLX_DIRECT_COLOR
};
return ((unsigned) visualType < NUM_VISUAL_TYPES)
? glx_visual_types[visualType] : GLX_NONE;
}
static void
_gl_context_modes_destroy(__GLcontextModes * modes)
{
while (modes != NULL) {
__GLcontextModes *const next = modes->next;
free(modes);
modes = next;
}
}
static __GLcontextModes *
_gl_context_modes_create(unsigned count, size_t minimum_size)
{
const size_t size = (minimum_size > sizeof(__GLcontextModes))
? minimum_size : sizeof(__GLcontextModes);
__GLcontextModes *base = NULL;
__GLcontextModes **next;
unsigned i;
next = &base;
for (i = 0; i < count; i++) {
*next = malloc(size);
if (*next == NULL) {
_gl_context_modes_destroy(base);
base = NULL;
break;
}
memset(*next, 0, size);
(*next)->visualID = GLX_DONT_CARE;
(*next)->visualType = GLX_DONT_CARE;
(*next)->visualRating = GLX_NONE;
(*next)->transparentPixel = GLX_NONE;
(*next)->transparentRed = GLX_DONT_CARE;
(*next)->transparentGreen = GLX_DONT_CARE;
(*next)->transparentBlue = GLX_DONT_CARE;
(*next)->transparentAlpha = GLX_DONT_CARE;
(*next)->transparentIndex = GLX_DONT_CARE;
(*next)->xRenderable = GLX_DONT_CARE;
(*next)->fbconfigID = GLX_DONT_CARE;
(*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
(*next)->bindToTextureRgb = GLX_DONT_CARE;
(*next)->bindToTextureRgba = GLX_DONT_CARE;
(*next)->bindToMipmapTexture = GLX_DONT_CARE;
(*next)->bindToTextureTargets = GLX_DONT_CARE;
(*next)->yInverted = GLX_DONT_CARE;
next = &((*next)->next);
}
return base;
}
static char *
__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
{
xGLXGenericGetStringReq *req;
xGLXSingleReply reply;
int length;
int numbytes;
char *buf;
CARD32 for_whom = screen;
CARD32 glxCode = X_GLXQueryServerString;
LockDisplay(dpy);
/* All of the GLX protocol requests for getting a string from the server
* look the same. The exact meaning of the for_whom field is usually
* either the screen number (for glXQueryServerString) or the context tag
* (for GLXSingle).
*/
GetReq(GLXGenericGetString, req);
req->reqType = opcode;
req->glxCode = glxCode;
req->for_whom = for_whom;
req->name = name;
_XReply(dpy, (xReply *) & reply, 0, False);
length = reply.length * 4;
numbytes = reply.size;
buf = malloc(numbytes);
if (buf != NULL) {
_XRead(dpy, buf, numbytes);
length -= numbytes;
}
_XEatData(dpy, length);
UnlockDisplay(dpy);
SyncHandle();
return buf;
}
/************************************************************************/
/*
** Free the per screen configs data as well as the array of
** __glXScreenConfigs.
*/
static void
FreeScreenConfigs(__GLXdisplayPrivate * priv)
{
__GLXscreenConfigs *psc;
GLint i, screens;
/* Free screen configuration information */
screens = ScreenCount(priv->dpy);
for (i = 0; i < screens; i++) {
psc = priv->screenConfigs[i];
if (!psc)
continue;
if (psc->configs) {
_gl_context_modes_destroy(psc->configs);
psc->configs = NULL; /* NOTE: just for paranoia */
}
free((char *) psc->serverGLXexts);
}
free((char *) priv->screenConfigs);
priv->screenConfigs = NULL;
}
/*
** Release the private memory referred to in a display private
** structure. The caller will free the extension structure.
*/
static int
__glXFreeDisplayPrivate(XExtData * extension)
{
__GLXdisplayPrivate *priv;
priv = (__GLXdisplayPrivate *) extension->private_data;
FreeScreenConfigs(priv);
free((char *) priv->serverGLXversion);
free((char *) priv);
return 0;
}
/************************************************************************/
/*
** Query the version of the GLX extension. This procedure works even if
** the client extension is not completely set up.
*/
#define GLX_MAJOR_VERSION 1 /* current version numbers */
#define GLX_MINOR_VERSION 4
static Bool
QueryVersion(Display * dpy, int opcode, int *major, int *minor)
{
xGLXQueryVersionReq *req;
xGLXQueryVersionReply reply;
/* Send the glXQueryVersion request */
LockDisplay(dpy);
GetReq(GLXQueryVersion, req);
req->reqType = opcode;
req->glxCode = X_GLXQueryVersion;
req->majorVersion = GLX_MAJOR_VERSION;
req->minorVersion = GLX_MINOR_VERSION;
_XReply(dpy, (xReply *) & reply, 0, False);
UnlockDisplay(dpy);
SyncHandle();
if (reply.majorVersion != GLX_MAJOR_VERSION) {
/*
** The server does not support the same major release as this
** client.
*/
return GL_FALSE;
}
*major = reply.majorVersion;
*minor = min(reply.minorVersion, GLX_MINOR_VERSION);
return GL_TRUE;
}
#define __GLX_MIN_CONFIG_PROPS 18
#define __GLX_MAX_CONFIG_PROPS 500
#define __GLX_EXT_CONFIG_PROPS 10
#define __GLX_TOTAL_CONFIG (__GLX_MIN_CONFIG_PROPS + \
2 * __GLX_EXT_CONFIG_PROPS)
static void
__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
const INT32 * bp, Bool tagged_only,
Bool fbconfig_style_tags)
{
int i;
if (!tagged_only) {
/* Copy in the first set of properties */
config->visualID = *bp++;
config->visualType = _gl_convert_from_x_visual_type(*bp++);
config->rgbMode = *bp++;
config->redBits = *bp++;
config->greenBits = *bp++;
config->blueBits = *bp++;
config->alphaBits = *bp++;
config->accumRedBits = *bp++;
config->accumGreenBits = *bp++;
config->accumBlueBits = *bp++;
config->accumAlphaBits = *bp++;
config->doubleBufferMode = *bp++;
config->stereoMode = *bp++;
config->rgbBits = *bp++;
config->depthBits = *bp++;
config->stencilBits = *bp++;
config->numAuxBuffers = *bp++;
config->level = *bp++;
count -= __GLX_MIN_CONFIG_PROPS;
}
/*
** Additional properties may be in a list at the end
** of the reply. They are in pairs of property type
** and property value.
*/
#define FETCH_OR_SET(tag) \
config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
for (i = 0; i < count; i += 2) {
switch (*bp++) {
case GLX_RGBA:
FETCH_OR_SET(rgbMode);
break;
case GLX_BUFFER_SIZE:
config->rgbBits = *bp++;
break;
case GLX_LEVEL:
config->level = *bp++;
break;
case GLX_DOUBLEBUFFER:
FETCH_OR_SET(doubleBufferMode);
break;
case GLX_STEREO:
FETCH_OR_SET(stereoMode);
break;
case GLX_AUX_BUFFERS:
config->numAuxBuffers = *bp++;
break;
case GLX_RED_SIZE:
config->redBits = *bp++;
break;
case GLX_GREEN_SIZE:
config->greenBits = *bp++;
break;
case GLX_BLUE_SIZE:
config->blueBits = *bp++;
break;
case GLX_ALPHA_SIZE:
config->alphaBits = *bp++;
break;
case GLX_DEPTH_SIZE:
config->depthBits = *bp++;
break;
case GLX_STENCIL_SIZE:
config->stencilBits = *bp++;
break;
case GLX_ACCUM_RED_SIZE:
config->accumRedBits = *bp++;
break;
case GLX_ACCUM_GREEN_SIZE:
config->accumGreenBits = *bp++;
break;
case GLX_ACCUM_BLUE_SIZE:
config->accumBlueBits = *bp++;
break;
case GLX_ACCUM_ALPHA_SIZE:
config->accumAlphaBits = *bp++;
break;
case GLX_VISUAL_CAVEAT_EXT:
config->visualRating = *bp++;
break;
case GLX_X_VISUAL_TYPE:
config->visualType = *bp++;
break;
case GLX_TRANSPARENT_TYPE:
config->transparentPixel = *bp++;
break;
case GLX_TRANSPARENT_INDEX_VALUE:
config->transparentIndex = *bp++;
break;
case GLX_TRANSPARENT_RED_VALUE:
config->transparentRed = *bp++;
break;
case GLX_TRANSPARENT_GREEN_VALUE:
config->transparentGreen = *bp++;
break;
case GLX_TRANSPARENT_BLUE_VALUE:
config->transparentBlue = *bp++;
break;
case GLX_TRANSPARENT_ALPHA_VALUE:
config->transparentAlpha = *bp++;
break;
case GLX_VISUAL_ID:
config->visualID = *bp++;
break;
case GLX_DRAWABLE_TYPE:
config->drawableType = *bp++;
break;
case GLX_RENDER_TYPE:
config->renderType = *bp++;
break;
case GLX_X_RENDERABLE:
config->xRenderable = *bp++;
break;
case GLX_FBCONFIG_ID:
config->fbconfigID = *bp++;
break;
case GLX_MAX_PBUFFER_WIDTH:
config->maxPbufferWidth = *bp++;
break;
case GLX_MAX_PBUFFER_HEIGHT:
config->maxPbufferHeight = *bp++;
break;
case GLX_MAX_PBUFFER_PIXELS:
config->maxPbufferPixels = *bp++;
break;
case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
config->optimalPbufferWidth = *bp++;
break;
case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
config->optimalPbufferHeight = *bp++;
break;
case GLX_VISUAL_SELECT_GROUP_SGIX:
config->visualSelectGroup = *bp++;
break;
case GLX_SWAP_METHOD_OML:
config->swapMethod = *bp++;
break;
case GLX_SAMPLE_BUFFERS_SGIS:
config->sampleBuffers = *bp++;
break;
case GLX_SAMPLES_SGIS:
config->samples = *bp++;
break;
case GLX_BIND_TO_TEXTURE_RGB_EXT:
config->bindToTextureRgb = *bp++;
break;
case GLX_BIND_TO_TEXTURE_RGBA_EXT:
config->bindToTextureRgba = *bp++;
break;
case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
config->bindToMipmapTexture = *bp++;
break;
case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
config->bindToTextureTargets = *bp++;
break;
case GLX_Y_INVERTED_EXT:
config->yInverted = *bp++;
break;
case None:
i = count;
break;
default:
break;
}
}
config->renderType =
(config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
config->haveAccumBuffer = ((config->accumRedBits +
config->accumGreenBits +
config->accumBlueBits +
config->accumAlphaBits) > 0);
config->haveDepthBuffer = (config->depthBits > 0);
config->haveStencilBuffer = (config->stencilBits > 0);
}
static __GLcontextModes *
createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
int screen, GLboolean tagged_only)
{
INT32 buf[__GLX_TOTAL_CONFIG], *props;
unsigned prop_size;
__GLcontextModes *modes, *m;
int i;
if (nprops == 0)
return NULL;
/* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
/* Check number of properties */
if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
return NULL;
/* Allocate memory for our config structure */
modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
if (!modes)
return NULL;
prop_size = nprops * __GLX_SIZE_INT32;
if (prop_size <= sizeof(buf))
props = buf;
else
props = malloc(prop_size);
/* Read each config structure and convert it into our format */
m = modes;
for (i = 0; i < nvisuals; i++) {
_XRead(dpy, (char *) props, prop_size);
/* Older X servers don't send this so we default it here. */
m->drawableType = GLX_WINDOW_BIT;
__glXInitializeVisualConfigFromTags(m, nprops, props,
tagged_only, GL_TRUE);
m->screen = screen;
m = m->next;
}
if (props != buf)
free(props);
return modes;
}
static GLboolean
getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen)
{
xGLXGetFBConfigsReq *fb_req;
xGLXGetFBConfigsSGIXReq *sgi_req;
xGLXVendorPrivateWithReplyReq *vpreq;
xGLXGetFBConfigsReply reply;
Display *dpy = priv->dpy;
psc->serverGLXexts =
__glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
LockDisplay(dpy);
psc->configs = NULL;
if (atof(priv->serverGLXversion) >= 1.3) {
GetReq(GLXGetFBConfigs, fb_req);
fb_req->reqType = priv->majorOpcode;
fb_req->glxCode = X_GLXGetFBConfigs;
fb_req->screen = screen;
}
else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
GetReqExtra(GLXVendorPrivateWithReply,
sz_xGLXGetFBConfigsSGIXReq +
sz_xGLXVendorPrivateWithReplyReq, vpreq);
sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
sgi_req->reqType = priv->majorOpcode;
sgi_req->glxCode = X_GLXVendorPrivateWithReply;
sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
sgi_req->screen = screen;
}
else
goto out;
if (!_XReply(dpy, (xReply *) & reply, 0, False))
goto out;
psc->configs = createConfigsFromProperties(dpy,
reply.numFBConfigs,
reply.numAttribs * 2,
screen, GL_TRUE);
out:
UnlockDisplay(dpy);
return psc->configs != NULL;
}
static GLboolean
AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
{
__GLXscreenConfigs *psc;
GLint i, screens;
/*
** First allocate memory for the array of per screen configs.
*/
screens = ScreenCount(dpy);
priv->screenConfigs = malloc(screens * sizeof *priv->screenConfigs);
if (!priv->screenConfigs) {
return GL_FALSE;
}
priv->serverGLXversion =
__glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
if (priv->serverGLXversion == NULL) {
FreeScreenConfigs(priv);
return GL_FALSE;
}
for (i = 0; i < screens; i++) {
psc = calloc(1, sizeof *psc);
if (!psc)
return GL_FALSE;
getFBConfigs(psc, priv, i);
priv->screenConfigs[i] = psc;
}
SyncHandle();
return GL_TRUE;
}
_X_HIDDEN __GLXdisplayPrivate *
__glXInitialize(Display * dpy)
{
XExtDisplayInfo *info = __glXFindDisplay(dpy);
XExtData **privList, *private, *found;
__GLXdisplayPrivate *dpyPriv;
XEDataObject dataObj;
int major, minor;
if (!XextHasExtension(info))
return NULL;
/* See if a display private already exists. If so, return it */
dataObj.display = dpy;
privList = XEHeadOfExtensionList(dataObj);
found = XFindOnExtensionList(privList, info->codes->extension);
if (found)
return (__GLXdisplayPrivate *) found->private_data;
/* See if the versions are compatible */
if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor))
return NULL;
/*
** Allocate memory for all the pieces needed for this buffer.
*/
private = malloc(sizeof(XExtData));
if (!private)
return NULL;
dpyPriv = calloc(1, sizeof(__GLXdisplayPrivate));
if (!dpyPriv) {
free(private);
return NULL;
}
/*
** Init the display private and then read in the screen config
** structures from the server.
*/
dpyPriv->majorOpcode = info->codes->major_opcode;
dpyPriv->dpy = dpy;
if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
free(dpyPriv);
free(private);
return NULL;
}
/*
** Fill in the private structure. This is the actual structure that
** hangs off of the Display structure. Our private structure is
** referred to by this structure. Got that?
*/
private->number = info->codes->extension;
private->next = 0;
private->free_private = __glXFreeDisplayPrivate;
private->private_data = (char *) dpyPriv;
XAddToExtensionList(privList, private);
return dpyPriv;
}
#endif /* GLX_DIRECT_RENDERING */
@@ -1,22 +0,0 @@
#ifndef GLXINIT_INCLUDED
#define GLXINIT_INCLUDED
#include <X11/Xlib.h>
#include <GL/gl.h>
typedef struct {
__GLcontextModes *configs;
char *serverGLXexts;
} __GLXscreenConfigs;
typedef struct {
Display *dpy;
__GLXscreenConfigs **screenConfigs;
char *serverGLXversion;
int majorOpcode;
struct x11_screen *xscr;
} __GLXdisplayPrivate;
extern __GLXdisplayPrivate *__glXInitialize(Display * dpy);
#endif /* GLXINIT_INCLUDED */
@@ -1,925 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_hash_table.h"
#include "pipe/p_compiler.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "state_tracker/drm_driver.h"
#include "egllog.h"
#include "native_x11.h"
#include "x11_screen.h"
#include "common/native_helper.h"
#ifdef HAVE_WAYLAND_BACKEND
#include "common/native_wayland_drm_bufmgr.h"
#endif
#ifdef GLX_DIRECT_RENDERING
struct dri2_display {
struct native_display base;
Display *dpy;
boolean own_dpy;
const struct native_event_handler *event_handler;
struct x11_screen *xscr;
int xscr_number;
const char *dri_driver;
int dri_major, dri_minor;
struct dri2_config *configs;
int num_configs;
struct util_hash_table *surfaces;
};
struct dri2_surface {
struct native_surface base;
Drawable drawable;
enum pipe_format color_format;
struct dri2_display *dri2dpy;
unsigned int server_stamp;
unsigned int client_stamp;
int width, height;
struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
uint valid_mask;
boolean have_back, have_fake;
struct x11_drawable_buffer *last_xbufs;
int last_num_xbufs;
};
struct dri2_config {
struct native_config base;
};
static INLINE struct dri2_display *
dri2_display(const struct native_display *ndpy)
{
return (struct dri2_display *) ndpy;
}
static INLINE struct dri2_surface *
dri2_surface(const struct native_surface *nsurf)
{
return (struct dri2_surface *) nsurf;
}
static INLINE struct dri2_config *
dri2_config(const struct native_config *nconf)
{
return (struct dri2_config *) nconf;
}
/**
* Process the buffers returned by the server.
*/
static void
dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
struct x11_drawable_buffer *xbufs,
int num_xbufs)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
struct pipe_resource templ;
struct winsys_handle whandle;
uint valid_mask;
int i;
/* free the old textures */
for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
pipe_resource_reference(&dri2surf->textures[i], NULL);
dri2surf->valid_mask = 0x0;
dri2surf->have_back = FALSE;
dri2surf->have_fake = FALSE;
if (!xbufs)
return;
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.last_level = 0;
templ.width0 = dri2surf->width;
templ.height0 = dri2surf->height;
templ.depth0 = 1;
templ.array_size = 1;
templ.format = dri2surf->color_format;
templ.bind = PIPE_BIND_RENDER_TARGET;
valid_mask = 0x0;
for (i = 0; i < num_xbufs; i++) {
struct x11_drawable_buffer *xbuf = &xbufs[i];
const char *desc;
enum native_attachment natt;
switch (xbuf->attachment) {
case DRI2BufferFrontLeft:
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
desc = "DRI2 Front Buffer";
break;
case DRI2BufferFakeFrontLeft:
natt = NATIVE_ATTACHMENT_FRONT_LEFT;
desc = "DRI2 Fake Front Buffer";
dri2surf->have_fake = TRUE;
break;
case DRI2BufferBackLeft:
natt = NATIVE_ATTACHMENT_BACK_LEFT;
desc = "DRI2 Back Buffer";
dri2surf->have_back = TRUE;
break;
default:
desc = NULL;
break;
}
if (!desc || dri2surf->textures[natt]) {
if (!desc)
_eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
else
_eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
continue;
}
memset(&whandle, 0, sizeof(whandle));
whandle.type = DRM_API_HANDLE_TYPE_SHARED;
whandle.stride = xbuf->pitch;
whandle.handle = xbuf->name;
dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle(
dri2dpy->base.screen, &templ, &whandle);
if (dri2surf->textures[natt])
valid_mask |= 1 << natt;
}
dri2surf->valid_mask = valid_mask;
}
/**
* Get the buffers from the server.
*/
static void
dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2];
int num_ins, num_outs, att;
struct x11_drawable_buffer *xbufs;
uint bpp = util_format_get_blocksizebits(dri2surf->color_format);
boolean with_format = FALSE; /* never ask for depth/stencil */
/* We must get the front on servers which doesn't support with format
* due to a silly bug in core dri2. You can't copy to/from a buffer
* that you haven't requested and you recive BadValue errors */
if (dri2surf->dri2dpy->dri_minor < 1) {
with_format = FALSE;
buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
}
/* prepare the attachments */
num_ins = 0;
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
if (native_attachment_mask_test(buffer_mask, att)) {
unsigned int dri2att;
switch (att) {
case NATIVE_ATTACHMENT_FRONT_LEFT:
dri2att = DRI2BufferFrontLeft;
break;
case NATIVE_ATTACHMENT_BACK_LEFT:
dri2att = DRI2BufferBackLeft;
break;
case NATIVE_ATTACHMENT_FRONT_RIGHT:
dri2att = DRI2BufferFrontRight;
break;
case NATIVE_ATTACHMENT_BACK_RIGHT:
dri2att = DRI2BufferBackRight;
break;
default:
assert(0);
dri2att = 0;
break;
}
dri2atts[num_ins++] = dri2att;
if (with_format)
dri2atts[num_ins++] = bpp;
}
}
if (with_format)
num_ins /= 2;
xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
&dri2surf->width, &dri2surf->height,
dri2atts, with_format, num_ins, &num_outs);
/* we should be able to do better... */
if (xbufs && dri2surf->last_num_xbufs == num_outs &&
memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
FREE(xbufs);
dri2surf->client_stamp = dri2surf->server_stamp;
return;
}
dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);
dri2surf->server_stamp++;
dri2surf->client_stamp = dri2surf->server_stamp;
FREE(dri2surf->last_xbufs);
dri2surf->last_xbufs = xbufs;
dri2surf->last_num_xbufs = num_outs;
}
/**
* Update the buffers of the surface. This is a slow function due to the
* round-trip to the server.
*/
static boolean
dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
dri2_surface_get_buffers(&dri2surf->base, buffer_mask);
return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
}
/**
* Return TRUE if the surface receives DRI2_InvalidateBuffers events.
*/
static INLINE boolean
dri2_surface_receive_events(struct native_surface *nsurf)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
return (dri2surf->dri2dpy->dri_minor >= 3);
}
static boolean
dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
struct native_display *ndpy = &dri2dpy->base;
struct pipe_context *pipe = ndpy_get_copy_context(ndpy);
/* flush buffer */
pipe->flush_resource(pipe, dri2surf->textures[NATIVE_ATTACHMENT_FRONT_LEFT]);
pipe->flush(pipe, NULL, 0);
/* copy to real front buffer */
if (dri2surf->have_fake)
x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
0, 0, dri2surf->width, dri2surf->height,
DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
/* force buffers to be updated in next validation call */
if (!dri2_surface_receive_events(&dri2surf->base)) {
dri2surf->server_stamp++;
dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
&dri2surf->base, dri2surf->server_stamp);
}
return TRUE;
}
static boolean
dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects,
const int *rects)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
struct native_display *ndpy = &dri2dpy->base;
struct pipe_context *pipe = ndpy_get_copy_context(ndpy);
/* copy to front buffer */
if (dri2surf->have_back) {
pipe->flush_resource(pipe, dri2surf->textures[NATIVE_ATTACHMENT_BACK_LEFT]);
pipe->flush(pipe, NULL, 0);
if (num_rects > 0)
x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
num_rects, rects,
DRI2BufferBackLeft, DRI2BufferFrontLeft);
else
x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
0, 0, dri2surf->width, dri2surf->height,
DRI2BufferBackLeft, DRI2BufferFrontLeft);
}
/* and update fake front buffer */
if (dri2surf->have_fake) {
if (num_rects > 0)
x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
num_rects, rects,
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
else
x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
0, 0, dri2surf->width, dri2surf->height,
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
}
/* force buffers to be updated in next validation call */
if (!dri2_surface_receive_events(&dri2surf->base)) {
dri2surf->server_stamp++;
dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
&dri2surf->base, dri2surf->server_stamp);
}
return TRUE;
}
static boolean
dri2_surface_present(struct native_surface *nsurf,
const struct native_present_control *ctrl)
{
boolean ret;
if (ctrl->swap_interval)
return FALSE;
switch (ctrl->natt) {
case NATIVE_ATTACHMENT_FRONT_LEFT:
ret = dri2_surface_flush_frontbuffer(nsurf);
break;
case NATIVE_ATTACHMENT_BACK_LEFT:
ret = dri2_surface_swap_buffers(nsurf, ctrl->num_rects, ctrl->rects);
break;
default:
ret = FALSE;
break;
}
return ret;
}
static boolean
dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
if (dri2surf->server_stamp != dri2surf->client_stamp ||
(dri2surf->valid_mask & attachment_mask) != attachment_mask) {
if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
return FALSE;
}
if (seq_num)
*seq_num = dri2surf->client_stamp;
if (textures) {
int att;
for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
if (native_attachment_mask_test(attachment_mask, att)) {
struct pipe_resource *ptex = dri2surf->textures[att];
textures[att] = NULL;
pipe_resource_reference(&textures[att], ptex);
}
}
}
if (width)
*width = dri2surf->width;
if (height)
*height = dri2surf->height;
return TRUE;
}
static void
dri2_surface_wait(struct native_surface *nsurf)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
struct dri2_display *dri2dpy = dri2surf->dri2dpy;
if (dri2surf->have_fake) {
x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
0, 0, dri2surf->width, dri2surf->height,
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
}
}
static void
dri2_surface_destroy(struct native_surface *nsurf)
{
struct dri2_surface *dri2surf = dri2_surface(nsurf);
int i;
FREE(dri2surf->last_xbufs);
for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
struct pipe_resource *ptex = dri2surf->textures[i];
pipe_resource_reference(&ptex, NULL);
}
if (dri2surf->drawable) {
x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
dri2surf->drawable, FALSE);
util_hash_table_remove(dri2surf->dri2dpy->surfaces,
(void *) dri2surf->drawable);
}
FREE(dri2surf);
}
static struct dri2_surface *
dri2_display_create_surface(struct native_display *ndpy,
Drawable drawable,
enum pipe_format color_format)
{
struct dri2_display *dri2dpy = dri2_display(ndpy);
struct dri2_surface *dri2surf;
dri2surf = CALLOC_STRUCT(dri2_surface);
if (!dri2surf)
return NULL;
dri2surf->dri2dpy = dri2dpy;
dri2surf->drawable = drawable;
dri2surf->color_format = color_format;
dri2surf->base.destroy = dri2_surface_destroy;
dri2surf->base.present = dri2_surface_present;
dri2surf->base.validate = dri2_surface_validate;
dri2surf->base.wait = dri2_surface_wait;
if (drawable) {
x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
/* initialize the geometry */
dri2_surface_update_buffers(&dri2surf->base, 0x0);
util_hash_table_set(dri2surf->dri2dpy->surfaces,
(void *) dri2surf->drawable, (void *) &dri2surf->base);
}
return dri2surf;
}
static struct native_surface *
dri2_display_create_window_surface(struct native_display *ndpy,
EGLNativeWindowType win,
const struct native_config *nconf)
{
struct dri2_surface *dri2surf;
dri2surf = dri2_display_create_surface(ndpy,
(Drawable) win, nconf->color_format);
return (dri2surf) ? &dri2surf->base : NULL;
}
static struct native_surface *
dri2_display_create_pixmap_surface(struct native_display *ndpy,
EGLNativePixmapType pix,
const struct native_config *nconf)
{
struct dri2_surface *dri2surf;
if (!nconf) {
struct dri2_display *dri2dpy = dri2_display(ndpy);
uint depth, nconf_depth;
int i;
depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
for (i = 0; i < dri2dpy->num_configs; i++) {
nconf_depth = util_format_get_blocksizebits(
dri2dpy->configs[i].base.color_format);
/* simple depth match for now */
if (depth == nconf_depth ||
(depth == 24 && depth + 8 == nconf_depth)) {
nconf = &dri2dpy->configs[i].base;
break;
}
}
if (!nconf)
return NULL;
}
dri2surf = dri2_display_create_surface(ndpy,
(Drawable) pix, nconf->color_format);
return (dri2surf) ? &dri2surf->base : NULL;
}
static int
choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
{
int count = 0;
switch (mode->rgbBits) {
case 32:
formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
break;
case 24:
formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
break;
case 16:
formats[count++] = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
break;
}
return count;
}
static boolean
is_format_supported(struct pipe_screen *screen,
enum pipe_format fmt, unsigned sample_count, boolean is_color)
{
return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count,
(is_color) ? PIPE_BIND_RENDER_TARGET :
PIPE_BIND_DEPTH_STENCIL);
}
static boolean
dri2_display_convert_config(struct native_display *ndpy,
const __GLcontextModes *mode,
struct native_config *nconf)
{
enum pipe_format formats[32];
int num_formats, i;
int sample_count = 0;
if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
return FALSE;
/* only interested in native renderable configs */
if (!mode->xRenderable || !mode->drawableType)
return FALSE;
/* fast/slow configs are probably not relevant */
if (mode->visualRating == GLX_SLOW_CONFIG)
return FALSE;
nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
if (mode->doubleBufferMode)
nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
if (mode->stereoMode) {
nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT;
if (mode->doubleBufferMode)
nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT;
}
/* choose color format */
num_formats = choose_color_format(mode, formats);
for (i = 0; i < num_formats; i++) {
if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) {
nconf->color_format = formats[i];
break;
}
}
if (nconf->color_format == PIPE_FORMAT_NONE)
return FALSE;
if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID)
nconf->window_bit = TRUE;
if (mode->drawableType & GLX_PIXMAP_BIT)
nconf->pixmap_bit = TRUE;
nconf->native_visual_id = mode->visualID;
switch (mode->visualType) {
case GLX_TRUE_COLOR:
nconf->native_visual_type = TrueColor;
break;
case GLX_DIRECT_COLOR:
nconf->native_visual_type = DirectColor;
break;
case GLX_PSEUDO_COLOR:
nconf->native_visual_type = PseudoColor;
break;
case GLX_STATIC_COLOR:
nconf->native_visual_type = StaticColor;
break;
case GLX_GRAY_SCALE:
nconf->native_visual_type = GrayScale;
break;
case GLX_STATIC_GRAY:
nconf->native_visual_type = StaticGray;
break;
}
nconf->level = mode->level;
if (mode->transparentPixel == GLX_TRANSPARENT_RGB) {
nconf->transparent_rgb = TRUE;
nconf->transparent_rgb_values[0] = mode->transparentRed;
nconf->transparent_rgb_values[1] = mode->transparentGreen;
nconf->transparent_rgb_values[2] = mode->transparentBlue;
}
return TRUE;
}
static const struct native_config **
dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct dri2_display *dri2dpy = dri2_display(ndpy);
const struct native_config **configs;
int i;
/* first time */
if (!dri2dpy->configs) {
const __GLcontextModes *modes;
int num_modes, count;
modes = x11_screen_get_glx_configs(dri2dpy->xscr);
if (!modes)
return NULL;
num_modes = x11_context_modes_count(modes);
dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs));
if (!dri2dpy->configs)
return NULL;
count = 0;
for (i = 0; i < num_modes; i++) {
struct native_config *nconf = &dri2dpy->configs[count].base;
if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) {
int j;
/* look for duplicates */
for (j = 0; j < count; j++) {
if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0)
break;
}
if (j == count)
count++;
}
modes = modes->next;
}
dri2dpy->num_configs = count;
}
configs = MALLOC(dri2dpy->num_configs * sizeof(*configs));
if (configs) {
for (i = 0; i < dri2dpy->num_configs; i++)
configs[i] = (const struct native_config *) &dri2dpy->configs[i];
if (num_configs)
*num_configs = dri2dpy->num_configs;
}
return configs;
}
static boolean
dri2_display_get_pixmap_format(struct native_display *ndpy,
EGLNativePixmapType pix,
enum pipe_format *format)
{
struct dri2_display *dri2dpy = dri2_display(ndpy);
boolean ret = EGL_TRUE;
uint depth;
depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
switch (depth) {
case 32:
case 24:
*format = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
case 16:
*format = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
*format = PIPE_FORMAT_NONE;
ret = EGL_FALSE;
break;
}
return ret;
}
static int
dri2_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
int val;
switch (param) {
case NATIVE_PARAM_USE_NATIVE_BUFFER:
/* DRI2GetBuffers uses the native buffers */
val = TRUE;
break;
case NATIVE_PARAM_PRESERVE_BUFFER:
/* DRI2CopyRegion is used */
val = TRUE;
break;
case NATIVE_PARAM_PRESENT_REGION:
val = TRUE;
break;
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
default:
val = 0;
break;
}
return val;
}
static void
dri2_display_destroy(struct native_display *ndpy)
{
struct dri2_display *dri2dpy = dri2_display(ndpy);
FREE(dri2dpy->configs);
if (dri2dpy->base.screen)
dri2dpy->base.screen->destroy(dri2dpy->base.screen);
if (dri2dpy->surfaces)
util_hash_table_destroy(dri2dpy->surfaces);
#ifdef HAVE_WAYLAND_BACKEND
wayland_drm_bufmgr_destroy(ndpy->wayland_bufmgr);
#endif
if (dri2dpy->xscr)
x11_screen_destroy(dri2dpy->xscr);
if (dri2dpy->own_dpy)
XCloseDisplay(dri2dpy->dpy);
FREE(dri2dpy);
}
static void
dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
void *user_data)
{
struct native_display *ndpy = (struct native_display* ) user_data;
struct dri2_display *dri2dpy = dri2_display(ndpy);
struct native_surface *nsurf;
struct dri2_surface *dri2surf;
nsurf = (struct native_surface *)
util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
if (!nsurf)
return;
dri2surf = dri2_surface(nsurf);
dri2surf->server_stamp++;
dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
&dri2surf->base, dri2surf->server_stamp);
}
#ifdef HAVE_WAYLAND_BACKEND
static int
dri2_display_authenticate(void *user_data, uint32_t magic)
{
struct native_display *ndpy = user_data;
struct dri2_display *dri2dpy = dri2_display(ndpy);
return x11_screen_authenticate(dri2dpy->xscr, magic);
}
#endif /* HAVE_WAYLAND_BACKEND */
/**
* Initialize DRI2 and pipe screen.
*/
static boolean
dri2_display_init_screen(struct native_display *ndpy)
{
struct dri2_display *dri2dpy = dri2_display(ndpy);
int fd;
if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
_eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
return FALSE;
}
dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
&dri2dpy->dri_major, &dri2dpy->dri_minor);
fd = x11_screen_enable_dri2(dri2dpy->xscr,
dri2_display_invalidate_buffers, &dri2dpy->base);
if (fd < 0)
return FALSE;
dri2dpy->base.screen =
dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
dri2dpy->dri_driver, fd);
if (!dri2dpy->base.screen) {
_eglLog(_EGL_DEBUG, "failed to create DRM screen");
return FALSE;
}
#ifdef HAVE_WAYLAND_BACKEND
dri2dpy->base.wayland_bufmgr = wayland_drm_bufmgr_create(
dri2_display_authenticate, dri2dpy,
x11_screen_get_device_name(dri2dpy->xscr));
#endif
return TRUE;
}
static unsigned
dri2_display_hash_table_hash(void *key)
{
XID drawable = pointer_to_uintptr(key);
return (unsigned) drawable;
}
static int
dri2_display_hash_table_compare(void *key1, void *key2)
{
return ((char *) key1 - (char *) key2);
}
struct native_display *
x11_create_dri2_display(Display *dpy,
const struct native_event_handler *event_handler)
{
struct dri2_display *dri2dpy;
dri2dpy = CALLOC_STRUCT(dri2_display);
if (!dri2dpy)
return NULL;
dri2dpy->event_handler = event_handler;
dri2dpy->dpy = dpy;
if (!dri2dpy->dpy) {
dri2dpy->dpy = XOpenDisplay(NULL);
if (!dri2dpy->dpy) {
dri2_display_destroy(&dri2dpy->base);
return NULL;
}
dri2dpy->own_dpy = TRUE;
}
dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
if (!dri2dpy->xscr) {
dri2_display_destroy(&dri2dpy->base);
return NULL;
}
dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
dri2_display_hash_table_compare);
if (!dri2dpy->surfaces) {
dri2_display_destroy(&dri2dpy->base);
return NULL;
}
dri2dpy->base.init_screen = dri2_display_init_screen;
dri2dpy->base.destroy = dri2_display_destroy;
dri2dpy->base.get_param = dri2_display_get_param;
dri2dpy->base.get_configs = dri2_display_get_configs;
dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format;
dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap;
dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
return &dri2dpy->base;
}
#else /* GLX_DIRECT_RENDERING */
struct native_display *
x11_create_dri2_display(Display *dpy,
const struct native_event_handler *event_handler)
{
return NULL;
}
#endif /* GLX_DIRECT_RENDERING */
@@ -1,63 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_string.h"
#include "egllog.h"
#include "native_x11.h"
static const struct native_event_handler *x11_event_handler;
static struct native_display *
native_create_display(void *dpy, boolean use_sw)
{
struct native_display *ndpy = NULL;
boolean force_sw;
force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
if (force_sw || use_sw) {
_eglLog(_EGL_INFO, "use software fallback");
ndpy = x11_create_ximage_display((Display *) dpy, x11_event_handler);
}
else {
ndpy = x11_create_dri2_display((Display *) dpy, x11_event_handler);
}
return ndpy;
}
static const struct native_platform x11_platform = {
"X11", /* name */
native_create_display
};
const struct native_platform *
native_get_x11_platform(const struct native_event_handler *event_handler)
{
x11_event_handler = event_handler;
return &x11_platform;
}
@@ -1,39 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _NATIVE_X11_H_
#define _NATIVE_X11_H_
#include "common/native.h"
#include <X11/Xlib.h>
struct native_display *
x11_create_ximage_display(Display *dpy,
const struct native_event_handler *event_handler);
struct native_display *
x11_create_dri2_display(Display *dpy,
const struct native_event_handler *event_handler);
#endif /* _NATIVE_X11_H_ */
@@ -1,587 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "pipe/p_compiler.h"
#include "util/u_inlines.h"
#include "state_tracker/xlibsw_api.h"
#include "sw/xlib/xlib_sw_winsys.h"
#include "util/u_debug.h"
#include "egllog.h"
#include "common/native_helper.h"
#include "native_x11.h"
#include "x11_screen.h"
struct ximage_display {
struct native_display base;
Display *dpy;
boolean own_dpy;
const struct native_event_handler *event_handler;
struct x11_screen *xscr;
int xscr_number;
struct ximage_config *configs;
int num_configs;
};
struct ximage_surface {
struct native_surface base;
Drawable drawable;
enum pipe_format color_format;
XVisualInfo visual;
struct ximage_display *xdpy;
unsigned int server_stamp;
unsigned int client_stamp;
struct resource_surface *rsurf;
struct xlib_drawable xdraw;
};
struct ximage_config {
struct native_config base;
const XVisualInfo *visual;
};
static INLINE struct ximage_display *
ximage_display(const struct native_display *ndpy)
{
return (struct ximage_display *) ndpy;
}
static INLINE struct ximage_surface *
ximage_surface(const struct native_surface *nsurf)
{
return (struct ximage_surface *) nsurf;
}
static INLINE struct ximage_config *
ximage_config(const struct native_config *nconf)
{
return (struct ximage_config *) nconf;
}
/**
* Update the geometry of the surface. This is a slow functions.
*/
static void
ximage_surface_update_geometry(struct native_surface *nsurf)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
Status ok;
Window root;
int x, y;
unsigned int w, h, border, depth;
ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
&root, &x, &y, &w, &h, &border, &depth);
if (ok && resource_surface_set_size(xsurf->rsurf, w, h))
xsurf->server_stamp++;
}
/**
* Update the buffers of the surface.
*/
static boolean
ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
if (xsurf->client_stamp != xsurf->server_stamp) {
ximage_surface_update_geometry(&xsurf->base);
xsurf->client_stamp = xsurf->server_stamp;
}
return resource_surface_add_resources(xsurf->rsurf, buffer_mask);
}
/**
* Emulate an invalidate event.
*/
static void
ximage_surface_invalidate(struct native_surface *nsurf)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
struct ximage_display *xdpy = xsurf->xdpy;
xsurf->server_stamp++;
xdpy->event_handler->invalid_surface(&xdpy->base,
&xsurf->base, xsurf->server_stamp);
}
static boolean
ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
boolean ret;
ret = resource_surface_present(xsurf->rsurf,
NATIVE_ATTACHMENT_FRONT_LEFT, (void *) &xsurf->xdraw);
/* force buffers to be updated in next validation call */
ximage_surface_invalidate(&xsurf->base);
return ret;
}
static boolean
ximage_surface_swap_buffers(struct native_surface *nsurf)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
boolean ret;
ret = resource_surface_present(xsurf->rsurf,
NATIVE_ATTACHMENT_BACK_LEFT, (void *) &xsurf->xdraw);
resource_surface_swap_buffers(xsurf->rsurf,
NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE);
/* the front/back buffers have been swapped */
ximage_surface_invalidate(&xsurf->base);
return ret;
}
static boolean
ximage_surface_present(struct native_surface *nsurf,
const struct native_present_control *ctrl)
{
boolean ret;
if (ctrl->preserve || ctrl->swap_interval)
return FALSE;
switch (ctrl->natt) {
case NATIVE_ATTACHMENT_FRONT_LEFT:
ret = ximage_surface_flush_frontbuffer(nsurf);
break;
case NATIVE_ATTACHMENT_BACK_LEFT:
ret = ximage_surface_swap_buffers(nsurf);
break;
default:
ret = FALSE;
break;
}
return ret;
}
static boolean
ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
unsigned int *seq_num, struct pipe_resource **textures,
int *width, int *height)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
uint w, h;
if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask))
return FALSE;
if (seq_num)
*seq_num = xsurf->client_stamp;
if (textures)
resource_surface_get_resources(xsurf->rsurf, textures, attachment_mask);
resource_surface_get_size(xsurf->rsurf, &w, &h);
if (width)
*width = w;
if (height)
*height = h;
return TRUE;
}
static void
ximage_surface_wait(struct native_surface *nsurf)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
XSync(xsurf->xdpy->dpy, FALSE);
/* TODO XGetImage and update the front texture */
}
static void
ximage_surface_destroy(struct native_surface *nsurf)
{
struct ximage_surface *xsurf = ximage_surface(nsurf);
resource_surface_destroy(xsurf->rsurf);
FREE(xsurf);
}
static struct ximage_surface *
ximage_display_create_surface(struct native_display *ndpy,
Drawable drawable,
const struct native_config *nconf)
{
struct ximage_display *xdpy = ximage_display(ndpy);
struct ximage_config *xconf = ximage_config(nconf);
struct ximage_surface *xsurf;
xsurf = CALLOC_STRUCT(ximage_surface);
if (!xsurf)
return NULL;
xsurf->xdpy = xdpy;
xsurf->color_format = xconf->base.color_format;
xsurf->drawable = drawable;
xsurf->rsurf = resource_surface_create(xdpy->base.screen,
xsurf->color_format,
PIPE_BIND_RENDER_TARGET |
PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT);
if (!xsurf->rsurf) {
FREE(xsurf);
return NULL;
}
xsurf->drawable = drawable;
xsurf->visual = *xconf->visual;
/* initialize the geometry */
ximage_surface_update_geometry(&xsurf->base);
xsurf->xdraw.visual = xsurf->visual.visual;
xsurf->xdraw.depth = xsurf->visual.depth;
xsurf->xdraw.drawable = xsurf->drawable;
xsurf->base.destroy = ximage_surface_destroy;
xsurf->base.present = ximage_surface_present;
xsurf->base.validate = ximage_surface_validate;
xsurf->base.wait = ximage_surface_wait;
return xsurf;
}
static struct native_surface *
ximage_display_create_window_surface(struct native_display *ndpy,
EGLNativeWindowType win,
const struct native_config *nconf)
{
struct ximage_surface *xsurf;
xsurf = ximage_display_create_surface(ndpy, (Drawable) win, nconf);
return (xsurf) ? &xsurf->base : NULL;
}
static enum pipe_format
get_pixmap_format(struct native_display *ndpy, EGLNativePixmapType pix)
{
struct ximage_display *xdpy = ximage_display(ndpy);
enum pipe_format fmt;
uint depth;
depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix);
switch (depth) {
case 32:
fmt = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
case 24:
fmt = PIPE_FORMAT_B8G8R8X8_UNORM;
break;
case 16:
fmt = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
fmt = PIPE_FORMAT_NONE;
break;
}
return fmt;
}
static struct native_surface *
ximage_display_create_pixmap_surface(struct native_display *ndpy,
EGLNativePixmapType pix,
const struct native_config *nconf)
{
struct ximage_surface *xsurf;
/* find the config */
if (!nconf) {
struct ximage_display *xdpy = ximage_display(ndpy);
enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix);
int i;
if (fmt != PIPE_FORMAT_NONE) {
for (i = 0; i < xdpy->num_configs; i++) {
if (xdpy->configs[i].base.color_format == fmt) {
nconf = &xdpy->configs[i].base;
break;
}
}
}
if (!nconf)
return NULL;
}
xsurf = ximage_display_create_surface(ndpy, (Drawable) pix, nconf);
return (xsurf) ? &xsurf->base : NULL;
}
static enum pipe_format
choose_format(const XVisualInfo *vinfo)
{
enum pipe_format fmt;
/* TODO elaborate the formats */
switch (vinfo->depth) {
case 32:
fmt = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
case 24:
fmt = PIPE_FORMAT_B8G8R8X8_UNORM;
break;
case 16:
fmt = PIPE_FORMAT_B5G6R5_UNORM;
break;
default:
fmt = PIPE_FORMAT_NONE;
break;
}
return fmt;
}
static const struct native_config **
ximage_display_get_configs(struct native_display *ndpy, int *num_configs)
{
struct ximage_display *xdpy = ximage_display(ndpy);
const struct native_config **configs;
int i;
/* first time */
if (!xdpy->configs) {
const XVisualInfo *visuals;
int num_visuals, count;
visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals);
if (!visuals)
return NULL;
/*
* Create two configs for each visual.
* One with depth/stencil buffer; one without
*/
xdpy->configs = CALLOC(num_visuals * 2, sizeof(*xdpy->configs));
if (!xdpy->configs)
return NULL;
count = 0;
for (i = 0; i < num_visuals; i++) {
struct ximage_config *xconf = &xdpy->configs[count];
xconf->visual = &visuals[i];
xconf->base.color_format = choose_format(xconf->visual);
if (xconf->base.color_format == PIPE_FORMAT_NONE)
continue;
xconf->base.buffer_mask =
(1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
(1 << NATIVE_ATTACHMENT_BACK_LEFT);
xconf->base.window_bit = TRUE;
xconf->base.pixmap_bit = TRUE;
xconf->base.native_visual_id = xconf->visual->visualid;
#if defined(__cplusplus) || defined(c_plusplus)
xconf->base.native_visual_type = xconf->visual->c_class;
#else
xconf->base.native_visual_type = xconf->visual->class;
#endif
count++;
}
xdpy->num_configs = count;
}
configs = MALLOC(xdpy->num_configs * sizeof(*configs));
if (configs) {
for (i = 0; i < xdpy->num_configs; i++)
configs[i] = (const struct native_config *) &xdpy->configs[i];
if (num_configs)
*num_configs = xdpy->num_configs;
}
return configs;
}
static boolean
ximage_display_get_pixmap_format(struct native_display *ndpy,
EGLNativePixmapType pix,
enum pipe_format *format)
{
struct ximage_display *xdpy = ximage_display(ndpy);
*format = get_pixmap_format(&xdpy->base, pix);
return (*format != PIPE_FORMAT_NONE);
}
static boolean
ximage_display_copy_to_pixmap(struct native_display *ndpy,
EGLNativePixmapType pix,
struct pipe_resource *src)
{
/* fast path to avoid unnecessary allocation and resource_copy_region */
if (src->bind & PIPE_BIND_DISPLAY_TARGET) {
struct ximage_display *xdpy = ximage_display(ndpy);
enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix);
const struct ximage_config *xconf = NULL;
struct xlib_drawable xdraw;
int i;
if (fmt == PIPE_FORMAT_NONE || src->format != fmt)
return FALSE;
for (i = 0; i < xdpy->num_configs; i++) {
if (xdpy->configs[i].base.color_format == fmt) {
xconf = &xdpy->configs[i];
break;
}
}
if (!xconf)
return FALSE;
memset(&xdraw, 0, sizeof(xdraw));
xdraw.visual = xconf->visual->visual;
xdraw.depth = xconf->visual->depth;
xdraw.drawable = (Drawable) pix;
xdpy->base.screen->flush_frontbuffer(xdpy->base.screen,
src, 0, 0, &xdraw, NULL);
return TRUE;
}
return native_display_copy_to_pixmap(ndpy, pix, src);
}
static int
ximage_display_get_param(struct native_display *ndpy,
enum native_param_type param)
{
int val;
switch (param) {
case NATIVE_PARAM_USE_NATIVE_BUFFER:
/* private buffers are allocated */
val = FALSE;
break;
case NATIVE_PARAM_PRESERVE_BUFFER:
case NATIVE_PARAM_MAX_SWAP_INTERVAL:
default:
val = 0;
break;
}
return val;
}
static void
ximage_display_destroy(struct native_display *ndpy)
{
struct ximage_display *xdpy = ximage_display(ndpy);
FREE(xdpy->configs);
ndpy_uninit(ndpy);
x11_screen_destroy(xdpy->xscr);
if (xdpy->own_dpy)
XCloseDisplay(xdpy->dpy);
FREE(xdpy);
}
static boolean
ximage_display_init_screen(struct native_display *ndpy)
{
struct ximage_display *xdpy = ximage_display(ndpy);
struct sw_winsys *winsys;
winsys = xlib_create_sw_winsys(xdpy->dpy);
if (!winsys)
return FALSE;
xdpy->base.screen =
xdpy->event_handler->new_sw_screen(&xdpy->base, winsys);
if (!xdpy->base.screen) {
if (winsys->destroy)
winsys->destroy(winsys);
return FALSE;
}
return TRUE;
}
struct native_display *
x11_create_ximage_display(Display *dpy,
const struct native_event_handler *event_handler)
{
struct ximage_display *xdpy;
xdpy = CALLOC_STRUCT(ximage_display);
if (!xdpy)
return NULL;
xdpy->dpy = dpy;
if (!xdpy->dpy) {
xdpy->dpy = XOpenDisplay(NULL);
if (!xdpy->dpy) {
FREE(xdpy);
return NULL;
}
xdpy->own_dpy = TRUE;
}
xdpy->event_handler = event_handler;
xdpy->xscr_number = DefaultScreen(xdpy->dpy);
xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number);
if (!xdpy->xscr) {
if (xdpy->own_dpy)
XCloseDisplay(xdpy->dpy);
FREE(xdpy);
return NULL;
}
xdpy->base.init_screen = ximage_display_init_screen;
xdpy->base.destroy = ximage_display_destroy;
xdpy->base.get_param = ximage_display_get_param;
xdpy->base.get_configs = ximage_display_get_configs;
xdpy->base.get_pixmap_format = ximage_display_get_pixmap_format;
xdpy->base.copy_to_pixmap = ximage_display_copy_to_pixmap;
xdpy->base.create_window_surface = ximage_display_create_window_surface;
xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface;
return &xdpy->base;
}
@@ -1,488 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <xf86drm.h>
#include <X11/Xlibint.h>
#include <X11/extensions/XShm.h>
#include "util/u_memory.h"
#include "egllog.h"
#include "x11_screen.h"
#include "dri2.h"
#include "glxinit.h"
struct x11_screen {
Display *dpy;
int number;
/*
* This is used to fetch GLX visuals/fbconfigs. It steals code from GLX.
* It might be better to rewrite the part in Xlib or XCB.
*/
__GLXdisplayPrivate *glx_dpy;
int dri_major, dri_minor;
char *dri_driver;
char *dri_device;
int dri_fd;
x11_drawable_invalidate_buffers dri_invalidate_buffers;
void *dri_user_data;
XVisualInfo *visuals;
int num_visuals;
/* cached values for x11_drawable_get_depth */
Drawable last_drawable;
unsigned int last_depth;
};
/**
* Create a X11 screen.
*/
struct x11_screen *
x11_screen_create(Display *dpy, int screen)
{
struct x11_screen *xscr;
if (screen >= ScreenCount(dpy))
return NULL;
xscr = CALLOC_STRUCT(x11_screen);
if (xscr) {
xscr->dpy = dpy;
xscr->number = screen;
xscr->dri_major = -1;
xscr->dri_fd = -1;
}
return xscr;
}
/**
* Destroy a X11 screen.
*/
void
x11_screen_destroy(struct x11_screen *xscr)
{
if (xscr->dri_fd >= 0)
close(xscr->dri_fd);
free(xscr->dri_driver);
free(xscr->dri_device);
#ifdef GLX_DIRECT_RENDERING
/* xscr->glx_dpy will be destroyed with the X display */
if (xscr->glx_dpy)
xscr->glx_dpy->xscr = NULL;
#endif
free(xscr->visuals);
FREE(xscr);
}
#ifdef GLX_DIRECT_RENDERING
static boolean
x11_screen_init_dri2(struct x11_screen *xscr)
{
if (xscr->dri_major < 0) {
int eventBase, errorBase;
if (!DRI2QueryExtension(xscr->dpy, &eventBase, &errorBase) ||
!DRI2QueryVersion(xscr->dpy, &xscr->dri_major, &xscr->dri_minor))
xscr->dri_major = -1;
}
return (xscr->dri_major >= 0);
}
static boolean
x11_screen_init_glx(struct x11_screen *xscr)
{
if (!xscr->glx_dpy)
xscr->glx_dpy = __glXInitialize(xscr->dpy);
return (xscr->glx_dpy != NULL);
}
#endif /* GLX_DIRECT_RENDERING */
/**
* Return true if the screen supports the extension.
*/
boolean
x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext)
{
boolean supported = FALSE;
switch (ext) {
case X11_SCREEN_EXTENSION_XSHM:
supported = XShmQueryExtension(xscr->dpy);
break;
#ifdef GLX_DIRECT_RENDERING
case X11_SCREEN_EXTENSION_GLX:
supported = x11_screen_init_glx(xscr);
break;
case X11_SCREEN_EXTENSION_DRI2:
supported = x11_screen_init_dri2(xscr);
break;
#endif
default:
break;
}
return supported;
}
/**
* Return the X visuals.
*/
const XVisualInfo *
x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals)
{
if (!xscr->visuals) {
XVisualInfo vinfo_template;
vinfo_template.screen = xscr->number;
xscr->visuals = XGetVisualInfo(xscr->dpy, VisualScreenMask,
&vinfo_template, &xscr->num_visuals);
}
if (num_visuals)
*num_visuals = xscr->num_visuals;
return xscr->visuals;
}
/**
* Return the depth of a drawable.
*
* Unlike other drawable functions, the drawable needs not be a DRI2 drawable.
*/
uint
x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable)
{
unsigned int depth;
if (drawable != xscr->last_drawable) {
Window root;
int x, y;
unsigned int w, h, border;
Status ok;
ok = XGetGeometry(xscr->dpy, drawable, &root,
&x, &y, &w, &h, &border, &depth);
if (!ok)
depth = 0;
xscr->last_drawable = drawable;
xscr->last_depth = depth;
}
else {
depth = xscr->last_depth;
}
return depth;
}
#ifdef GLX_DIRECT_RENDERING
/**
* Return the GLX fbconfigs.
*/
const __GLcontextModes *
x11_screen_get_glx_configs(struct x11_screen *xscr)
{
return (x11_screen_init_glx(xscr))
? xscr->glx_dpy->screenConfigs[xscr->number]->configs
: NULL;
}
/**
* Probe the screen for the DRI2 driver name.
*/
const char *
x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor)
{
if (!x11_screen_init_dri2(xscr))
return NULL;
/* get the driver name and the device name */
if (!xscr->dri_driver) {
if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number),
&xscr->dri_driver, &xscr->dri_device))
xscr->dri_driver = xscr->dri_device = NULL;
}
if (major)
*major = xscr->dri_major;
if (minor)
*minor = xscr->dri_minor;
return xscr->dri_driver;
}
/**
* Enable DRI2 and returns the file descriptor of the DRM device. The file
* descriptor will be closed automatically when the screen is destoryed.
*/
int
x11_screen_enable_dri2(struct x11_screen *xscr,
x11_drawable_invalidate_buffers invalidate_buffers,
void *user_data)
{
if (xscr->dri_fd < 0) {
int fd;
drm_magic_t magic;
/* get the driver name and the device name first */
if (!x11_screen_probe_dri2(xscr, NULL, NULL))
return -1;
#ifdef O_CLOEXEC
fd = open(xscr->dri_device, O_RDWR | O_CLOEXEC);
if (fd == -1 && errno == EINVAL)
#endif
{
fd = open(xscr->dri_device, O_RDWR);
if (fd != -1)
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
}
if (fd < 0) {
_eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
return -1;
}
memset(&magic, 0, sizeof(magic));
if (drmGetMagic(fd, &magic)) {
_eglLog(_EGL_WARNING, "failed to get magic");
close(fd);
return -1;
}
if (!DRI2Authenticate(xscr->dpy,
RootWindow(xscr->dpy, xscr->number), magic)) {
_eglLog(_EGL_WARNING, "failed to authenticate magic");
close(fd);
return -1;
}
if (!x11_screen_init_glx(xscr)) {
_eglLog(_EGL_WARNING, "failed to initialize GLX");
close(fd);
return -1;
}
if (xscr->glx_dpy->xscr) {
_eglLog(_EGL_WARNING,
"display is already managed by another x11 screen");
close(fd);
return -1;
}
xscr->glx_dpy->xscr = xscr;
xscr->dri_invalidate_buffers = invalidate_buffers;
xscr->dri_user_data = user_data;
xscr->dri_fd = fd;
}
return xscr->dri_fd;
}
char *
x11_screen_get_device_name(struct x11_screen *xscr)
{
return xscr->dri_device;
}
int
x11_screen_authenticate(struct x11_screen *xscr, uint32_t id)
{
boolean authenticated;
authenticated = DRI2Authenticate(xscr->dpy,
RootWindow(xscr->dpy, xscr->number), id);
return authenticated ? 0 : -1;
}
/**
* Create/Destroy the DRI drawable.
*/
void
x11_drawable_enable_dri2(struct x11_screen *xscr,
Drawable drawable, boolean on)
{
if (on)
DRI2CreateDrawable(xscr->dpy, drawable);
else
DRI2DestroyDrawable(xscr->dpy, drawable);
}
/**
* Copy between buffers of the DRI2 drawable.
*/
void
x11_drawable_copy_buffers_region(struct x11_screen *xscr, Drawable drawable,
int num_rects, const int *rects,
int src_buf, int dst_buf)
{
XserverRegion region;
XRectangle *rectangles = CALLOC(num_rects, sizeof(XRectangle));
for (int i = 0; i < num_rects; i++) {
rectangles[i].x = rects[i * 4 + 0];
rectangles[i].y = rects[i * 4 + 1];
rectangles[i].width = rects[i * 4 + 2];
rectangles[i].height = rects[i * 4 + 3];
}
region = XFixesCreateRegion(xscr->dpy, rectangles, num_rects);
DRI2CopyRegion(xscr->dpy, drawable, region, dst_buf, src_buf);
XFixesDestroyRegion(xscr->dpy, region);
FREE(rectangles);
}
/**
* Get the buffers of the DRI2 drawable. The returned array should be freed.
*/
struct x11_drawable_buffer *
x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
int *width, int *height, unsigned int *attachments,
boolean with_format, int num_ins, int *num_outs)
{
DRI2Buffer *dri2bufs;
if (with_format)
dri2bufs = DRI2GetBuffersWithFormat(xscr->dpy, drawable, width, height,
attachments, num_ins, num_outs);
else
dri2bufs = DRI2GetBuffers(xscr->dpy, drawable, width, height,
attachments, num_ins, num_outs);
return (struct x11_drawable_buffer *) dri2bufs;
}
/**
* Create a mode list of the given size.
*/
__GLcontextModes *
x11_context_modes_create(unsigned count)
{
const size_t size = sizeof(__GLcontextModes);
__GLcontextModes *base = NULL;
__GLcontextModes **next;
unsigned i;
next = &base;
for (i = 0; i < count; i++) {
*next = (__GLcontextModes *) CALLOC(1, size);
if (*next == NULL) {
x11_context_modes_destroy(base);
base = NULL;
break;
}
next = &((*next)->next);
}
return base;
}
/**
* Destroy a mode list.
*/
void
x11_context_modes_destroy(__GLcontextModes *modes)
{
while (modes != NULL) {
__GLcontextModes *next = modes->next;
FREE(modes);
modes = next;
}
}
/**
* Return the number of the modes in the mode list.
*/
unsigned
x11_context_modes_count(const __GLcontextModes *modes)
{
const __GLcontextModes *mode;
int count = 0;
for (mode = modes; mode; mode = mode->next)
count++;
return count;
}
extern void
dri2InvalidateBuffers(Display *dpy, XID drawable);
/**
* This is called from src/glx/dri2.c.
*/
void
dri2InvalidateBuffers(Display *dpy, XID drawable)
{
__GLXdisplayPrivate *priv = __glXInitialize(dpy);
struct x11_screen *xscr = NULL;
if (priv && priv->xscr)
xscr = priv->xscr;
if (!xscr || !xscr->dri_invalidate_buffers)
return;
xscr->dri_invalidate_buffers(xscr, drawable, xscr->dri_user_data);
}
extern unsigned
dri2GetSwapEventType(Display *dpy, XID drawable);
extern void *
dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id);
extern void *
GetGLXDrawable(Display *dpy, XID drawable);
/**
* This is also called from src/glx/dri2.c.
*/
unsigned dri2GetSwapEventType(Display *dpy, XID drawable)
{
return 0;
}
void *
dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id)
{
return NULL;
}
void *
GetGLXDrawable(Display *dpy, XID drawable)
{
return NULL;
}
#endif /* GLX_DIRECT_RENDERING */
@@ -1,133 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _X11_SCREEN_H_
#define _X11_SCREEN_H_
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/dri2tokens.h>
#include "GL/gl.h" /* for GL types needed by __GLcontextModes */
#include "glcore.h" /* for __GLcontextModes */
#include "pipe/p_compiler.h"
#include "common/native.h"
enum x11_screen_extension {
X11_SCREEN_EXTENSION_XSHM,
X11_SCREEN_EXTENSION_GLX,
X11_SCREEN_EXTENSION_DRI2,
};
/* the same as DRI2Buffer */
struct x11_drawable_buffer {
unsigned int attachment;
unsigned int name;
unsigned int pitch;
unsigned int cpp;
unsigned int flags;
};
struct x11_screen;
typedef void (*x11_drawable_invalidate_buffers)(struct x11_screen *xscr,
Drawable drawable,
void *user_data);
struct x11_screen *
x11_screen_create(Display *dpy, int screen);
void
x11_screen_destroy(struct x11_screen *xscr);
boolean
x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext);
const XVisualInfo *
x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals);
uint
x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable);
#ifdef GLX_DIRECT_RENDERING
/* GLX */
const __GLcontextModes *
x11_screen_get_glx_configs(struct x11_screen *xscr);
const __GLcontextModes *
x11_screen_get_glx_visuals(struct x11_screen *xscr);
__GLcontextModes *
x11_context_modes_create(unsigned count);
void
x11_context_modes_destroy(__GLcontextModes *modes);
unsigned
x11_context_modes_count(const __GLcontextModes *modes);
/* DRI2 */
const char *
x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor);
int
x11_screen_enable_dri2(struct x11_screen *xscr,
x11_drawable_invalidate_buffers invalidate_buffers,
void *user_data);
char *
x11_screen_get_device_name(struct x11_screen *xscr);
int
x11_screen_authenticate(struct x11_screen *xscr, uint32_t id);
void
x11_drawable_enable_dri2(struct x11_screen *xscr,
Drawable drawable, boolean on);
void
x11_drawable_copy_buffers_region(struct x11_screen *xscr, Drawable drawable,
int num_rects, const int *rects,
int src_buf, int dst_buf);
/**
* Copy between buffers of the DRI2 drawable.
*/
static INLINE void
x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
int x, int y, int width, int height,
int src_buf, int dst_buf)
{
int rect[4] = { x, y, width, height };
x11_drawable_copy_buffers_region(xscr, drawable, 1, rect, src_buf, dst_buf);
}
struct x11_drawable_buffer *
x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
int *width, int *height, unsigned int *attachments,
boolean with_format, int num_ins, int *num_outs);
#endif /* GLX_DIRECT_RENDERING */
#endif /* _X11_SCREEN_H_ */
-81
View File
@@ -1,81 +0,0 @@
# Mesa 3-D graphics library
#
# Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
# Copyright (C) 2010-2011 LunarG Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
egl.c \
egl_pipe.c \
egl_st.c
LOCAL_CFLAGS := \
-DFEATURE_ES1=1 \
-DFEATURE_ES2=1 \
-D_EGL_MAIN=_eglBuiltInDriverGALLIUM
LOCAL_C_INCLUDES := \
$(GALLIUM_TOP)/state_trackers/vega \
$(GALLIUM_TOP)/state_trackers/egl \
$(MESA_TOP)/src/egl/main \
$(MESA_TOP)/src/loader \
$(MESA_TOP)/src/mesa
# swrast
LOCAL_CFLAGS += -DGALLIUM_SOFTPIPE
# !swrast only
ifneq ($(MESA_GPU_DRIVERS),swrast)
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/libdrm
endif
ifneq ($(filter freedreno, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_FREEDRENO
endif
ifneq ($(filter i915g, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_I915
endif
ifneq ($(filter ilo, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_ILO
endif
ifneq ($(filter nouveau, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_NOUVEAU
endif
ifneq ($(filter r300g, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_R300
endif
ifneq ($(filter r600g, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_R600
endif
ifneq ($(filter radeonsi, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_RADEONSI
endif
ifneq ($(filter vmwgfx, $(MESA_GPU_DRIVERS)),)
LOCAL_CFLAGS += -DGALLIUM_VMWGFX
endif
LOCAL_MODULE := libmesa_egl_gallium
include $(GALLIUM_COMMON_MK)
include $(BUILD_STATIC_LIBRARY)
-210
View File
@@ -1,210 +0,0 @@
# Copyright © 2012 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
# This is Makefile for egl_gallium.so. It is static in that all state trackers
# and pipe drivers are linked statically when possible.
#
# The following variables are examined
#
# EGL_CLIENT_APIS - state trackers to support
# GALLIUM_WINSYS_DIRS - pipe drivers to support
#
include $(top_srcdir)/src/gallium/Automake.inc
AM_CFLAGS = \
$(GALLIUM_TARGET_CFLAGS) \
$(MSVC2013_COMPAT_CFLAGS)
AM_CPPFLAGS = \
-I$(top_srcdir)/src/gallium/state_trackers/egl \
-I$(top_srcdir)/src/egl/main \
-DGALLIUM_TRACE \
-DGALLIUM_RBUG \
-D_EGL_MAIN=_eglMain
AM_LDFLAGS = \
-module \
-no-undefined \
-avoid-version \
$(GC_SECTIONS) \
$(LD_NO_UNDEFINED)
if HAVE_LD_VERSION_SCRIPT
AM_LDFLAGS += \
-Wl,--version-script=$(top_srcdir)/src/gallium/targets/egl-static/egl.sym
endif
egldir = $(libdir)/egl
egl_LTLIBRARIES = egl_gallium.la
nodist_EXTRA_egl_gallium_la_SOURCES = dummy.cpp
egl_gallium_la_SOURCES = \
egl.c \
egl_pipe.c \
egl_pipe.h \
egl_st.c \
egl_st.h
egl_gallium_la_LIBADD = \
$(top_builddir)/src/loader/libloader.la \
$(top_builddir)/src/gallium/auxiliary/libgalliumvl_stub.la \
$(top_builddir)/src/gallium/auxiliary/libgallium.la \
$(top_builddir)/src/gallium/drivers/trace/libtrace.la \
$(top_builddir)/src/gallium/drivers/rbug/librbug.la \
$(top_builddir)/src/gallium/state_trackers/egl/libegl.la \
$(top_builddir)/src/egl/main/libEGL.la \
$(GALLIUM_COMMON_LIB_DEPS)
if HAVE_EGL_PLATFORM_X11
AM_CPPFLAGS += $(LIBDRM_CFLAGS)
egl_gallium_la_LIBADD += \
$(top_builddir)/src/gallium/winsys/sw/xlib/libws_xlib.la \
-lX11 -lXext -lXfixes $(LIBDRM_LIBS)
endif
if HAVE_EGL_PLATFORM_WAYLAND
AM_CPPFLAGS += $(LIBDRM_CFLAGS)
egl_gallium_la_LIBADD += \
$(top_builddir)/src/gallium/winsys/sw/wayland/libws_wayland.la \
$(top_builddir)/src/egl/wayland/wayland-drm/libwayland-drm.la \
$(LIBDRM_LIBS) \
$(WAYLAND_LIBS)
endif
if HAVE_EGL_PLATFORM_DRM
AM_CPPFLAGS += $(LIBDRM_CFLAGS)
egl_gallium_la_LIBADD += \
$(top_builddir)/src/gbm/libgbm.la \
$(LIBDRM_LIBS)
endif
if HAVE_EGL_PLATFORM_FBDEV
egl_gallium_la_LIBADD += $(top_builddir)/src/gallium/winsys/sw/fbdev/libfbdev.la
endif
if HAVE_EGL_PLATFORM_NULL
egl_gallium_la_LIBADD += $(top_builddir)/src/gallium/winsys/sw/null/libws_null.la
endif
if HAVE_OPENGL
AM_CPPFLAGS += \
-I$(top_srcdir)/src/mesa \
-DFEATURE_GL=1
egl_gallium_la_LIBADD += \
$(top_builddir)/src/mesa/libmesagallium.la
# make st/mesa built-in when there is a single glapi provider
if HAVE_SHARED_GLAPI
egl_gallium_la_LIBADD += \
$(top_builddir)/src/mapi/shared-glapi/libglapi.la
else
egl_gallium_la_LIBADD += \
$(top_builddir)/src/mapi/glapi/libglapi.la
AM_CPPFLAGS += -D_EGL_EXTERNAL_GL=1
egl_LTLIBRARIES += st_GL.la
nodist_EXTRA_st_GL_la_SOURCES = dummy.cpp
st_GL_la_SOURCES = st_GL.c
# st_GL, built only when shared glapi is not enabled
st_GL_la_LIBADD = \
$(top_builddir)/src/mesa/libmesagallium.la \
$(top_builddir)/src/gallium/auxiliary/libgallium.la \
$(top_builddir)/src/mapi/glapi/libglapi.la \
$(GALLIUM_COMMON_LIB_DEPS)
endif
endif
if HAVE_OPENGL_ES1
AM_CPPFLAGS += \
-DFEATURE_ES1=1
endif
if HAVE_OPENGL_ES2
AM_CPPFLAGS += \
-DFEATURE_ES2=1
endif
if HAVE_OPENVG
AM_CPPFLAGS += \
-I$(top_srcdir)/src/gallium/state_trackers/vega \
-DFEATURE_VG=1
egl_gallium_la_LIBADD += \
$(top_builddir)/src/gallium/state_trackers/vega/libvega.la \
$(top_builddir)/src/mapi/vgapi/libOpenVG.la
endif
EXTRA_egl_gallium_la_DEPENDENCIES = egl.sym
EXTRA_DIST = SConscript
#if HAVE_GALLIUM_STATIC_TARGETS
TARGET_DRIVERS =
TARGET_CPPFLAGS =
TARGET_LIB_DEPS =
include $(top_srcdir)/src/gallium/drivers/i915/Automake.inc
include $(top_srcdir)/src/gallium/drivers/ilo/Automake.inc
include $(top_srcdir)/src/gallium/drivers/nouveau/Automake.inc
include $(top_srcdir)/src/gallium/drivers/r300/Automake.inc
include $(top_srcdir)/src/gallium/drivers/r600/Automake.inc
include $(top_srcdir)/src/gallium/drivers/radeonsi/Automake.inc
include $(top_srcdir)/src/gallium/drivers/svga/Automake.inc
include $(top_srcdir)/src/gallium/drivers/freedreno/Automake.inc
include $(top_srcdir)/src/gallium/drivers/softpipe/Automake.inc
include $(top_srcdir)/src/gallium/drivers/llvmpipe/Automake.inc
egl_gallium_la_CPPFLAGS = $(AM_CPPFLAGS) $(TARGET_CPPFLAGS)
egl_gallium_la_LIBADD += $(TARGET_LIB_DEPS) \
$(TARGET_RADEON_WINSYS) $(TARGET_RADEON_COMMON)
#else # HAVE_GALLIUM_STATIC_TARGETS
#egl_gallium_la_LIBADD += \
# $(top_builddir)/src/gallium/auxiliary/pipe-loader/libpipe_loader.la \
# $(GALLIUM_PIPE_LOADER_WINSYS_LIBS) \
# $(GALLIUM_PIPE_LOADER_LIBS)
#endif
if HAVE_MESA_LLVM
AM_LDFLAGS += $(LLVM_LDFLAGS)
egl_gallium_la_LIBADD += $(LLVM_LIBS)
if HAVE_OPENGL
if !HAVE_SHARED_GLAPI
st_GL_la_LIBADD += $(LLVM_LIBS)
endif
endif
endif
include $(top_srcdir)/install-gallium-links.mk
-114
View File
@@ -1,114 +0,0 @@
#######################################################################
# SConscript for egl-static target
Import('*')
env = env.Clone()
env.Append(CPPPATH = [
'#/include',
'#/src/loader',
'#/src/egl/main',
'#/src/gallium/auxiliary',
'#/src/gallium/drivers',
'#/src/gallium/include',
'#/src/gallium/winsys',
'#/src/gallium/state_trackers/egl',
'#/src/gallium/state_trackers/vega',
'#/src/mesa',
])
env.Append(CPPDEFINES = [
'GALLIUM_SOFTPIPE',
'GALLIUM_RBUG',
'GALLIUM_TRACE',
'GALLIUM_GALAHAD',
'_EGL_MAIN=_eglBuiltInDriverGALLIUM',
])
env.Prepend(LIBS = [
softpipe,
rbug,
trace,
galahad,
libloader,
mesautil,
gallium,
egl,
st_egl,
])
if env['llvm']:
env.Append(CPPDEFINES = ['GALLIUM_LLVMPIPE'])
env.Prepend(LIBS = [llvmpipe])
sources = [
'egl.c',
'egl_pipe.c',
'egl_st.c',
]
if env['platform'] == 'windows':
sources.append('#src/egl/main/egl.def')
env.Append(LIBS = [
'gdi32',
'user32',
'kernel32',
'ws2_32',
])
env.Prepend(LIBS = [
ws_gdi,
])
# OpenGL ES and OpenGL
if env['gles']:
env.Append(CPPDEFINES = [
'FEATURE_GL=1',
'FEATURE_ES1=1',
'FEATURE_ES2=1'
])
env.Prepend(LIBPATH = [shared_glapi.dir])
# manually add LIBPREFIX on windows
glapi_name = 'glapi' if env['platform'] != 'windows' else 'libglapi'
env.Prepend(LIBS = [glapi_name, glsl, mesa])
# OpenVG
if True:
env.Append(CPPDEFINES = ['FEATURE_VG=1'])
env.Prepend(LIBPATH = [openvg.dir])
# manually add LIBPREFIX on windows
openvg_name = 'OpenVG' if env['platform'] != 'windows' else 'libOpenVG'
env.Prepend(LIBS = [openvg_name, st_vega])
if env['HAVE_X11']:
env.Prepend(LIBS = [
ws_xlib,
])
env.PkgUseModules('X11')
# pipe drivers
if env['HAVE_DRM']:
env.PkgUseModules('DRM')
env.Append(CPPDEFINES = ['GALLIUM_VMWGFX'])
env.Prepend(LIBS = [
svgadrm,
svga,
])
# libEGL.dll
env['LIBPREFIX'] = 'lib'
env['SHLIBPREFIX'] = 'lib'
egl_gallium = env.SharedLibrary(
target ='EGL',
source = sources,
)
env.Depends(egl_gallium, [openvg])
egl_gallium = env.InstallSharedLibrary(egl_gallium, version=(1, 4, 0))
env.Alias('egl-gallium', egl_gallium)
-122
View File
@@ -1,122 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010-2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "common/egl_g3d_loader.h"
#include "egldriver.h"
#include "egllog.h"
#include "loader.h"
#include "egl_pipe.h"
#include "egl_st.h"
#include "target-helpers/inline_drm_helper.h"
static struct egl_g3d_loader egl_g3d_loader;
static struct st_module {
boolean initialized;
struct st_api *stapi;
} st_modules[ST_API_COUNT];
static struct st_api *
get_st_api(enum st_api_type api)
{
struct st_module *stmod = &st_modules[api];
if (!stmod->initialized) {
stmod->stapi = egl_st_create_api(api);
stmod->initialized = TRUE;
}
return stmod->stapi;
}
static struct pipe_screen *
create_drm_screen(const char *constname, int fd)
{
return dd_create_screen(fd);
}
static struct pipe_screen *
create_sw_screen(struct sw_winsys *ws)
{
return egl_pipe_create_swrast_screen(ws);
}
static const struct egl_g3d_loader *
loader_init(void)
{
egl_g3d_loader.get_st_api = get_st_api;
egl_g3d_loader.create_drm_screen = create_drm_screen;
egl_g3d_loader.create_sw_screen = create_sw_screen;
loader_set_logger(_eglLog);
return &egl_g3d_loader;
}
static void
loader_fini(void)
{
int i;
for (i = 0; i < ST_API_COUNT; i++) {
struct st_module *stmod = &st_modules[i];
if (stmod->stapi) {
egl_st_destroy_api(stmod->stapi);
stmod->stapi = NULL;
}
stmod->initialized = FALSE;
}
}
static void
egl_g3d_unload(_EGLDriver *drv)
{
egl_g3d_destroy_driver(drv);
loader_fini();
}
_EGLDriver *
_EGL_MAIN(const char *args)
{
const struct egl_g3d_loader *loader;
_EGLDriver *drv;
loader = loader_init();
drv = egl_g3d_create_driver(loader);
if (!drv) {
loader_fini();
return NULL;
}
drv->Name = "Gallium";
drv->Unload = egl_g3d_unload;
return drv;
}
-6
View File
@@ -1,6 +0,0 @@
{
global:
_eglMain;
local:
*;
};
-41
View File
@@ -1,41 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "target-helpers/inline_debug_helper.h"
#include "target-helpers/inline_sw_helper.h"
#include "egl_pipe.h"
struct pipe_screen *
egl_pipe_create_swrast_screen(struct sw_winsys *ws)
{
struct pipe_screen *screen;
screen = sw_screen_create(ws);
if (screen)
screen = debug_screen_wrap(screen);
return screen;
}
-36
View File
@@ -1,36 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _EGL_PIPE_H_
#define _EGL_PIPE_H_
struct pipe_screen;
struct sw_winsys;
struct pipe_screen *
egl_pipe_create_swrast_screen(struct sw_winsys *ws);
#endif /* _EGL_PIPE_H_ */
-167
View File
@@ -1,167 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "util/u_debug.h"
#include "state_tracker/st_api.h"
#include "egl_st.h"
#if FEATURE_GL || FEATURE_ES1 || FEATURE_ES2
#include "state_tracker/st_gl_api.h"
#endif
#if FEATURE_VG
#include "vg_api.h"
#endif
#if _EGL_EXTERNAL_GL
#include "util/u_string.h"
#include "util/u_dl.h"
#include "egldriver.h"
#include "egllog.h"
static struct util_dl_library *egl_st_gl_lib;
static EGLBoolean
dlopen_gl_lib_cb(const char *dir, size_t len, void *callback_data)
{
const char *name = (const char *) callback_data;
char path[1024];
int ret;
if (len) {
assert(len <= INT_MAX && "path is insanely long!");
ret = util_snprintf(path, sizeof(path), "%.*s/%s" UTIL_DL_EXT,
(int)len, dir, name);
}
else {
ret = util_snprintf(path, sizeof(path), "%s" UTIL_DL_EXT, name);
}
if (ret > 0 && ret < sizeof(path)) {
egl_st_gl_lib = util_dl_open(path);
if (egl_st_gl_lib)
_eglLog(_EGL_DEBUG, "loaded %s", path);
}
return !egl_st_gl_lib;
}
static struct st_api *
load_gl(const char *name, const char *procname)
{
struct st_api *(*create_api)(void);
struct st_api *stapi = NULL;
_eglSearchPathForEach(dlopen_gl_lib_cb, (void *) name);
if (!egl_st_gl_lib)
return NULL;
create_api = (struct st_api *(*)(void))
util_dl_get_proc_address(egl_st_gl_lib, procname);
if (create_api)
stapi = create_api();
if (!stapi) {
util_dl_close(egl_st_gl_lib);
egl_st_gl_lib = NULL;
}
return stapi;
}
static struct st_api *
egl_st_load_gl(void)
{
const char module[] = "st_GL";
const char symbol[] = "st_api_create_OpenGL";
struct st_api *stapi;
stapi = load_gl(module, symbol);
/* try again with libglapi.so loaded */
if (!stapi) {
struct util_dl_library *glapi = util_dl_open("libglapi" UTIL_DL_EXT);
if (glapi) {
_eglLog(_EGL_DEBUG, "retry with libglapi" UTIL_DL_EXT " loaded");
stapi = load_gl(module, symbol);
util_dl_close(glapi);
}
}
if (!stapi)
_eglLog(_EGL_WARNING, "unable to load %s" UTIL_DL_EXT, module);
return stapi;
}
#endif /* _EGL_EXTERNAL_GL */
struct st_api *
egl_st_create_api(enum st_api_type api)
{
struct st_api *stapi = NULL;
switch (api) {
case ST_API_OPENGL:
#if FEATURE_GL || FEATURE_ES1 || FEATURE_ES2
#if _EGL_EXTERNAL_GL
stapi = egl_st_load_gl();
#else
stapi = st_gl_api_create();
#endif
#endif
break;
case ST_API_OPENVG:
#if FEATURE_VG
stapi = (struct st_api *) vg_api_get();
#endif
break;
default:
assert(!"Unknown API Type\n");
break;
}
return stapi;
}
void
egl_st_destroy_api(struct st_api *stapi)
{
#if _EGL_EXTERNAL_GL
boolean is_gl = (stapi->api == ST_API_OPENGL);
stapi->destroy(stapi);
if (is_gl) {
util_dl_close(egl_st_gl_lib);
egl_st_gl_lib = NULL;
}
#else
stapi->destroy(stapi);
#endif
}
-39
View File
@@ -1,39 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _EGL_ST_H_
#define _EGL_ST_H_
#include "pipe/p_compiler.h"
#include "state_tracker/st_api.h"
struct st_api *
egl_st_create_api(enum st_api_type api);
void
egl_st_destroy_api(struct st_api *stapi);
#endif /* _EGL_ST_H_ */
-37
View File
@@ -1,37 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2011 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "state_tracker/st_gl_api.h"
#include "pipe/p_compiler.h"
PUBLIC struct st_api *
st_api_create_OpenGL(void);
struct st_api *
st_api_create_OpenGL(void)
{
return st_gl_api_create();
}