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:
+3
-26
@@ -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_<hw></code>) and client API modules
|
||||
(<code>st_<api></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>
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ TBD.
|
||||
|
||||
<ul>
|
||||
<li>Removed classic Windows software rasterizer.</li>
|
||||
<li>Removed egl_gallium EGL driver.</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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, ®istry_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, ®istry_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
|
||||
@@ -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_ */
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
global:
|
||||
_eglMain;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user