Compare commits
104 Commits
android-x8
...
mesa_7_6_r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc8084932c | ||
|
|
54107a0979 | ||
|
|
940ca2e837 | ||
|
|
1730b8db12 | ||
|
|
726a04a2cd | ||
|
|
a9a47afe7e | ||
|
|
9018a7dd17 | ||
|
|
601769a2c0 | ||
|
|
60b152a1b3 | ||
|
|
adfa778c8e | ||
|
|
b849c6f1b3 | ||
|
|
f0339f502c | ||
|
|
964792b025 | ||
|
|
1a81611725 | ||
|
|
1d2dca194c | ||
|
|
7549a8397b | ||
|
|
a64d4516a0 | ||
|
|
a491e25b1f | ||
|
|
00ddd4f9e9 | ||
|
|
e44c084be5 | ||
|
|
2058dfaa47 | ||
|
|
639fb1472d | ||
|
|
28308c9260 | ||
|
|
ed91d10347 | ||
|
|
48559c7605 | ||
|
|
095db818c6 | ||
|
|
ec14d59afa | ||
|
|
dbec27be85 | ||
|
|
2cd2dc34ac | ||
|
|
9437ac9bcc | ||
|
|
93a7ea6ba0 | ||
|
|
7f5a958c80 | ||
|
|
9edd1a441c | ||
|
|
6552a103f9 | ||
|
|
65b01d449c | ||
|
|
b1e417413f | ||
|
|
cbab3d7f2a | ||
|
|
84c7afd9e0 | ||
|
|
2acd5de226 | ||
|
|
890f37d4d9 | ||
|
|
ad935c3f47 | ||
|
|
be66ff51ec | ||
|
|
e41707beca | ||
|
|
84b956c29b | ||
|
|
926b965ed5 | ||
|
|
f338de4018 | ||
|
|
ba002eb196 | ||
|
|
bc75464760 | ||
|
|
52cadf7592 | ||
|
|
8cc12ffb34 | ||
|
|
e857303305 | ||
|
|
6559eaef59 | ||
|
|
2655d43756 | ||
|
|
44d260329e | ||
|
|
ff5535c521 | ||
|
|
db928a5e91 | ||
|
|
ab4ec85f6c | ||
|
|
2b83483fb4 | ||
|
|
5a0b29050f | ||
|
|
077e3de989 | ||
|
|
526430ade1 | ||
|
|
736e1ae42f | ||
|
|
1d4dbd8d9b | ||
|
|
999592745f | ||
|
|
284a7af274 | ||
|
|
7e3b8b0d8f | ||
|
|
3640e4acde | ||
|
|
5fa9a7a9a9 | ||
|
|
94a3c5979f | ||
|
|
82c2f7756a | ||
|
|
e617dd14ab | ||
|
|
c4ce6f6a7c | ||
|
|
c8c5de9e9a | ||
|
|
6c323a2473 | ||
|
|
1e4c353511 | ||
|
|
a66bab0e37 | ||
|
|
fac38e8c8f | ||
|
|
9666529b5a | ||
|
|
08d39251a7 | ||
|
|
cfa1a0a609 | ||
|
|
88e3a57605 | ||
|
|
2921a2555d | ||
|
|
76e836a41a | ||
|
|
d9ddbc3f47 | ||
|
|
41fff1b9a1 | ||
|
|
6681981fe1 | ||
|
|
3ad108b77f | ||
|
|
f42c66c138 | ||
|
|
81de9d68f7 | ||
|
|
6c6fe0a704 | ||
|
|
1f309c40b8 | ||
|
|
5d526ed21a | ||
|
|
2b992dc327 | ||
|
|
799631acb1 | ||
|
|
ac3c8e3b53 | ||
|
|
3129b2403e | ||
|
|
b8b774c775 | ||
|
|
2729db8976 | ||
|
|
1402ea8f39 | ||
|
|
9c8b69302c | ||
|
|
280933f793 | ||
|
|
d81086a86b | ||
|
|
0fa1692f14 | ||
|
|
796c96de80 |
@@ -1 +0,0 @@
|
||||
include $(call all-subdir-makefiles)
|
||||
24
Makefile
24
Makefile
@@ -105,8 +105,6 @@ irix6-n32-static \
|
||||
irix6-o32 \
|
||||
irix6-o32-static \
|
||||
linux \
|
||||
mine \
|
||||
mine-dri \
|
||||
linux-alpha \
|
||||
linux-alpha-static \
|
||||
linux-cell \
|
||||
@@ -184,7 +182,7 @@ ultrix-gcc:
|
||||
|
||||
# Rules for making release tarballs
|
||||
|
||||
VERSION=7.7-devel
|
||||
VERSION=7.6-devel
|
||||
DIRECTORY = Mesa-$(VERSION)
|
||||
LIB_NAME = MesaLib-$(VERSION)
|
||||
DEMO_NAME = MesaDemos-$(VERSION)
|
||||
@@ -305,25 +303,10 @@ MAIN_FILES = \
|
||||
$(DIRECTORY)/progs/util/sampleMakefile \
|
||||
$(DIRECTORY)/windows/VC8/
|
||||
|
||||
ES_FILES = \
|
||||
$(DIRECTORY)/include/GLES/*.h \
|
||||
$(DIRECTORY)/include/GLES2/*.h \
|
||||
$(DIRECTORY)/src/mesa/glapi/*.xml \
|
||||
$(DIRECTORY)/src/mesa/glapi/*.py \
|
||||
$(DIRECTORY)/src/mesa/glapi/*.dtd \
|
||||
$(DIRECTORY)/src/mesa/es/glapi/Makefile \
|
||||
$(DIRECTORY)/src/mesa/es/glapi/*.xml \
|
||||
$(DIRECTORY)/src/mesa/es/glapi/*.py \
|
||||
$(DIRECTORY)/src/mesa/es/state_tracker/*.[ch] \
|
||||
$(DIRECTORY)/src/mesa/es/main/*.[ch] \
|
||||
$(DIRECTORY)/src/mesa/es/main/*.py \
|
||||
$(DIRECTORY)/src/mesa/es/main/*.txt \
|
||||
$(DIRECTORY)/src/mesa/es/main/es*_special \
|
||||
$(DIRECTORY)/src/mesa/es/Makefile \
|
||||
$(DIRECTORY)/src/mesa/es/sources.mak \
|
||||
|
||||
EGL_FILES = \
|
||||
$(DIRECTORY)/include/EGL/*.h \
|
||||
$(DIRECTORY)/include/GLES/*.h \
|
||||
$(DIRECTORY)/include/GLES2/*.h \
|
||||
$(DIRECTORY)/src/egl/Makefile \
|
||||
$(DIRECTORY)/src/egl/*/Makefile \
|
||||
$(DIRECTORY)/src/egl/*/*.[ch] \
|
||||
@@ -488,7 +471,6 @@ DEPEND_FILES = \
|
||||
|
||||
LIB_FILES = \
|
||||
$(MAIN_FILES) \
|
||||
$(ES_FILES) \
|
||||
$(EGL_FILES) \
|
||||
$(GALLIUM_FILES) \
|
||||
$(DRI_FILES) \
|
||||
|
||||
@@ -59,7 +59,7 @@ def AddOptions(opts):
|
||||
opts.Add(EnumOption('machine', 'use machine-specific assembly code', default_machine,
|
||||
allowed_values=('generic', 'ppc', 'x86', 'x86_64')))
|
||||
opts.Add(EnumOption('platform', 'target platform', default_platform,
|
||||
allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince', 'darwin')))
|
||||
allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince')))
|
||||
opts.Add(EnumOption('toolchain', 'compiler toolchain', 'default',
|
||||
allowed_values=('default', 'crossmingw', 'winsdk', 'winddk')))
|
||||
opts.Add(BoolOption('llvm', 'use LLVM', 'no'))
|
||||
|
||||
@@ -9,7 +9,7 @@ CONFIG_NAME = default
|
||||
|
||||
# Version info
|
||||
MESA_MAJOR=7
|
||||
MESA_MINOR=7
|
||||
MESA_MINOR=6
|
||||
MESA_TINY=0
|
||||
MESA_VERSION = $(MESA_MAJOR).$(MESA_MINOR).$(MESA_TINY)
|
||||
|
||||
@@ -23,6 +23,7 @@ HOST_CC = $(CC)
|
||||
CFLAGS = -O
|
||||
CXXFLAGS = -O
|
||||
LDFLAGS =
|
||||
HOST_CFLAGS = $(CFLAGS)
|
||||
GLU_CFLAGS =
|
||||
|
||||
# Compiler for building demos/tests/etc
|
||||
|
||||
82
configs/mine
82
configs/mine
@@ -1,82 +0,0 @@
|
||||
# -*-makefile-*-
|
||||
# Configuration for linux-dri: Linux DRI hardware drivers for XFree86 & others
|
||||
|
||||
include $(TOP)/configs/default
|
||||
|
||||
CONFIG_NAME = mine
|
||||
|
||||
# Compiler and flags
|
||||
CC = ccache gcc
|
||||
CXX = ccache g++
|
||||
|
||||
#MKDEP = /usr/X11R6/bin/makedepend
|
||||
#MKDEP = gcc -M
|
||||
#MKDEP_OPTIONS = -MF depend
|
||||
|
||||
OPT_FLAGS = -O0 -g
|
||||
PIC_FLAGS = -fPIC
|
||||
|
||||
# Add '-DGLX_USE_TLS' to ARCH_FLAGS to enable TLS support.
|
||||
ARCH_FLAGS ?=
|
||||
|
||||
DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \
|
||||
-D_BSD_SOURCE -D_GNU_SOURCE \
|
||||
-DPTHREADS -DUSE_EXTERNAL_DXTN_LIB=1 \
|
||||
-DGLX_DIRECT_RENDERING \
|
||||
-DHAVE_ALIAS -DHAVE_POSIX_MEMALIGN
|
||||
|
||||
X11_INCLUDES = -I/usr/X11R6/include
|
||||
|
||||
CFLAGS = -Wall -Wmissing-prototypes -std=c99 -ffast-math \
|
||||
$(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) $(ASM_FLAGS)
|
||||
|
||||
CXXFLAGS = -Wall $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES)
|
||||
|
||||
GLUT_CFLAGS = -fexceptions
|
||||
|
||||
# Work around aliasing bugs - developers should comment this out
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CXXFLAGS += -fno-strict-aliasing
|
||||
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
# Library/program dependencies
|
||||
EXTRA_LIB_PATH=-L/usr/X11R6/lib
|
||||
|
||||
DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
|
||||
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
|
||||
-lm -lpthread -ldl $(LIBDRM_LIB)
|
||||
|
||||
|
||||
# Directories
|
||||
SRC_DIRS = egl mesa gallium gallium/winsys
|
||||
PROGRAM_DIRS := egl openvg/demos demos xdemos
|
||||
|
||||
# EGL directories
|
||||
EGL_DRIVERS_DIRS = glx xdri
|
||||
|
||||
ifeq ($(USE_DRI),yes)
|
||||
DEFINES += -DIN_DRI_DRIVER -DGLX_INDIRECT_RENDERING
|
||||
|
||||
LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm)
|
||||
LIBDRM_LIB = $(shell pkg-config --libs libdrm)
|
||||
|
||||
SRC_DIRS := glx/x11 $(SRC_DIRS)
|
||||
DRIVER_DIRS = dri
|
||||
WINDOW_SYSTEM = dri
|
||||
DRI_DIRS = i915
|
||||
|
||||
GALLIUM_WINSYS_DIRS = drm egl_xlib
|
||||
GALLIUM_WINSYS_DRM_DIRS = intel
|
||||
GALLIUM_STATE_TRACKERS_DIRS = egl glx vega
|
||||
|
||||
else
|
||||
|
||||
DRIVER_DIRS =
|
||||
WINDOW_SYSTEM =
|
||||
DRI_DIRS =
|
||||
|
||||
GALLIUM_WINSYS_DIRS = egl_xlib xlib
|
||||
GALLIUM_STATE_TRACKERS_DIRS = glx vega
|
||||
|
||||
endif
|
||||
@@ -1,5 +0,0 @@
|
||||
# -*-makefile-*-
|
||||
# Configuration for linux-dri: Linux DRI hardware drivers for XFree86 & others
|
||||
|
||||
USE_DRI = yes
|
||||
include $(TOP)/configs/mine
|
||||
@@ -1202,7 +1202,7 @@ if test "x$enable_gallium_radeon" = xyes; then
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Gallium Radeon configuration
|
||||
dnl Gallium Nouveau configuration
|
||||
dnl
|
||||
AC_ARG_ENABLE([gallium-nouveau],
|
||||
[AS_HELP_STRING([--enable-gallium-nouveau],
|
||||
|
||||
@@ -45,6 +45,10 @@ tbd
|
||||
<ul>
|
||||
<li>Assorted bug fixes for i965/i945 drivers
|
||||
<li>Fixed Gallium glDrawPixels(GL_STENCIL_INDEX) failure.
|
||||
<li>Fixed GLSL linker/preprocessor version directive issue seen in Wine
|
||||
(such as bug 23946)
|
||||
<li>glUseProgram() is now compiled into display lists (bug 23746).
|
||||
<li>glUniform functions are now compiled into display lists
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ This was written by Zack Rusin at Tungsten Graphics.
|
||||
<li>Rewritten radeon/r200/r300 driver using a buffer manager
|
||||
<li>radeon/r200/r300 GL_EXT_framebuffer_object support when used with
|
||||
kernel memory manager
|
||||
<li>radeon/r200/r300 support for GL_ARB_occlusion_query</li>
|
||||
<li>r300 driver supports OpenGL 1.5</li>
|
||||
<li>r300 driver support for GL_EXT_vertex_array_bgra, GL_EXT_texture_sRGB
|
||||
<li>i915/945 driver support for GL_ARB_point_sprite, GL_EXT_stencil_two_side
|
||||
and GL_ATI_separate_stencil extensions
|
||||
@@ -57,6 +59,10 @@ This was written by Zack Rusin at Tungsten Graphics.
|
||||
GL_ARB_fragment_program.</li>
|
||||
<li>Added configure --with-max-width=W, --with-max-height=H options to specify
|
||||
max framebuffer, viewport size.
|
||||
<li>Initial version of Gallium llvmpipe driver. This is a new driver based
|
||||
on LLVM which makes exensive use of run-time code generation. This is
|
||||
an "alpha" stage driver. See the src/gallium/drivers/llvmpipe/README
|
||||
file for more information.
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<HTML>
|
||||
|
||||
<TITLE>Mesa Release Notes</TITLE>
|
||||
|
||||
<head><link rel="stylesheet" type="text/css" href="mesa.css"></head>
|
||||
|
||||
<BODY>
|
||||
|
||||
<body bgcolor="#eeeeee">
|
||||
|
||||
<H1>Mesa 7.7 Release Notes / date TBD</H1>
|
||||
|
||||
<p>
|
||||
Mesa 7.7 is a new development release.
|
||||
People who are concerned with stability and reliability should stick
|
||||
with a previous release or wait for Mesa 7.7.1.
|
||||
</p>
|
||||
<p>
|
||||
Mesa 7.7 implements the OpenGL 2.1 API, but the version reported by
|
||||
glGetString(GL_VERSION) depends on the particular driver being used.
|
||||
Some drivers don't support all the features required in OpenGL 2.1.
|
||||
</p>
|
||||
<p>
|
||||
See the <a href="install.html">Compiling/Installing page</a> for prerequisites
|
||||
for DRI hardware acceleration.
|
||||
</p>
|
||||
|
||||
|
||||
<h2>MD5 checksums</h2>
|
||||
<pre>
|
||||
tbd
|
||||
</pre>
|
||||
|
||||
|
||||
<h2>New features</h2>
|
||||
<ul>
|
||||
<li>GL_ARB_draw_elements_base_vertex (supported in Intel i965 and software drivers)</li>
|
||||
<li>GL_ARB_depth_clamp (supported in Intel i965 DRI and software drivers)</li>
|
||||
<li>GL_NV_depth_clamp (supported in Intel i965 DRI and software drivers)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Bug fixes</h2>
|
||||
<ul>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Changes</h2>
|
||||
<ul>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,7 +13,6 @@ The release notes summarize what's new or changed in each Mesa release.
|
||||
</p>
|
||||
|
||||
<UL>
|
||||
<LI><A HREF="relnotes-7.7.html">7.7 release notes</A>
|
||||
<LI><A HREF="relnotes-7.6.html">7.6 release notes</A>
|
||||
<LI><A HREF="relnotes-7.5.2.html">7.5.2 release notes</A>
|
||||
<LI><A HREF="relnotes-7.5.1.html">7.5.1 release notes</A>
|
||||
|
||||
@@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2007-2009 The Khronos Group Inc.
|
||||
** Copyright (c) 2007 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
@@ -33,9 +33,9 @@ extern "C" {
|
||||
/*************************************************************/
|
||||
|
||||
/* Header file version number */
|
||||
/* eglext.h last updated 2007/11/20 */
|
||||
/* Current version at http://www.khronos.org/registry/egl/ */
|
||||
/* $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $ */
|
||||
#define EGL_EGLEXT_VERSION 3
|
||||
#define EGL_EGLEXT_VERSION 1
|
||||
|
||||
#ifndef EGL_KHR_config_attribs
|
||||
#define EGL_KHR_config_attribs 1
|
||||
@@ -79,12 +79,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display
|
||||
#define EGL_KHR_image 1
|
||||
#define EGL_NATIVE_PIXMAP_KHR 0x30B0 /* eglCreateImageKHR target */
|
||||
typedef void *EGLImageKHR;
|
||||
#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
|
||||
extern const EGLImageKHR EGL_NO_IMAGE_KHR;
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, EGLint *attr_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
|
||||
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, EGLint *attr_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
|
||||
#endif
|
||||
|
||||
@@ -179,17 +179,6 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOPYCONTEXTMESA) (EGLDisplay dpy, EGLCont
|
||||
|
||||
#endif /* EGL_MESA_copy_context */
|
||||
|
||||
#ifndef EGL_KHR_image_base
|
||||
#define EGL_KHR_image_base 1
|
||||
/* Most interfaces defined by EGL_KHR_image_pixmap above */
|
||||
#define EGL_IMAGE_PRESERVED_KHR 0x30D2 /* eglCreateImageKHR attribute */
|
||||
#endif
|
||||
|
||||
#ifndef EGL_KHR_image_pixmap
|
||||
#define EGL_KHR_image_pixmap 1
|
||||
/* Interfaces defined by EGL_KHR_image above */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef EGLIMAGE_DRI_INCLUDED
|
||||
#define EGLIMAGE_DRI_INCLUDED
|
||||
|
||||
#include "GL/internal/dri_interface.h"
|
||||
|
||||
#define __DRI_EGL_IMAGE_MAGIC \
|
||||
(('D' << 24) | \
|
||||
('R' << 16) | \
|
||||
('I' << 8) | \
|
||||
('0'))
|
||||
|
||||
typedef void *__DRIEGLImageHandle;
|
||||
typedef struct __DRIEGLImageRec __DRIEGLImage;
|
||||
|
||||
struct __DRIEGLImageRec {
|
||||
GLint magic;
|
||||
|
||||
__DRIdrawable *drawable;
|
||||
|
||||
GLboolean texture_format_rgba;
|
||||
GLint level;
|
||||
GLint __pad[4];
|
||||
};
|
||||
|
||||
extern __DRIEGLImage *_eglClientGetImageData(__DRIEGLImageHandle handle);
|
||||
|
||||
#endif /* EGLIMAGE_DRI_INCLUDED */
|
||||
@@ -1740,6 +1740,9 @@ GLAPI void GLAPIENTRY glSeparableFilter2D( GLenum target,
|
||||
GLAPI void GLAPIENTRY glGetSeparableFilter( GLenum target, GLenum format,
|
||||
GLenum type, GLvoid *row, GLvoid *column, GLvoid *span );
|
||||
|
||||
typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -1945,6 +1948,18 @@ GLAPI void GLAPIENTRY glMultTransposeMatrixf( const GLfloat m[16] );
|
||||
GLAPI void GLAPIENTRY glSampleCoverage( GLclampf value, GLboolean invert );
|
||||
|
||||
|
||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
|
||||
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* GL_ARB_multitexture (ARB extension 1 and OpenGL 1.2.1)
|
||||
*/
|
||||
|
||||
@@ -708,19 +708,6 @@ struct __DRIdri2LoaderExtensionRec {
|
||||
int *out_count, void *loaderPrivate);
|
||||
};
|
||||
|
||||
#define __DRI_COPY_BUFFER "DRI_CopyBuffer"
|
||||
#define __DRI_COPY_BUFFER_VERSION 1
|
||||
typedef struct __DRIcopyBufferExtensionRec __DRIcopyBufferExtension;
|
||||
struct __DRIcopyBufferExtensionRec {
|
||||
__DRIextension base;
|
||||
|
||||
int (*copyBuffer)(__DRIcontext *context,
|
||||
__DRIbuffer *dst, int dst_x, int dst_y,
|
||||
__DRIdrawable *src, unsigned int src_attachment,
|
||||
int x, int y, int width, int height);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This extension provides alternative screen, drawable and context
|
||||
* constructors for DRI2.
|
||||
|
||||
@@ -26,7 +26,6 @@ static int Scissor = 0;
|
||||
static float Xzoom, Yzoom;
|
||||
static GLboolean DrawFront = GL_FALSE;
|
||||
static GLboolean Dither = GL_TRUE;
|
||||
static GLboolean Invert = GL_FALSE;
|
||||
|
||||
|
||||
static void Reset( void )
|
||||
@@ -60,15 +59,6 @@ static void Display( void )
|
||||
if (Scissor)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
if (Invert) {
|
||||
glPixelTransferf(GL_RED_SCALE, -1.0);
|
||||
glPixelTransferf(GL_GREEN_SCALE, -1.0);
|
||||
glPixelTransferf(GL_BLUE_SCALE, -1.0);
|
||||
glPixelTransferf(GL_RED_BIAS, 1.0);
|
||||
glPixelTransferf(GL_GREEN_BIAS, 1.0);
|
||||
glPixelTransferf(GL_BLUE_BIAS, 1.0);
|
||||
}
|
||||
|
||||
/* draw copy */
|
||||
glPixelZoom(Xzoom, Yzoom);
|
||||
glWindowPos2iARB(Xpos, Ypos);
|
||||
@@ -77,15 +67,6 @@ static void Display( void )
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
if (Invert) {
|
||||
glPixelTransferf(GL_RED_SCALE, 1.0);
|
||||
glPixelTransferf(GL_GREEN_SCALE, 1.0);
|
||||
glPixelTransferf(GL_BLUE_SCALE, 1.0);
|
||||
glPixelTransferf(GL_RED_BIAS, 0.0);
|
||||
glPixelTransferf(GL_GREEN_BIAS, 0.0);
|
||||
glPixelTransferf(GL_BLUE_BIAS, 0.0);
|
||||
}
|
||||
|
||||
if (DrawFront)
|
||||
glFinish();
|
||||
else
|
||||
@@ -124,9 +105,6 @@ static void Key( unsigned char key, int x, int y )
|
||||
else
|
||||
glDisable(GL_DITHER);
|
||||
break;
|
||||
case 'i':
|
||||
Invert = !Invert;
|
||||
break;
|
||||
case 's':
|
||||
Scissor = !Scissor;
|
||||
break;
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
# progs/es1/xegl/Makefile
|
||||
|
||||
TOP = ../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I$(TOP)/include \
|
||||
|
||||
HEADERS = $(TOP)/include/GLES/egl.h
|
||||
|
||||
|
||||
ES1_LIB_DEPS = \
|
||||
$(TOP)/$(LIB_DIR)/libEGL.so \
|
||||
$(TOP)/$(LIB_DIR)/libGLESv1_CM.so
|
||||
|
||||
|
||||
ES1_LIBS = \
|
||||
-L$(TOP)/$(LIB_DIR) -lEGL \
|
||||
-L$(TOP)/$(LIB_DIR) -lGLESv1_CM $(LIBDRM_LIB) -lX11
|
||||
|
||||
PROGRAMS = \
|
||||
drawtex \
|
||||
es1_info \
|
||||
msaa \
|
||||
pbuffer \
|
||||
render_tex \
|
||||
torus \
|
||||
tri \
|
||||
two_win
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
default: $(PROGRAMS)
|
||||
|
||||
|
||||
|
||||
drawtex: drawtex.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) drawtex.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
es1_info: es1_info.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) es1_info.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
msaa: msaa.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) msaa.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
pbuffer: pbuffer.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) pbuffer.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
render_tex: render_tex.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) render_tex.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
torus: torus.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) torus.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
two_win: two_win.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) two_win.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
tri: tri.o $(ES1_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) tri.o $(ES1_LIBS) -o $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
rm -f $(PROGRAMS)
|
||||
|
||||
@@ -1,427 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test GL_OES_draw_texture
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
static GLfloat view_posx = 10.0, view_posy = 20.0;
|
||||
static GLfloat width = 200, height = 200;
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glDrawTexfOES(view_posx, view_posy, 0.0, width, height);
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
}
|
||||
|
||||
|
||||
static float
|
||||
dist(GLuint i, GLuint j, float x, float y)
|
||||
{
|
||||
return sqrt((i-x) * (i-x) + (j-y) * (j-y));
|
||||
}
|
||||
|
||||
static void
|
||||
make_smile_texture(void)
|
||||
{
|
||||
#define SZ 128
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
GLint cropRect[4];
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d_mouth = dist(i, j, SZ/2, SZ/2);
|
||||
GLfloat d_rt_eye = dist(i, j, SZ*3/4, SZ*3/4);
|
||||
GLfloat d_lt_eye = dist(i, j, SZ*3/4, SZ*1/4);
|
||||
if (d_rt_eye < SZ / 8 || d_lt_eye < SZ / 8) {
|
||||
image[i][j][0] = 20;
|
||||
image[i][j][1] = 50;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else if (i < SZ/2 && d_mouth < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 20;
|
||||
image[i][j][2] = 20;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 200;
|
||||
image[i][j][1] = 200;
|
||||
image[i][j][2] = 200;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0); /* unit 0 */
|
||||
glBindTexture(GL_TEXTURE_2D, 42);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
cropRect[0] = 0;
|
||||
cropRect[1] = 0;
|
||||
cropRect[2] = SZ;
|
||||
cropRect[3] = SZ;
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
const char *ext = (char *) glGetString(GL_EXTENSIONS);
|
||||
|
||||
if (!strstr(ext, "GL_OES_draw_texture")) {
|
||||
fprintf(stderr, "Sorry, this program requires GL_OES_draw_texture");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
|
||||
make_smile_texture();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
int anim = 0;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_posx -= 1.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_posx += 1.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_posy += 1.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_posy -= 1.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 'w') {
|
||||
width -= 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 'W') {
|
||||
width += 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 'h') {
|
||||
height -= 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 'H') {
|
||||
height += 1.0f;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_posx += 1.0;
|
||||
view_posy += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 400, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"drawtex", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* List OpenGL ES extensions.
|
||||
* Print ES 1 or ES 2 extensions depending on which library we're
|
||||
* linked with: libGLESv1_CM.so vs libGLESv2.so
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
/*
|
||||
* Print a list of extensions, with word-wrapping.
|
||||
*/
|
||||
static void
|
||||
print_extension_list(const char *ext)
|
||||
{
|
||||
const char *indentString = " ";
|
||||
const int indent = 4;
|
||||
const int max = 79;
|
||||
int width, i, j;
|
||||
|
||||
if (!ext || !ext[0])
|
||||
return;
|
||||
|
||||
width = indent;
|
||||
printf(indentString);
|
||||
i = j = 0;
|
||||
while (1) {
|
||||
if (ext[j] == ' ' || ext[j] == 0) {
|
||||
/* found end of an extension name */
|
||||
const int len = j - i;
|
||||
if (width + len > max) {
|
||||
/* start a new line */
|
||||
printf("\n");
|
||||
width = indent;
|
||||
printf(indentString);
|
||||
}
|
||||
/* print the extension name between ext[i] and ext[j] */
|
||||
while (i < j) {
|
||||
printf("%c", ext[i]);
|
||||
i++;
|
||||
}
|
||||
/* either we're all done, or we'll continue with next extension */
|
||||
width += len + 1;
|
||||
if (ext[j] == 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
j++;
|
||||
if (ext[j] == 0)
|
||||
break;
|
||||
printf(", ");
|
||||
width += 2;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
info(EGLDisplay egl_dpy)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_EXTENSIONS:\n");
|
||||
print_extension_list((char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 400, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"ES info", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
/*XMapWindow(x_dpy, win);*/
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
info(egl_dpy);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,442 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Brian Paul 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
|
||||
* BRIAN PAUL 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test MSAA with X/EGL and OpenGL ES 1.x
|
||||
* Brian Paul
|
||||
* 15 September 2008
|
||||
*/
|
||||
|
||||
#define USE_FULL_GL 0
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#if USE_FULL_GL
|
||||
#include <GL/gl.h> /* use full OpenGL */
|
||||
#else
|
||||
#include <GLES/gl.h> /* use OpenGL ES 1.x */
|
||||
#include <GLES/glext.h>
|
||||
#endif
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
static GLboolean AA = 0*GL_TRUE;
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
float a;
|
||||
|
||||
static const GLfloat verts[4][2] = {
|
||||
{ -1, -.1 },
|
||||
{ 1, -.1 },
|
||||
{ -1, .1 },
|
||||
{ 1, .1 }
|
||||
};
|
||||
static const GLfloat colors[4][4] = {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 1, 1 },
|
||||
{ 1, 0, 1, 1 }
|
||||
};
|
||||
|
||||
if (AA) {
|
||||
printf("MSAA enabled\n");
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
else {
|
||||
printf("MSAA disabled\n");
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
{
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
for (a = 0; a < 360; a += 20.0) {
|
||||
glPushMatrix();
|
||||
|
||||
glRotatef(a, 0, 0, 1);
|
||||
glTranslatef(1.5, 0, 0);
|
||||
|
||||
/* draw triangle */
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ary = 3.0;
|
||||
GLfloat arx = ary * (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glOrthof(-arx, arx, -ary, ary, -1.0, 1.0);
|
||||
#else
|
||||
glOrtho(-arx, arx, -ary, ary, -1.0, 1.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
printf("Press 'a' to toggle multisample antialiasing\n");
|
||||
printf("Press 'Esc' to exit\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_SAMPLES, 1,
|
||||
EGL_SAMPLE_BUFFERS, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (num_configs < 1) {
|
||||
printf("Error: Unable to find multisample pixel format.\n");
|
||||
printf("Try running glxinfo to see if your server supports MSAA.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 'a') {
|
||||
AA = !AA;
|
||||
redraw = 1;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 600, winHeight = 600;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
GLenum value;
|
||||
enum {GetString, GetInteger} type;
|
||||
} info_items[] = {
|
||||
{"GL_RENDERER", GL_RENDERER, GetString},
|
||||
{"GL_VERSION", GL_VERSION, GetString},
|
||||
{"GL_VENDOR", GL_VENDOR, GetString},
|
||||
{"GL_EXTENSIONS", GL_EXTENSIONS, GetString},
|
||||
{"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES, GetInteger},
|
||||
{"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES, GetInteger},
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"msaa", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
|
||||
switch (info_items[i].type) {
|
||||
case GetString:
|
||||
printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
|
||||
break;
|
||||
case GetInteger: {
|
||||
GLint rv = -1;
|
||||
glGetIntegerv(info_items[i].value, &rv);
|
||||
printf("%s = %d\n", info_items[i].name, rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,607 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test EGL Pbuffers
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
static int WinWidth = 300, WinHeight = 300;
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
static void
|
||||
Normal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
|
||||
{
|
||||
n[0] = nx;
|
||||
n[1] = ny;
|
||||
n[2] = nz;
|
||||
}
|
||||
|
||||
static void
|
||||
Vertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
|
||||
{
|
||||
v[0] = vx;
|
||||
v[1] = vy;
|
||||
v[2] = vz;
|
||||
}
|
||||
|
||||
static void
|
||||
Texcoord(GLfloat *v, GLfloat s, GLfloat t)
|
||||
{
|
||||
v[0] = s;
|
||||
v[1] = t;
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from glut, adapted */
|
||||
static void
|
||||
draw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
GLfloat varray[100][3], narray[100][3], tarray[100][2];
|
||||
int vcount;
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, varray);
|
||||
glNormalPointer(GL_FLOAT, 0, narray);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tarray);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
|
||||
vcount = 0; /* glBegin(GL_QUAD_STRIP); */
|
||||
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat s0, s1, t;
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
s0 = 20.0 * theta / (2.0 * M_PI);
|
||||
s1 = 20.0 * theta1 / (2.0 * M_PI);
|
||||
t = 8.0 * phi / (2.0 * M_PI);
|
||||
|
||||
Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s1, t);
|
||||
Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
vcount++;
|
||||
|
||||
Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s0, t);
|
||||
Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
vcount++;
|
||||
}
|
||||
|
||||
/*glEnd();*/
|
||||
assert(vcount <= 100);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
|
||||
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
glScalef(0.5, 0.5, 0.5);
|
||||
|
||||
draw_torus(1.0, 3.0, 30, 60);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glFinish();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw to both the window and pbuffer and compare results.
|
||||
*/
|
||||
static void
|
||||
draw_both(EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
unsigned *wbuf, *pbuf;
|
||||
int x = 100, y = 110;
|
||||
int i, dif;
|
||||
|
||||
wbuf = (unsigned *) malloc(WinWidth * WinHeight * 4);
|
||||
pbuf = (unsigned *) malloc(WinWidth * WinHeight * 4);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
/* first draw to window */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(window) failed\n");
|
||||
return;
|
||||
}
|
||||
draw();
|
||||
glReadPixels(0, 0, WinWidth, WinHeight, GL_RGBA, GL_UNSIGNED_BYTE, wbuf);
|
||||
printf("Window[%d,%d] = 0x%08x\n", x, y, wbuf[y*WinWidth+x]);
|
||||
|
||||
/* then draw to pbuffer */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_pbuf, egl_pbuf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(pbuffer) failed\n");
|
||||
return;
|
||||
}
|
||||
draw();
|
||||
glReadPixels(0, 0, WinWidth, WinHeight, GL_RGBA, GL_UNSIGNED_BYTE, pbuf);
|
||||
printf("Pbuffer[%d,%d] = 0x%08x\n", x, y, pbuf[y*WinWidth+x]);
|
||||
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
|
||||
/* compare renderings */
|
||||
for (dif = i = 0; i < WinWidth * WinHeight; i++) {
|
||||
if (wbuf[i] != pbuf[i]) {
|
||||
dif = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dif)
|
||||
printf("Difference at %d: 0x%08x vs. 0x%08x\n", i, wbuf[i], pbuf[i]);
|
||||
else
|
||||
printf("Window rendering matches Pbuffer rendering!\n");
|
||||
|
||||
free(wbuf);
|
||||
free(pbuf);
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
WinWidth = width;
|
||||
WinHeight = height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
make_texture(void)
|
||||
{
|
||||
#define SZ 64
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
|
||||
d = sqrt(d);
|
||||
if (d < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 255;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 127;
|
||||
image[i][j][1] = 127;
|
||||
image[i][j][2] = 127;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0); /* unit 0 */
|
||||
glBindTexture(GL_TEXTURE_2D, 42);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
static const GLfloat red[4] = {1, 0, 0, 0};
|
||||
static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
|
||||
static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
|
||||
static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
|
||||
static const GLfloat pos[4] = {20, 20, 50, 1};
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
make_texture();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static EGLSurface
|
||||
make_pbuffer(Display *x_dpy, EGLDisplay egl_dpy, int width, int height)
|
||||
{
|
||||
static const EGLint config_attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config;
|
||||
EGLSurface pbuf;
|
||||
EGLint num_configs;
|
||||
EGLint pbuf_attribs[5];
|
||||
|
||||
pbuf_attribs[0] = EGL_WIDTH;
|
||||
pbuf_attribs[1] = width;
|
||||
pbuf_attribs[2] = EGL_HEIGHT;
|
||||
pbuf_attribs[3] = height;
|
||||
pbuf_attribs[4] = EGL_NONE;
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, config_attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL config for pbuffer\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pbuf = eglCreatePbufferSurface(egl_dpy, config, pbuf_attribs);
|
||||
|
||||
return pbuf;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
int anim = 0;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if (event.xconfigure.window == win)
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_rotx += 1.0;
|
||||
view_roty += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw_both(egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf, egl_pbuf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"pbuffer", 0, 0, WinWidth, WinHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
egl_pbuf = make_pbuffer(x_dpy, egl_dpy, WinWidth, WinHeight);
|
||||
if (!egl_pbuf) {
|
||||
printf("Error: eglCreatePBufferSurface() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(WinWidth, WinHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,657 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test EGL render to texture.
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
static int TexWidth = 256, TexHeight = 256;
|
||||
|
||||
static int WinWidth = 300, WinHeight = 300;
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
static GLuint DotTexture, RenderTexture;
|
||||
|
||||
|
||||
static void
|
||||
Normal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
|
||||
{
|
||||
n[0] = nx;
|
||||
n[1] = ny;
|
||||
n[2] = nz;
|
||||
}
|
||||
|
||||
static void
|
||||
Vertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
|
||||
{
|
||||
v[0] = vx;
|
||||
v[1] = vy;
|
||||
v[2] = vz;
|
||||
}
|
||||
|
||||
static void
|
||||
Texcoord(GLfloat *v, GLfloat s, GLfloat t)
|
||||
{
|
||||
v[0] = s;
|
||||
v[1] = t;
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from glut, adapted */
|
||||
static void
|
||||
draw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
GLfloat varray[100][3], narray[100][3], tarray[100][2];
|
||||
int vcount;
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, varray);
|
||||
glNormalPointer(GL_FLOAT, 0, narray);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tarray);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
|
||||
vcount = 0; /* glBegin(GL_QUAD_STRIP); */
|
||||
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat s0, s1, t;
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
s0 = 20.0 * theta / (2.0 * M_PI);
|
||||
s1 = 20.0 * theta1 / (2.0 * M_PI);
|
||||
t = 8.0 * phi / (2.0 * M_PI);
|
||||
|
||||
Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s1, t);
|
||||
Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
vcount++;
|
||||
|
||||
Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s0, t);
|
||||
Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
vcount++;
|
||||
}
|
||||
|
||||
/*glEnd();*/
|
||||
assert(vcount <= 100);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
|
||||
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_torus_to_texture(void)
|
||||
{
|
||||
glViewport(0, 0, TexWidth, TexHeight);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustumf(-1, 1, -1, 1, 5.0, 60.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, DotTexture);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glScalef(0.5, 0.5, 0.5);
|
||||
|
||||
draw_torus(1.0, 3.0, 30, 60);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
#if 0
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
|
||||
#endif
|
||||
|
||||
glFinish();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw_textured_quad(void)
|
||||
{
|
||||
GLfloat ar = (GLfloat) WinWidth / (GLfloat) WinHeight;
|
||||
|
||||
glViewport(0, 0, WinWidth, WinHeight);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -8.0);
|
||||
|
||||
glClearColor(0.4, 0.4, 1.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
{
|
||||
static const GLfloat texcoord[4][2] = {
|
||||
{ 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 }
|
||||
};
|
||||
static const GLfloat vertex[4][2] = {
|
||||
{ -1, -1 }, { 1, -1 }, { -1, 1 }, { 1, 1 }
|
||||
};
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, vertex);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, texcoord);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
draw(EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
/*printf("Begin draw\n");*/
|
||||
|
||||
/* first draw torus to pbuffer /texture */
|
||||
#if 01
|
||||
if (!eglMakeCurrent(egl_dpy, egl_pbuf, egl_pbuf, egl_ctx)) {
|
||||
#else
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
#endif
|
||||
printf("Error: eglMakeCurrent(pbuf) failed\n");
|
||||
return;
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
eglBindTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
|
||||
draw_torus_to_texture();
|
||||
eglReleaseTexImage(egl_dpy, egl_pbuf, EGL_BACK_BUFFER);
|
||||
|
||||
/* draw textured quad to window */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(pbuffer) failed\n");
|
||||
return;
|
||||
}
|
||||
draw_textured_quad();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
|
||||
/*printf("End draw\n");*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
make_dot_texture(void)
|
||||
{
|
||||
#define SZ 64
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
|
||||
d = sqrt(d);
|
||||
if (d < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 255;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 127;
|
||||
image[i][j][1] = 127;
|
||||
image[i][j][2] = 127;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glGenTextures(1, &DotTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, DotTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
make_render_texture(void)
|
||||
{
|
||||
GLenum Filter = GL_LINEAR;
|
||||
glGenTextures(1, &RenderTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, RenderTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
static const GLfloat red[4] = {1, 0, 0, 0};
|
||||
static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
|
||||
static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
|
||||
static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
|
||||
static const GLfloat pos[4] = {20, 20, 50, 1};
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
|
||||
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
make_dot_texture();
|
||||
make_render_texture();
|
||||
|
||||
printf("DotTexture=%u RenderTexture=%u\n", DotTexture, RenderTexture);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static EGLSurface
|
||||
make_pbuffer(Display *x_dpy, EGLDisplay egl_dpy, int width, int height)
|
||||
{
|
||||
static const EGLint config_attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config;
|
||||
EGLSurface pbuf;
|
||||
EGLint num_configs;
|
||||
EGLint pbuf_attribs[15];
|
||||
int i = 0;
|
||||
|
||||
pbuf_attribs[i++] = EGL_WIDTH;
|
||||
pbuf_attribs[i++] = width;
|
||||
pbuf_attribs[i++] = EGL_HEIGHT;
|
||||
pbuf_attribs[i++] = height;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_FORMAT;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_RGBA;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_TARGET;
|
||||
pbuf_attribs[i++] = EGL_TEXTURE_2D;
|
||||
pbuf_attribs[i++] = EGL_MIPMAP_TEXTURE;
|
||||
pbuf_attribs[i++] = EGL_FALSE;
|
||||
pbuf_attribs[i++] = EGL_NONE;
|
||||
assert(i <= 15);
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, config_attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL config for pbuffer\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pbuf = eglCreatePbufferSurface(egl_dpy, config, pbuf_attribs);
|
||||
|
||||
return pbuf;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf, EGLSurface egl_pbuf,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
int anim = 0;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if (event.xconfigure.window == win) {
|
||||
WinWidth = event.xconfigure.width;
|
||||
WinHeight = event.xconfigure.height;
|
||||
}
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 'z') {
|
||||
view_rotz += 5.0;
|
||||
}
|
||||
else if (buffer[0] == 'Z') {
|
||||
view_rotz -= 5.0;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_rotx += 1.0;
|
||||
view_roty += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw(egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf, egl_pbuf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"render_tex", 0, 0, WinWidth, WinHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
egl_pbuf = make_pbuffer(x_dpy, egl_dpy, TexWidth, TexHeight);
|
||||
if (!egl_pbuf) {
|
||||
printf("Error: eglCreatePBufferSurface() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf, egl_pbuf, egl_ctx);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,509 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Draw a lit, textured torus with X/EGL and OpenGL ES 1.x
|
||||
* Brian Paul
|
||||
* July 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
static void
|
||||
Normal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz)
|
||||
{
|
||||
n[0] = nx;
|
||||
n[1] = ny;
|
||||
n[2] = nz;
|
||||
}
|
||||
|
||||
static void
|
||||
Vertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz)
|
||||
{
|
||||
v[0] = vx;
|
||||
v[1] = vy;
|
||||
v[2] = vz;
|
||||
}
|
||||
|
||||
static void
|
||||
Texcoord(GLfloat *v, GLfloat s, GLfloat t)
|
||||
{
|
||||
v[0] = s;
|
||||
v[1] = t;
|
||||
}
|
||||
|
||||
|
||||
/* Borrowed from glut, adapted */
|
||||
static void
|
||||
draw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings)
|
||||
{
|
||||
int i, j;
|
||||
GLfloat theta, phi, theta1;
|
||||
GLfloat cosTheta, sinTheta;
|
||||
GLfloat cosTheta1, sinTheta1;
|
||||
GLfloat ringDelta, sideDelta;
|
||||
GLfloat varray[100][3], narray[100][3], tarray[100][2];
|
||||
int vcount;
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, varray);
|
||||
glNormalPointer(GL_FLOAT, 0, narray);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tarray);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
ringDelta = 2.0 * M_PI / rings;
|
||||
sideDelta = 2.0 * M_PI / nsides;
|
||||
|
||||
theta = 0.0;
|
||||
cosTheta = 1.0;
|
||||
sinTheta = 0.0;
|
||||
for (i = rings - 1; i >= 0; i--) {
|
||||
theta1 = theta + ringDelta;
|
||||
cosTheta1 = cos(theta1);
|
||||
sinTheta1 = sin(theta1);
|
||||
|
||||
vcount = 0; /* glBegin(GL_QUAD_STRIP); */
|
||||
|
||||
phi = 0.0;
|
||||
for (j = nsides; j >= 0; j--) {
|
||||
GLfloat s0, s1, t;
|
||||
GLfloat cosPhi, sinPhi, dist;
|
||||
|
||||
phi += sideDelta;
|
||||
cosPhi = cos(phi);
|
||||
sinPhi = sin(phi);
|
||||
dist = R + r * cosPhi;
|
||||
|
||||
s0 = 20.0 * theta / (2.0 * M_PI);
|
||||
s1 = 20.0 * theta1 / (2.0 * M_PI);
|
||||
t = 8.0 * phi / (2.0 * M_PI);
|
||||
|
||||
Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s1, t);
|
||||
Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
|
||||
vcount++;
|
||||
|
||||
Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
|
||||
Texcoord(tarray[vcount], s0, t);
|
||||
Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi);
|
||||
vcount++;
|
||||
}
|
||||
|
||||
/*glEnd();*/
|
||||
assert(vcount <= 100);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount);
|
||||
|
||||
theta = theta1;
|
||||
cosTheta = cosTheta1;
|
||||
sinTheta = sinTheta1;
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
glScalef(0.5, 0.5, 0.5);
|
||||
|
||||
draw_torus(1.0, 3.0, 30, 60);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
make_texture(void)
|
||||
{
|
||||
#define SZ 64
|
||||
GLenum Filter = GL_LINEAR;
|
||||
GLubyte image[SZ][SZ][4];
|
||||
GLuint i, j;
|
||||
|
||||
for (i = 0; i < SZ; i++) {
|
||||
for (j = 0; j < SZ; j++) {
|
||||
GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2);
|
||||
d = sqrt(d);
|
||||
if (d < SZ/3) {
|
||||
image[i][j][0] = 255;
|
||||
image[i][j][1] = 255;
|
||||
image[i][j][2] = 255;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
else {
|
||||
image[i][j][0] = 127;
|
||||
image[i][j][1] = 127;
|
||||
image[i][j][2] = 127;
|
||||
image[i][j][3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0); /* unit 0 */
|
||||
glBindTexture(GL_TEXTURE_2D, 42);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
#undef SZ
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
static const GLfloat red[4] = {1, 0, 0, 0};
|
||||
static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0};
|
||||
static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0};
|
||||
static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0};
|
||||
static const GLfloat pos[4] = {20, 20, 50, 1};
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
make_texture();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
int anim = 1;
|
||||
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
|
||||
if (!anim || XPending(dpy)) {
|
||||
XEvent event;
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == ' ') {
|
||||
anim = !anim;
|
||||
}
|
||||
else if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
}
|
||||
|
||||
if (anim) {
|
||||
view_rotx += 1.0;
|
||||
view_roty += 2.0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 300, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"torus", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,473 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Brian Paul 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
|
||||
* BRIAN PAUL 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Draw a triangle with X/EGL and OpenGL ES 1.x
|
||||
* Brian Paul
|
||||
* 5 June 2008
|
||||
*/
|
||||
|
||||
#define USE_FULL_GL 0
|
||||
|
||||
#define USE_FIXED_POINT 0
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#if USE_FULL_GL
|
||||
#include <GL/gl.h> /* use full OpenGL */
|
||||
#else
|
||||
#include <GLES/gl.h> /* use OpenGL ES 1.x */
|
||||
#include <GLES/glext.h>
|
||||
#endif
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
#define FLOAT_TO_FIXED(X) ((X) * 65535.0)
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
#if USE_FIXED_POINT
|
||||
static const GLfixed verts[3][2] = {
|
||||
{ -65536, -65536 },
|
||||
{ 65536, -65536 },
|
||||
{ 0, 65536 }
|
||||
};
|
||||
static const GLfixed colors[3][4] = {
|
||||
{ 65536, 0, 0, 65536 },
|
||||
{ 0, 65536, 0 , 65536},
|
||||
{ 0, 0, 65536 , 65536}
|
||||
};
|
||||
#else
|
||||
static const GLfloat verts[3][2] = {
|
||||
{ -1, -1 },
|
||||
{ 1, -1 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
static const GLfloat colors[3][4] = {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 1, 1 }
|
||||
};
|
||||
#endif
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
{
|
||||
#if USE_FIXED_POINT
|
||||
glVertexPointer(2, GL_FIXED, 0, verts);
|
||||
glColorPointer(4, GL_FIXED, 0, colors);
|
||||
#else
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors);
|
||||
#endif
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
/* draw triangle */
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
/* draw some points */
|
||||
glPointSizex(FLOAT_TO_FIXED(15.5));
|
||||
glDrawArrays(GL_POINTS, 0, 3);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
/* test code */
|
||||
GLfixed size;
|
||||
glGetFixedv(GL_POINT_SIZE, &size);
|
||||
printf("GL_POINT_SIZE = 0x%x %f\n", size, size / 65536.0);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -10.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_query_matrix(void)
|
||||
{
|
||||
PFNGLQUERYMATRIXXOESPROC procQueryMatrixx;
|
||||
typedef void (*voidproc)();
|
||||
GLfixed mantissa[16];
|
||||
GLint exponent[16];
|
||||
GLbitfield rv;
|
||||
int i;
|
||||
voidproc p = eglGetProcAddress("eglCreateContext");
|
||||
|
||||
assert(p);
|
||||
procQueryMatrixx = (PFNGLQUERYMATRIXXOESPROC) eglGetProcAddress("glQueryMatrixxOES");
|
||||
assert(procQueryMatrixx);
|
||||
/* Actually try out this one */
|
||||
rv = (*procQueryMatrixx)(mantissa, exponent);
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (rv & (1<<i)) {
|
||||
printf("matrix[%d] invalid\n", i);
|
||||
}
|
||||
else {
|
||||
printf("matrix[%d] = %f * 2^(%d)\n", i, mantissa[i]/65536.0, exponent[i]);
|
||||
}
|
||||
}
|
||||
p = eglGetProcAddress("glFoo");
|
||||
assert(!p);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
|
||||
if (0)
|
||||
test_query_matrix();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 300, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
GLenum value;
|
||||
enum {GetString, GetInteger} type;
|
||||
} info_items[] = {
|
||||
{"GL_RENDERER", GL_RENDERER, GetString},
|
||||
{"GL_VERSION", GL_VERSION, GetString},
|
||||
{"GL_VENDOR", GL_VENDOR, GetString},
|
||||
{"GL_EXTENSIONS", GL_EXTENSIONS, GetString},
|
||||
{"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES, GetInteger},
|
||||
{"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES, GetInteger},
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"OpenGL ES 1.x tri", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
|
||||
switch (info_items[i].type) {
|
||||
case GetString:
|
||||
printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
|
||||
break;
|
||||
case GetInteger: {
|
||||
GLint rv = -1;
|
||||
glGetIntegerv(info_items[i].value, &rv);
|
||||
printf("%s = %d\n", info_items[i].name, rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,433 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Brian Paul 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
|
||||
* BRIAN PAUL 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test drawing to two windows.
|
||||
* Brian Paul
|
||||
* August 2008
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
static int WinWidth[2] = {150, 300}, WinHeight[2] = {150, 300};
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0;
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
GLfloat ar = (GLfloat) width / (GLfloat) height;
|
||||
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
#ifdef GL_VERSION_ES_CM_1_0
|
||||
glFrustumf(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#else
|
||||
glFrustum(-ar, ar, -1, 1, 5.0, 60.0);
|
||||
#endif
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -10.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(int win)
|
||||
{
|
||||
static const GLfloat verts[3][2] = {
|
||||
{ -1, -1 },
|
||||
{ 1, -1 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
static const GLfloat colors[3][4] = {
|
||||
{ 1, 0, 0, 1 },
|
||||
{ 0, 1, 0, 1 },
|
||||
{ 0, 0, 1, 1 }
|
||||
};
|
||||
|
||||
assert(win == 0 || win == 1);
|
||||
|
||||
reshape(WinWidth[win], WinHeight[win]);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1, 0, 0);
|
||||
glRotatef(view_roty, 0, 1, 0);
|
||||
glRotatef(view_rotz, 0, 0, 1);
|
||||
|
||||
/* draw triangle */
|
||||
{
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts);
|
||||
glColorPointer(4, GL_FLOAT, 0, colors);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, x, y, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
if (ctxRet) {
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, NULL );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win1, Window win2,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf1, EGLSurface egl_surf2,
|
||||
EGLContext egl_ctx)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
int win;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if (event.xconfigure.window == win1)
|
||||
win = 0;
|
||||
else
|
||||
win = 1;
|
||||
WinWidth[win] = event.xconfigure.width;
|
||||
WinHeight[win] = event.xconfigure.height;
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
/* win 1 */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf1, egl_surf1, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(1) failed\n");
|
||||
return;
|
||||
}
|
||||
draw(0);
|
||||
eglSwapBuffers(egl_dpy, egl_surf1);
|
||||
|
||||
/* win 2 */
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf2, egl_surf2, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent(2) failed\n");
|
||||
return;
|
||||
}
|
||||
draw(1);
|
||||
eglSwapBuffers(egl_dpy, egl_surf2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
Display *x_dpy;
|
||||
Window win1, win2;
|
||||
EGLSurface egl_surf1, egl_surf2;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
GLenum value;
|
||||
enum {GetString, GetInteger} type;
|
||||
} info_items[] = {
|
||||
{"GL_RENDERER", GL_RENDERER, GetString},
|
||||
{"GL_VERSION", GL_VERSION, GetString},
|
||||
{"GL_VENDOR", GL_VENDOR, GetString},
|
||||
{"GL_EXTENSIONS", GL_EXTENSIONS, GetString},
|
||||
{"GL_MAX_PALETTE_MATRICES_OES", GL_MAX_PALETTE_MATRICES_OES, GetInteger},
|
||||
{"GL_MAX_VERTEX_UNITS_OES", GL_MAX_VERTEX_UNITS_OES, GetInteger},
|
||||
};
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"xegl_two_win #1", 0, 0, WinWidth[0], WinHeight[0],
|
||||
&win1, &egl_ctx, &egl_surf1);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"xegl_two_win #2", WinWidth[0] + 50, 0,
|
||||
WinWidth[1], WinHeight[1],
|
||||
&win2, NULL, &egl_surf2);
|
||||
|
||||
XMapWindow(x_dpy, win1);
|
||||
|
||||
XMapWindow(x_dpy, win2);
|
||||
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf1, egl_surf1, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
for (i = 0; i < sizeof(info_items)/sizeof(info_items[0]); i++) {
|
||||
switch (info_items[i].type) {
|
||||
case GetString:
|
||||
printf("%s = %s\n", info_items[i].name, (char *)glGetString(info_items[i].value));
|
||||
break;
|
||||
case GetInteger: {
|
||||
GLint rv = -1;
|
||||
glGetIntegerv(info_items[i].value, &rv);
|
||||
printf("%s = %d\n", info_items[i].name, rv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
event_loop(x_dpy, win1, win2, egl_dpy, egl_surf1, egl_surf2, egl_ctx);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf1);
|
||||
eglDestroySurface(egl_dpy, egl_surf2);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
XDestroyWindow(x_dpy, win1);
|
||||
XDestroyWindow(x_dpy, win2);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
# progs/es2/xegl/Makefile
|
||||
|
||||
TOP = ../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
INCLUDE_DIRS = \
|
||||
-I$(TOP)/include \
|
||||
|
||||
HEADERS = $(TOP)/include/GLES/egl.h
|
||||
|
||||
|
||||
ES2_LIB_DEPS = \
|
||||
$(TOP)/$(LIB_DIR)/libEGL.so \
|
||||
$(TOP)/$(LIB_DIR)/libGLESv2.so
|
||||
|
||||
|
||||
ES2_LIBS = \
|
||||
-L$(TOP)/$(LIB_DIR) -lEGL \
|
||||
-L$(TOP)/$(LIB_DIR) -lGLESv2 $(LIBDRM_LIB) -lX11
|
||||
|
||||
PROGRAMS = \
|
||||
es2_info \
|
||||
tri
|
||||
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
|
||||
default: $(PROGRAMS)
|
||||
|
||||
|
||||
|
||||
es2_info.c:
|
||||
cp ../../es1/xegl/es1_info.c es2_info.c
|
||||
|
||||
es2_info: es2_info.o $(ES2_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) es2_info.o $(ES2_LIBS) -o $@
|
||||
|
||||
tri: tri.o $(ES2_LIB_DEPS)
|
||||
$(CC) $(CFLAGS) tri.o $(ES2_LIBS) -o $@
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
rm -f $(PROGRAMS)
|
||||
rm -f es2_info.c
|
||||
|
||||
@@ -1,516 +0,0 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Draw a triangle with X/EGL and OpenGL ES 2.x
|
||||
*/
|
||||
|
||||
#define USE_FULL_GL 0
|
||||
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#if USE_FULL_GL
|
||||
#include <GL/gl.h> /* use full OpenGL */
|
||||
#else
|
||||
#include <GLES2/gl2.h> /* use OpenGL ES 2.x */
|
||||
#endif
|
||||
#include <EGL/egl.h>
|
||||
|
||||
|
||||
#define FLOAT_TO_FIXED(X) ((X) * 65535.0)
|
||||
|
||||
|
||||
|
||||
static GLfloat view_rotx = 0.0, view_roty = 0.0;
|
||||
|
||||
static GLint u_matrix = -1;
|
||||
static GLint attr_pos = 0, attr_color = 1;
|
||||
|
||||
|
||||
static void
|
||||
make_z_rot_matrix(GLfloat angle, GLfloat *m)
|
||||
{
|
||||
float c = cos(angle * M_PI / 180.0);
|
||||
float s = sin(angle * M_PI / 180.0);
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
m[i] = 0.0;
|
||||
m[0] = m[5] = m[10] = m[15] = 1.0;
|
||||
|
||||
m[0] = c;
|
||||
m[1] = s;
|
||||
m[4] = -s;
|
||||
m[5] = c;
|
||||
}
|
||||
|
||||
static void
|
||||
make_scale_matrix(GLfloat xs, GLfloat ys, GLfloat zs, GLfloat *m)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++)
|
||||
m[i] = 0.0;
|
||||
m[0] = xs;
|
||||
m[5] = ys;
|
||||
m[10] = zs;
|
||||
m[15] = 1.0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mul_matrix(GLfloat *prod, const GLfloat *a, const GLfloat *b)
|
||||
{
|
||||
#define A(row,col) a[(col<<2)+row]
|
||||
#define B(row,col) b[(col<<2)+row]
|
||||
#define P(row,col) p[(col<<2)+row]
|
||||
GLfloat p[16];
|
||||
GLint i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
|
||||
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
|
||||
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
|
||||
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
|
||||
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
|
||||
}
|
||||
memcpy(prod, p, sizeof(p));
|
||||
#undef A
|
||||
#undef B
|
||||
#undef PROD
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
static const GLfloat verts[3][2] = {
|
||||
{ -1, -1 },
|
||||
{ 1, -1 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
static const GLfloat colors[3][3] = {
|
||||
{ 1, 0, 0 },
|
||||
{ 0, 1, 0 },
|
||||
{ 0, 0, 1 }
|
||||
};
|
||||
GLfloat mat[16], rot[16], scale[16];
|
||||
|
||||
/* Set modelview/projection matrix */
|
||||
make_z_rot_matrix(view_rotx, rot);
|
||||
make_scale_matrix(0.5, 0.5, 0.5, scale);
|
||||
mul_matrix(mat, rot, scale);
|
||||
glUniformMatrix4fv(u_matrix, 1, GL_FALSE, mat);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
{
|
||||
glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(attr_color, 3, GL_FLOAT, GL_FALSE, 0, colors);
|
||||
glEnableVertexAttribArray(attr_pos);
|
||||
glEnableVertexAttribArray(attr_color);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
glDisableVertexAttribArray(attr_pos);
|
||||
glDisableVertexAttribArray(attr_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
glViewport(0, 0, (GLint) width, (GLint) height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
create_shaders(void)
|
||||
{
|
||||
static const char *fragShaderText =
|
||||
"varying vec4 v_color;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = v_color;\n"
|
||||
"}\n";
|
||||
static const char *vertShaderText =
|
||||
"uniform mat4 modelviewProjection;\n"
|
||||
"attribute vec4 pos;\n"
|
||||
"attribute vec4 color;\n"
|
||||
"varying vec4 v_color;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = modelviewProjection * pos;\n"
|
||||
" v_color = color;\n"
|
||||
"}\n";
|
||||
|
||||
GLuint fragShader, vertShader, program;
|
||||
GLint stat;
|
||||
|
||||
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragShader, 1, (const char **) &fragShaderText, NULL);
|
||||
glCompileShader(fragShader);
|
||||
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &stat);
|
||||
if (!stat) {
|
||||
printf("Error: fragment shader did not compile!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vertShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertShader, 1, (const char **) &vertShaderText, NULL);
|
||||
glCompileShader(vertShader);
|
||||
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &stat);
|
||||
if (!stat) {
|
||||
printf("Error: vertex shader did not compile!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, fragShader);
|
||||
glAttachShader(program, vertShader);
|
||||
glLinkProgram(program);
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &stat);
|
||||
if (!stat) {
|
||||
char log[1000];
|
||||
GLsizei len;
|
||||
glGetProgramInfoLog(program, 1000, &len, log);
|
||||
printf("Error: linking:\n%s\n", log);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
if (1) {
|
||||
/* test setting attrib locations */
|
||||
glBindAttribLocation(program, attr_pos, "pos");
|
||||
glBindAttribLocation(program, attr_color, "color");
|
||||
glLinkProgram(program); /* needed to put attribs into effect */
|
||||
}
|
||||
else {
|
||||
/* test automatic attrib locations */
|
||||
attr_pos = glGetAttribLocation(program, "pos");
|
||||
attr_color = glGetAttribLocation(program, "color");
|
||||
}
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "modelviewProjection");
|
||||
printf("Uniform modelviewProjection at %d\n", u_matrix);
|
||||
printf("Attrib pos at %d\n", attr_pos);
|
||||
printf("Attrib color at %d\n", attr_color);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(void)
|
||||
{
|
||||
typedef void (*proc)();
|
||||
|
||||
#if 1 /* test code */
|
||||
proc p = eglGetProcAddress("eglCreateContext");
|
||||
assert(p);
|
||||
p = eglGetProcAddress("glMapBufferOES");
|
||||
assert(p);
|
||||
#endif
|
||||
|
||||
glClearColor(0.4, 0.4, 0.4, 0.0);
|
||||
|
||||
create_shaders();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create an RGB, double-buffered X window.
|
||||
* Return the window and context handles.
|
||||
*/
|
||||
static void
|
||||
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
|
||||
const char *name,
|
||||
int x, int y, int width, int height,
|
||||
Window *winRet,
|
||||
EGLContext *ctxRet,
|
||||
EGLSurface *surfRet)
|
||||
{
|
||||
static const EGLint attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
static const EGLint ctx_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
int scrnum;
|
||||
XSetWindowAttributes attr;
|
||||
unsigned long mask;
|
||||
Window root;
|
||||
Window win;
|
||||
XVisualInfo *visInfo, visTemplate;
|
||||
int num_visuals;
|
||||
EGLContext ctx;
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
EGLint vid;
|
||||
|
||||
scrnum = DefaultScreen( x_dpy );
|
||||
root = RootWindow( x_dpy, scrnum );
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
|
||||
printf("Error: couldn't get an EGL visual config\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(config);
|
||||
assert(num_configs > 0);
|
||||
|
||||
if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
|
||||
printf("Error: eglGetConfigAttrib() failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The X window visual must match the EGL config */
|
||||
visTemplate.visualid = vid;
|
||||
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
|
||||
if (!visInfo) {
|
||||
printf("Error: couldn't get X visual\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* window attributes */
|
||||
attr.background_pixel = 0;
|
||||
attr.border_pixel = 0;
|
||||
attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
|
||||
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
|
||||
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
||||
|
||||
win = XCreateWindow( x_dpy, root, 0, 0, width, height,
|
||||
0, visInfo->depth, InputOutput,
|
||||
visInfo->visual, mask, &attr );
|
||||
|
||||
/* set hints and properties */
|
||||
{
|
||||
XSizeHints sizehints;
|
||||
sizehints.x = x;
|
||||
sizehints.y = y;
|
||||
sizehints.width = width;
|
||||
sizehints.height = height;
|
||||
sizehints.flags = USSize | USPosition;
|
||||
XSetNormalHints(x_dpy, win, &sizehints);
|
||||
XSetStandardProperties(x_dpy, win, name, name,
|
||||
None, (char **)NULL, 0, &sizehints);
|
||||
}
|
||||
|
||||
#if USE_FULL_GL /* XXX fix this when eglBindAPI() works */
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
|
||||
ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
|
||||
if (!ctx) {
|
||||
printf("Error: eglCreateContext failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* test eglQueryContext() */
|
||||
{
|
||||
EGLint val;
|
||||
eglQueryContext(egl_dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &val);
|
||||
assert(val == 2);
|
||||
}
|
||||
|
||||
*surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
|
||||
if (!*surfRet) {
|
||||
printf("Error: eglCreateWindowSurface failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
{
|
||||
EGLint val;
|
||||
eglQuerySurface(egl_dpy, *surfRet, EGL_WIDTH, &val);
|
||||
assert(val == width);
|
||||
eglQuerySurface(egl_dpy, *surfRet, EGL_HEIGHT, &val);
|
||||
assert(val == height);
|
||||
eglQuerySurface(egl_dpy, *surfRet, EGL_SURFACE_TYPE, &val);
|
||||
assert(val == EGL_WINDOW_BIT);
|
||||
}
|
||||
|
||||
XFree(visInfo);
|
||||
|
||||
*winRet = win;
|
||||
*ctxRet = ctx;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
event_loop(Display *dpy, Window win,
|
||||
EGLDisplay egl_dpy, EGLSurface egl_surf)
|
||||
{
|
||||
while (1) {
|
||||
int redraw = 0;
|
||||
XEvent event;
|
||||
|
||||
XNextEvent(dpy, &event);
|
||||
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
redraw = 1;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
reshape(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case KeyPress:
|
||||
{
|
||||
char buffer[10];
|
||||
int r, code;
|
||||
code = XLookupKeysym(&event.xkey, 0);
|
||||
if (code == XK_Left) {
|
||||
view_roty += 5.0;
|
||||
}
|
||||
else if (code == XK_Right) {
|
||||
view_roty -= 5.0;
|
||||
}
|
||||
else if (code == XK_Up) {
|
||||
view_rotx += 5.0;
|
||||
}
|
||||
else if (code == XK_Down) {
|
||||
view_rotx -= 5.0;
|
||||
}
|
||||
else {
|
||||
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
|
||||
NULL, NULL);
|
||||
if (buffer[0] == 27) {
|
||||
/* escape */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw = 1;
|
||||
break;
|
||||
default:
|
||||
; /*no-op*/
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
draw();
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf(" -display <displayname> set the display to run on\n");
|
||||
printf(" -info display OpenGL renderer info\n");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const int winWidth = 300, winHeight = 300;
|
||||
Display *x_dpy;
|
||||
Window win;
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
char *dpyName = NULL;
|
||||
GLboolean printInfo = GL_FALSE;
|
||||
EGLint egl_major, egl_minor;
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
dpyName = argv[i+1];
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-info") == 0) {
|
||||
printInfo = GL_TRUE;
|
||||
}
|
||||
else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
x_dpy = XOpenDisplay(dpyName);
|
||||
if (!x_dpy) {
|
||||
printf("Error: couldn't open display %s\n",
|
||||
dpyName ? dpyName : getenv("DISPLAY"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
egl_dpy = eglGetDisplay(x_dpy);
|
||||
if (!egl_dpy) {
|
||||
printf("Error: eglGetDisplay() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) {
|
||||
printf("Error: eglInitialize() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VERSION);
|
||||
printf("EGL_VERSION = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_VENDOR);
|
||||
printf("EGL_VENDOR = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_EXTENSIONS);
|
||||
printf("EGL_EXTENSIONS = %s\n", s);
|
||||
|
||||
s = eglQueryString(egl_dpy, EGL_CLIENT_APIS);
|
||||
printf("EGL_CLIENT_APIS = %s\n", s);
|
||||
|
||||
make_x_window(x_dpy, egl_dpy,
|
||||
"OpenGL ES 2.x tri", 0, 0, winWidth, winHeight,
|
||||
&win, &egl_ctx, &egl_surf);
|
||||
|
||||
XMapWindow(x_dpy, win);
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) {
|
||||
printf("Error: eglMakeCurrent() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (printInfo) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
/* Set initial projection/viewing transformation.
|
||||
* We can't be sure we'll get a ConfigureNotify event when the window
|
||||
* first appears.
|
||||
*/
|
||||
reshape(winWidth, winHeight);
|
||||
|
||||
event_loop(x_dpy, win, egl_dpy, egl_surf);
|
||||
|
||||
eglDestroyContext(egl_dpy, egl_ctx);
|
||||
eglDestroySurface(egl_dpy, egl_surf);
|
||||
eglTerminate(egl_dpy);
|
||||
|
||||
|
||||
XDestroyWindow(x_dpy, win);
|
||||
XCloseDisplay(x_dpy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <GL/glut.h>
|
||||
|
||||
static GLint WinWidth = 500, WinHeight = 500;
|
||||
static GLboolean Invert = GL_FALSE;
|
||||
|
||||
|
||||
static void Display(void)
|
||||
@@ -51,15 +50,7 @@ static void Display(void)
|
||||
glPixelZoom(4.0, 4.0);
|
||||
glColor4f(1, 0, 0, 0);
|
||||
glWindowPos2i(100, 0);
|
||||
if (Invert) {
|
||||
glPixelTransferf(GL_DEPTH_SCALE, -1.0);
|
||||
glPixelTransferf(GL_DEPTH_BIAS, 1.0);
|
||||
}
|
||||
glDrawPixels(100, 100, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
|
||||
if (Invert) {
|
||||
glPixelTransferf(GL_DEPTH_SCALE, 1.0);
|
||||
glPixelTransferf(GL_DEPTH_BIAS, 0.0);
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
@@ -86,9 +77,6 @@ static void Key(unsigned char key, int x, int y)
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case 'i':
|
||||
Invert = !Invert;
|
||||
break;
|
||||
case 27:
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
@@ -119,6 +119,12 @@ static void Init( void )
|
||||
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum);
|
||||
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
sz, (const GLubyte *) buf);
|
||||
if (glGetError()) {
|
||||
printf("Program failed to compile:\n%s\n", buf);
|
||||
printf("Error: %s\n",
|
||||
(char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
||||
exit(1);
|
||||
}
|
||||
assert(glIsProgramARB(prognum));
|
||||
}
|
||||
|
||||
|
||||
@@ -340,7 +340,6 @@ def generate(env):
|
||||
'-m32',
|
||||
#'-march=pentium4',
|
||||
'-mmmx', '-msse', '-msse2', # enable SIMD intrinsics
|
||||
'-mstackrealign', # ensure stack is aligned -- do not enabled -msse without it!
|
||||
#'-mfpmath=sse',
|
||||
]
|
||||
if env['machine'] == 'x86_64':
|
||||
|
||||
@@ -56,17 +56,15 @@ def generate(env):
|
||||
env.PrependENVPath('PATH', llvm_bin_dir)
|
||||
|
||||
if env.Detect('llvm-config'):
|
||||
version = env.backtick('llvm-config --version').rstrip()
|
||||
|
||||
try:
|
||||
env.ParseConfig('llvm-config --cppflags')
|
||||
env.ParseConfig('llvm-config --libs jit interpreter nativecodegen bitwriter')
|
||||
env.ParseConfig('llvm-config --ldflags')
|
||||
except OSError:
|
||||
print 'llvm-config version %s failed' % version
|
||||
else:
|
||||
env['LINK'] = env['CXX']
|
||||
env['LLVM_VERSION'] = version
|
||||
env['LLVM_VERSION'] = env.backtick('llvm-config --version')
|
||||
except AttributeError:
|
||||
env['LLVM_VERSION'] = 'X.X'
|
||||
|
||||
env.ParseConfig('llvm-config --cppflags')
|
||||
env.ParseConfig('llvm-config --libs jit interpreter nativecodegen bitwriter')
|
||||
env.ParseConfig('llvm-config --ldflags')
|
||||
env['LINK'] = env['CXX']
|
||||
|
||||
def exists(env):
|
||||
return True
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
include $(call all-subdir-makefiles)
|
||||
@@ -1,41 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
main/eglapi.c \
|
||||
main/eglclient.c \
|
||||
main/eglconfig.c \
|
||||
main/eglconfigutil.c \
|
||||
main/eglcontext.c \
|
||||
main/eglcurrent.c \
|
||||
main/egldisplay.c \
|
||||
main/egldriver.c \
|
||||
main/eglglobals.c \
|
||||
main/eglimage.c \
|
||||
main/egllog.c \
|
||||
main/eglmisc.c \
|
||||
main/eglmode.c \
|
||||
main/eglscreen.c \
|
||||
main/eglstring.c \
|
||||
main/eglsurface.c
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
drivers/android/egl_android.c \
|
||||
drivers/android/droid_loader.c \
|
||||
drivers/android/droid_ui.cpp \
|
||||
drivers/android/droid_intel.c
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH)/main \
|
||||
external/mesa/include \
|
||||
external/mesa/src/mesa \
|
||||
external/drm/shared-core
|
||||
|
||||
LOCAL_CFLAGS += -DPTHREADS
|
||||
LOCAL_SHARED_LIBRARIES := libdl libui libutils
|
||||
LOCAL_STATIC_LIBRARIES := libes1api
|
||||
|
||||
LOCAL_MODULE := libhgl
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
|
||||
*
|
||||
* This is based on the work of eagle, by
|
||||
* Copyright © 2008, 2009 Kristian Høgsberg
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DROID_H_
|
||||
#define _DROID_H_
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/internal/dri_interface.h"
|
||||
|
||||
#include "eglcurrent.h"
|
||||
#include "egldisplay.h"
|
||||
#include "eglcontext.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglconfig.h"
|
||||
|
||||
/* opaque types */
|
||||
struct droid_loader;
|
||||
struct droid_context;
|
||||
struct droid_drawable;
|
||||
struct droid_image;
|
||||
struct droid_surface;
|
||||
|
||||
struct droid_backend {
|
||||
/* these are usually used by a loader */
|
||||
const char *driver_name;
|
||||
int (*initialize)(struct droid_backend *backend, int *fd, int *screen_number);
|
||||
int (*process_config)(struct droid_backend *backend, _EGLConfig *conf);
|
||||
void (*destroy)(struct droid_backend *backend);
|
||||
|
||||
__DRIbuffer *(*get_native_buffer)(struct droid_backend *backend,
|
||||
struct droid_surface *surf,
|
||||
int *width, int *height);
|
||||
__DRIbuffer *(*get_surface_buffers)(struct droid_backend *backend,
|
||||
struct droid_surface *surf,
|
||||
int *width, int *height,
|
||||
unsigned int *attachments, int count,
|
||||
int *out_count, int has_format);
|
||||
|
||||
/* public methods */
|
||||
struct droid_surface *(*create_window_surface)(struct droid_backend *backend,
|
||||
_EGLSurface *surf,
|
||||
NativeWindowType win);
|
||||
struct droid_surface *(*create_image_surface)(struct droid_backend *backend,
|
||||
NativePixmapType pix);
|
||||
void (*destroy_surface)(struct droid_backend *backend, struct droid_surface *surf);
|
||||
void (*swap_native_buffers)(struct droid_backend *backend,
|
||||
struct droid_surface *surf);
|
||||
|
||||
int (*match_pixmap)(struct droid_backend *backend, _EGLConfig *conf,
|
||||
NativePixmapType pix);
|
||||
};
|
||||
|
||||
struct droid_screen {
|
||||
struct droid_loader *loader;
|
||||
|
||||
__DRIscreen *dri_screen;
|
||||
__DRItexBufferExtension *tex_buffer;
|
||||
__DRIcopyBufferExtension *copy_buffer;
|
||||
|
||||
const __DRIconfig **dri_configs;
|
||||
int num_dri_configs;
|
||||
};
|
||||
|
||||
struct droid_backend *
|
||||
droid_backend_create_intel(const char *dev);
|
||||
|
||||
void
|
||||
droid_backend_destroy(struct droid_backend *backend);
|
||||
|
||||
struct droid_screen *
|
||||
droid_screen_create(struct droid_backend *backend);
|
||||
|
||||
void
|
||||
droid_screen_destroy(struct droid_screen *screen);
|
||||
|
||||
int
|
||||
droid_screen_convert_config(struct droid_screen *screen,
|
||||
const __DRIconfig *conf, _EGLConfig *egl_conf);
|
||||
|
||||
struct droid_context *
|
||||
droid_screen_create_context(struct droid_screen *screen,
|
||||
const __DRIconfig *conf,
|
||||
struct droid_context *shared);
|
||||
|
||||
void
|
||||
droid_screen_destroy_context(struct droid_screen *screen,
|
||||
struct droid_context *ctx);
|
||||
|
||||
struct droid_drawable *
|
||||
droid_screen_create_drawable(struct droid_screen *screen,
|
||||
const __DRIconfig *conf,
|
||||
struct droid_surface *surf);
|
||||
|
||||
void *
|
||||
droid_screen_get_drawable_data(struct droid_screen *screen,
|
||||
struct droid_drawable *drawable);
|
||||
|
||||
void
|
||||
droid_screen_destroy_drawable(struct droid_screen *screen,
|
||||
struct droid_drawable *drawable);
|
||||
|
||||
int
|
||||
droid_screen_bind_context(struct droid_screen *screen,
|
||||
struct droid_drawable *draw,
|
||||
struct droid_drawable *read,
|
||||
struct droid_context *ctx);
|
||||
|
||||
int
|
||||
droid_screen_swap_buffers(struct droid_screen *screen,
|
||||
struct droid_context *ctx,
|
||||
struct droid_drawable *drawable);
|
||||
|
||||
#endif /* _DROID_H_ */
|
||||
@@ -1,648 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
|
||||
*
|
||||
* This is based on the work of eagle, by
|
||||
* Copyright © 2008, 2009 Kristian Høgsberg
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DROID-INTEL"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <i915_drm.h>
|
||||
#include <GL/gl.h> /* dri_interface.h uses some GL integer types... */
|
||||
#include <GL/internal/dri_interface.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include "droid.h"
|
||||
#include "droid_ui.h"
|
||||
|
||||
#define INTEL_IS_I965(x) ((x) & INTEL_GEN_4)
|
||||
#define INTEL_IS_I915(x) ((x) & INTEL_GEN_3)
|
||||
#define INTEL_IS_I9xx(x) ((x) & (INTEL_GEN_3 | INTEL_GEN_4))
|
||||
#define INTEL_IS_I8xx(x) ((x) & (INTEL_GEN_1 | INTEL_GEN_2))
|
||||
|
||||
#define INTEL_HAS_128_BYTE_Y_TILING(x) \
|
||||
(((x) & (INTEL_GEN_3 | INTEL_GEN_4 | INTEL_GEN_MINOR_MASK)) > INTEL_GEN_3)
|
||||
|
||||
enum {
|
||||
INTEL_SURFACE_TYPE_WINDOW,
|
||||
INTEL_SURFACE_TYPE_IMAGE,
|
||||
};
|
||||
|
||||
/* Look at xf86-video-intel/src/common.h for the full horror of device
|
||||
* identification.
|
||||
*/
|
||||
enum {
|
||||
INTEL_GEN_1 = 0x10,
|
||||
INTEL_GEN_2 = 0x20,
|
||||
INTEL_GEN_3 = 0x40,
|
||||
INTEL_GEN_31 = 0x41,
|
||||
INTEL_GEN_4 = 0x80,
|
||||
|
||||
INTEL_GEN_MAJOR_MASK = 0xf0,
|
||||
INTEL_GEN_MINOR_MASK = 0x0f,
|
||||
};
|
||||
|
||||
struct droid_backend_intel {
|
||||
struct droid_backend base;
|
||||
int fd;
|
||||
int screen_number;
|
||||
|
||||
uint32_t generation;
|
||||
int pitch_align;
|
||||
int enable_tiling;
|
||||
};
|
||||
|
||||
struct droid_surface_intel {
|
||||
int type;
|
||||
union {
|
||||
NativeWindowType win;
|
||||
NativePixmapType pix;
|
||||
} native;
|
||||
__DRIbuffer native_buffer;
|
||||
unsigned int native_width, native_height;
|
||||
int native_changed;
|
||||
|
||||
unsigned int attachments[20];
|
||||
__DRIbuffer buffers[10];
|
||||
uint32_t handles[10];
|
||||
int num_buffers;
|
||||
int depth_idx;
|
||||
|
||||
_EGLSurface *surf;
|
||||
};
|
||||
|
||||
static INLINE struct droid_backend_intel *
|
||||
lookup_backend(struct droid_backend *backend)
|
||||
{
|
||||
return (struct droid_backend_intel *) backend;
|
||||
}
|
||||
|
||||
static INLINE struct droid_surface_intel *
|
||||
lookup_surface(struct droid_surface *surface)
|
||||
{
|
||||
return (struct droid_surface_intel *) surface;
|
||||
}
|
||||
|
||||
static __DRIbuffer *
|
||||
intel_get_native_buffer(struct droid_backend *backend,
|
||||
struct droid_surface *surf,
|
||||
int *width, int *height)
|
||||
{
|
||||
struct droid_surface_intel *isurf = lookup_surface(surf);
|
||||
|
||||
/* non-window surface is single-buffered */
|
||||
if (isurf->type != INTEL_SURFACE_TYPE_WINDOW)
|
||||
return NULL;
|
||||
|
||||
if (!isurf->native_buffer.name)
|
||||
return NULL;
|
||||
|
||||
if (width)
|
||||
*width = isurf->native_width;
|
||||
if (height)
|
||||
*height = isurf->native_height;
|
||||
|
||||
return &isurf->native_buffer;
|
||||
}
|
||||
|
||||
static INLINE uint32_t
|
||||
align_to(uint32_t value, uint32_t align)
|
||||
{
|
||||
return (value + align - 1) & ~(align - 1);
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
fence_pitch(struct droid_backend *backend, int pitch, int tiling)
|
||||
{
|
||||
struct droid_backend_intel *intel = lookup_backend(backend);
|
||||
int pitch_align, tile_width;
|
||||
|
||||
switch (tiling) {
|
||||
case I915_TILING_NONE:
|
||||
default:
|
||||
pitch_align = intel->pitch_align;
|
||||
tile_width = 1; /* not used */
|
||||
break;
|
||||
case I915_TILING_X:
|
||||
pitch_align = 512;
|
||||
tile_width = 512;
|
||||
break;
|
||||
case I915_TILING_Y:
|
||||
pitch_align = 512;
|
||||
tile_width =
|
||||
(INTEL_HAS_128_BYTE_Y_TILING(intel->generation)) ? 128 : 512;
|
||||
break;
|
||||
}
|
||||
|
||||
pitch = align_to(pitch, pitch_align);
|
||||
if (tiling == I915_TILING_NONE)
|
||||
return pitch;
|
||||
|
||||
/* 965+ just needs multiples of tile width */
|
||||
if (INTEL_IS_I965(intel->generation)) {
|
||||
pitch = align_to(pitch, tile_width);
|
||||
}
|
||||
else {
|
||||
/* Pre-965 needs power of two tile widths */
|
||||
while (tile_width < pitch)
|
||||
tile_width <<= 1;
|
||||
pitch = tile_width;
|
||||
}
|
||||
|
||||
return pitch;
|
||||
}
|
||||
|
||||
static INLINE uint32_t
|
||||
fence_size(struct droid_backend *backend, int height, int pitch, int tiling)
|
||||
{
|
||||
struct droid_backend_intel *intel = lookup_backend(backend);
|
||||
int height_align;
|
||||
uint32_t size;
|
||||
|
||||
switch (tiling) {
|
||||
case I915_TILING_NONE:
|
||||
default:
|
||||
/* Round the height up so that the GPU's access to a 2x2 aligned
|
||||
* subspan doesn't address an invalid page offset beyond the
|
||||
* end of the GTT.
|
||||
*/
|
||||
height_align = 2;
|
||||
break;
|
||||
case I915_TILING_X:
|
||||
height_align = 8;
|
||||
break;
|
||||
case I915_TILING_Y:
|
||||
height_align = 32;
|
||||
break;
|
||||
}
|
||||
|
||||
height = align_to(height, height_align);
|
||||
size = pitch * height;
|
||||
if (tiling == I915_TILING_NONE)
|
||||
return size;
|
||||
|
||||
/* The 965 can have fences at any page boundary. */
|
||||
if (INTEL_IS_I965(intel->generation)) {
|
||||
size = align_to(size, 4096);
|
||||
}
|
||||
else {
|
||||
uint32_t fence;
|
||||
|
||||
/* Align the size to a power of two greater than the smallest fence. */
|
||||
if (INTEL_IS_I9xx(intel->generation))
|
||||
fence = 1 << 20; /* 1 MiB */
|
||||
else
|
||||
fence = 1 << 19; /* 512 KiB */
|
||||
|
||||
while (fence < size)
|
||||
fence <<= 1;
|
||||
|
||||
size = fence;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int
|
||||
create_buffer(struct droid_backend *backend, __DRIbuffer *buffer,
|
||||
int width, int height, int cpp, int tiling)
|
||||
{
|
||||
struct droid_backend_intel *intel = lookup_backend(backend);
|
||||
struct drm_i915_gem_create create;
|
||||
struct drm_gem_flink flink;
|
||||
|
||||
buffer->pitch = fence_pitch(backend, width * cpp, tiling);
|
||||
create.size = fence_size(backend, height, buffer->pitch, tiling);
|
||||
if (ioctl(intel->fd, DRM_IOCTL_I915_GEM_CREATE, &create)) {
|
||||
LOGE("failed to create buffer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tiling != I915_TILING_NONE) {
|
||||
struct drm_i915_gem_set_tiling set_tiling;
|
||||
|
||||
memset(&set_tiling, 0, sizeof(set_tiling));
|
||||
set_tiling.handle = create.handle;
|
||||
set_tiling.tiling_mode = tiling;
|
||||
set_tiling.stride = buffer->pitch;
|
||||
|
||||
if (ioctl(intel->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling))
|
||||
LOGW("failed to enable tiling");
|
||||
}
|
||||
|
||||
flink.handle = create.handle;
|
||||
if (ioctl(intel->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
|
||||
LOGE("failed to flink buffer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer->name = flink.name;
|
||||
buffer->cpp = cpp;
|
||||
buffer->flags = 0;
|
||||
|
||||
return create.handle;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_buffers(struct droid_backend *backend, struct droid_surface *surf)
|
||||
{
|
||||
struct droid_backend_intel *intel = lookup_backend(backend);
|
||||
struct droid_surface_intel *isurf = lookup_surface(surf);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < isurf->num_buffers; i++) {
|
||||
if (isurf->handles[i]) {
|
||||
struct drm_gem_close close;
|
||||
|
||||
close.handle = isurf->handles[i];
|
||||
if (ioctl(intel->fd, DRM_IOCTL_GEM_CLOSE, &close) < 0)
|
||||
LOGE("failed to close bo %d", close.handle);
|
||||
isurf->handles[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
isurf->num_buffers = 0;
|
||||
}
|
||||
|
||||
static __DRIbuffer *
|
||||
intel_get_surface_buffers(struct droid_backend *backend,
|
||||
struct droid_surface *surf,
|
||||
int *width, int *height,
|
||||
unsigned int *attachments, int count,
|
||||
int *out_count, int has_format)
|
||||
{
|
||||
struct droid_backend_intel *intel = lookup_backend(backend);
|
||||
struct droid_surface_intel *isurf = lookup_surface(surf);
|
||||
unsigned int att_size;
|
||||
__DRIbuffer buffers[10];
|
||||
uint32_t handles[10];
|
||||
int num = 0;
|
||||
|
||||
if (count > 10) {
|
||||
LOGW("too many buffers requested");
|
||||
count = 10;
|
||||
}
|
||||
|
||||
att_size = sizeof(attachments[0]) * count * ((has_format) ? 2 : 1);
|
||||
|
||||
if (isurf->native_changed) {
|
||||
delete_buffers(backend, surf);
|
||||
isurf->native_changed = 0;
|
||||
}
|
||||
|
||||
/* same buffers requested */
|
||||
if (isurf->num_buffers == count &&
|
||||
memcmp(isurf->attachments, attachments, att_size) == 0) {
|
||||
num = isurf->num_buffers;
|
||||
goto end;
|
||||
}
|
||||
memcpy(isurf->attachments, attachments, att_size);
|
||||
|
||||
while (count-- > 0) {
|
||||
unsigned int att = *attachments++;
|
||||
unsigned int format = (has_format) ? *attachments++ : 0;
|
||||
unsigned int cpp = (format) ? format / 8 : isurf->native_buffer.cpp;
|
||||
__DRIbuffer *buf = NULL;
|
||||
int reuse;
|
||||
|
||||
/* re-use buffer */
|
||||
for (reuse = 0; reuse < isurf->num_buffers; reuse++) {
|
||||
if (isurf->buffers[reuse].attachment == att) {
|
||||
if (isurf->buffers[reuse].cpp == cpp &&
|
||||
isurf->handles[reuse])
|
||||
buf = &isurf->buffers[reuse];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0)
|
||||
LOGD("%s buffer %d: att %d cpp %d",
|
||||
(buf) ? "reuse" : "create", num, att, cpp);
|
||||
|
||||
if (buf) {
|
||||
buffers[num] = isurf->buffers[reuse];
|
||||
handles[num] = isurf->handles[reuse];
|
||||
isurf->handles[reuse] = 0;
|
||||
}
|
||||
else {
|
||||
int tiling =
|
||||
(intel->enable_tiling) ? I915_TILING_X : I915_TILING_NONE;
|
||||
|
||||
buffers[num].attachment = att;
|
||||
|
||||
if (isurf->type == INTEL_SURFACE_TYPE_IMAGE &&
|
||||
att == __DRI_BUFFER_FRONT_LEFT) {
|
||||
/* return native buffer */
|
||||
buffers[num] = isurf->native_buffer;
|
||||
buffers[num].attachment = att;
|
||||
handles[num] = 0;
|
||||
} else {
|
||||
buffers[num].attachment = att;
|
||||
handles[num] = create_buffer(backend, &buffers[num],
|
||||
isurf->native_width,
|
||||
isurf->native_height,
|
||||
cpp,
|
||||
tiling);
|
||||
}
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
/* delete old buffers that are not re-used */
|
||||
delete_buffers(backend, surf);
|
||||
|
||||
memcpy(isurf->buffers, buffers, sizeof(buffers[0]) * num);
|
||||
memcpy(isurf->handles, handles, sizeof(handles[0]) * num);
|
||||
isurf->num_buffers = num;
|
||||
|
||||
end:
|
||||
*out_count = num;
|
||||
*width = isurf->native_width;
|
||||
*height = isurf->native_height;
|
||||
|
||||
return isurf->buffers;
|
||||
}
|
||||
|
||||
static void
|
||||
update_native_buffer(struct droid_surface *surf)
|
||||
{
|
||||
struct droid_surface_intel *isurf = lookup_surface(surf);
|
||||
__DRIbuffer *buf = &isurf->native_buffer;
|
||||
unsigned int name, cpp, pitch, width, height;
|
||||
|
||||
switch (isurf->type) {
|
||||
case INTEL_SURFACE_TYPE_WINDOW:
|
||||
/* oem[0] always point to the buffer that a client is drawing to */
|
||||
name = isurf->native.win->oem[0];
|
||||
cpp = ui_bytes_per_pixel(isurf->native.win->format);
|
||||
pitch = isurf->native.win->stride * cpp;
|
||||
width = isurf->native.win->width;
|
||||
height = isurf->native.win->height;
|
||||
break;
|
||||
case INTEL_SURFACE_TYPE_IMAGE:
|
||||
name = isurf->native.pix->reserved;
|
||||
cpp = ui_bytes_per_pixel(isurf->native.pix->format);
|
||||
pitch = isurf->native.pix->stride * cpp;
|
||||
width = isurf->native.pix->width;
|
||||
height = isurf->native.pix->height;
|
||||
break;
|
||||
default:
|
||||
name = cpp = pitch = width = height = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf->name != name || buf->cpp != cpp || buf->pitch != pitch ||
|
||||
isurf->native_width != width || isurf->native_height != height) {
|
||||
buf->attachment = __DRI_BUFFER_FRONT_LEFT;
|
||||
buf->name = name;
|
||||
buf->cpp = cpp;
|
||||
buf->pitch = pitch;
|
||||
buf->flags = 0;
|
||||
|
||||
isurf->native_width = width;
|
||||
isurf->native_height = height;
|
||||
|
||||
isurf->native_changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static struct droid_surface *
|
||||
intel_create_window_surface(struct droid_backend *backend,
|
||||
_EGLSurface *surf,
|
||||
NativeWindowType win)
|
||||
{
|
||||
struct droid_surface_intel *isurf;
|
||||
|
||||
if (!win) {
|
||||
LOGE("invalid native window");
|
||||
_eglError(EGL_BAD_NATIVE_WINDOW, "eglCreateWindowSurface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO lift this limitation */
|
||||
if (!win->oem[0]) {
|
||||
LOGE("TODO support for non-gem based window");
|
||||
_eglError(EGL_BAD_NATIVE_WINDOW, "eglCreateWindowSurface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
isurf = calloc(1, sizeof(*isurf));
|
||||
if (!isurf) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
isurf->type = INTEL_SURFACE_TYPE_WINDOW;
|
||||
isurf->native.win = win;
|
||||
|
||||
surf->Width = win->width;
|
||||
surf->Height = win->height;
|
||||
/* always back buffer */
|
||||
surf->RenderBuffer = EGL_BACK_BUFFER;
|
||||
|
||||
isurf->surf = surf;
|
||||
|
||||
update_native_buffer((struct droid_surface *) isurf);
|
||||
|
||||
return (struct droid_surface *) isurf;
|
||||
}
|
||||
|
||||
static struct droid_surface *
|
||||
intel_create_image_surface(struct droid_backend *backend,
|
||||
NativePixmapType pix)
|
||||
{
|
||||
struct droid_surface_intel *isurf;
|
||||
int cpp;
|
||||
|
||||
if (!pix) {
|
||||
LOGE("invalid native pixmap");
|
||||
_eglError(EGL_BAD_NATIVE_PIXMAP, "eglCreateImage");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO lift this limitation */
|
||||
if (!pix->reserved) {
|
||||
LOGE("TODO support for non-gem based pixmap");
|
||||
_eglError(EGL_BAD_NATIVE_PIXMAP, "eglCreateImage");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
isurf = calloc(1, sizeof(*isurf));
|
||||
if (!isurf) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
isurf->type = INTEL_SURFACE_TYPE_IMAGE;
|
||||
isurf->native.pix = pix;
|
||||
|
||||
update_native_buffer((struct droid_surface *) isurf);
|
||||
|
||||
return (struct droid_surface *) isurf;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_destroy_surface(struct droid_backend *backend, struct droid_surface *surf)
|
||||
{
|
||||
struct droid_surface_intel *isurf = lookup_surface(surf);
|
||||
delete_buffers(backend, surf);
|
||||
free(isurf);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_swap_native_buffers(struct droid_backend *backend,
|
||||
struct droid_surface *surf)
|
||||
{
|
||||
struct droid_surface_intel *isurf = lookup_surface(surf);
|
||||
|
||||
if (isurf->type == INTEL_SURFACE_TYPE_WINDOW) {
|
||||
uint32_t flags;
|
||||
|
||||
flags = isurf->native.win->swapBuffers(isurf->native.win);
|
||||
if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) {
|
||||
update_native_buffer(surf);
|
||||
} else {
|
||||
/* oem[0] is changed after buffer swap */
|
||||
isurf->native_buffer.name = isurf->native.win->oem[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
intel_match_pixmap(struct droid_backend *backend, _EGLConfig *conf,
|
||||
NativePixmapType pix)
|
||||
{
|
||||
int val;
|
||||
val = GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE);
|
||||
/* match the visual type */
|
||||
return (pix->format == val);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_initialize(struct droid_backend *backend, int *fd, int *screen_number)
|
||||
{
|
||||
struct droid_backend_intel *intel = lookup_backend(backend);
|
||||
drm_auth_t auth;
|
||||
int err;
|
||||
|
||||
err = ioctl(intel->fd, DRM_IOCTL_GET_MAGIC, &auth);
|
||||
if (!err)
|
||||
err = ui_auth_gpu(auth.magic);
|
||||
|
||||
if (err) {
|
||||
LOGE("failed to authenticate");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fd)
|
||||
*fd = intel->fd;
|
||||
if (screen_number)
|
||||
*screen_number = intel->screen_number;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
static int
|
||||
intel_process_config(struct droid_backend *backend, _EGLConfig *conf)
|
||||
{
|
||||
int r, g, b, a;
|
||||
int surface_type;
|
||||
int format;
|
||||
|
||||
r = GET_CONFIG_ATTRIB(conf, EGL_RED_SIZE);
|
||||
g = GET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE);
|
||||
b = GET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE);
|
||||
a = GET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE);
|
||||
format = ui_get_rgb_format(r, g, b, a);
|
||||
|
||||
if (format) {
|
||||
SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, format);
|
||||
SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE,
|
||||
EGL_WINDOW_BIT |
|
||||
EGL_PIXMAP_BIT |
|
||||
EGL_PBUFFER_BIT);
|
||||
}
|
||||
else {
|
||||
SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_destroy(struct droid_backend *backend)
|
||||
{
|
||||
struct droid_backend_intel *intel = lookup_backend(backend);
|
||||
close(intel->fd);
|
||||
free(intel);
|
||||
}
|
||||
|
||||
struct droid_backend *
|
||||
droid_backend_create_intel(const char *dev)
|
||||
{
|
||||
struct droid_backend_intel *intel;
|
||||
|
||||
intel = calloc(1, sizeof(*intel));
|
||||
if (!intel)
|
||||
return NULL;
|
||||
|
||||
intel->fd = open(dev, O_RDWR);
|
||||
if (intel->fd < 0) {
|
||||
LOGE("failed to open %s", dev);
|
||||
free(intel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
intel->screen_number = 0;
|
||||
|
||||
/* XXX query using I915_GETPARAM + PARAM_CHIPSET_ID */
|
||||
intel->generation = INTEL_GEN_3;
|
||||
|
||||
intel->pitch_align = 64;
|
||||
intel->enable_tiling = 1;
|
||||
|
||||
intel->base.driver_name = "i915";
|
||||
intel->base.initialize = intel_initialize;
|
||||
intel->base.process_config = intel_process_config;
|
||||
intel->base.destroy = intel_destroy;
|
||||
|
||||
intel->base.get_native_buffer = intel_get_native_buffer;
|
||||
intel->base.get_surface_buffers = intel_get_surface_buffers;
|
||||
|
||||
intel->base.create_window_surface = intel_create_window_surface;
|
||||
intel->base.create_image_surface = intel_create_image_surface;
|
||||
intel->base.destroy_surface = intel_destroy_surface;
|
||||
intel->base.swap_native_buffers = intel_swap_native_buffers;
|
||||
|
||||
intel->base.match_pixmap = intel_match_pixmap;
|
||||
|
||||
return &intel->base;
|
||||
}
|
||||
@@ -1,509 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.com>
|
||||
*
|
||||
* This is based on the work of eagle, by
|
||||
* Copyright © 2008, 2009 Kristian Høgsberg
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DROID-LOADER"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "droid.h"
|
||||
#include "EGL/internal/eglimage_dri.h"
|
||||
|
||||
#ifndef DROID_DRIVER_PATH
|
||||
#define DROID_DRIVER_PATH "/system/lib"
|
||||
#endif
|
||||
|
||||
struct droid_loader {
|
||||
struct droid_backend *backend;
|
||||
|
||||
char *filename;
|
||||
void *handle;
|
||||
|
||||
__DRIcoreExtension *core;
|
||||
__DRIdri2Extension *dri2;
|
||||
};
|
||||
|
||||
struct droid_context {
|
||||
__DRIcontext *dri_context;
|
||||
};
|
||||
|
||||
struct droid_drawable {
|
||||
struct droid_loader *loader;
|
||||
struct droid_surface *surface;
|
||||
|
||||
__DRIdrawable *dri_drawable;
|
||||
const __DRIconfig *dri_config;
|
||||
__DRIEGLImage *dri_image;
|
||||
};
|
||||
|
||||
static __DRIbuffer *
|
||||
loader_ext_get_buffers_with_format(__DRIdrawable *driDrawable,
|
||||
int *width, int *height,
|
||||
unsigned int *attachments, int count,
|
||||
int *out_count, void *loaderPrivate)
|
||||
{
|
||||
struct droid_drawable *drawable = (struct droid_drawable *) loaderPrivate;
|
||||
struct droid_loader *loader = drawable->loader;
|
||||
__DRIbuffer *buffers;
|
||||
|
||||
buffers = loader->backend->get_surface_buffers(loader->backend,
|
||||
drawable->surface,
|
||||
width, height,
|
||||
attachments, count,
|
||||
out_count, 1);
|
||||
|
||||
return buffers;
|
||||
}
|
||||
|
||||
static const __DRIdri2LoaderExtension loader_ext_dri2_loader = {
|
||||
{ __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
|
||||
NULL,
|
||||
NULL,
|
||||
loader_ext_get_buffers_with_format,
|
||||
};
|
||||
|
||||
static int
|
||||
loader_ext_get_ust(int64_t *ust)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
if (ust == NULL)
|
||||
return -EFAULT;
|
||||
|
||||
if (gettimeofday(&tv, NULL) == 0) {
|
||||
ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||
return 0;
|
||||
} else {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
static const __DRIsystemTimeExtension loader_ext_system_time = {
|
||||
{ __DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION },
|
||||
loader_ext_get_ust,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const __DRIextension *loader_extensions[] = {
|
||||
&loader_ext_dri2_loader.base,
|
||||
&loader_ext_system_time.base,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct droid_loader *
|
||||
loader_create(struct droid_backend *backend)
|
||||
{
|
||||
struct droid_loader *loader;
|
||||
|
||||
loader = calloc(1, sizeof(*loader));
|
||||
if (!loader)
|
||||
return NULL;
|
||||
|
||||
loader->backend = backend;
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
static void
|
||||
loader_destroy(struct droid_loader *loader)
|
||||
{
|
||||
if (loader->filename)
|
||||
free(loader->filename);
|
||||
if (loader->handle)
|
||||
dlclose(loader->handle);
|
||||
free(loader);
|
||||
}
|
||||
|
||||
static int
|
||||
loader_load(struct droid_loader *loader, const char *filename)
|
||||
{
|
||||
const __DRIextension **extensions;
|
||||
const char *path = NULL;
|
||||
int i;
|
||||
|
||||
LOGD("Loading DRI driver %s", filename);
|
||||
|
||||
loader->handle = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
|
||||
if (loader->handle == NULL) {
|
||||
LOGE("dlopen: %s", dlerror());
|
||||
return 0;
|
||||
}
|
||||
|
||||
extensions = dlsym(loader->handle, __DRI_DRIVER_EXTENSIONS);
|
||||
if (extensions == NULL) {
|
||||
LOGE("dlsym: %s", dlerror());
|
||||
dlclose(loader->handle);
|
||||
loader->handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; extensions[i]; i++) {
|
||||
if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
|
||||
extensions[i]->version >= __DRI_CORE_VERSION) {
|
||||
loader->core = (__DRIcoreExtension *) extensions[i];
|
||||
}
|
||||
|
||||
if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
|
||||
extensions[i]->version >= __DRI_DRI2_VERSION) {
|
||||
loader->dri2 = (__DRIdri2Extension *) extensions[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (loader->core == NULL || loader->dri2 == NULL) {
|
||||
LOGE("missing required DRI extensions");
|
||||
dlclose(loader->handle);
|
||||
loader->handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
loader_init(struct droid_loader *loader)
|
||||
{
|
||||
char filename[1024];
|
||||
const char *path;
|
||||
|
||||
path = DROID_DRIVER_PATH;
|
||||
snprintf(filename, sizeof(filename), "%s/%s_dri.so",
|
||||
path, loader->backend->driver_name);
|
||||
|
||||
if (!loader_load(loader, filename))
|
||||
return 0;
|
||||
|
||||
loader->filename = strdup(filename);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
droid_backend_destroy(struct droid_backend *backend)
|
||||
{
|
||||
backend->destroy(backend);
|
||||
}
|
||||
|
||||
struct droid_screen *
|
||||
droid_screen_create(struct droid_backend *backend)
|
||||
{
|
||||
struct droid_screen *screen = NULL;
|
||||
struct droid_loader *loader;
|
||||
const __DRIextension **extensions;
|
||||
int fd, screen_number;
|
||||
int i;
|
||||
|
||||
loader = loader_create(backend);
|
||||
if (!loader || !loader_init(loader)) {
|
||||
LOGE("failed to initialize loader");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
screen = calloc(1, sizeof(*screen));
|
||||
if (!screen) {
|
||||
LOGE("failed to allocate new screen");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!loader->backend->initialize(loader->backend, &fd, &screen_number)) {
|
||||
LOGE("failed to initialize backend");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
screen->loader = loader;
|
||||
screen->dri_screen =
|
||||
loader->dri2->createNewScreen(screen_number, fd,
|
||||
loader_extensions,
|
||||
&screen->dri_configs, NULL);
|
||||
if (!screen->dri_screen) {
|
||||
LOGE("failed to create DRI screen");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
extensions = loader->core->getExtensions(screen->dri_screen);
|
||||
|
||||
for (i = 0; extensions && extensions[i]; i++) {
|
||||
if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0 &&
|
||||
extensions[i]->version >= __DRI_TEX_BUFFER_VERSION)
|
||||
screen->tex_buffer = (__DRItexBufferExtension *) extensions[i];
|
||||
|
||||
if (strcmp(extensions[i]->name, __DRI_COPY_BUFFER) == 0 &&
|
||||
extensions[i]->version >= __DRI_COPY_BUFFER_VERSION)
|
||||
screen->copy_buffer = (__DRIcopyBufferExtension *) extensions[i];
|
||||
}
|
||||
|
||||
if (!screen->tex_buffer) {
|
||||
LOGE("DRI driver has no TexBuffer extension");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!screen->tex_buffer) {
|
||||
LOGE("DRI driver has no CopyBuffer extension");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; screen->dri_configs[i]; i++)
|
||||
;
|
||||
screen->num_dri_configs = i;
|
||||
|
||||
return screen;
|
||||
|
||||
fail:
|
||||
if (screen)
|
||||
droid_screen_destroy(screen);
|
||||
if (loader)
|
||||
loader_destroy(loader);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
droid_screen_destroy(struct droid_screen *screen)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
if (screen->dri_screen)
|
||||
loader->core->destroyScreen(screen->dri_screen);
|
||||
free(screen);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
EGLenum egl_attrib;
|
||||
unsigned int dri_attrib;
|
||||
} droid_attrib_map[] = {
|
||||
{ EGL_BUFFER_SIZE, __DRI_ATTRIB_BUFFER_SIZE },
|
||||
{ EGL_RED_SIZE, __DRI_ATTRIB_RED_SIZE },
|
||||
{ EGL_GREEN_SIZE, __DRI_ATTRIB_GREEN_SIZE },
|
||||
{ EGL_BLUE_SIZE, __DRI_ATTRIB_BLUE_SIZE },
|
||||
{ EGL_ALPHA_SIZE, __DRI_ATTRIB_ALPHA_SIZE },
|
||||
{ EGL_BIND_TO_TEXTURE_RGB, __DRI_ATTRIB_BIND_TO_TEXTURE_RGB },
|
||||
{ EGL_BIND_TO_TEXTURE_RGBA, __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA },
|
||||
{ EGL_CONFIG_CAVEAT, __DRI_ATTRIB_CONFIG_CAVEAT },
|
||||
{ EGL_DEPTH_SIZE, __DRI_ATTRIB_DEPTH_SIZE },
|
||||
{ EGL_LEVEL, __DRI_ATTRIB_LEVEL },
|
||||
{ EGL_MAX_PBUFFER_WIDTH, __DRI_ATTRIB_MAX_PBUFFER_WIDTH },
|
||||
{ EGL_MAX_PBUFFER_HEIGHT, __DRI_ATTRIB_MAX_PBUFFER_HEIGHT },
|
||||
{ EGL_MAX_PBUFFER_PIXELS, __DRI_ATTRIB_MAX_PBUFFER_PIXELS },
|
||||
{ EGL_SAMPLE_BUFFERS, __DRI_ATTRIB_SAMPLE_BUFFERS },
|
||||
{ EGL_SAMPLES, __DRI_ATTRIB_SAMPLES },
|
||||
{ EGL_STENCIL_SIZE, __DRI_ATTRIB_STENCIL_SIZE },
|
||||
};
|
||||
|
||||
int
|
||||
droid_screen_convert_config(struct droid_screen *screen,
|
||||
const __DRIconfig *conf, _EGLConfig *egl_conf)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
const int num_attrs =
|
||||
sizeof(droid_attrib_map) / sizeof(droid_attrib_map[0]);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_attrs; i++) {
|
||||
unsigned int dri_attrib = droid_attrib_map[i].dri_attrib;
|
||||
unsigned int dri_value;
|
||||
EGLenum egl_attrib = droid_attrib_map[i].egl_attrib;
|
||||
EGLint egl_value;
|
||||
|
||||
if (!loader->core->getConfigAttrib(conf, dri_attrib, &dri_value)) {
|
||||
LOGE("failed to get attribute %02d for %p", dri_attrib, conf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (egl_attrib) {
|
||||
case EGL_CONFIG_CAVEAT:
|
||||
if (dri_value & __DRI_ATTRIB_SLOW_BIT)
|
||||
egl_value = EGL_SLOW_CONFIG;
|
||||
else if (dri_value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
|
||||
egl_value = EGL_NON_CONFORMANT_CONFIG;
|
||||
else
|
||||
egl_value = EGL_NONE;
|
||||
break;
|
||||
default:
|
||||
egl_value = (EGLint) dri_value;
|
||||
break;
|
||||
}
|
||||
SET_CONFIG_ATTRIB(egl_conf, egl_attrib, egl_value);
|
||||
}
|
||||
|
||||
return loader->backend->process_config(loader->backend, egl_conf);
|
||||
}
|
||||
|
||||
struct droid_context *
|
||||
droid_screen_create_context(struct droid_screen *screen,
|
||||
const __DRIconfig *conf,
|
||||
struct droid_context *shared)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
struct droid_context *ctx;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
LOGE("failed to allocate context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->dri_context =
|
||||
loader->dri2->createNewContext(screen->dri_screen, conf,
|
||||
(shared) ? shared->dri_context : NULL,
|
||||
NULL);
|
||||
if (!ctx->dri_context) {
|
||||
LOGE("failed to create DRI context");
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void
|
||||
droid_screen_destroy_context(struct droid_screen *screen,
|
||||
struct droid_context *ctx)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
loader->core->destroyContext(ctx->dri_context);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
struct droid_drawable *
|
||||
droid_screen_create_drawable(struct droid_screen *screen,
|
||||
const __DRIconfig *conf,
|
||||
struct droid_surface *surf)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
struct droid_drawable *drawable;
|
||||
|
||||
drawable = calloc(1, sizeof(*drawable));
|
||||
if (!drawable) {
|
||||
LOGE("failed to allocate drawable");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* needed in GetBuffers */
|
||||
drawable->loader = loader;
|
||||
drawable->surface = surf;
|
||||
drawable->dri_config = conf;
|
||||
|
||||
drawable->dri_drawable =
|
||||
loader->dri2->createNewDrawable(screen->dri_screen,
|
||||
conf, (void *) drawable);
|
||||
if (!drawable->dri_drawable) {
|
||||
LOGE("failed to create DRI drawable");
|
||||
free(drawable);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return drawable;
|
||||
}
|
||||
|
||||
void *
|
||||
droid_screen_get_drawable_data(struct droid_screen *screen,
|
||||
struct droid_drawable *drawable)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
__DRIEGLImage *img = drawable->dri_image;
|
||||
|
||||
if (!img) {
|
||||
unsigned int val;
|
||||
|
||||
img = calloc(1, sizeof(__DRIEGLImage));
|
||||
if (!img)
|
||||
return NULL;
|
||||
|
||||
img->magic = __DRI_EGL_IMAGE_MAGIC;
|
||||
img->drawable = drawable->dri_drawable;
|
||||
img->level = 0;
|
||||
if (loader->core->getConfigAttrib(drawable->dri_config,
|
||||
__DRI_ATTRIB_ALPHA_SIZE, &val))
|
||||
img->texture_format_rgba = (val > 0);
|
||||
|
||||
drawable->dri_image = img;
|
||||
}
|
||||
|
||||
return (void *) img;
|
||||
}
|
||||
|
||||
void
|
||||
droid_screen_destroy_drawable(struct droid_screen *screen,
|
||||
struct droid_drawable *drawable)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
if (drawable->dri_image)
|
||||
free(drawable->dri_image);
|
||||
loader->core->destroyDrawable(drawable->dri_drawable);
|
||||
free(drawable);
|
||||
}
|
||||
|
||||
int
|
||||
droid_screen_bind_context(struct droid_screen *screen,
|
||||
struct droid_drawable *draw,
|
||||
struct droid_drawable *read,
|
||||
struct droid_context *ctx)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
int ret = 0;
|
||||
|
||||
if (ctx) {
|
||||
if (draw && read)
|
||||
ret = loader->core->bindContext(ctx->dri_context,
|
||||
draw->dri_drawable,
|
||||
read->dri_drawable);
|
||||
else if (!draw && !read)
|
||||
ret = loader->core->unbindContext(ctx->dri_context);
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
LOGE("failed to bind context %p", ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
droid_screen_swap_buffers(struct droid_screen *screen,
|
||||
struct droid_context *ctx,
|
||||
struct droid_drawable *drawable)
|
||||
{
|
||||
struct droid_loader *loader = screen->loader;
|
||||
__DRIbuffer *native;
|
||||
int width, height;
|
||||
int err = 0;
|
||||
|
||||
native = loader->backend->get_native_buffer(loader->backend,
|
||||
drawable->surface,
|
||||
&width, &height);
|
||||
|
||||
/* copy from front buffer to native buffer */
|
||||
if (native)
|
||||
err = screen->copy_buffer->copyBuffer(ctx->dri_context, native, 0, 0,
|
||||
drawable->dri_drawable,
|
||||
__DRI_BUFFER_FRONT_LEFT, 0, 0,
|
||||
width, height);
|
||||
|
||||
if (!err)
|
||||
loader->backend->swap_native_buffers(loader->backend, drawable->surface);
|
||||
|
||||
return (!err);
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.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 (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.
|
||||
*/
|
||||
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/ISurfaceComposer.h>
|
||||
|
||||
#include "droid_ui.h"
|
||||
|
||||
using namespace android;
|
||||
|
||||
namespace android {
|
||||
const sp<ISurfaceComposer>& _get_surface_manager();
|
||||
};
|
||||
|
||||
int
|
||||
ui_auth_gpu(drm_magic_t magic)
|
||||
{
|
||||
/*
|
||||
* surface flinger itself or root; we might want something like
|
||||
* getSurfaceFlinger() from libEGL
|
||||
*/
|
||||
if (getuid() == 1000 || getuid() == 0)
|
||||
return 0;
|
||||
|
||||
sp<ISurfaceComposer> sm(_get_surface_manager());
|
||||
if (sm == NULL)
|
||||
return -ENODEV;
|
||||
return sm->authGPU(magic);
|
||||
}
|
||||
|
||||
int ui_bytes_per_pixel(int format)
|
||||
{
|
||||
return bytesPerPixel(format);
|
||||
}
|
||||
|
||||
int ui_get_rgb_format(int red, int green, int blue, int alpha)
|
||||
{
|
||||
PixelFormatInfo info;
|
||||
PixelFormat fmt;
|
||||
|
||||
/* look in the RGB range */
|
||||
for (fmt = 1; fmt < PIXEL_FORMAT_YCbCr_422_SP; fmt++) {
|
||||
status_t err = getPixelFormatInfo(fmt, &info);
|
||||
if (err)
|
||||
return -1;
|
||||
/* bpp must be equal to depth */
|
||||
if (info.bytesPerPixel * 8 != info.bitsPerPixel)
|
||||
continue;
|
||||
|
||||
if ((info.h_red - info.l_red != red) ||
|
||||
(info.h_green - info.l_green != green) ||
|
||||
(info.h_blue - info.l_blue != blue) ||
|
||||
(info.h_alpha - info.l_alpha != alpha))
|
||||
continue;
|
||||
|
||||
/* mask? */
|
||||
return fmt;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.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 (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.
|
||||
*/
|
||||
|
||||
#ifndef _DROID_UI_H
|
||||
#define _DROID_UI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus */
|
||||
|
||||
#include <drm.h>
|
||||
|
||||
int ui_auth_gpu(drm_magic_t magic);
|
||||
int ui_bytes_per_pixel(int format);
|
||||
int ui_get_rgb_format(int red, int green, int blue, int alpha);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus */
|
||||
|
||||
#endif /* _DROID_UI_H */
|
||||
@@ -1,596 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Chia-I Wu <olvaffe@gmail.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 (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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DROID-EGL"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "glapi/glapi.h"
|
||||
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglglobals.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglimage.h"
|
||||
|
||||
#include "droid.h"
|
||||
|
||||
#ifndef DROID_DEVICE_PATH
|
||||
#define DROID_DEVICE_PATH "/dev/dri/card0"
|
||||
#endif
|
||||
|
||||
struct droid_egl_driver
|
||||
{
|
||||
_EGLDriver base;
|
||||
|
||||
/* EGL_DEFAULT_DISPLAY */
|
||||
struct droid_egl_display *default_display;
|
||||
void (*flush_current)(void);
|
||||
void (*finish_current)(void);
|
||||
};
|
||||
|
||||
struct droid_egl_display
|
||||
{
|
||||
EGLint refcnt;
|
||||
|
||||
EGLint apis;
|
||||
EGLint major;
|
||||
EGLint minor;
|
||||
|
||||
struct droid_backend *backend;
|
||||
struct droid_screen *screen;
|
||||
};
|
||||
|
||||
struct droid_egl_context {
|
||||
_EGLContext base;
|
||||
struct droid_context *context;
|
||||
};
|
||||
|
||||
struct droid_egl_surface {
|
||||
_EGLSurface base;
|
||||
struct droid_drawable *drawable;
|
||||
struct droid_surface *surface;
|
||||
};
|
||||
|
||||
struct droid_egl_image {
|
||||
_EGLImage base;
|
||||
struct droid_drawable *drawable;
|
||||
struct droid_surface *surface;
|
||||
};
|
||||
|
||||
struct droid_egl_config {
|
||||
_EGLConfig base;
|
||||
const __DRIconfig *config;
|
||||
};
|
||||
|
||||
static INLINE struct droid_egl_driver *
|
||||
lookup_driver(_EGLDriver *drv)
|
||||
{
|
||||
return (struct droid_egl_driver *) drv;
|
||||
}
|
||||
|
||||
static INLINE struct droid_egl_display *
|
||||
lookup_display(_EGLDisplay *dpy)
|
||||
{
|
||||
return (struct droid_egl_display *) dpy->DriverData;
|
||||
}
|
||||
|
||||
static INLINE struct droid_egl_context *
|
||||
lookup_context(_EGLContext *context)
|
||||
{
|
||||
return (struct droid_egl_context *) context;
|
||||
}
|
||||
|
||||
static INLINE struct droid_egl_surface *
|
||||
lookup_surface(_EGLSurface *surface)
|
||||
{
|
||||
return (struct droid_egl_surface *) surface;
|
||||
}
|
||||
|
||||
static INLINE struct droid_egl_image *
|
||||
lookup_image(_EGLImage *image)
|
||||
{
|
||||
return (struct droid_egl_image *) image;
|
||||
}
|
||||
|
||||
static INLINE struct droid_egl_config *
|
||||
lookup_config(_EGLConfig *conf)
|
||||
{
|
||||
return (struct droid_egl_config *) conf;
|
||||
}
|
||||
|
||||
static void
|
||||
droid_create_configs(_EGLDisplay *dpy, struct droid_egl_display *droid_dpy,
|
||||
const __DRIconfig **configs, EGLint num_configs)
|
||||
{
|
||||
EGLint i;
|
||||
EGLint id = 1;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
struct droid_egl_config *droid_conf = calloc(1, sizeof(*droid_conf));
|
||||
EGLint val;
|
||||
|
||||
if (!droid_conf)
|
||||
break;
|
||||
|
||||
_eglInitConfig(&droid_conf->base, id);
|
||||
droid_conf->config = configs[i];
|
||||
if (!droid_screen_convert_config(droid_dpy->screen, droid_conf->config,
|
||||
&droid_conf->base)) {
|
||||
free(droid_conf);
|
||||
continue;
|
||||
}
|
||||
|
||||
val = GET_CONFIG_ATTRIB(&droid_conf->base, EGL_CONFIG_CAVEAT);
|
||||
/* we do not want slow configs */
|
||||
if (val == EGL_SLOW_CONFIG) {
|
||||
free(droid_conf);
|
||||
} else {
|
||||
_eglAddConfig(dpy, &droid_conf->base);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
droid_initialize_display(struct droid_egl_display *droid_dpy)
|
||||
{
|
||||
const char *path = DROID_DEVICE_PATH;
|
||||
|
||||
droid_dpy->backend = droid_backend_create_intel(path);
|
||||
if (!droid_dpy->backend)
|
||||
return EGL_FALSE;
|
||||
|
||||
droid_dpy->screen = droid_screen_create(droid_dpy->backend);
|
||||
if (!droid_dpy->screen) {
|
||||
free(droid_dpy->backend);
|
||||
droid_dpy->backend = NULL;
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
droid_dpy->apis = EGL_OPENGL_ES_BIT;
|
||||
droid_dpy->major = 1;
|
||||
droid_dpy->major = 4;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
EGLint *major, EGLint *minor)
|
||||
{
|
||||
struct droid_egl_driver *droid_drv = lookup_driver(drv);
|
||||
struct droid_egl_display *droid_dpy;
|
||||
|
||||
if (dpy->NativeDisplay != EGL_DEFAULT_DISPLAY)
|
||||
return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
|
||||
|
||||
/* the default display */
|
||||
droid_dpy = droid_drv->default_display;
|
||||
if (!droid_dpy) {
|
||||
droid_dpy = calloc(1, sizeof(*droid_dpy));
|
||||
if (!droid_dpy)
|
||||
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
|
||||
if (!droid_initialize_display(droid_dpy))
|
||||
return _eglError(EGL_NOT_INITIALIZED, "eglInitialize");
|
||||
|
||||
droid_create_configs(dpy, droid_dpy, droid_dpy->screen->dri_configs,
|
||||
droid_dpy->screen->num_dri_configs);
|
||||
|
||||
#if EGL_KHR_image_base
|
||||
if (droid_dpy->backend->create_image_surface) {
|
||||
dpy->Extensions.KHR_image = EGL_TRUE;
|
||||
dpy->Extensions.KHR_image_base = EGL_TRUE;
|
||||
dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
droid_drv->default_display = droid_dpy;
|
||||
}
|
||||
|
||||
dpy->DriverData = (void *) droid_dpy;
|
||||
droid_dpy->refcnt++;
|
||||
|
||||
*major = droid_dpy->major;
|
||||
*minor = droid_dpy->minor;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||
{
|
||||
struct droid_egl_driver *droid_drv = lookup_driver(drv);
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
|
||||
dpy->DriverData = NULL;
|
||||
droid_dpy->refcnt--;
|
||||
if (!droid_dpy->refcnt) {
|
||||
_eglReleaseDisplayResources(drv, dpy);
|
||||
_eglCleanupDisplay(dpy);
|
||||
|
||||
free(droid_dpy);
|
||||
droid_drv->default_display = NULL;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static _EGLProc
|
||||
droid_eglGetProcAddress(const char *procname)
|
||||
{
|
||||
return (_EGLProc) _glapi_get_proc_address(procname);
|
||||
}
|
||||
|
||||
static _EGLContext *
|
||||
droid_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
||||
_EGLContext *share_list, const EGLint *attrib_list)
|
||||
{
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_config *droid_conf = lookup_config(conf);
|
||||
struct droid_egl_context *shared = lookup_context(share_list);
|
||||
struct droid_egl_context *ctx;
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateContext");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitContext(drv, &ctx->base, &droid_conf->base, attrib_list)) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->context =
|
||||
droid_screen_create_context(droid_dpy->screen, droid_conf->config,
|
||||
(shared) ? shared->context : NULL);
|
||||
if (!ctx->context) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &ctx->base;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
|
||||
{
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_context *droid_ctx = lookup_context(ctx);
|
||||
|
||||
if (!_eglIsContextBound(ctx))
|
||||
droid_screen_destroy_context(droid_dpy->screen, droid_ctx->context);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d,
|
||||
_EGLSurface *r, _EGLContext *ctx)
|
||||
{
|
||||
struct droid_egl_driver *droid_drv = lookup_driver(drv);
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_surface *draw = lookup_surface(d);
|
||||
struct droid_egl_surface *read = lookup_surface(r);
|
||||
struct droid_egl_context *droid_ctx = lookup_context(ctx);
|
||||
_EGLContext *old;
|
||||
struct droid_egl_context *droid_old;
|
||||
|
||||
old = _eglGetCurrentContext();
|
||||
/* an unlinked context will be invalid after context switch */
|
||||
if (!_eglIsContextLinked(old))
|
||||
old = NULL;
|
||||
|
||||
droid_old = lookup_context(old);
|
||||
|
||||
if (!_eglMakeCurrent(drv, dpy, d, r, ctx))
|
||||
return EGL_FALSE;
|
||||
|
||||
if (droid_old && droid_old != droid_ctx && droid_drv->flush_current)
|
||||
droid_drv->flush_current();
|
||||
|
||||
_glapi_check_multithread();
|
||||
|
||||
/* bind new context or unbind old one */
|
||||
if (droid_ctx)
|
||||
droid_screen_bind_context(droid_dpy->screen,
|
||||
draw->drawable, read->drawable,
|
||||
droid_ctx->context);
|
||||
else if (droid_old)
|
||||
droid_screen_bind_context(droid_dpy->screen,
|
||||
NULL, NULL,
|
||||
droid_old->context);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
droid_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
|
||||
NativeWindowType window, const EGLint *attrib_list)
|
||||
{
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_config *droid_conf = lookup_config(conf);
|
||||
struct droid_egl_surface *surf;
|
||||
|
||||
surf = calloc(1, sizeof(*surf));
|
||||
if (!surf) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitSurface(drv, &surf->base, EGL_WINDOW_BIT, &droid_conf->base, attrib_list)) {
|
||||
free(surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surf->surface =
|
||||
droid_dpy->backend->create_window_surface(droid_dpy->backend,
|
||||
&surf->base, window);
|
||||
if (!surf->surface) {
|
||||
free(surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surf->drawable = droid_screen_create_drawable(droid_dpy->screen,
|
||||
droid_conf->config,
|
||||
surf->surface);
|
||||
if (!surf->drawable) {
|
||||
droid_dpy->backend->destroy_surface(droid_dpy->backend, surf->surface);
|
||||
free(surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &surf->base;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
||||
{
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_surface *droid_surf = lookup_surface(surf);
|
||||
|
||||
if (_eglIsSurfaceBound(&droid_surf->base))
|
||||
return EGL_TRUE;
|
||||
|
||||
droid_screen_destroy_drawable(droid_dpy->screen, droid_surf->drawable);
|
||||
droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_surf->surface);
|
||||
free(droid_surf);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
||||
{
|
||||
struct droid_egl_driver *droid_drv = lookup_driver(drv);
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_surface *droid_surf = lookup_surface(surf);
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct droid_egl_context *droid_ctx = lookup_context(ctx);
|
||||
|
||||
if (droid_ctx) {
|
||||
if (droid_drv->flush_current)
|
||||
droid_drv->flush_current();
|
||||
|
||||
droid_screen_swap_buffers(droid_dpy->screen,
|
||||
droid_ctx->context,
|
||||
droid_surf->drawable);
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
#if EGL_KHR_image_base
|
||||
|
||||
static _EGLImage *
|
||||
droid_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
|
||||
EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_image *droid_img;
|
||||
struct droid_egl_config *droid_conf;
|
||||
_EGLConfig *conf;
|
||||
EGLint val, i;
|
||||
|
||||
/* only EGL_KHR_image_pixmap is supported */
|
||||
if (target != EGL_NATIVE_PIXMAP_KHR || ctx) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dpy->NumConfigs; i++) {
|
||||
conf = dpy->Configs[i];
|
||||
if (droid_dpy->backend->match_pixmap(droid_dpy->backend, conf,
|
||||
(NativePixmapType) buffer)) {
|
||||
EGLint val;
|
||||
val = GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB);
|
||||
val |= GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA);
|
||||
if (val)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= dpy->NumConfigs)
|
||||
return NULL;
|
||||
|
||||
droid_img = calloc(1, sizeof(*droid_img));
|
||||
if (!droid_img) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitImage(drv, &droid_img->base, attr_list)) {
|
||||
free(droid_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
droid_img->surface =
|
||||
droid_dpy->backend->create_image_surface(droid_dpy->backend,
|
||||
(NativePixmapType) buffer);
|
||||
if (!droid_img->surface) {
|
||||
free(droid_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
droid_conf = lookup_config(conf);
|
||||
droid_img->drawable =
|
||||
droid_screen_create_drawable(droid_dpy->screen, droid_conf->config,
|
||||
droid_img->surface);
|
||||
|
||||
if (!droid_img->drawable) {
|
||||
droid_dpy->backend->destroy_surface(droid_dpy->backend,
|
||||
droid_img->surface);
|
||||
free(droid_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
droid_img->base.ClientData =
|
||||
droid_screen_get_drawable_data(droid_dpy->screen, droid_img->drawable);
|
||||
|
||||
return &droid_img->base;
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
|
||||
{
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
struct droid_egl_image *droid_img = lookup_image(img);
|
||||
|
||||
droid_screen_destroy_drawable(droid_dpy->screen, droid_img->drawable);
|
||||
droid_dpy->backend->destroy_surface(droid_dpy->backend, droid_img->surface);
|
||||
free(droid_img);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy)
|
||||
{
|
||||
struct droid_egl_driver *droid_drv = lookup_driver(drv);
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
|
||||
if (!ctx || !droid_drv->finish_current)
|
||||
return EGL_TRUE;
|
||||
|
||||
if (!_eglIsSurfaceLinked(ctx->DrawSurface))
|
||||
return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitClient");
|
||||
|
||||
droid_drv->finish_current();
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
droid_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
|
||||
{
|
||||
struct droid_egl_display *droid_dpy = lookup_display(dpy);
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct droid_egl_surface *droid_surf;
|
||||
|
||||
if (engine != EGL_CORE_NATIVE_ENGINE)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
|
||||
|
||||
if (!ctx)
|
||||
return EGL_TRUE;
|
||||
|
||||
if (!_eglIsSurfaceLinked(ctx->DrawSurface))
|
||||
return _eglError(EGL_BAD_CURRENT_SURFACE, "eglWaitNative");
|
||||
|
||||
droid_surf = lookup_surface(ctx->DrawSurface);
|
||||
droid_dpy->backend->swap_native_buffers(droid_dpy->backend,
|
||||
droid_surf->surface);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
droid_Unload(_EGLDriver *drv)
|
||||
{
|
||||
struct droid_egl_driver *droid_drv = lookup_driver(drv);
|
||||
free(droid_drv);
|
||||
}
|
||||
|
||||
static void
|
||||
droid_Log(EGLint level, const char *msg)
|
||||
{
|
||||
switch (level) {
|
||||
case _EGL_DEBUG:
|
||||
LOGD(msg);
|
||||
break;
|
||||
case _EGL_INFO:
|
||||
LOGI(msg);
|
||||
break;
|
||||
case _EGL_WARNING:
|
||||
LOGW(msg);
|
||||
break;
|
||||
case _EGL_FATAL:
|
||||
LOGE(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_EGLDriver *
|
||||
_eglMain(const char *args)
|
||||
{
|
||||
struct droid_egl_driver *droid_drv = calloc(1, sizeof(*droid_drv));
|
||||
if (!droid_drv)
|
||||
return NULL;
|
||||
|
||||
_eglInitDriverFallbacks(&droid_drv->base);
|
||||
droid_drv->base.API.Initialize = droid_eglInitialize;
|
||||
droid_drv->base.API.Terminate = droid_eglTerminate;
|
||||
|
||||
droid_drv->base.API.GetProcAddress = droid_eglGetProcAddress;
|
||||
|
||||
droid_drv->base.API.CreateContext = droid_eglCreateContext;
|
||||
droid_drv->base.API.DestroyContext = droid_eglDestroyContext;
|
||||
droid_drv->base.API.MakeCurrent = droid_eglMakeCurrent;
|
||||
droid_drv->base.API.CreateWindowSurface = droid_eglCreateWindowSurface;
|
||||
droid_drv->base.API.DestroySurface = droid_eglDestroySurface;
|
||||
droid_drv->base.API.SwapBuffers = droid_eglSwapBuffers;
|
||||
#if EGL_KHR_image_base
|
||||
droid_drv->base.API.CreateImageKHR = droid_eglCreateImageKHR;
|
||||
droid_drv->base.API.DestroyImageKHR = droid_eglDestroyImageKHR;
|
||||
#endif /* EGL_KHR_image_base */
|
||||
droid_drv->base.API.WaitClient = droid_eglWaitClient;
|
||||
droid_drv->base.API.WaitNative = droid_eglWaitNative;
|
||||
|
||||
droid_drv->base.Name = "Android/i915";
|
||||
droid_drv->base.Unload = droid_Unload;
|
||||
|
||||
/* we need a way to flush commands */
|
||||
droid_drv->flush_current =
|
||||
(void (*)(void)) droid_eglGetProcAddress("glFlush");
|
||||
droid_drv->finish_current =
|
||||
(void (*)(void)) droid_eglGetProcAddress("glFinish");
|
||||
|
||||
_eglSetLogProc(droid_Log);
|
||||
|
||||
return &droid_drv->base;
|
||||
}
|
||||
@@ -54,18 +54,13 @@
|
||||
#include "eglglobals.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglimage.h"
|
||||
|
||||
#include "EGL/internal/eglimage_dri.h"
|
||||
|
||||
#define MAX_DEPTH 32
|
||||
#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
|
||||
|
||||
/** subclass of _EGLDriver */
|
||||
struct xdri_egl_driver
|
||||
{
|
||||
_EGLDriver Base; /**< base class */
|
||||
void (*FlushCurrentContext)(void);
|
||||
};
|
||||
|
||||
|
||||
@@ -78,8 +73,6 @@ struct xdri_egl_display
|
||||
|
||||
__GLXscreenConfigs *psc;
|
||||
EGLint scr;
|
||||
|
||||
const __GLcontextModes *imageConfigs[MAX_DEPTH + 1];
|
||||
};
|
||||
|
||||
|
||||
@@ -105,16 +98,6 @@ struct xdri_egl_surface
|
||||
};
|
||||
|
||||
|
||||
/** subclass of _EGLImage */
|
||||
struct xdri_egl_image
|
||||
{
|
||||
_EGLImage Base; /**< base class */
|
||||
|
||||
Drawable pixmap;
|
||||
__GLXDRIdrawable *driDrawable;
|
||||
};
|
||||
|
||||
|
||||
/** subclass of _EGLConfig */
|
||||
struct xdri_egl_config
|
||||
{
|
||||
@@ -164,14 +147,6 @@ lookup_config(_EGLConfig *conf)
|
||||
}
|
||||
|
||||
|
||||
/** Map EGLImage handle to xdri_egl_image object */
|
||||
static INLINE struct xdri_egl_image *
|
||||
lookup_image(_EGLImage *img)
|
||||
{
|
||||
return (struct xdri_egl_image *) img;
|
||||
}
|
||||
|
||||
|
||||
/** Get size of given window */
|
||||
static Status
|
||||
get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
|
||||
@@ -187,62 +162,6 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
|
||||
}
|
||||
|
||||
|
||||
#if EGL_KHR_image_base
|
||||
/** Get depth of given window */
|
||||
static Status
|
||||
get_drawable_depth(Display *dpy, Drawable d, uint *depth_ret)
|
||||
{
|
||||
Window root;
|
||||
Status stat;
|
||||
int xpos, ypos;
|
||||
unsigned int w, h, bw, depth;
|
||||
stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
|
||||
*depth_ret = depth;
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The config of a pixmap must be guessed from its depth. Do the guess once
|
||||
* for all depths.
|
||||
*/
|
||||
static void
|
||||
find_image_configs(_EGLDisplay *dpy, const __GLcontextModes *modes)
|
||||
{
|
||||
struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
|
||||
EGLint depth;
|
||||
|
||||
for (depth = 0; depth < MAX_DEPTH + 1; depth++) {
|
||||
const __GLcontextModes *m;
|
||||
|
||||
for (m = modes; m; m = m->next) {
|
||||
/* the depth of a pixmap might not include alpha */
|
||||
if (m->rgbBits != depth && (m->rgbBits - m->alphaBits) != depth)
|
||||
continue;
|
||||
if (!m->visualID)
|
||||
continue;
|
||||
|
||||
if (depth == 32) {
|
||||
if (m->bindToTextureRgba) {
|
||||
xdri_dpy->imageConfigs[depth] = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m->bindToTextureRgb) {
|
||||
xdri_dpy->imageConfigs[depth] = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m)
|
||||
_eglLog(_EGL_DEBUG, "Use mode 0x%02x for depth %d",
|
||||
m->visualID, depth);
|
||||
}
|
||||
}
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
|
||||
/**
|
||||
* Produce a set of EGL configs.
|
||||
*/
|
||||
@@ -356,15 +275,6 @@ xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
EGL_OPENGL_ES2_BIT |
|
||||
EGL_OPENVG_BIT);
|
||||
|
||||
#if EGL_KHR_image_base
|
||||
/* must be called after DriverData is set */
|
||||
find_image_configs(dpy, psc->configs);
|
||||
|
||||
dpy->Extensions.KHR_image = EGL_TRUE;
|
||||
dpy->Extensions.KHR_image_base = EGL_TRUE;
|
||||
dpy->Extensions.KHR_image_pixmap = EGL_TRUE;
|
||||
#endif
|
||||
|
||||
/* we're supporting EGL 1.4 */
|
||||
*minor = 1;
|
||||
*major = 4;
|
||||
@@ -496,23 +406,13 @@ static EGLBoolean
|
||||
xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d,
|
||||
_EGLSurface *r, _EGLContext *context)
|
||||
{
|
||||
struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv);
|
||||
struct xdri_egl_context *xdri_ctx = lookup_context(context);
|
||||
struct xdri_egl_surface *draw = lookup_surface(d);
|
||||
struct xdri_egl_surface *read = lookup_surface(r);
|
||||
_EGLContext *old = _eglGetCurrentContext();
|
||||
|
||||
/* an unlinked context will be invalid after context switch */
|
||||
if (!_eglIsContextLinked(old))
|
||||
old = NULL;
|
||||
|
||||
if (!_eglMakeCurrent(drv, dpy, d, r, context))
|
||||
return EGL_FALSE;
|
||||
|
||||
/* flush before context switch */
|
||||
if (old && old != context && xdri_driver->FlushCurrentContext)
|
||||
xdri_driver->FlushCurrentContext();
|
||||
|
||||
/* the symbol is defined in libGL.so */
|
||||
_glapi_check_multithread();
|
||||
|
||||
@@ -523,9 +423,12 @@ xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d,
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
else if (old) {
|
||||
xdri_ctx = lookup_context(old);
|
||||
xdri_ctx->driContext->unbindContext(xdri_ctx->driContext);
|
||||
else {
|
||||
_EGLContext *old = _eglGetCurrentContext();
|
||||
if (old) {
|
||||
xdri_ctx = lookup_context(old);
|
||||
xdri_ctx->driContext->unbindContext(xdri_ctx->driContext);
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
@@ -621,119 +524,15 @@ xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
||||
static EGLBoolean
|
||||
xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
|
||||
{
|
||||
struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv);
|
||||
struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
|
||||
struct xdri_egl_surface *xdri_surf = lookup_surface(draw);
|
||||
|
||||
/* swapBuffers does not flush commands */
|
||||
if (draw == _eglGetCurrentSurface(EGL_DRAW) &&
|
||||
xdri_driver->FlushCurrentContext)
|
||||
xdri_driver->FlushCurrentContext();
|
||||
|
||||
xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#if EGL_KHR_image_base
|
||||
|
||||
|
||||
static _EGLImage *
|
||||
xdri_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
|
||||
EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
struct xdri_egl_display *xdri_dpy = lookup_display(dpy);
|
||||
struct xdri_egl_image *xdri_img;
|
||||
__DRIEGLImage *driImage;
|
||||
EGLint err = EGL_SUCCESS;
|
||||
const __GLcontextModes *mode;
|
||||
uint depth;
|
||||
|
||||
xdri_img = CALLOC_STRUCT(xdri_egl_image);
|
||||
if (!xdri_img) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case EGL_NATIVE_PIXMAP_KHR:
|
||||
if (ctx) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
xdri_img->pixmap = (Pixmap) buffer;
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR");
|
||||
free(xdri_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitImage(drv, &xdri_img->Base, attr_list)) {
|
||||
free(xdri_img);
|
||||
return NULL;
|
||||
}
|
||||
if (!get_drawable_depth(xdri_dpy->dpy, xdri_img->pixmap, &depth) ||
|
||||
depth > MAX_DEPTH) {
|
||||
free(xdri_img);
|
||||
return NULL;
|
||||
}
|
||||
mode = xdri_dpy->imageConfigs[depth];
|
||||
if (!mode) {
|
||||
free(xdri_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driImage = CALLOC_STRUCT(__DRIEGLImageRec);
|
||||
if (!driImage) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreateImageKHR");
|
||||
free(xdri_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xdri_img->driDrawable =
|
||||
xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc,
|
||||
(XID) xdri_img->pixmap,
|
||||
(GLXDrawable) xdri_img->pixmap,
|
||||
mode);
|
||||
if (!xdri_img->driDrawable) {
|
||||
free(driImage);
|
||||
free(xdri_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driImage->magic = __DRI_EGL_IMAGE_MAGIC;
|
||||
driImage->drawable = xdri_img->driDrawable->driDrawable;
|
||||
driImage->texture_format_rgba = (depth == 32 && mode->bindToTextureRgba);
|
||||
driImage->level = 0;
|
||||
|
||||
xdri_img->Base.ClientData = (void *) driImage;
|
||||
|
||||
return &xdri_img->Base;
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
xdri_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
|
||||
{
|
||||
struct xdri_egl_image *xdri_img = lookup_image(img);
|
||||
|
||||
free(xdri_img->Base.ClientData);
|
||||
xdri_img->driDrawable->destroyDrawable(xdri_img->driDrawable);
|
||||
free(xdri_img);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
|
||||
static void
|
||||
xdri_Unload(_EGLDriver *drv)
|
||||
{
|
||||
@@ -768,17 +567,9 @@ _eglMain(const char *args)
|
||||
xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
|
||||
xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
|
||||
xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
|
||||
#if EGL_KHR_image_base
|
||||
xdri_drv->Base.API.CreateImageKHR = xdri_eglCreateImageKHR;
|
||||
xdri_drv->Base.API.DestroyImageKHR = xdri_eglDestroyImageKHR;
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
xdri_drv->Base.Name = "X/DRI";
|
||||
xdri_drv->Base.Unload = xdri_Unload;
|
||||
|
||||
/* we need a way to flush commands */
|
||||
xdri_drv->FlushCurrentContext =
|
||||
(void (*)(void)) xdri_eglGetProcAddress("glFlush");
|
||||
|
||||
return &xdri_drv->Base;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ include $(TOP)/configs/current
|
||||
INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi $(X11_INCLUDES)
|
||||
|
||||
HEADERS = \
|
||||
eglclient.h \
|
||||
eglcompiler.h \
|
||||
eglconfig.h \
|
||||
eglconfigutil.h \
|
||||
@@ -17,7 +16,6 @@ HEADERS = \
|
||||
egldisplay.h \
|
||||
egldriver.h \
|
||||
eglglobals.h \
|
||||
eglimage.h \
|
||||
egllog.h \
|
||||
eglmisc.h \
|
||||
eglmode.h \
|
||||
@@ -28,7 +26,6 @@ HEADERS = \
|
||||
|
||||
SOURCES = \
|
||||
eglapi.c \
|
||||
eglclient.c \
|
||||
eglconfig.c \
|
||||
eglconfigutil.c \
|
||||
eglcontext.c \
|
||||
@@ -36,7 +33,6 @@ SOURCES = \
|
||||
egldisplay.c \
|
||||
egldriver.c \
|
||||
eglglobals.c \
|
||||
eglimage.c \
|
||||
egllog.c \
|
||||
eglmisc.c \
|
||||
eglmode.c \
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "eglconfig.h"
|
||||
#include "eglscreen.h"
|
||||
#include "eglmode.h"
|
||||
#include "eglimage.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -93,8 +92,8 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
|
||||
snprintf(disp->Version, sizeof(disp->Version),
|
||||
"%d.%d (%s)", major_int, minor_int, drv->Name);
|
||||
|
||||
/* limit to APIs supported by core */
|
||||
disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
|
||||
/* update the global notion of supported APIs */
|
||||
_eglGlobal.ClientAPIsMask |= disp->ClientAPIsMask;
|
||||
|
||||
disp->Driver = drv;
|
||||
} else {
|
||||
@@ -645,10 +644,6 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
|
||||
{ "eglReleaseThread", (_EGLProc) eglReleaseThread },
|
||||
{ "eglWaitClient", (_EGLProc) eglWaitClient },
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
#ifdef EGL_KHR_image_base
|
||||
{ "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
|
||||
{ "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
|
||||
#endif /* EGL_KHR_image_base */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
EGLint i;
|
||||
@@ -658,10 +653,6 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
|
||||
}
|
||||
}
|
||||
|
||||
/* preload a driver if there isn't one */
|
||||
if (!_eglGlobal.NumDrivers)
|
||||
_eglPreloadDriver(NULL);
|
||||
|
||||
/* now loop over drivers to query their procs */
|
||||
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
|
||||
_EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
|
||||
@@ -876,7 +867,33 @@ eglBindAPI(EGLenum api)
|
||||
if (!_eglIsApiValid(api))
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
|
||||
|
||||
t->CurrentAPIIndex = _eglConvertApiToIndex(api);
|
||||
switch (api) {
|
||||
#ifdef EGL_VERSION_1_4
|
||||
case EGL_OPENGL_API:
|
||||
if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) {
|
||||
t->CurrentAPIIndex = _eglConvertApiToIndex(api);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
|
||||
return EGL_FALSE;
|
||||
#endif
|
||||
case EGL_OPENGL_ES_API:
|
||||
if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) {
|
||||
t->CurrentAPIIndex = _eglConvertApiToIndex(api);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
|
||||
return EGL_FALSE;
|
||||
case EGL_OPENVG_API:
|
||||
if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) {
|
||||
t->CurrentAPIIndex = _eglConvertApiToIndex(api);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
|
||||
return EGL_FALSE;
|
||||
default:
|
||||
return EGL_FALSE;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
@@ -951,50 +968,3 @@ eglWaitClient(void)
|
||||
|
||||
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
|
||||
|
||||
#ifdef EGL_KHR_image_base
|
||||
|
||||
|
||||
EGLImageKHR
|
||||
eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
_EGLContext *context = _eglLookupContext(ctx, disp);
|
||||
_EGLDriver *drv;
|
||||
_EGLImage *img;
|
||||
|
||||
drv = _eglCheckDisplay(disp, __FUNCTION__);
|
||||
if (!drv)
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
if (!context && ctx != EGL_NO_CONTEXT) {
|
||||
_eglError(EGL_BAD_CONTEXT, __FUNCTION__);
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
img = drv->API.CreateImageKHR(drv, disp, context, target, buffer, attr_list);
|
||||
if (img)
|
||||
return _eglLinkImage(img, disp);
|
||||
else
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLookupDisplay(dpy);
|
||||
_EGLImage *img = _eglLookupImage(image, disp);
|
||||
_EGLDriver *drv;
|
||||
|
||||
drv = _eglCheckDisplay(disp, __FUNCTION__);
|
||||
if (!drv)
|
||||
return EGL_FALSE;
|
||||
if (!img)
|
||||
return _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
|
||||
|
||||
_eglUnlinkImage(img);
|
||||
return drv->API.DestroyImageKHR(drv, disp, img);
|
||||
}
|
||||
|
||||
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
@@ -70,11 +70,6 @@ typedef _EGLSurface *(*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, _EGLDis
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
|
||||
|
||||
#ifdef EGL_KHR_image_base
|
||||
typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list);
|
||||
typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
|
||||
/**
|
||||
* The API dispatcher jumps through these functions
|
||||
@@ -110,7 +105,7 @@ struct _egl_api
|
||||
WaitNative_t WaitNative;
|
||||
GetProcAddress_t GetProcAddress;
|
||||
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
/* EGL_MESA_screen extension */
|
||||
ChooseModeMESA_t ChooseModeMESA;
|
||||
GetModesMESA_t GetModesMESA;
|
||||
GetModeAttribMESA_t GetModeAttribMESA;
|
||||
@@ -123,17 +118,11 @@ struct _egl_api
|
||||
QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA;
|
||||
QueryScreenModeMESA_t QueryScreenModeMESA;
|
||||
QueryModeStringMESA_t QueryModeStringMESA;
|
||||
#endif /* EGL_MESA_screen_surface */
|
||||
|
||||
#ifdef EGL_VERSION_1_2
|
||||
WaitClient_t WaitClient;
|
||||
CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer;
|
||||
#endif
|
||||
|
||||
#ifdef EGL_KHR_image_base
|
||||
CreateImageKHR_t CreateImageKHR;
|
||||
DestroyImageKHR_t DestroyImageKHR;
|
||||
#endif /* EGL_KHR_image_base */
|
||||
};
|
||||
|
||||
#endif /* EGLAPI_INCLUDED */
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Functions that client APIs can call.
|
||||
*/
|
||||
|
||||
|
||||
#include "eglcurrent.h"
|
||||
#include "egldisplay.h"
|
||||
#include "eglimage.h"
|
||||
#include "eglclient.h"
|
||||
|
||||
|
||||
/**
|
||||
* Return the opaque client data of an image.
|
||||
*/
|
||||
void *
|
||||
_eglClientGetImageData(EGLImageKHR image)
|
||||
{
|
||||
_EGLDisplay *dpy = _eglGetCurrentDisplay();
|
||||
_EGLImage *img = _eglLookupImage(image, dpy);
|
||||
return (img) ? img->ClientData : NULL;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef EGLCLIENT_INCLUDED
|
||||
#define EGLCLIENT_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
|
||||
extern void *
|
||||
_eglClientGetImageData(EGLImageKHR image);
|
||||
|
||||
|
||||
#endif /* EGLCLIENT_INCLUDED */
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
/* This should be kept in sync with _eglInitThreadInfo() */
|
||||
#define _EGL_THREAD_INFO_INITIALIZER \
|
||||
{ EGL_SUCCESS, { NULL }, 0 }
|
||||
{ EGL_SUCCESS, { NULL }, 1 }
|
||||
|
||||
/* a fallback thread info to guarantee that every thread always has one */
|
||||
static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER;
|
||||
|
||||
@@ -4,16 +4,8 @@
|
||||
#include "egltypedefs.h"
|
||||
|
||||
|
||||
#define _EGL_API_ALL_BITS \
|
||||
(EGL_OPENGL_ES_BIT | \
|
||||
EGL_OPENVG_BIT | \
|
||||
EGL_OPENGL_ES2_BIT | \
|
||||
EGL_OPENGL_BIT)
|
||||
|
||||
|
||||
#define _EGL_API_FIRST_API EGL_OPENGL_ES_API
|
||||
#define _EGL_API_LAST_API EGL_OPENGL_API
|
||||
#define _EGL_API_NUM_APIS (_EGL_API_LAST_API - _EGL_API_FIRST_API + 1)
|
||||
#define _EGL_API_NUM_INDICES \
|
||||
(EGL_OPENGL_API - EGL_OPENGL_ES_API + 2) /* idx 0 is for EGL_NONE */
|
||||
|
||||
|
||||
/**
|
||||
@@ -22,19 +14,20 @@
|
||||
struct _egl_thread_info
|
||||
{
|
||||
EGLint LastError;
|
||||
_EGLContext *CurrentContexts[_EGL_API_NUM_APIS];
|
||||
_EGLContext *CurrentContexts[_EGL_API_NUM_INDICES];
|
||||
/* use index for fast access to current context */
|
||||
EGLint CurrentAPIIndex;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return true if a client API enum is recognized.
|
||||
* Return true if a client API enum can be converted to an index.
|
||||
*/
|
||||
static INLINE EGLBoolean
|
||||
_eglIsApiValid(EGLenum api)
|
||||
{
|
||||
return (api >= _EGL_API_FIRST_API && api <= _EGL_API_LAST_API);
|
||||
return ((api >= EGL_OPENGL_ES_API && api <= EGL_OPENGL_API) ||
|
||||
api == EGL_NONE);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +38,7 @@ _eglIsApiValid(EGLenum api)
|
||||
static INLINE EGLint
|
||||
_eglConvertApiToIndex(EGLenum api)
|
||||
{
|
||||
return api - _EGL_API_FIRST_API;
|
||||
return (api != EGL_NONE) ? api - EGL_OPENGL_ES_API + 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +49,7 @@ _eglConvertApiToIndex(EGLenum api)
|
||||
static INLINE EGLenum
|
||||
_eglConvertApiFromIndex(EGLint idx)
|
||||
{
|
||||
return _EGL_API_FIRST_API + idx;
|
||||
return (idx) ? EGL_OPENGL_ES_API + idx - 1 : EGL_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,9 +14,6 @@ struct _egl_extensions
|
||||
{
|
||||
EGLBoolean MESA_screen_surface;
|
||||
EGLBoolean MESA_copy_context;
|
||||
EGLBoolean KHR_image;
|
||||
EGLBoolean KHR_image_base;
|
||||
EGLBoolean KHR_image_pixmap;
|
||||
|
||||
char String[_EGL_MAX_EXTENSIONS_LEN];
|
||||
};
|
||||
@@ -53,8 +50,6 @@ struct _egl_display
|
||||
/* lists of linked contexts and surface */
|
||||
_EGLContext *ContextList;
|
||||
_EGLSurface *SurfaceList;
|
||||
|
||||
_EGLImage *ImageList;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -19,74 +19,62 @@
|
||||
#include "eglscreen.h"
|
||||
#include "eglstring.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglimage.h"
|
||||
|
||||
#if defined(_EGL_PLATFORM_X)
|
||||
#include <dlfcn.h>
|
||||
#elif defined(_EGL_PLATFORM_WINDOWS)
|
||||
/* Use static linking on Windows for now */
|
||||
#define WINDOWS_STATIC_LINK
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Wrappers for dlopen/dlclose()
|
||||
*/
|
||||
#if defined(_EGL_PLATFORM_WINDOWS)
|
||||
#ifdef WINDOWS_STATIC_LINK
|
||||
static const char *DefaultDriverName = "Windows EGL Static Library";
|
||||
#else
|
||||
/* XXX Need to decide how to do dynamic name lookup on Windows */
|
||||
static const char *DefaultDriverName = "TBD";
|
||||
#endif
|
||||
typedef HMODULE lib_handle;
|
||||
|
||||
static HMODULE
|
||||
open_library(const char *filename)
|
||||
{
|
||||
#ifdef WINDOWS_STATIC_LINK
|
||||
return 0;
|
||||
#else
|
||||
return LoadLibrary(filename);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* XXX Need to decide how to do dynamic name lookup on Windows */
|
||||
static const char DefaultDriverName[] = "TBD";
|
||||
|
||||
typedef HMODULE lib_handle;
|
||||
|
||||
static HMODULE
|
||||
open_library(const char *filename)
|
||||
{
|
||||
return LoadLibrary(filename);
|
||||
}
|
||||
|
||||
static void
|
||||
close_library(HMODULE lib)
|
||||
{
|
||||
FreeLibrary(lib);
|
||||
}
|
||||
|
||||
static void
|
||||
close_library(HMODULE lib)
|
||||
{
|
||||
#ifdef WINDOWS_STATIC_LINK
|
||||
#else
|
||||
FreeLibrary(lib);
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(_EGL_PLATFORM_X)
|
||||
static const char *DefaultDriverName = "egl_softpipe";
|
||||
|
||||
typedef void * lib_handle;
|
||||
|
||||
static const char DefaultDriverName[] = "egl_softpipe";
|
||||
|
||||
typedef void * lib_handle;
|
||||
|
||||
static void *
|
||||
open_library(const char *filename)
|
||||
{
|
||||
return dlopen(filename, RTLD_LAZY);
|
||||
}
|
||||
|
||||
static void
|
||||
close_library(void *lib)
|
||||
{
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
#else /* _EGL_PLATFORM_NO_OS */
|
||||
|
||||
static const char DefaultDriverName[] = "builtin";
|
||||
|
||||
typedef void *lib_handle;
|
||||
|
||||
static INLINE void *
|
||||
open_library(const char *filename)
|
||||
{
|
||||
return (void *) filename;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
close_library(void *lib)
|
||||
{
|
||||
}
|
||||
|
||||
static void *
|
||||
open_library(const char *filename)
|
||||
{
|
||||
return dlopen(filename, RTLD_LAZY);
|
||||
}
|
||||
|
||||
static void
|
||||
close_library(void *lib)
|
||||
{
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -107,22 +95,14 @@ _eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
|
||||
path = _eglstrdup(path);
|
||||
|
||||
#if defined(_EGL_PLATFORM_X)
|
||||
if (!path && dpy && dpy->NativeDisplay) {
|
||||
if (!path && dpy->NativeDisplay) {
|
||||
/* assume (wrongly!) that the native display is a display string */
|
||||
path = _eglSplitDisplayString((const char *) dpy->NativeDisplay, &args);
|
||||
}
|
||||
suffix = "so";
|
||||
#elif defined(_EGL_PLATFORM_WINDOWS)
|
||||
suffix = "dll";
|
||||
#else /* _EGL_PLATFORM_NO_OS */
|
||||
if (path) {
|
||||
/* force the use of the default driver */
|
||||
_eglLog(_EGL_DEBUG, "ignore EGL_DRIVER");
|
||||
free(path);
|
||||
path = NULL;
|
||||
}
|
||||
suffix = NULL;
|
||||
#endif
|
||||
#endif /* _EGL_PLATFORM_X */
|
||||
|
||||
if (!path)
|
||||
path = _eglstrdup(DefaultDriverName);
|
||||
@@ -156,48 +136,43 @@ _eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
|
||||
static _EGLMain_t
|
||||
_eglOpenLibrary(const char *driverPath, lib_handle *handle)
|
||||
{
|
||||
_EGLMain_t mainFunc;
|
||||
lib_handle lib;
|
||||
_EGLMain_t mainFunc = NULL;
|
||||
const char *error = "unknown error";
|
||||
|
||||
assert(driverPath);
|
||||
|
||||
#if defined(_EGL_PLATFORM_WINDOWS)
|
||||
/* Use static linking on Windows for now */
|
||||
#ifdef WINDOWS_STATIC_LINK
|
||||
lib = 0;
|
||||
mainFunc = (_EGLMain_t)_eglMain;
|
||||
#else
|
||||
/* XXX untested */
|
||||
_eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
|
||||
lib = open_library(driverPath);
|
||||
|
||||
#if defined(_EGL_PLATFORM_WINDOWS)
|
||||
/* XXX untested */
|
||||
if (lib)
|
||||
mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
|
||||
#elif defined(_EGL_PLATFORM_X)
|
||||
if (lib) {
|
||||
mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
|
||||
if (!mainFunc)
|
||||
error = dlerror();
|
||||
}
|
||||
else {
|
||||
error = dlerror();
|
||||
}
|
||||
#else /* _EGL_PLATFORM_NO_OS */
|
||||
/* must be the default driver name */
|
||||
if (strcmp(driverPath, DefaultDriverName) == 0)
|
||||
mainFunc = (_EGLMain_t) _eglMain;
|
||||
else
|
||||
error = "not builtin driver";
|
||||
#endif
|
||||
|
||||
if (!lib) {
|
||||
_eglLog(_EGL_WARNING, "Could not open driver %s (%s)",
|
||||
driverPath, error);
|
||||
_eglLog(_EGL_WARNING, "Could not open %s",
|
||||
driverPath);
|
||||
return NULL;
|
||||
}
|
||||
mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
|
||||
#endif
|
||||
#elif defined(_EGL_PLATFORM_X)
|
||||
_eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
|
||||
lib = open_library(driverPath);
|
||||
if (!lib) {
|
||||
_eglLog(_EGL_WARNING, "Could not open %s (%s)",
|
||||
driverPath, dlerror());
|
||||
if (!getenv("EGL_DRIVER"))
|
||||
_eglLog(_EGL_WARNING,
|
||||
"The driver can be overridden by setting EGL_DRIVER");
|
||||
return NULL;
|
||||
}
|
||||
mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
|
||||
#endif
|
||||
|
||||
if (!mainFunc) {
|
||||
_eglLog(_EGL_WARNING, "_eglMain not found in %s (%s)",
|
||||
driverPath, error);
|
||||
_eglLog(_EGL_WARNING, "_eglMain not found in %s", driverPath);
|
||||
if (lib)
|
||||
close_library(lib);
|
||||
return NULL;
|
||||
@@ -429,11 +404,6 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
|
||||
#ifdef EGL_VERSION_1_2
|
||||
drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
|
||||
#endif /* EGL_VERSION_1_2 */
|
||||
|
||||
#ifdef EGL_KHR_image_base
|
||||
drv->API.CreateImageKHR = _eglCreateImageKHR;
|
||||
drv->API.DestroyImageKHR = _eglDestroyImageKHR;
|
||||
#endif /* EGL_KHR_image_base */
|
||||
}
|
||||
|
||||
|
||||
@@ -458,11 +428,6 @@ _eglFindAPIs(void)
|
||||
const char *es2_libname = "libGLESv2.so";
|
||||
const char *gl_libname = "libGL.so";
|
||||
const char *vg_libname = "libOpenVG.so";
|
||||
#else /* _EGL_PLATFORM_NO_OS */
|
||||
const char *es1_libname = NULL;
|
||||
const char *es2_libname = NULL;
|
||||
const char *gl_libname = NULL;
|
||||
const char *vg_libname = NULL;
|
||||
#endif
|
||||
|
||||
if ((lib = open_library(es1_libname))) {
|
||||
|
||||
@@ -15,13 +15,13 @@ struct _egl_global _eglGlobal =
|
||||
&_eglGlobalMutex, /* Mutex */
|
||||
NULL, /* DisplayList */
|
||||
1, /* FreeScreenHandle */
|
||||
0x0, /* ClientAPIsMask */
|
||||
0, /* NumDrivers */
|
||||
{ NULL }, /* Drivers */
|
||||
2, /* NumAtExitCalls */
|
||||
{
|
||||
/* default AtExitCalls, called in reverse order */
|
||||
_eglUnloadDrivers, /* always called last */
|
||||
_eglFiniDisplay
|
||||
{ /* AtExitCalls */
|
||||
_eglFiniDisplay,
|
||||
_eglUnloadDrivers
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ struct _egl_global
|
||||
|
||||
EGLScreenMESA FreeScreenHandle;
|
||||
|
||||
/* bitmaks of supported APIs (supported by _some_ driver) */
|
||||
EGLint ClientAPIsMask;
|
||||
|
||||
EGLint NumDrivers;
|
||||
_EGLDriver *Drivers[10];
|
||||
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "eglimage.h"
|
||||
#include "egldisplay.h"
|
||||
|
||||
EGLBoolean
|
||||
_eglInitImage(_EGLDriver *drv, _EGLImage *img, const EGLint *attrib_list)
|
||||
{
|
||||
EGLint i;
|
||||
|
||||
img->Preserved = EGL_FALSE;
|
||||
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
||||
switch (attrib_list[i]) {
|
||||
case EGL_IMAGE_PRESERVED_KHR:
|
||||
i++;
|
||||
img->Preserved = attrib_list[i];
|
||||
break;
|
||||
default:
|
||||
/* not an error */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
_EGLImage *
|
||||
_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
|
||||
EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
/* driver should override this function */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image)
|
||||
{
|
||||
/* driver should override this function */
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLImageKHR
|
||||
_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy)
|
||||
{
|
||||
img->Display = dpy;
|
||||
img->Next = dpy->ImageList;
|
||||
dpy->ImageList = img;
|
||||
return (EGLImageKHR) img;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_eglUnlinkImage(_EGLImage *img)
|
||||
{
|
||||
_EGLImage *prev;
|
||||
|
||||
prev = img->Display->ImageList;
|
||||
if (prev != img) {
|
||||
while (prev) {
|
||||
if (prev->Next == img)
|
||||
break;
|
||||
prev = prev->Next;
|
||||
}
|
||||
assert(prev);
|
||||
prev->Next = img->Next;
|
||||
}
|
||||
else {
|
||||
img->Display->ImageList = img->Next;
|
||||
}
|
||||
|
||||
img->Next = NULL;
|
||||
img->Display = NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _EGL_SKIP_HANDLE_CHECK
|
||||
|
||||
|
||||
/**
|
||||
* Return EGL_TRUE if the given handle is a valid handle to an image.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy)
|
||||
{
|
||||
_EGLImage *cur = NULL;
|
||||
|
||||
if (dpy)
|
||||
cur = dpy->ImageList;
|
||||
while (cur) {
|
||||
if (cur == (_EGLImage *) img) {
|
||||
assert(cur->Display == dpy);
|
||||
break;
|
||||
}
|
||||
cur = cur->Next;
|
||||
}
|
||||
return (cur != NULL);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _EGL_SKIP_HANDLE_CHECK */
|
||||
@@ -1,93 +0,0 @@
|
||||
#ifndef EGLIMAGE_INCLUDED
|
||||
#define EGLIMAGE_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
|
||||
/**
|
||||
* "Base" class for device driver images.
|
||||
*/
|
||||
struct _egl_image
|
||||
{
|
||||
/* Client data that client APIs and the driver agree on */
|
||||
void *ClientData;
|
||||
|
||||
/* Managed by EGLDisplay for linking */
|
||||
_EGLDisplay *Display;
|
||||
_EGLImage *Next;
|
||||
|
||||
EGLBoolean Preserved;
|
||||
};
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglInitImage(_EGLDriver *drv, _EGLImage *img, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern _EGLImage *
|
||||
_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
|
||||
EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
|
||||
|
||||
|
||||
extern EGLImageKHR
|
||||
_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy);
|
||||
|
||||
|
||||
extern void
|
||||
_eglUnlinkImage(_EGLImage *img);
|
||||
|
||||
|
||||
#ifndef _EGL_SKIP_HANDLE_CHECK
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
/**
|
||||
* Perform a quick check on the handle.
|
||||
*/
|
||||
static INLINE EGLBoolean
|
||||
_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy)
|
||||
{
|
||||
_EGLImage *i = (_EGLImage *) img;
|
||||
return (dpy && i && i->Display == dpy);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Lookup a handle to find the linked image.
|
||||
* Return NULL if the handle has no corresponding linked image.
|
||||
*/
|
||||
static INLINE _EGLImage *
|
||||
_eglLookupImage(EGLImageKHR image, _EGLDisplay *dpy)
|
||||
{
|
||||
_EGLImage *img = (_EGLImage *) image;
|
||||
if (!_eglCheckImageHandle(img, dpy))
|
||||
img = NULL;
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the handle of a linked image.
|
||||
*/
|
||||
static INLINE EGLImageKHR
|
||||
_eglGetImageHandle(_EGLImage *img)
|
||||
{
|
||||
return (EGLImageKHR) ((img && img->Display) ? img : EGL_NO_IMAGE_KHR);
|
||||
}
|
||||
|
||||
|
||||
#endif /* EGLIMAGE_INCLUDED */
|
||||
@@ -9,140 +9,51 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "egllog.h"
|
||||
#include "eglmutex.h"
|
||||
|
||||
#define MAXSTRING 1000
|
||||
#define FALLBACK_LOG_LEVEL _EGL_WARNING
|
||||
#define FALLBACK_LOG_LEVEL _EGL_WARNING
|
||||
#define FALLBACK_LOG_LEVEL_STR "warning"
|
||||
|
||||
static EGLint ReportingLevel = -1;
|
||||
|
||||
|
||||
static struct {
|
||||
_EGLMutex mutex;
|
||||
|
||||
EGLBoolean initialized;
|
||||
EGLint level;
|
||||
_EGLLogProc logger;
|
||||
EGLint num_messages;
|
||||
} logging = {
|
||||
_EGL_MUTEX_INITIALIZER,
|
||||
EGL_FALSE,
|
||||
FALLBACK_LOG_LEVEL,
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
|
||||
static const char *level_strings[] = {
|
||||
/* the order is important */
|
||||
"fatal",
|
||||
"warning",
|
||||
"info",
|
||||
"debug",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the function to be called when there is a message to log.
|
||||
* Note that the function will be called with an internal lock held.
|
||||
* Recursive logging is not allowed.
|
||||
*/
|
||||
void
|
||||
_eglSetLogProc(_EGLLogProc logger)
|
||||
{
|
||||
EGLint num_messages = 0;
|
||||
|
||||
_eglLockMutex(&logging.mutex);
|
||||
|
||||
if (logging.logger != logger) {
|
||||
logging.logger = logger;
|
||||
|
||||
num_messages = logging.num_messages;
|
||||
logging.num_messages = 0;
|
||||
}
|
||||
|
||||
_eglUnlockMutex(&logging.mutex);
|
||||
|
||||
if (num_messages)
|
||||
_eglLog(_EGL_DEBUG,
|
||||
"New logger installed. "
|
||||
"Messages before the new logger might not be available.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the log reporting level.
|
||||
*/
|
||||
void
|
||||
_eglSetLogLevel(EGLint level)
|
||||
{
|
||||
switch (level) {
|
||||
case _EGL_FATAL:
|
||||
case _EGL_WARNING:
|
||||
case _EGL_INFO:
|
||||
case _EGL_DEBUG:
|
||||
_eglLockMutex(&logging.mutex);
|
||||
logging.level = level;
|
||||
_eglUnlockMutex(&logging.mutex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The default logger. It prints the message to stderr.
|
||||
*/
|
||||
static void
|
||||
_eglDefaultLogger(EGLint level, const char *msg)
|
||||
log_level_initialize(void)
|
||||
{
|
||||
fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg);
|
||||
}
|
||||
#if defined(_EGL_PLATFORM_X)
|
||||
char *log_env = getenv("EGL_LOG_LEVEL");
|
||||
#else
|
||||
char *log_env = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the logging facility.
|
||||
*/
|
||||
static void
|
||||
_eglInitLogger(void)
|
||||
{
|
||||
const char *log_env;
|
||||
EGLint i, level = -1;
|
||||
|
||||
if (logging.initialized)
|
||||
return;
|
||||
|
||||
log_env = getenv("EGL_LOG_LEVEL");
|
||||
if (log_env) {
|
||||
for (i = 0; level_strings[i]; i++) {
|
||||
if (strcasecmp(log_env, level_strings[i]) == 0) {
|
||||
level = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (log_env == NULL) {
|
||||
ReportingLevel = FALLBACK_LOG_LEVEL;
|
||||
}
|
||||
else if (strcasecmp(log_env, "fatal") == 0) {
|
||||
ReportingLevel = _EGL_FATAL;
|
||||
}
|
||||
else if (strcasecmp(log_env, "warning") == 0) {
|
||||
ReportingLevel = _EGL_WARNING;
|
||||
}
|
||||
else if (strcasecmp(log_env, "info") == 0) {
|
||||
ReportingLevel = _EGL_INFO;
|
||||
}
|
||||
else if (strcasecmp(log_env, "debug") == 0) {
|
||||
ReportingLevel = _EGL_DEBUG;
|
||||
}
|
||||
else {
|
||||
level = FALLBACK_LOG_LEVEL;
|
||||
}
|
||||
|
||||
logging.logger = _eglDefaultLogger;
|
||||
logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL;
|
||||
logging.initialized = EGL_TRUE;
|
||||
|
||||
/* it is fine to call _eglLog now */
|
||||
if (log_env && level < 0) {
|
||||
_eglLog(_EGL_WARNING,
|
||||
"Unrecognized EGL_LOG_LEVEL environment variable value. "
|
||||
fprintf(stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. "
|
||||
"Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
|
||||
"Got \"%s\". Falling back to \"%s\".",
|
||||
log_env, level_strings[FALLBACK_LOG_LEVEL]);
|
||||
"Got \"%s\". Falling back to \"%s\".\n",
|
||||
log_env, FALLBACK_LOG_LEVEL_STR);
|
||||
ReportingLevel = FALLBACK_LOG_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message with message logger.
|
||||
* Log a message to stderr.
|
||||
* \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
|
||||
*/
|
||||
void
|
||||
@@ -150,26 +61,40 @@ _eglLog(EGLint level, const char *fmtStr, ...)
|
||||
{
|
||||
va_list args;
|
||||
char msg[MAXSTRING];
|
||||
const char *levelStr;
|
||||
static int log_level_initialized = 0;
|
||||
|
||||
/* one-time initialization; a little race here is fine */
|
||||
if (!logging.initialized)
|
||||
_eglInitLogger();
|
||||
if (level > logging.level || level < 0)
|
||||
return;
|
||||
if (!log_level_initialized) {
|
||||
log_level_initialize();
|
||||
log_level_initialized = 1;
|
||||
}
|
||||
|
||||
_eglLockMutex(&logging.mutex);
|
||||
if (level <= ReportingLevel) {
|
||||
switch (level) {
|
||||
case _EGL_FATAL:
|
||||
levelStr = "Fatal";
|
||||
break;
|
||||
case _EGL_WARNING:
|
||||
levelStr = "Warning";
|
||||
break;
|
||||
case _EGL_INFO:
|
||||
levelStr = "Info";
|
||||
break;
|
||||
case _EGL_DEBUG:
|
||||
levelStr = "Debug";
|
||||
break;
|
||||
default:
|
||||
levelStr = "";
|
||||
}
|
||||
|
||||
if (logging.logger) {
|
||||
va_start(args, fmtStr);
|
||||
vsnprintf(msg, MAXSTRING, fmtStr, args);
|
||||
va_end(args);
|
||||
|
||||
logging.logger(level, msg);
|
||||
logging.num_messages++;
|
||||
fprintf(stderr, "libEGL %s: %s\n", levelStr, msg);
|
||||
|
||||
if (level == _EGL_FATAL) {
|
||||
exit(1); /* or abort()? */
|
||||
}
|
||||
}
|
||||
|
||||
_eglUnlockMutex(&logging.mutex);
|
||||
|
||||
if (level == _EGL_FATAL)
|
||||
exit(1); /* or abort()? */
|
||||
}
|
||||
|
||||
@@ -9,17 +9,6 @@
|
||||
#define _EGL_DEBUG 3 /* useful info for debugging */
|
||||
|
||||
|
||||
typedef void (*_EGLLogProc)(EGLint level, const char *msg);
|
||||
|
||||
|
||||
extern void
|
||||
_eglSetLogProc(_EGLLogProc logger);
|
||||
|
||||
|
||||
extern void
|
||||
_eglSetLogLevel(EGLint level);
|
||||
|
||||
|
||||
extern void
|
||||
_eglLog(EGLint level, const char *fmtStr, ...);
|
||||
|
||||
|
||||
@@ -54,12 +54,6 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
|
||||
strcat(exts, "EGL_MESA_screen_surface ");
|
||||
if (dpy->Extensions.MESA_copy_context)
|
||||
strcat(exts, "EGL_MESA_copy_context ");
|
||||
if (dpy->Extensions.KHR_image)
|
||||
strcat(exts, "EGL_KHR_image ");
|
||||
if (dpy->Extensions.KHR_image_base)
|
||||
strcat(exts, "EGL_KHR_image_base ");
|
||||
if (dpy->Extensions.KHR_image_pixmap)
|
||||
strcat(exts, "EGL_KHR_image_pixmap ");
|
||||
assert(strlen(exts) < _EGL_MAX_EXTENSIONS_LEN);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,62 +6,6 @@
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#ifndef EGL_MESA_screen_surface
|
||||
#define EGL_MESA_screen_surface 1
|
||||
|
||||
#define EGL_BAD_SCREEN_MESA 0x4000
|
||||
#define EGL_BAD_MODE_MESA 0x4001
|
||||
#define EGL_SCREEN_COUNT_MESA 0x4002
|
||||
#define EGL_SCREEN_POSITION_MESA 0x4003
|
||||
#define EGL_SCREEN_POSITION_GRANULARITY_MESA 0x4004
|
||||
#define EGL_MODE_ID_MESA 0x4005
|
||||
#define EGL_REFRESH_RATE_MESA 0x4006
|
||||
#define EGL_OPTIMAL_MESA 0x4007
|
||||
#define EGL_INTERLACED_MESA 0x4008
|
||||
#define EGL_SCREEN_BIT_MESA 0x08
|
||||
|
||||
typedef uint32_t EGLScreenMESA;
|
||||
typedef uint32_t EGLModeMESA;
|
||||
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
|
||||
EGLAPI const char * EGLAPIENTRY eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLCHOOSEMODEMESA) (EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETMODESMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGetModeATTRIBMESA) (EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSCRREENSMESA) (EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens);
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESCREENSURFACEMESA) (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSHOWSCREENSURFACEMESA) (EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSCREENPOSIITONMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSCREENMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSCREENSURFACEMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSCREENMODEMESA) (EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode);
|
||||
typedef const char * (EGLAPIENTRYP PFNEGLQUERYMODESTRINGMESA) (EGLDisplay dpy, EGLModeMESA mode);
|
||||
|
||||
#endif /* EGL_MESA_screen_surface */
|
||||
|
||||
#ifndef EGL_MESA_copy_context
|
||||
#define EGL_MESA_copy_context 1
|
||||
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOPYCONTEXTMESA) (EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask);
|
||||
|
||||
#endif /* EGL_MESA_copy_context */
|
||||
|
||||
#include "eglcompiler.h"
|
||||
|
||||
typedef struct _egl_api _EGLAPI;
|
||||
@@ -84,8 +28,6 @@ typedef struct _egl_surface _EGLSurface;
|
||||
|
||||
typedef struct _egl_thread_info _EGLThreadInfo;
|
||||
|
||||
typedef struct _egl_image _EGLImage;
|
||||
|
||||
|
||||
typedef _EGLDriver *(*_EGLMain_t)(const char *args);
|
||||
|
||||
|
||||
@@ -1431,11 +1431,11 @@ fetch_texel( struct tgsi_sampler **sampler,
|
||||
{
|
||||
float rgba[NUM_CHANNELS][QUAD_SIZE];
|
||||
(*sampler)->get_samples(*sampler,
|
||||
&store[0],
|
||||
&store[4],
|
||||
&store[8],
|
||||
0.0f, /*store[12], lodbias */
|
||||
rgba);
|
||||
&store[0], /* s */
|
||||
&store[4], /* t */
|
||||
&store[8], /* r */
|
||||
store[12], /* lodbias */
|
||||
rgba); /* results */
|
||||
|
||||
memcpy( store, rgba, 16 * sizeof(float));
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright © 2009 Jakob Bornecrantz
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef U_FIFO_H
|
||||
#define U_FIFO_H
|
||||
|
||||
#include "util/u_memory.h"
|
||||
|
||||
struct util_fifo
|
||||
{
|
||||
size_t head;
|
||||
size_t tail;
|
||||
size_t num;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static INLINE struct util_fifo *
|
||||
u_fifo_create(size_t size)
|
||||
{
|
||||
struct util_fifo *fifo;
|
||||
fifo = MALLOC(sizeof(*fifo) + size * sizeof(void*));
|
||||
|
||||
fifo->head = 0;
|
||||
fifo->tail = 0;
|
||||
fifo->num = 0;
|
||||
fifo->size = size;
|
||||
|
||||
return fifo;
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
u_fifo_add(struct util_fifo *fifo, void *ptr)
|
||||
{
|
||||
void **array = (void**)&fifo[1];
|
||||
if (fifo->num >= fifo->size)
|
||||
return FALSE;
|
||||
|
||||
if (++fifo->head >= fifo->size)
|
||||
fifo->head = 0;
|
||||
|
||||
array[fifo->head] = ptr;
|
||||
|
||||
++fifo->num;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE boolean
|
||||
u_fifo_pop(struct util_fifo *fifo, void **ptr)
|
||||
{
|
||||
void **array = (void**)&fifo[1];
|
||||
|
||||
if (!fifo->num)
|
||||
return FALSE;
|
||||
|
||||
if (++fifo->tail >= fifo->size)
|
||||
fifo->tail = 0;
|
||||
|
||||
*ptr = array[fifo->tail];
|
||||
|
||||
++fifo->num;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
u_fifo_destroy(struct util_fifo *fifo)
|
||||
{
|
||||
FREE(fifo);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,10 +14,10 @@ PIPE_FORMAT_L16_UNORM , arith , 1, 1, un16, , , , xxx1,
|
||||
PIPE_FORMAT_Z16_UNORM , array , 1, 1, un16, , , , x___, zs
|
||||
PIPE_FORMAT_Z32_UNORM , array , 1, 1, un32, , , , x___, zs
|
||||
PIPE_FORMAT_Z32_FLOAT , array , 1, 1, f32 , , , , x___, zs
|
||||
PIPE_FORMAT_S8Z24_UNORM , arith , 1, 1, un24, un8 , , , xy__, zs
|
||||
PIPE_FORMAT_Z24S8_UNORM , arith , 1, 1, un8 , un24, , , yx__, zs
|
||||
PIPE_FORMAT_X8Z24_UNORM , arith , 1, 1, un24, un8 , , , x___, zs
|
||||
PIPE_FORMAT_Z24X8_UNORM , arith , 1, 1, un8 , un24, , , y___, zs
|
||||
PIPE_FORMAT_S8Z24_UNORM , arith , 1, 1, un8 , un24, , , yx__, zs
|
||||
PIPE_FORMAT_Z24S8_UNORM , arith , 1, 1, un24, un8 , , , xy__, zs
|
||||
PIPE_FORMAT_X8Z24_UNORM , arith , 1, 1, un8 , un24, , , y___, zs
|
||||
PIPE_FORMAT_Z24X8_UNORM , arith , 1, 1, un24, un8 , , , x___, zs
|
||||
PIPE_FORMAT_S8_UNORM , array , 1, 1, un8 , , , , _x__, zs
|
||||
PIPE_FORMAT_R64_FLOAT , array , 1, 1, f64 , , , , x001, rgb
|
||||
PIPE_FORMAT_R64G64_FLOAT , array , 1, 1, f64 , f64 , , , xy01, rgb
|
||||
|
||||
|
@@ -340,16 +340,6 @@ util_is_inf_or_nan(float x)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test whether x is a power of two.
|
||||
*/
|
||||
static INLINE boolean
|
||||
util_is_pot(unsigned x)
|
||||
{
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find first bit set in word. Least significant bit is 1.
|
||||
* Return 0 if no bits set.
|
||||
|
||||
@@ -52,7 +52,8 @@ pass_user_buffer_create(struct pipe_screen *screen,
|
||||
unsigned bytes)
|
||||
{
|
||||
struct pipe_buffer *buffer =
|
||||
screen->winsys->user_buffer_create(screen->winsys, ptr, bytes);
|
||||
screen->winsys->user_buffer_create(screen->winsys,
|
||||
ptr, bytes);
|
||||
|
||||
buffer->screen = screen;
|
||||
|
||||
@@ -68,8 +69,9 @@ pass_surface_buffer_create(struct pipe_screen *screen,
|
||||
unsigned *stride)
|
||||
{
|
||||
struct pipe_buffer *buffer =
|
||||
screen->winsys->surface_buffer_create(screen->winsys, width, height,
|
||||
format, usage, tex_usage, stride);
|
||||
screen->winsys->surface_buffer_create(screen->winsys,
|
||||
width, height,
|
||||
format, usage, tex_usage, stride);
|
||||
|
||||
buffer->screen = screen;
|
||||
|
||||
@@ -81,7 +83,8 @@ pass_buffer_map(struct pipe_screen *screen,
|
||||
struct pipe_buffer *buf,
|
||||
unsigned usage)
|
||||
{
|
||||
return screen->winsys->buffer_map(screen->winsys, buf, usage);
|
||||
return screen->winsys->buffer_map(screen->winsys,
|
||||
buf, usage);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -103,7 +106,8 @@ pass_flush_frontbuffer(struct pipe_screen *screen,
|
||||
struct pipe_surface *surf,
|
||||
void *context_private)
|
||||
{
|
||||
screen->winsys->flush_frontbuffer(screen->winsys, surf, context_private);
|
||||
screen->winsys->flush_frontbuffer(screen->winsys,
|
||||
surf, context_private);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -111,7 +115,8 @@ pass_fence_reference(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle **ptr,
|
||||
struct pipe_fence_handle *fence)
|
||||
{
|
||||
screen->winsys->fence_reference(screen->winsys, ptr, fence);
|
||||
screen->winsys->fence_reference(screen->winsys,
|
||||
ptr, fence);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -119,7 +124,8 @@ pass_fence_signalled(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle *fence,
|
||||
unsigned flag)
|
||||
{
|
||||
return screen->winsys->fence_signalled(screen->winsys, fence, flag);
|
||||
return screen->winsys->fence_signalled(screen->winsys,
|
||||
fence, flag);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -127,11 +133,11 @@ pass_fence_finish(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle *fence,
|
||||
unsigned flag)
|
||||
{
|
||||
return screen->winsys->fence_finish(screen->winsys, fence, flag);
|
||||
return screen->winsys->fence_finish(screen->winsys,
|
||||
fence, flag);
|
||||
}
|
||||
|
||||
void
|
||||
u_simple_screen_init(struct pipe_screen *screen)
|
||||
void u_simple_screen_init(struct pipe_screen *screen)
|
||||
{
|
||||
screen->buffer_create = pass_buffer_create;
|
||||
screen->user_buffer_create = pass_user_buffer_create;
|
||||
@@ -146,8 +152,7 @@ u_simple_screen_init(struct pipe_screen *screen)
|
||||
screen->fence_finish = pass_fence_finish;
|
||||
}
|
||||
|
||||
const char *
|
||||
u_simple_screen_winsys_name(struct pipe_screen *screen)
|
||||
const char* u_simple_screen_winsys_name(struct pipe_screen *screen)
|
||||
{
|
||||
return screen->winsys->get_name(screen->winsys);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,14 @@
|
||||
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_simple_shaders.h"
|
||||
|
||||
#include "tgsi/tgsi_ureg.h"
|
||||
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ x8r8g8b8_get_tile_rgba(const unsigned *src,
|
||||
pRow[0] = ubyte_to_float((pixel >> 16) & 0xff);
|
||||
pRow[1] = ubyte_to_float((pixel >> 8) & 0xff);
|
||||
pRow[2] = ubyte_to_float((pixel >> 0) & 0xff);
|
||||
pRow[3] = 1.0F;
|
||||
pRow[3] = ubyte_to_float(0xff);
|
||||
}
|
||||
p += dst_stride;
|
||||
}
|
||||
@@ -394,52 +394,6 @@ r5g6b5_put_tile_rgba(ushort *dst,
|
||||
|
||||
|
||||
|
||||
/*** PIPE_FORMAT_R8G8B8_UNORM ***/
|
||||
|
||||
static void
|
||||
r8g8b8_get_tile_rgba(const ubyte *src,
|
||||
unsigned w, unsigned h,
|
||||
float *p,
|
||||
unsigned dst_stride)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
float *pRow = p;
|
||||
for (j = 0; j < w; j++, pRow += 4) {
|
||||
pRow[0] = ubyte_to_float(src[0]);
|
||||
pRow[1] = ubyte_to_float(src[1]);
|
||||
pRow[2] = ubyte_to_float(src[2]);
|
||||
pRow[3] = 1.0f;
|
||||
src += 3;
|
||||
}
|
||||
p += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
r8g8b8_put_tile_rgba(ubyte *dst,
|
||||
unsigned w, unsigned h,
|
||||
const float *p,
|
||||
unsigned src_stride)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
const float *pRow = p;
|
||||
for (j = 0; j < w; j++, pRow += 4) {
|
||||
dst[0] = float_to_ubyte(pRow[0]);
|
||||
dst[1] = float_to_ubyte(pRow[1]);
|
||||
dst[2] = float_to_ubyte(pRow[2]);
|
||||
dst += 3;
|
||||
}
|
||||
p += src_stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*** PIPE_FORMAT_Z16_UNORM ***/
|
||||
|
||||
/**
|
||||
@@ -1152,9 +1106,6 @@ pipe_tile_raw_to_rgba(enum pipe_format format,
|
||||
case PIPE_FORMAT_R5G6B5_UNORM:
|
||||
r5g6b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
|
||||
break;
|
||||
case PIPE_FORMAT_R8G8B8_UNORM:
|
||||
r8g8b8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
|
||||
break;
|
||||
case PIPE_FORMAT_L8_UNORM:
|
||||
l8_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride);
|
||||
break;
|
||||
@@ -1271,9 +1222,6 @@ pipe_put_tile_rgba(struct pipe_transfer *pt,
|
||||
case PIPE_FORMAT_R5G6B5_UNORM:
|
||||
r5g6b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride);
|
||||
break;
|
||||
case PIPE_FORMAT_R8G8B8_UNORM:
|
||||
r8g8b8_put_tile_rgba((ubyte *) packed, w, h, p, src_stride);
|
||||
break;
|
||||
case PIPE_FORMAT_R8G8B8A8_UNORM:
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "pipe/p_inlines.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_fifo.h"
|
||||
|
||||
#include "i915_context.h"
|
||||
#include "i915_reg.h"
|
||||
@@ -77,13 +76,8 @@ struct i915_vbuf_render {
|
||||
size_t vbo_size;
|
||||
size_t vbo_offset;
|
||||
void *vbo_ptr;
|
||||
size_t vbo_alloc_size;
|
||||
size_t vbo_max_used;
|
||||
|
||||
/* stuff for the pool */
|
||||
struct util_fifo *pool_fifo;
|
||||
unsigned pool_used;
|
||||
unsigned pool_buffer_size;
|
||||
boolean pool_not_used;
|
||||
};
|
||||
|
||||
|
||||
@@ -111,55 +105,6 @@ i915_vbuf_render_get_vertex_info(struct vbuf_render *render)
|
||||
return &i915->current.vertex_info;
|
||||
}
|
||||
|
||||
static boolean
|
||||
i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size)
|
||||
{
|
||||
struct i915_context *i915 = i915_render->i915;
|
||||
|
||||
if (i915_render->vbo_size < size + i915_render->vbo_offset)
|
||||
return FALSE;
|
||||
|
||||
if (i915->vbo_flushed)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size)
|
||||
{
|
||||
struct i915_context *i915 = i915_render->i915;
|
||||
struct intel_winsys *iws = i915->iws;
|
||||
|
||||
if (i915_render->vbo) {
|
||||
if (i915_render->pool_not_used)
|
||||
iws->buffer_destroy(iws, i915_render->vbo);
|
||||
else
|
||||
u_fifo_add(i915_render->pool_fifo, i915_render->vbo);
|
||||
i915_render->vbo = NULL;
|
||||
}
|
||||
|
||||
i915->vbo_flushed = 0;
|
||||
|
||||
i915_render->vbo_size = MAX2(size, i915_render->pool_buffer_size);
|
||||
i915_render->vbo_offset = 0;
|
||||
|
||||
if (i915_render->vbo_size != i915_render->pool_buffer_size) {
|
||||
i915_render->pool_not_used = TRUE;
|
||||
i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, 64,
|
||||
INTEL_NEW_VERTEX);
|
||||
} else {
|
||||
i915_render->pool_not_used = FALSE;
|
||||
|
||||
if (i915_render->pool_used >= 2) {
|
||||
FLUSH_BATCH(NULL);
|
||||
i915->vbo_flushed = 0;
|
||||
i915_render->pool_used = 0;
|
||||
}
|
||||
u_fifo_pop(i915_render->pool_fifo, (void**)&i915_render->vbo);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean
|
||||
i915_vbuf_render_allocate_vertices(struct vbuf_render *render,
|
||||
ushort vertex_size,
|
||||
@@ -167,17 +112,27 @@ i915_vbuf_render_allocate_vertices(struct vbuf_render *render,
|
||||
{
|
||||
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
|
||||
struct i915_context *i915 = i915_render->i915;
|
||||
struct intel_winsys *iws = i915->iws;
|
||||
size_t size = (size_t)vertex_size * (size_t)nr_vertices;
|
||||
|
||||
/* FIXME: handle failure */
|
||||
assert(!i915->vbo);
|
||||
|
||||
if (!i915_vbuf_render_reserve(i915_render, size)) {
|
||||
if (i915_render->vbo_size > size + i915_render->vbo_offset && !i915->vbo_flushed) {
|
||||
} else {
|
||||
i915->vbo_flushed = 0;
|
||||
if (i915_render->vbo) {
|
||||
iws->buffer_destroy(iws, i915_render->vbo);
|
||||
i915_render->vbo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (i915->vbo_flushed)
|
||||
i915_render->pool_used = 0;
|
||||
if (!i915_render->vbo) {
|
||||
i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size);
|
||||
i915_render->vbo_offset = 0;
|
||||
i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, 64,
|
||||
INTEL_NEW_VERTEX);
|
||||
|
||||
i915_vbuf_render_new_buf(i915_render, size);
|
||||
}
|
||||
|
||||
i915_render->vertex_size = vertex_size;
|
||||
@@ -549,7 +504,6 @@ i915_vbuf_render_create(struct i915_context *i915)
|
||||
{
|
||||
struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render);
|
||||
struct intel_winsys *iws = i915->iws;
|
||||
int i;
|
||||
|
||||
i915_render->i915 = i915;
|
||||
|
||||
@@ -570,24 +524,14 @@ i915_vbuf_render_create(struct i915_context *i915)
|
||||
i915_render->base.release_vertices = i915_vbuf_render_release_vertices;
|
||||
i915_render->base.destroy = i915_vbuf_render_destroy;
|
||||
|
||||
|
||||
i915_render->vbo = NULL;
|
||||
i915_render->vbo_size = 0;
|
||||
i915_render->vbo_alloc_size = 128 * 4096;
|
||||
i915_render->vbo_size = i915_render->vbo_alloc_size;
|
||||
i915_render->vbo_offset = 0;
|
||||
|
||||
i915_render->pool_used = FALSE;
|
||||
i915_render->pool_buffer_size = 128 * 4096;
|
||||
i915_render->pool_fifo = u_fifo_create(6);
|
||||
for (i = 0; i < 6; i++)
|
||||
u_fifo_add(i915_render->pool_fifo,
|
||||
iws->buffer_create(iws, i915_render->pool_buffer_size, 64,
|
||||
INTEL_NEW_VERTEX));
|
||||
|
||||
#if 0
|
||||
i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, 64,
|
||||
INTEL_NEW_VERTEX);
|
||||
/* TODO JB: is this realy needed? */
|
||||
i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE);
|
||||
iws->buffer_unmap(iws, i915_render->vbo);
|
||||
#endif
|
||||
|
||||
return &i915_render->base;
|
||||
}
|
||||
|
||||
@@ -150,17 +150,6 @@ struct intel_winsys {
|
||||
void (*buffer_unmap)(struct intel_winsys *iws,
|
||||
struct intel_buffer *buffer);
|
||||
|
||||
/**
|
||||
* Write to a buffer.
|
||||
*
|
||||
* Arguments follows pwrite(2)
|
||||
*/
|
||||
int (*buffer_write)(struct intel_winsys *iws,
|
||||
struct intel_buffer *dst,
|
||||
const void *src,
|
||||
size_t size,
|
||||
size_t offset);
|
||||
|
||||
void (*buffer_destroy)(struct intel_winsys *iws,
|
||||
struct intel_buffer *buffer);
|
||||
/*@}*/
|
||||
|
||||
@@ -3,6 +3,8 @@ include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = llvmpipe
|
||||
|
||||
CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
|
||||
|
||||
C_SOURCES = \
|
||||
lp_bld_alpha.c \
|
||||
lp_bld_arit.c \
|
||||
@@ -15,11 +17,9 @@ C_SOURCES = \
|
||||
lp_bld_depth.c \
|
||||
lp_bld_flow.c \
|
||||
lp_bld_format_aos.c \
|
||||
lp_bld_format_soa.c \
|
||||
lp_bld_interp.c \
|
||||
lp_bld_intr.c \
|
||||
lp_bld_logic.c \
|
||||
lp_bld_sample_soa.c \
|
||||
lp_bld_swizzle.c \
|
||||
lp_bld_struct.c \
|
||||
lp_bld_tgsi_soa.c \
|
||||
@@ -46,8 +46,7 @@ C_SOURCES = \
|
||||
lp_state_vs.c \
|
||||
lp_surface.c \
|
||||
lp_tex_cache.c \
|
||||
lp_tex_sample_c.c \
|
||||
lp_tex_sample_llvm.c \
|
||||
lp_tex_sample.c \
|
||||
lp_texture.c \
|
||||
lp_tile_cache.c \
|
||||
lp_tile_soa.c
|
||||
|
||||
@@ -8,16 +8,13 @@ Done so far is:
|
||||
|
||||
- the whole fragment pipeline is code generated in a single function
|
||||
|
||||
- input interpolation
|
||||
|
||||
- depth testing
|
||||
|
||||
- texture sampling (not all state/formats are supported)
|
||||
|
||||
- fragment shader TGSI translation
|
||||
- same level of support as the TGSI SSE2 exec machine, with the exception
|
||||
we don't fallback to TGSI interpretation when an unsupported opcode is
|
||||
found, but just ignore it
|
||||
- texture sampling via an intrinsic call
|
||||
- done in SoA layout
|
||||
- input interpolation also code generated
|
||||
|
||||
@@ -31,17 +28,16 @@ Done so far is:
|
||||
any width and length
|
||||
- not all operations are implemented for these types yet though
|
||||
|
||||
Most mesa/progs/demos/* work.
|
||||
Most mesa/progs/demos/* work. Speed is on par with Keith's softpipe-opt branch,
|
||||
which includes hand written fast implementations for common cases.
|
||||
|
||||
To do (probably by this order):
|
||||
|
||||
- code generate stipple and stencil testing
|
||||
|
||||
- translate the remaining bits of texture sampling state
|
||||
- code generate texture sampling
|
||||
|
||||
- translate TGSI control flow instructions, and all other remaining opcodes
|
||||
|
||||
- integrate with the draw module for VS code generation
|
||||
|
||||
- code generate the triangle setup and rasterization
|
||||
|
||||
@@ -97,7 +93,7 @@ Alternatively, you can build it with GNU make, if you prefer, by invoking it as
|
||||
|
||||
make linux-llvm
|
||||
|
||||
but the rest of these instructions assume that scons is used.
|
||||
but the rest of these instructions assume scons is used.
|
||||
|
||||
|
||||
Using
|
||||
@@ -112,9 +108,6 @@ or
|
||||
|
||||
export LD_LIBRARY_PATH=$PWD/build/linux-x86-debug/lib:$LD_LIBRARY_PATH
|
||||
|
||||
For performance evaluation pass debug=no to scons, and use the corresponding
|
||||
lib directory without the "-debug" suffix.
|
||||
|
||||
|
||||
Unit testing
|
||||
============
|
||||
@@ -126,7 +119,7 @@ build/linux-???-debug/gallium/drivers/llvmpipe:
|
||||
- lp_test_conv: SIMD vector conversion
|
||||
- lp_test_format: pixel unpacking/packing
|
||||
|
||||
Some of this tests can output results and benchmarks to a tab-separated-file
|
||||
Some of this tests can output results and benchmarks to a tab-seperated-file
|
||||
for posterior analysis, e.g.:
|
||||
|
||||
build/linux-x86_64-debug/gallium/drivers/llvmpipe/lp_test_blend -o blend.tsv
|
||||
@@ -140,10 +133,10 @@ Development Notes
|
||||
at the top of the lp_bld_*.c functions.
|
||||
|
||||
- All lp_bld_*.[ch] are isolated from the rest of the driver, and could/may be
|
||||
put in a stand-alone Gallium state -> LLVM IR translation module.
|
||||
put in a standalone Gallium state -> LLVM IR translation module.
|
||||
|
||||
- We use LLVM-C bindings for now. They are not documented, but follow the C++
|
||||
interfaces very closely, and appear to be complete enough for code
|
||||
generation. See
|
||||
http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
|
||||
for a stand-alone example.
|
||||
for a standalone example.
|
||||
|
||||
@@ -3,7 +3,7 @@ Import('*')
|
||||
env = env.Clone()
|
||||
|
||||
env.Tool('llvm')
|
||||
if env.has_key('LLVM_VERSION') is False:
|
||||
if 'LLVM_VERSION' not in env:
|
||||
print 'warning: LLVM not found: not building llvmpipe'
|
||||
Return()
|
||||
|
||||
@@ -23,10 +23,8 @@ llvmpipe = env.ConvenienceLibrary(
|
||||
'lp_bld_depth.c',
|
||||
'lp_bld_flow.c',
|
||||
'lp_bld_format_aos.c',
|
||||
'lp_bld_format_soa.c',
|
||||
'lp_bld_interp.c',
|
||||
'lp_bld_intr.c',
|
||||
'lp_bld_sample_soa.c',
|
||||
'lp_bld_struct.c',
|
||||
'lp_bld_logic.c',
|
||||
'lp_bld_swizzle.c',
|
||||
@@ -54,8 +52,7 @@ llvmpipe = env.ConvenienceLibrary(
|
||||
'lp_state_vs.c',
|
||||
'lp_surface.c',
|
||||
'lp_tex_cache.c',
|
||||
'lp_tex_sample_c.c',
|
||||
'lp_tex_sample_llvm.c',
|
||||
'lp_tex_sample.c',
|
||||
'lp_texture.c',
|
||||
'lp_tile_cache.c',
|
||||
'lp_tile_soa.c',
|
||||
|
||||
@@ -502,31 +502,6 @@ lp_build_div(struct lp_build_context *bld,
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_lerp(struct lp_build_context *bld,
|
||||
LLVMValueRef x,
|
||||
LLVMValueRef v0,
|
||||
LLVMValueRef v1)
|
||||
{
|
||||
return lp_build_add(bld, v0, lp_build_mul(bld, x, lp_build_sub(bld, v1, v0)));
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_lerp_2d(struct lp_build_context *bld,
|
||||
LLVMValueRef x,
|
||||
LLVMValueRef y,
|
||||
LLVMValueRef v00,
|
||||
LLVMValueRef v01,
|
||||
LLVMValueRef v10,
|
||||
LLVMValueRef v11)
|
||||
{
|
||||
LLVMValueRef v0 = lp_build_lerp(bld, x, v00, v01);
|
||||
LLVMValueRef v1 = lp_build_lerp(bld, x, v10, v11);
|
||||
return lp_build_lerp(bld, y, v0, v1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate min(a, b)
|
||||
* Do checks for special cases.
|
||||
@@ -591,31 +566,20 @@ lp_build_abs(struct lp_build_context *bld,
|
||||
LLVMValueRef a)
|
||||
{
|
||||
const union lp_type type = bld->type;
|
||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||
|
||||
if(!type.sign)
|
||||
return a;
|
||||
|
||||
if(type.floating) {
|
||||
/* Mask out the sign bit */
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long)1 << type.width) - 1);
|
||||
a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
|
||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||
a = LLVMBuildBitCast(bld->builder, a, vec_type, "");
|
||||
return a;
|
||||
}
|
||||
|
||||
/* XXX: is this really necessary? */
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
if(type.width*type.length == 128) {
|
||||
switch(type.width) {
|
||||
case 8:
|
||||
if(!type.floating && type.width*type.length == 128) {
|
||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||
if(type.width == 8)
|
||||
return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.b.128", vec_type, a);
|
||||
case 16:
|
||||
if(type.width == 16)
|
||||
return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.w.128", vec_type, a);
|
||||
case 32:
|
||||
if(type.width == 32)
|
||||
return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.d.128", vec_type, a);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -623,89 +587,6 @@ lp_build_abs(struct lp_build_context *bld,
|
||||
}
|
||||
|
||||
|
||||
enum lp_build_round_sse41_mode
|
||||
{
|
||||
LP_BUILD_ROUND_SSE41_NEAREST = 0,
|
||||
LP_BUILD_ROUND_SSE41_FLOOR = 1,
|
||||
LP_BUILD_ROUND_SSE41_CEIL = 2,
|
||||
LP_BUILD_ROUND_SSE41_TRUNCATE = 3
|
||||
};
|
||||
|
||||
|
||||
static INLINE LLVMValueRef
|
||||
lp_build_round_sse41(struct lp_build_context *bld,
|
||||
LLVMValueRef a,
|
||||
enum lp_build_round_sse41_mode mode)
|
||||
{
|
||||
const union lp_type type = bld->type;
|
||||
LLVMTypeRef vec_type = lp_build_vec_type(type);
|
||||
const char *intrinsic;
|
||||
|
||||
assert(type.floating);
|
||||
assert(type.width*type.length == 128);
|
||||
|
||||
switch(type.width) {
|
||||
case 32:
|
||||
intrinsic = "llvm.x86.sse41.round.ps";
|
||||
break;
|
||||
case 64:
|
||||
intrinsic = "llvm.x86.sse41.round.pd";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return bld->undef;
|
||||
}
|
||||
|
||||
return lp_build_intrinsic_binary(bld->builder, intrinsic, vec_type, a,
|
||||
LLVMConstInt(LLVMInt32Type(), mode, 0));
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_floor(struct lp_build_context *bld,
|
||||
LLVMValueRef a)
|
||||
{
|
||||
const union lp_type type = bld->type;
|
||||
|
||||
assert(type.floating);
|
||||
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
return lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_FLOOR);
|
||||
#endif
|
||||
|
||||
/* FIXME */
|
||||
assert(0);
|
||||
return bld->undef;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert to integer, through whichever rounding method that's fastest,
|
||||
* typically truncating to zero.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_int(struct lp_build_context *bld,
|
||||
LLVMValueRef a)
|
||||
{
|
||||
const union lp_type type = bld->type;
|
||||
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
|
||||
|
||||
assert(type.floating);
|
||||
|
||||
return LLVMBuildFPToSI(bld->builder, a, int_vec_type, "");
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_ifloor(struct lp_build_context *bld,
|
||||
LLVMValueRef a)
|
||||
{
|
||||
a = lp_build_floor(bld, a);
|
||||
a = lp_build_int(bld, a);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_sqrt(struct lp_build_context *bld,
|
||||
LLVMValueRef a)
|
||||
|
||||
@@ -71,26 +71,6 @@ lp_build_div(struct lp_build_context *bld,
|
||||
LLVMValueRef a,
|
||||
LLVMValueRef b);
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_lerp(struct lp_build_context *bld,
|
||||
LLVMValueRef x,
|
||||
LLVMValueRef v0,
|
||||
LLVMValueRef v1);
|
||||
|
||||
/**
|
||||
* Bilinear interpolation.
|
||||
*
|
||||
* Values indices are in v_{yx}.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_lerp_2d(struct lp_build_context *bld,
|
||||
LLVMValueRef x,
|
||||
LLVMValueRef y,
|
||||
LLVMValueRef v00,
|
||||
LLVMValueRef v01,
|
||||
LLVMValueRef v10,
|
||||
LLVMValueRef v11);
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_min(struct lp_build_context *bld,
|
||||
LLVMValueRef a,
|
||||
@@ -105,18 +85,6 @@ LLVMValueRef
|
||||
lp_build_abs(struct lp_build_context *bld,
|
||||
LLVMValueRef a);
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_floor(struct lp_build_context *bld,
|
||||
LLVMValueRef a);
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_int(struct lp_build_context *bld,
|
||||
LLVMValueRef a);
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_ifloor(struct lp_build_context *bld,
|
||||
LLVMValueRef a);
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_sqrt(struct lp_build_context *bld,
|
||||
LLVMValueRef a);
|
||||
|
||||
@@ -122,7 +122,7 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
|
||||
int shift = dst_width - n;
|
||||
res = LLVMBuildShl(builder, res, lp_build_int_const_scalar(src_type, shift), "");
|
||||
|
||||
/* TODO: Fill in the empty lower bits for additional precision? */
|
||||
/* Fill in the empty lower bits for added precision? */
|
||||
#if 0
|
||||
{
|
||||
LLVMValueRef msb;
|
||||
@@ -244,7 +244,7 @@ lp_build_const_pack_shuffle(unsigned n)
|
||||
* Expand the bit width.
|
||||
*
|
||||
* This will only change the number of bits the values are represented, not the
|
||||
* values themselves.
|
||||
* values themselved.
|
||||
*/
|
||||
static void
|
||||
lp_build_expand(LLVMBuilderRef builder,
|
||||
|
||||
@@ -30,27 +30,10 @@
|
||||
#include <udis86.h>
|
||||
#endif
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "lp_bld_debug.h"
|
||||
|
||||
|
||||
/**
|
||||
* Check alignment.
|
||||
*
|
||||
* It is important that this check is not implemented as a macro or inlined
|
||||
* function, as the compiler assumptions in respect to alignment of global
|
||||
* and stack variables would often make the check a no op, defeating the
|
||||
* whole purpose of the exercise.
|
||||
*/
|
||||
boolean
|
||||
lp_check_alignment(const void *ptr, unsigned alignment)
|
||||
{
|
||||
assert(util_is_pot(alignment));
|
||||
return ((uintptr_t)ptr & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_disassemble(const void* func)
|
||||
{
|
||||
|
||||
@@ -53,10 +53,6 @@ lp_build_name(LLVMValueRef val, const char *format, ...)
|
||||
}
|
||||
|
||||
|
||||
boolean
|
||||
lp_check_alignment(const void *ptr, unsigned alignment);
|
||||
|
||||
|
||||
void
|
||||
lp_disassemble(const void* func);
|
||||
|
||||
|
||||
@@ -179,13 +179,12 @@ lp_build_depth_test(LLVMBuilderRef builder,
|
||||
padding_right = 0;
|
||||
for(chan = 0; chan < z_swizzle; ++chan)
|
||||
padding_right += format_desc->channel[chan].size;
|
||||
padding_left = format_desc->block.bits -
|
||||
(padding_right + format_desc->channel[z_swizzle].size);
|
||||
padding_left = format_desc->block.bits - format_desc->channel[z_swizzle].size;
|
||||
|
||||
if(padding_left || padding_right) {
|
||||
const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1;
|
||||
const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1;
|
||||
z_bitmask = lp_build_int_const_scalar(type, mask_left ^ mask_right);
|
||||
const long long mask_left = ((long long)1 << (format_desc->block.bits - padding_left)) - 1;
|
||||
const long long mask_right = ((long long)1 << (padding_right)) - 1;
|
||||
z_bitmask = lp_build_int_const_scalar(type, mask_left & mask_right);
|
||||
}
|
||||
|
||||
if(padding_left)
|
||||
@@ -211,6 +210,5 @@ lp_build_depth_test(LLVMBuilderRef builder,
|
||||
LLVMBuildStore(builder, dst, dst_ptr);
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
assert(!state->occlusion_count);
|
||||
}
|
||||
|
||||
@@ -32,261 +32,59 @@
|
||||
*/
|
||||
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "lp_bld_type.h"
|
||||
#include "lp_bld_flow.h"
|
||||
|
||||
|
||||
#define LP_BUILD_FLOW_MAX_VARIABLES 32
|
||||
#define LP_BUILD_FLOW_MAX_DEPTH 32
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of all possible flow constructs.
|
||||
*/
|
||||
enum lp_build_flow_construct_kind {
|
||||
lP_BUILD_FLOW_SCOPE,
|
||||
LP_BUILD_FLOW_SKIP,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Variable declaration scope.
|
||||
*/
|
||||
struct lp_build_flow_scope
|
||||
void
|
||||
lp_build_mask_begin(struct lp_build_mask_context *mask,
|
||||
LLVMBuilderRef builder,
|
||||
union lp_type type,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
/** Number of variables declared in this scope */
|
||||
unsigned num_variables;
|
||||
};
|
||||
memset(mask, 0, sizeof *mask);
|
||||
|
||||
|
||||
/**
|
||||
* Early exit. Useful to skip to the end of a function or block when
|
||||
* the execution mask becomes zero or when there is an error condition.
|
||||
*/
|
||||
struct lp_build_flow_skip
|
||||
{
|
||||
/** Block to skip to */
|
||||
LLVMBasicBlockRef block;
|
||||
|
||||
/** Number of variables declared at the beginning */
|
||||
unsigned num_variables;
|
||||
|
||||
LLVMValueRef *phi;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Union of all possible flow constructs' data
|
||||
*/
|
||||
union lp_build_flow_construct_data
|
||||
{
|
||||
struct lp_build_flow_scope scope;
|
||||
struct lp_build_flow_skip skip;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Element of the flow construct stack.
|
||||
*/
|
||||
struct lp_build_flow_construct
|
||||
{
|
||||
enum lp_build_flow_construct_kind kind;
|
||||
union lp_build_flow_construct_data data;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* All necessary data to generate LLVM control flow constructs.
|
||||
*
|
||||
* Besides keeping track of the control flow construct themselves we also
|
||||
* need to keep track of variables in order to generate SSA Phi values.
|
||||
*/
|
||||
struct lp_build_flow_context
|
||||
{
|
||||
LLVMBuilderRef builder;
|
||||
|
||||
/**
|
||||
* Control flow stack.
|
||||
*/
|
||||
struct lp_build_flow_construct constructs[LP_BUILD_FLOW_MAX_DEPTH];
|
||||
unsigned num_constructs;
|
||||
|
||||
/**
|
||||
* Variable stack
|
||||
*/
|
||||
LLVMValueRef *variables[LP_BUILD_FLOW_MAX_VARIABLES];
|
||||
unsigned num_variables;
|
||||
};
|
||||
|
||||
|
||||
struct lp_build_flow_context *
|
||||
lp_build_flow_create(LLVMBuilderRef builder)
|
||||
{
|
||||
struct lp_build_flow_context *flow;
|
||||
|
||||
flow = CALLOC_STRUCT(lp_build_flow_context);
|
||||
if(!flow)
|
||||
return NULL;
|
||||
|
||||
flow->builder = builder;
|
||||
|
||||
return flow;
|
||||
mask->builder = builder;
|
||||
mask->reg_type = LLVMIntType(type.width * type.length);
|
||||
mask->value = value;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_flow_destroy(struct lp_build_flow_context *flow)
|
||||
lp_build_mask_update(struct lp_build_mask_context *mask,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
assert(flow->num_constructs == 0);
|
||||
assert(flow->num_variables == 0);
|
||||
FREE(flow);
|
||||
}
|
||||
|
||||
|
||||
static union lp_build_flow_construct_data *
|
||||
lp_build_flow_push(struct lp_build_flow_context *flow,
|
||||
enum lp_build_flow_construct_kind kind)
|
||||
{
|
||||
assert(flow->num_constructs < LP_BUILD_FLOW_MAX_DEPTH);
|
||||
if(flow->num_constructs >= LP_BUILD_FLOW_MAX_DEPTH)
|
||||
return NULL;
|
||||
|
||||
flow->constructs[flow->num_constructs].kind = kind;
|
||||
return &flow->constructs[flow->num_constructs++].data;
|
||||
}
|
||||
|
||||
|
||||
static union lp_build_flow_construct_data *
|
||||
lp_build_flow_peek(struct lp_build_flow_context *flow,
|
||||
enum lp_build_flow_construct_kind kind)
|
||||
{
|
||||
assert(flow->num_constructs);
|
||||
if(!flow->num_constructs)
|
||||
return NULL;
|
||||
|
||||
assert(flow->constructs[flow->num_constructs - 1].kind == kind);
|
||||
if(flow->constructs[flow->num_constructs - 1].kind != kind)
|
||||
return NULL;
|
||||
|
||||
return &flow->constructs[flow->num_constructs - 1].data;
|
||||
}
|
||||
|
||||
|
||||
static union lp_build_flow_construct_data *
|
||||
lp_build_flow_pop(struct lp_build_flow_context *flow,
|
||||
enum lp_build_flow_construct_kind kind)
|
||||
{
|
||||
assert(flow->num_constructs);
|
||||
if(!flow->num_constructs)
|
||||
return NULL;
|
||||
|
||||
assert(flow->constructs[flow->num_constructs - 1].kind == kind);
|
||||
if(flow->constructs[flow->num_constructs - 1].kind != kind)
|
||||
return NULL;
|
||||
|
||||
return &flow->constructs[--flow->num_constructs].data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begin a variable scope.
|
||||
*
|
||||
*
|
||||
*/
|
||||
void
|
||||
lp_build_flow_scope_begin(struct lp_build_flow_context *flow)
|
||||
{
|
||||
struct lp_build_flow_scope *scope;
|
||||
|
||||
scope = &lp_build_flow_push(flow, lP_BUILD_FLOW_SCOPE)->scope;
|
||||
if(!scope)
|
||||
return;
|
||||
|
||||
scope->num_variables = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Declare a variable.
|
||||
*
|
||||
* A variable is a named entity which can have different LLVMValueRef's at
|
||||
* different points of the program. This is relevant for control flow because
|
||||
* when there are mutiple branches to a same location we need to replace
|
||||
* the variable's value with a Phi function as explained in
|
||||
* http://en.wikipedia.org/wiki/Static_single_assignment_form .
|
||||
*
|
||||
* We keep track of variables by keeping around a pointer to where their
|
||||
* current.
|
||||
*
|
||||
* There are a few cautions to observe:
|
||||
*
|
||||
* - Variable's value must not be NULL. If there is no initial value then
|
||||
* LLVMGetUndef() should be used.
|
||||
*
|
||||
* - Variable's value must be kept up-to-date. If the variable is going to be
|
||||
* modified by a function then a pointer should be passed so that its value
|
||||
* is accurate. Failure to do this will cause some of the variables'
|
||||
* transient values to be lost, leading to wrong results.
|
||||
*
|
||||
* - A program should be written from top to bottom, by always appending
|
||||
* instructions to the bottom with a single LLVMBuilderRef. Inserting and/or
|
||||
* modifying existing statements will most likely lead to wrong results.
|
||||
*
|
||||
*/
|
||||
void
|
||||
lp_build_flow_scope_declare(struct lp_build_flow_context *flow,
|
||||
LLVMValueRef *variable)
|
||||
{
|
||||
struct lp_build_flow_scope *scope;
|
||||
|
||||
scope = &lp_build_flow_peek(flow, lP_BUILD_FLOW_SCOPE)->scope;
|
||||
if(!scope)
|
||||
return;
|
||||
|
||||
assert(*variable);
|
||||
if(!*variable)
|
||||
return;
|
||||
|
||||
assert(flow->num_variables < LP_BUILD_FLOW_MAX_VARIABLES);
|
||||
if(flow->num_variables >= LP_BUILD_FLOW_MAX_VARIABLES)
|
||||
return;
|
||||
|
||||
flow->variables[flow->num_variables++] = variable;
|
||||
++scope->num_variables;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_flow_scope_end(struct lp_build_flow_context *flow)
|
||||
{
|
||||
struct lp_build_flow_scope *scope;
|
||||
|
||||
scope = &lp_build_flow_pop(flow, lP_BUILD_FLOW_SCOPE)->scope;
|
||||
if(!scope)
|
||||
return;
|
||||
|
||||
assert(flow->num_variables >= scope->num_variables);
|
||||
if(flow->num_variables < scope->num_variables) {
|
||||
flow->num_variables = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
flow->num_variables -= scope->num_variables;
|
||||
}
|
||||
|
||||
|
||||
static LLVMBasicBlockRef
|
||||
lp_build_flow_insert_block(struct lp_build_flow_context *flow)
|
||||
{
|
||||
LLVMValueRef cond;
|
||||
LLVMBasicBlockRef current_block;
|
||||
LLVMBasicBlockRef next_block;
|
||||
LLVMBasicBlockRef new_block;
|
||||
|
||||
current_block = LLVMGetInsertBlock(flow->builder);
|
||||
if(mask->value)
|
||||
mask->value = LLVMBuildAnd(mask->builder, mask->value, value, "");
|
||||
else
|
||||
mask->value = value;
|
||||
|
||||
/* FIXME: disabled until we have proper control flow helpers */
|
||||
#if 0
|
||||
cond = LLVMBuildICmp(mask->builder,
|
||||
LLVMIntEQ,
|
||||
LLVMBuildBitCast(mask->builder, mask->value, mask->reg_type, ""),
|
||||
LLVMConstNull(mask->reg_type),
|
||||
"");
|
||||
|
||||
current_block = LLVMGetInsertBlock(mask->builder);
|
||||
|
||||
if(!mask->skip_block) {
|
||||
LLVMValueRef function = LLVMGetBasicBlockParent(current_block);
|
||||
mask->skip_block = LLVMAppendBasicBlock(function, "skip");
|
||||
|
||||
mask->phi = LLVMBuildPhi(mask->builder, LLVMTypeOf(mask->value), "");
|
||||
}
|
||||
|
||||
next_block = LLVMGetNextBasicBlock(current_block);
|
||||
assert(next_block);
|
||||
if(next_block) {
|
||||
new_block = LLVMInsertBasicBlock(next_block, "");
|
||||
}
|
||||
@@ -295,148 +93,30 @@ lp_build_flow_insert_block(struct lp_build_flow_context *flow)
|
||||
new_block = LLVMAppendBasicBlock(function, "");
|
||||
}
|
||||
|
||||
return new_block;
|
||||
}
|
||||
LLVMAddIncoming(mask->phi, &mask->value, ¤t_block, 1);
|
||||
LLVMBuildCondBr(mask->builder, cond, mask->skip_block, new_block);
|
||||
|
||||
void
|
||||
lp_build_flow_skip_begin(struct lp_build_flow_context *flow)
|
||||
{
|
||||
struct lp_build_flow_skip *skip;
|
||||
LLVMBuilderRef builder;
|
||||
unsigned i;
|
||||
|
||||
skip = &lp_build_flow_push(flow, LP_BUILD_FLOW_SKIP)->skip;
|
||||
if(!skip)
|
||||
return;
|
||||
|
||||
skip->block = lp_build_flow_insert_block(flow);
|
||||
skip->num_variables = flow->num_variables;
|
||||
if(!skip->num_variables) {
|
||||
skip->phi = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
skip->phi = MALLOC(skip->num_variables * sizeof *skip->phi);
|
||||
if(!skip->phi) {
|
||||
skip->num_variables = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
builder = LLVMCreateBuilder();
|
||||
LLVMPositionBuilderAtEnd(builder, skip->block);
|
||||
|
||||
for(i = 0; i < skip->num_variables; ++i)
|
||||
skip->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), "");
|
||||
|
||||
LLVMDisposeBuilder(builder);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
|
||||
LLVMValueRef cond)
|
||||
{
|
||||
struct lp_build_flow_skip *skip;
|
||||
LLVMBasicBlockRef current_block;
|
||||
LLVMBasicBlockRef new_block;
|
||||
unsigned i;
|
||||
|
||||
skip = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SKIP)->skip;
|
||||
if(!skip)
|
||||
return;
|
||||
|
||||
current_block = LLVMGetInsertBlock(flow->builder);
|
||||
|
||||
new_block = lp_build_flow_insert_block(flow);
|
||||
|
||||
for(i = 0; i < skip->num_variables; ++i) {
|
||||
assert(*flow->variables[i]);
|
||||
LLVMAddIncoming(skip->phi[i], flow->variables[i], ¤t_block, 1);
|
||||
}
|
||||
|
||||
LLVMBuildCondBr(flow->builder, cond, skip->block, new_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(flow->builder, new_block);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_flow_skip_end(struct lp_build_flow_context *flow)
|
||||
{
|
||||
struct lp_build_flow_skip *skip;
|
||||
LLVMBasicBlockRef current_block;
|
||||
unsigned i;
|
||||
|
||||
skip = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SKIP)->skip;
|
||||
if(!skip)
|
||||
return;
|
||||
|
||||
current_block = LLVMGetInsertBlock(flow->builder);
|
||||
|
||||
for(i = 0; i < skip->num_variables; ++i) {
|
||||
assert(*flow->variables[i]);
|
||||
LLVMAddIncoming(skip->phi[i], flow->variables[i], ¤t_block, 1);
|
||||
*flow->variables[i] = skip->phi[i];
|
||||
}
|
||||
|
||||
LLVMBuildBr(flow->builder, skip->block);
|
||||
LLVMPositionBuilderAtEnd(flow->builder, skip->block);
|
||||
|
||||
FREE(skip->phi);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lp_build_mask_check(struct lp_build_mask_context *mask)
|
||||
{
|
||||
LLVMBuilderRef builder = mask->flow->builder;
|
||||
LLVMValueRef cond;
|
||||
|
||||
cond = LLVMBuildICmp(builder,
|
||||
LLVMIntEQ,
|
||||
LLVMBuildBitCast(builder, mask->value, mask->reg_type, ""),
|
||||
LLVMConstNull(mask->reg_type),
|
||||
"");
|
||||
|
||||
lp_build_flow_skip_cond_break(mask->flow, cond);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_mask_begin(struct lp_build_mask_context *mask,
|
||||
struct lp_build_flow_context *flow,
|
||||
union lp_type type,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
memset(mask, 0, sizeof *mask);
|
||||
|
||||
mask->flow = flow;
|
||||
mask->reg_type = LLVMIntType(type.width * type.length);
|
||||
mask->value = value;
|
||||
|
||||
lp_build_flow_scope_begin(flow);
|
||||
lp_build_flow_scope_declare(flow, &mask->value);
|
||||
lp_build_flow_skip_begin(flow);
|
||||
|
||||
lp_build_mask_check(mask);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_mask_update(struct lp_build_mask_context *mask,
|
||||
LLVMValueRef value)
|
||||
{
|
||||
mask->value = LLVMBuildAnd( mask->flow->builder, mask->value, value, "");
|
||||
|
||||
lp_build_mask_check(mask);
|
||||
LLVMPositionBuilderAtEnd(mask->builder, new_block);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_mask_end(struct lp_build_mask_context *mask)
|
||||
{
|
||||
lp_build_flow_skip_end(mask->flow);
|
||||
lp_build_flow_scope_end(mask->flow);
|
||||
if(mask->skip_block) {
|
||||
LLVMBasicBlockRef current_block = LLVMGetInsertBlock(mask->builder);
|
||||
|
||||
LLVMAddIncoming(mask->phi, &mask->value, ¤t_block, 1);
|
||||
LLVMBuildBr(mask->builder, mask->skip_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(mask->builder, mask->skip_block);
|
||||
|
||||
mask->value = mask->phi;
|
||||
mask->phi = NULL;
|
||||
mask->skip_block = NULL;
|
||||
}
|
||||
|
||||
return mask->value;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,49 +41,23 @@
|
||||
union lp_type;
|
||||
|
||||
|
||||
struct lp_build_flow_context;
|
||||
|
||||
|
||||
struct lp_build_flow_context *
|
||||
lp_build_flow_create(LLVMBuilderRef builder);
|
||||
|
||||
void
|
||||
lp_build_flow_destroy(struct lp_build_flow_context *flow);
|
||||
|
||||
void
|
||||
lp_build_flow_scope_begin(struct lp_build_flow_context *flow);
|
||||
|
||||
void
|
||||
lp_build_flow_scope_declare(struct lp_build_flow_context *flow,
|
||||
LLVMValueRef *variable);
|
||||
|
||||
void
|
||||
lp_build_flow_scope_end(struct lp_build_flow_context *flow);
|
||||
|
||||
void
|
||||
lp_build_flow_skip_begin(struct lp_build_flow_context *flow);
|
||||
|
||||
void
|
||||
lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow,
|
||||
LLVMValueRef cond);
|
||||
|
||||
void
|
||||
lp_build_flow_skip_end(struct lp_build_flow_context *flow);
|
||||
|
||||
|
||||
struct lp_build_mask_context
|
||||
{
|
||||
struct lp_build_flow_context *flow;
|
||||
LLVMBuilderRef builder;
|
||||
|
||||
LLVMTypeRef reg_type;
|
||||
|
||||
LLVMValueRef value;
|
||||
|
||||
LLVMValueRef phi;
|
||||
|
||||
LLVMBasicBlockRef skip_block;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
lp_build_mask_begin(struct lp_build_mask_context *mask,
|
||||
struct lp_build_flow_context *flow,
|
||||
LLVMBuilderRef builder,
|
||||
union lp_type type,
|
||||
LLVMValueRef value);
|
||||
|
||||
|
||||
@@ -31,14 +31,20 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Pixel format helpers.
|
||||
* LLVM IR building helpers interfaces.
|
||||
*
|
||||
* We use LLVM-C bindings for now. They are not documented, but follow the C++
|
||||
* interfaces very closely, and appear to be complete enough for code
|
||||
* genration. See
|
||||
* http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
|
||||
* for a standalone example.
|
||||
*/
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
|
||||
|
||||
#include "pipe/p_format.h"
|
||||
|
||||
struct util_format_description;
|
||||
|
||||
union lp_type;
|
||||
|
||||
|
||||
@@ -50,9 +56,9 @@ union lp_type;
|
||||
* @return RGBA in a 4 floats vector.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef packed);
|
||||
lp_build_unpack_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef packed);
|
||||
|
||||
|
||||
/**
|
||||
@@ -61,9 +67,9 @@ lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
|
||||
* @param rgba 4 float vector with the unpacked components.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_pack_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef rgba);
|
||||
lp_build_pack_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef rgba);
|
||||
|
||||
|
||||
/**
|
||||
@@ -75,9 +81,9 @@ lp_build_pack_rgba_aos(LLVMBuilderRef builder,
|
||||
* @return RGBA in a 4 floats vector.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_load_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr);
|
||||
lp_build_load_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr);
|
||||
|
||||
|
||||
/**
|
||||
@@ -86,34 +92,10 @@ lp_build_load_rgba_aos(LLVMBuilderRef builder,
|
||||
* @param rgba 4 float vector with the unpacked components.
|
||||
*/
|
||||
void
|
||||
lp_build_store_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr,
|
||||
LLVMValueRef rgba);
|
||||
lp_build_store_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr,
|
||||
LLVMValueRef rgba);
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_gather(LLVMBuilderRef builder,
|
||||
unsigned length,
|
||||
unsigned src_width,
|
||||
unsigned dst_width,
|
||||
LLVMValueRef base_ptr,
|
||||
LLVMValueRef offsets);
|
||||
|
||||
|
||||
void
|
||||
lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
|
||||
const struct util_format_description *format_desc,
|
||||
union lp_type type,
|
||||
LLVMValueRef packed,
|
||||
LLVMValueRef *rgba);
|
||||
|
||||
|
||||
void
|
||||
lp_build_load_rgba_soa(LLVMBuilderRef builder,
|
||||
const struct util_format_description *format_desc,
|
||||
union lp_type type,
|
||||
LLVMValueRef base_ptr,
|
||||
LLVMValueRef offsets,
|
||||
LLVMValueRef *rgba);
|
||||
|
||||
#endif /* !LP_BLD_H */
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef packed)
|
||||
lp_build_unpack_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef packed)
|
||||
{
|
||||
const struct util_format_description *desc;
|
||||
LLVMTypeRef type;
|
||||
@@ -152,9 +152,9 @@ lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_pack_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef rgba)
|
||||
lp_build_pack_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef rgba)
|
||||
{
|
||||
const struct util_format_description *desc;
|
||||
LLVMTypeRef type;
|
||||
@@ -250,9 +250,9 @@ lp_build_pack_rgba_aos(LLVMBuilderRef builder,
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_load_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr)
|
||||
lp_build_load_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr)
|
||||
{
|
||||
const struct util_format_description *desc;
|
||||
LLVMTypeRef type;
|
||||
@@ -272,15 +272,15 @@ lp_build_load_rgba_aos(LLVMBuilderRef builder,
|
||||
|
||||
packed = LLVMBuildLoad(builder, ptr, "");
|
||||
|
||||
return lp_build_unpack_rgba_aos(builder, format, packed);
|
||||
return lp_build_unpack_rgba(builder, format, packed);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_store_rgba_aos(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr,
|
||||
LLVMValueRef rgba)
|
||||
lp_build_store_rgba(LLVMBuilderRef builder,
|
||||
enum pipe_format format,
|
||||
LLVMValueRef ptr,
|
||||
LLVMValueRef rgba)
|
||||
{
|
||||
const struct util_format_description *desc;
|
||||
LLVMTypeRef type;
|
||||
@@ -294,7 +294,7 @@ lp_build_store_rgba_aos(LLVMBuilderRef builder,
|
||||
|
||||
type = LLVMIntType(desc->block.bits);
|
||||
|
||||
packed = lp_build_pack_rgba_aos(builder, format, rgba);
|
||||
packed = lp_build_pack_rgba(builder, format, rgba);
|
||||
|
||||
ptr = LLVMBuildBitCast(builder, ptr, LLVMPointerType(type, 0), "");
|
||||
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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_format.h"
|
||||
|
||||
#include "lp_bld_type.h"
|
||||
#include "lp_bld_const.h"
|
||||
#include "lp_bld_conv.h"
|
||||
#include "lp_bld_format.h"
|
||||
|
||||
|
||||
/**
|
||||
* Gather elements from scatter positions in memory into a single vector.
|
||||
*
|
||||
* @param src_width src element width
|
||||
* @param dst_width result element width (source will be expanded to fit)
|
||||
* @param length length of the offsets,
|
||||
* @param base_ptr base pointer, should be a i8 pointer type.
|
||||
* @param offsets vector with offsets
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_gather(LLVMBuilderRef builder,
|
||||
unsigned length,
|
||||
unsigned src_width,
|
||||
unsigned dst_width,
|
||||
LLVMValueRef base_ptr,
|
||||
LLVMValueRef offsets)
|
||||
{
|
||||
LLVMTypeRef src_type = LLVMIntType(src_width);
|
||||
LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0);
|
||||
LLVMTypeRef dst_elem_type = LLVMIntType(dst_width);
|
||||
LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length);
|
||||
LLVMValueRef res;
|
||||
unsigned i;
|
||||
|
||||
res = LLVMGetUndef(dst_vec_type);
|
||||
for(i = 0; i < length; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
LLVMValueRef elem_offset;
|
||||
LLVMValueRef elem_ptr;
|
||||
LLVMValueRef elem;
|
||||
|
||||
elem_offset = LLVMBuildExtractElement(builder, offsets, index, "");
|
||||
elem_ptr = LLVMBuildGEP(builder, base_ptr, &elem_offset, 1, "");
|
||||
elem_ptr = LLVMBuildBitCast(builder, elem_ptr, src_ptr_type, "");
|
||||
elem = LLVMBuildLoad(builder, elem_ptr, "");
|
||||
|
||||
assert(src_width <= dst_width);
|
||||
if(src_width > dst_width)
|
||||
elem = LLVMBuildTrunc(builder, elem, dst_elem_type, "");
|
||||
if(src_width < dst_width)
|
||||
elem = LLVMBuildZExt(builder, elem, dst_elem_type, "");
|
||||
|
||||
res = LLVMBuildInsertElement(builder, res, elem, index, "");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
lp_build_format_swizzle(union lp_type type,
|
||||
const LLVMValueRef *inputs,
|
||||
enum util_format_swizzle swizzle)
|
||||
{
|
||||
switch (swizzle) {
|
||||
case UTIL_FORMAT_SWIZZLE_X:
|
||||
case UTIL_FORMAT_SWIZZLE_Y:
|
||||
case UTIL_FORMAT_SWIZZLE_Z:
|
||||
case UTIL_FORMAT_SWIZZLE_W:
|
||||
return inputs[swizzle];
|
||||
case UTIL_FORMAT_SWIZZLE_0:
|
||||
return lp_build_zero(type);
|
||||
case UTIL_FORMAT_SWIZZLE_1:
|
||||
return lp_build_one(type);
|
||||
case UTIL_FORMAT_SWIZZLE_NONE:
|
||||
return lp_build_undef(type);
|
||||
default:
|
||||
assert(0);
|
||||
return lp_build_undef(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
|
||||
const struct util_format_description *format_desc,
|
||||
union lp_type type,
|
||||
LLVMValueRef packed,
|
||||
LLVMValueRef *rgba)
|
||||
{
|
||||
LLVMValueRef inputs[4];
|
||||
unsigned start;
|
||||
unsigned chan;
|
||||
|
||||
/* FIXME: Support more formats */
|
||||
assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
|
||||
assert(format_desc->block.width == 1);
|
||||
assert(format_desc->block.height == 1);
|
||||
assert(format_desc->block.bits <= 32);
|
||||
|
||||
/* Decode the input vector components */
|
||||
start = 0;
|
||||
for (chan = 0; chan < 4; ++chan) {
|
||||
unsigned width = format_desc->channel[chan].size;
|
||||
unsigned stop = start + width;
|
||||
LLVMValueRef input;
|
||||
|
||||
input = packed;
|
||||
|
||||
switch(format_desc->channel[chan].type) {
|
||||
case UTIL_FORMAT_TYPE_VOID:
|
||||
input = NULL;
|
||||
break;
|
||||
|
||||
case UTIL_FORMAT_TYPE_UNSIGNED:
|
||||
if(type.floating) {
|
||||
if(start)
|
||||
input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(type, start), "");
|
||||
if(stop < format_desc->block.bits) {
|
||||
unsigned mask = ((unsigned long long)1 << width) - 1;
|
||||
input = LLVMBuildAnd(builder, input, lp_build_int_const_scalar(type, mask), "");
|
||||
}
|
||||
|
||||
if(format_desc->channel[chan].normalized)
|
||||
input = lp_build_unsigned_norm_to_float(builder, width, type, input);
|
||||
else
|
||||
input = LLVMBuildFPToSI(builder, input, lp_build_vec_type(type), "");
|
||||
}
|
||||
else {
|
||||
/* FIXME */
|
||||
assert(0);
|
||||
input = lp_build_undef(type);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* fall through */
|
||||
input = lp_build_undef(type);
|
||||
break;
|
||||
}
|
||||
|
||||
inputs[chan] = input;
|
||||
|
||||
start = stop;
|
||||
}
|
||||
|
||||
if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
|
||||
enum util_format_swizzle swizzle = format_desc->swizzle[0];
|
||||
LLVMValueRef depth = lp_build_format_swizzle(type, inputs, swizzle);
|
||||
rgba[2] = rgba[1] = rgba[0] = depth;
|
||||
rgba[3] = lp_build_one(type);
|
||||
}
|
||||
else {
|
||||
for (chan = 0; chan < 4; ++chan) {
|
||||
enum util_format_swizzle swizzle = format_desc->swizzle[chan];
|
||||
rgba[chan] = lp_build_format_swizzle(type, inputs, swizzle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_load_rgba_soa(LLVMBuilderRef builder,
|
||||
const struct util_format_description *format_desc,
|
||||
union lp_type type,
|
||||
LLVMValueRef base_ptr,
|
||||
LLVMValueRef offsets,
|
||||
LLVMValueRef *rgba)
|
||||
{
|
||||
LLVMValueRef packed;
|
||||
|
||||
assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
|
||||
assert(format_desc->block.width == 1);
|
||||
assert(format_desc->block.height == 1);
|
||||
assert(format_desc->block.bits <= 32);
|
||||
|
||||
packed = lp_build_gather(builder,
|
||||
type.length, format_desc->block.bits, type.width,
|
||||
base_ptr, offsets);
|
||||
|
||||
lp_build_unpack_rgba_soa(builder, format_desc, type, packed, rgba);
|
||||
}
|
||||
@@ -313,6 +313,8 @@ lp_build_select(struct lp_build_context *bld,
|
||||
b = LLVMBuildBitCast(bld->builder, b, int_vec_type, "");
|
||||
}
|
||||
|
||||
/* TODO: On SSE4 we could do this with a single instruction -- PBLENDVB */
|
||||
|
||||
a = LLVMBuildAnd(bld->builder, a, mask, "");
|
||||
|
||||
/* This often gets translated to PANDN, but sometimes the NOT is
|
||||
@@ -374,9 +376,9 @@ lp_build_select_aos(struct lp_build_context *bld,
|
||||
|
||||
return LLVMBuildShuffleVector(bld->builder, a, b, LLVMConstVector(shuffles, n), "");
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
/* XXX: Unfortunately select of vectors do not work */
|
||||
else if(0) {
|
||||
/* FIXME: Unfortunately select of vectors do not work */
|
||||
/* Use a select */
|
||||
LLVMTypeRef elem_type = LLVMInt1Type();
|
||||
LLVMValueRef cond[LP_MAX_VECTOR_LENGTH];
|
||||
@@ -386,9 +388,10 @@ lp_build_select_aos(struct lp_build_context *bld,
|
||||
cond[j + i] = LLVMConstInt(elem_type, cond[i] ? 1 : 0, 0);
|
||||
|
||||
return LLVMBuildSelect(bld->builder, LLVMConstVector(cond, n), a, b, "");
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
LLVMValueRef mask = lp_build_const_mask_aos(type, cond);
|
||||
return lp_build_select(bld, mask, a, b);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Texture sampling.
|
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef LP_BLD_SAMPLE_H
|
||||
#define LP_BLD_SAMPLE_H
|
||||
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
|
||||
struct pipe_texture;
|
||||
struct pipe_sampler_state;
|
||||
union lp_type;
|
||||
|
||||
|
||||
/**
|
||||
* Sampler static state.
|
||||
*
|
||||
* These are the bits of state from pipe_texture and pipe_sampler_state that
|
||||
* are embedded in the generated code.
|
||||
*/
|
||||
struct lp_sampler_static_state
|
||||
{
|
||||
/* pipe_texture's state */
|
||||
enum pipe_format format;
|
||||
unsigned target:2;
|
||||
unsigned pot_width:1;
|
||||
unsigned pot_height:1;
|
||||
unsigned pot_depth:1;
|
||||
|
||||
/* pipe_sampler_state's state */
|
||||
unsigned wrap_s:3;
|
||||
unsigned wrap_t:3;
|
||||
unsigned wrap_r:3;
|
||||
unsigned min_img_filter:2;
|
||||
unsigned min_mip_filter:2;
|
||||
unsigned mag_img_filter:2;
|
||||
unsigned compare_mode:1;
|
||||
unsigned compare_func:3;
|
||||
unsigned normalized_coords:1;
|
||||
unsigned prefilter:4;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sampler dynamic state.
|
||||
*
|
||||
* These are the bits of state from pipe_texture and pipe_sampler_state that
|
||||
* are computed in runtime.
|
||||
*
|
||||
* There are obtained through callbacks, as we don't want to tie the texture
|
||||
* sampling code generation logic to any particular texture layout or pipe
|
||||
* driver.
|
||||
*/
|
||||
struct lp_sampler_dynamic_state
|
||||
{
|
||||
|
||||
/** Obtain the base texture width. */
|
||||
LLVMValueRef
|
||||
(*width)( struct lp_sampler_dynamic_state *state,
|
||||
LLVMBuilderRef builder,
|
||||
unsigned unit);
|
||||
|
||||
/** Obtain the base texture height. */
|
||||
LLVMValueRef
|
||||
(*height)( struct lp_sampler_dynamic_state *state,
|
||||
LLVMBuilderRef builder,
|
||||
unsigned unit);
|
||||
|
||||
LLVMValueRef
|
||||
(*stride)( struct lp_sampler_dynamic_state *state,
|
||||
LLVMBuilderRef builder,
|
||||
unsigned unit);
|
||||
|
||||
LLVMValueRef
|
||||
(*data_ptr)( struct lp_sampler_dynamic_state *state,
|
||||
LLVMBuilderRef builder,
|
||||
unsigned unit);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Derive the sampler static state.
|
||||
*/
|
||||
void
|
||||
lp_sampler_static_state(struct lp_sampler_static_state *state,
|
||||
const struct pipe_texture *texture,
|
||||
const struct pipe_sampler_state *sampler);
|
||||
|
||||
|
||||
void
|
||||
lp_build_sample_soa(LLVMBuilderRef builder,
|
||||
const struct lp_sampler_static_state *static_state,
|
||||
struct lp_sampler_dynamic_state *dynamic_state,
|
||||
union lp_type fp_type,
|
||||
unsigned unit,
|
||||
unsigned num_coords,
|
||||
const LLVMValueRef *coords,
|
||||
LLVMValueRef lodbias,
|
||||
LLVMValueRef *texel);
|
||||
|
||||
|
||||
|
||||
#endif /* LP_BLD_SAMPLE_H */
|
||||
@@ -1,411 +0,0 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Texture sampling.
|
||||
*
|
||||
* @author Jose Fonseca <jfonseca@vmware.com>
|
||||
*/
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_format.h"
|
||||
#include "lp_bld_debug.h"
|
||||
#include "lp_bld_type.h"
|
||||
#include "lp_bld_const.h"
|
||||
#include "lp_bld_arit.h"
|
||||
#include "lp_bld_logic.h"
|
||||
#include "lp_bld_swizzle.h"
|
||||
#include "lp_bld_format.h"
|
||||
#include "lp_bld_sample.h"
|
||||
|
||||
|
||||
void
|
||||
lp_sampler_static_state(struct lp_sampler_static_state *state,
|
||||
const struct pipe_texture *texture,
|
||||
const struct pipe_sampler_state *sampler)
|
||||
{
|
||||
memset(state, 0, sizeof *state);
|
||||
|
||||
if(!texture)
|
||||
return;
|
||||
|
||||
if(!sampler)
|
||||
return;
|
||||
|
||||
state->format = texture->format;
|
||||
state->target = texture->target;
|
||||
state->pot_width = util_is_pot(texture->width[0]);
|
||||
state->pot_height = util_is_pot(texture->height[0]);
|
||||
state->pot_depth = util_is_pot(texture->depth[0]);
|
||||
|
||||
state->wrap_s = sampler->wrap_s;
|
||||
state->wrap_t = sampler->wrap_t;
|
||||
state->wrap_r = sampler->wrap_r;
|
||||
state->min_img_filter = sampler->min_img_filter;
|
||||
state->min_mip_filter = sampler->min_mip_filter;
|
||||
state->mag_img_filter = sampler->mag_img_filter;
|
||||
if(sampler->compare_mode) {
|
||||
state->compare_mode = sampler->compare_mode;
|
||||
state->compare_func = sampler->compare_func;
|
||||
}
|
||||
state->normalized_coords = sampler->normalized_coords;
|
||||
state->prefilter = sampler->prefilter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Keep all information for sampling code generation in a single place.
|
||||
*/
|
||||
struct lp_build_sample_context
|
||||
{
|
||||
LLVMBuilderRef builder;
|
||||
|
||||
const struct lp_sampler_static_state *static_state;
|
||||
|
||||
struct lp_sampler_dynamic_state *dynamic_state;
|
||||
|
||||
const struct util_format_description *format_desc;
|
||||
|
||||
/** Incoming coordinates type and build context */
|
||||
union lp_type coord_type;
|
||||
struct lp_build_context coord_bld;
|
||||
|
||||
/** Integer coordinates */
|
||||
union lp_type int_coord_type;
|
||||
struct lp_build_context int_coord_bld;
|
||||
|
||||
/** Output texels type and build context */
|
||||
union lp_type texel_type;
|
||||
struct lp_build_context texel_bld;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
lp_build_sample_texel(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef x,
|
||||
LLVMValueRef y,
|
||||
LLVMValueRef y_stride,
|
||||
LLVMValueRef data_ptr,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
LLVMValueRef x_stride;
|
||||
LLVMValueRef offset;
|
||||
|
||||
x_stride = lp_build_const_scalar(bld->int_coord_type, bld->format_desc->block.bits/8);
|
||||
|
||||
if(bld->format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
|
||||
LLVMValueRef x_lo, x_hi;
|
||||
LLVMValueRef y_lo, y_hi;
|
||||
LLVMValueRef x_stride_lo, x_stride_hi;
|
||||
LLVMValueRef y_stride_lo, y_stride_hi;
|
||||
LLVMValueRef x_offset_lo, x_offset_hi;
|
||||
LLVMValueRef y_offset_lo, y_offset_hi;
|
||||
LLVMValueRef offset_lo, offset_hi;
|
||||
|
||||
x_lo = LLVMBuildAnd(bld->builder, x, int_coord_bld->one, "");
|
||||
y_lo = LLVMBuildAnd(bld->builder, y, int_coord_bld->one, "");
|
||||
|
||||
x_hi = LLVMBuildLShr(bld->builder, x, int_coord_bld->one, "");
|
||||
y_hi = LLVMBuildLShr(bld->builder, y, int_coord_bld->one, "");
|
||||
|
||||
x_stride_lo = x_stride;
|
||||
y_stride_lo = lp_build_const_scalar(bld->int_coord_type, 2*bld->format_desc->block.bits/8);
|
||||
|
||||
x_stride_hi = lp_build_const_scalar(bld->int_coord_type, 4*bld->format_desc->block.bits/8);
|
||||
y_stride_hi = LLVMBuildShl(bld->builder, y_stride, int_coord_bld->one, "");
|
||||
|
||||
x_offset_lo = lp_build_mul(int_coord_bld, x_lo, x_stride_lo);
|
||||
y_offset_lo = lp_build_mul(int_coord_bld, y_lo, y_stride_lo);
|
||||
offset_lo = lp_build_add(int_coord_bld, x_offset_lo, y_offset_lo);
|
||||
|
||||
x_offset_hi = lp_build_mul(int_coord_bld, x_hi, x_stride_hi);
|
||||
y_offset_hi = lp_build_mul(int_coord_bld, y_hi, y_stride_hi);
|
||||
offset_hi = lp_build_add(int_coord_bld, x_offset_hi, y_offset_hi);
|
||||
|
||||
offset = lp_build_add(int_coord_bld, offset_hi, offset_lo);
|
||||
}
|
||||
else {
|
||||
LLVMValueRef x_offset;
|
||||
LLVMValueRef y_offset;
|
||||
|
||||
x_offset = lp_build_mul(int_coord_bld, x, x_stride);
|
||||
y_offset = lp_build_mul(int_coord_bld, y, y_stride);
|
||||
|
||||
offset = lp_build_add(int_coord_bld, x_offset, y_offset);
|
||||
}
|
||||
|
||||
lp_build_load_rgba_soa(bld->builder,
|
||||
bld->format_desc,
|
||||
bld->texel_type,
|
||||
data_ptr,
|
||||
offset,
|
||||
texel);
|
||||
}
|
||||
|
||||
|
||||
static LLVMValueRef
|
||||
lp_build_sample_wrap(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef coord,
|
||||
LLVMValueRef length,
|
||||
boolean is_pot,
|
||||
unsigned wrap_mode)
|
||||
{
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
LLVMValueRef length_minus_one;
|
||||
|
||||
length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one);
|
||||
|
||||
switch(wrap_mode) {
|
||||
case PIPE_TEX_WRAP_REPEAT:
|
||||
if(is_pot)
|
||||
coord = LLVMBuildAnd(bld->builder, coord, length_minus_one, "");
|
||||
else
|
||||
/* Signed remainder won't give the right results for negative
|
||||
* dividends but unsigned remainder does.*/
|
||||
coord = LLVMBuildURem(bld->builder, coord, length, "");
|
||||
break;
|
||||
|
||||
case PIPE_TEX_WRAP_CLAMP:
|
||||
coord = lp_build_max(int_coord_bld, coord, int_coord_bld->zero);
|
||||
coord = lp_build_min(int_coord_bld, coord, length_minus_one);
|
||||
break;
|
||||
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
|
||||
case PIPE_TEX_WRAP_MIRROR_REPEAT:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
|
||||
/* FIXME */
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return coord;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef s,
|
||||
LLVMValueRef t,
|
||||
LLVMValueRef width,
|
||||
LLVMValueRef height,
|
||||
LLVMValueRef stride,
|
||||
LLVMValueRef data_ptr,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
LLVMValueRef x;
|
||||
LLVMValueRef y;
|
||||
|
||||
x = lp_build_ifloor(&bld->coord_bld, s);
|
||||
y = lp_build_ifloor(&bld->coord_bld, t);
|
||||
|
||||
x = lp_build_sample_wrap(bld, x, width, bld->static_state->pot_width, bld->static_state->wrap_s);
|
||||
y = lp_build_sample_wrap(bld, y, height, bld->static_state->pot_height, bld->static_state->wrap_t);
|
||||
|
||||
lp_build_sample_texel(bld, x, y, stride, data_ptr, texel);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef s,
|
||||
LLVMValueRef t,
|
||||
LLVMValueRef width,
|
||||
LLVMValueRef height,
|
||||
LLVMValueRef stride,
|
||||
LLVMValueRef data_ptr,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
LLVMValueRef half;
|
||||
LLVMValueRef s_ipart;
|
||||
LLVMValueRef t_ipart;
|
||||
LLVMValueRef s_fpart;
|
||||
LLVMValueRef t_fpart;
|
||||
LLVMValueRef x0, x1;
|
||||
LLVMValueRef y0, y1;
|
||||
LLVMValueRef neighbors[2][2][4];
|
||||
unsigned chan;
|
||||
|
||||
half = lp_build_const_scalar(bld->coord_type, 0.5);
|
||||
s = lp_build_sub(&bld->coord_bld, s, half);
|
||||
t = lp_build_sub(&bld->coord_bld, t, half);
|
||||
|
||||
s_ipart = lp_build_floor(&bld->coord_bld, s);
|
||||
t_ipart = lp_build_floor(&bld->coord_bld, t);
|
||||
|
||||
s_fpart = lp_build_sub(&bld->coord_bld, s, s_ipart);
|
||||
t_fpart = lp_build_sub(&bld->coord_bld, t, t_ipart);
|
||||
|
||||
x0 = lp_build_int(&bld->coord_bld, s_ipart);
|
||||
y0 = lp_build_int(&bld->coord_bld, t_ipart);
|
||||
|
||||
x0 = lp_build_sample_wrap(bld, x0, width, bld->static_state->pot_width, bld->static_state->wrap_s);
|
||||
y0 = lp_build_sample_wrap(bld, y0, height, bld->static_state->pot_height, bld->static_state->wrap_t);
|
||||
|
||||
x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one);
|
||||
y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one);
|
||||
|
||||
x1 = lp_build_sample_wrap(bld, x1, width, bld->static_state->pot_width, bld->static_state->wrap_s);
|
||||
y1 = lp_build_sample_wrap(bld, y1, height, bld->static_state->pot_height, bld->static_state->wrap_t);
|
||||
|
||||
lp_build_sample_texel(bld, x0, y0, stride, data_ptr, neighbors[0][0]);
|
||||
lp_build_sample_texel(bld, x1, y0, stride, data_ptr, neighbors[0][1]);
|
||||
lp_build_sample_texel(bld, x0, y1, stride, data_ptr, neighbors[1][0]);
|
||||
lp_build_sample_texel(bld, x1, y1, stride, data_ptr, neighbors[1][1]);
|
||||
|
||||
/* TODO: Don't interpolate missing channels */
|
||||
for(chan = 0; chan < 4; ++chan) {
|
||||
texel[chan] = lp_build_lerp_2d(&bld->texel_bld,
|
||||
s_fpart, t_fpart,
|
||||
neighbors[0][0][chan],
|
||||
neighbors[0][1][chan],
|
||||
neighbors[1][0][chan],
|
||||
neighbors[1][1][chan]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lp_build_sample_compare(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef p,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
struct lp_build_context *texel_bld = &bld->texel_bld;
|
||||
LLVMValueRef res;
|
||||
unsigned chan;
|
||||
|
||||
if(!bld->static_state->compare_mode)
|
||||
return;
|
||||
|
||||
/* TODO: Compare before swizzling, to avoid redundant computations */
|
||||
res = NULL;
|
||||
for(chan = 0; chan < 4; ++chan) {
|
||||
LLVMValueRef cmp;
|
||||
cmp = lp_build_cmp(texel_bld, bld->static_state->compare_func, p, texel[chan]);
|
||||
cmp = lp_build_select(texel_bld, cmp, texel_bld->one, texel_bld->zero);
|
||||
|
||||
if(res)
|
||||
res = lp_build_add(texel_bld, res, cmp);
|
||||
else
|
||||
res = cmp;
|
||||
}
|
||||
|
||||
assert(res);
|
||||
res = lp_build_mul(texel_bld, res, lp_build_const_scalar(texel_bld->type, 0.25));
|
||||
|
||||
/* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
|
||||
for(chan = 0; chan < 3; ++chan)
|
||||
texel[chan] = res;
|
||||
texel[3] = texel_bld->one;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_sample_soa(LLVMBuilderRef builder,
|
||||
const struct lp_sampler_static_state *static_state,
|
||||
struct lp_sampler_dynamic_state *dynamic_state,
|
||||
union lp_type type,
|
||||
unsigned unit,
|
||||
unsigned num_coords,
|
||||
const LLVMValueRef *coords,
|
||||
LLVMValueRef lodbias,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
struct lp_build_sample_context bld;
|
||||
LLVMValueRef width;
|
||||
LLVMValueRef height;
|
||||
LLVMValueRef stride;
|
||||
LLVMValueRef data_ptr;
|
||||
LLVMValueRef s;
|
||||
LLVMValueRef t;
|
||||
LLVMValueRef p;
|
||||
|
||||
/* Setup our build context */
|
||||
memset(&bld, 0, sizeof bld);
|
||||
bld.builder = builder;
|
||||
bld.static_state = static_state;
|
||||
bld.dynamic_state = dynamic_state;
|
||||
bld.format_desc = util_format_description(static_state->format);
|
||||
bld.coord_type = type;
|
||||
bld.int_coord_type = lp_int_type(type);
|
||||
bld.texel_type = type;
|
||||
lp_build_context_init(&bld.coord_bld, builder, bld.coord_type);
|
||||
lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type);
|
||||
lp_build_context_init(&bld.texel_bld, builder, bld.texel_type);
|
||||
|
||||
/* Get the dynamic state */
|
||||
width = dynamic_state->width(dynamic_state, builder, unit);
|
||||
height = dynamic_state->height(dynamic_state, builder, unit);
|
||||
stride = dynamic_state->stride(dynamic_state, builder, unit);
|
||||
data_ptr = dynamic_state->data_ptr(dynamic_state, builder, unit);
|
||||
|
||||
s = coords[0];
|
||||
t = coords[1];
|
||||
p = coords[2];
|
||||
|
||||
width = lp_build_broadcast_scalar(&bld.int_coord_bld, width);
|
||||
height = lp_build_broadcast_scalar(&bld.int_coord_bld, height);
|
||||
stride = lp_build_broadcast_scalar(&bld.int_coord_bld, stride);
|
||||
|
||||
if(static_state->target == PIPE_TEXTURE_1D)
|
||||
t = bld.coord_bld.zero;
|
||||
|
||||
if(static_state->normalized_coords) {
|
||||
LLVMTypeRef coord_vec_type = lp_build_vec_type(bld.coord_type);
|
||||
LLVMValueRef fp_width = LLVMBuildSIToFP(builder, width, coord_vec_type, "");
|
||||
LLVMValueRef fp_height = LLVMBuildSIToFP(builder, height, coord_vec_type, "");
|
||||
s = lp_build_mul(&bld.coord_bld, s, fp_width);
|
||||
t = lp_build_mul(&bld.coord_bld, t, fp_height);
|
||||
}
|
||||
|
||||
switch (static_state->min_img_filter) {
|
||||
case PIPE_TEX_FILTER_NEAREST:
|
||||
lp_build_sample_2d_nearest_soa(&bld, s, t, width, height, stride, data_ptr, texel);
|
||||
break;
|
||||
case PIPE_TEX_FILTER_LINEAR:
|
||||
case PIPE_TEX_FILTER_ANISO:
|
||||
lp_build_sample_2d_linear_soa(&bld, s, t, width, height, stride, data_ptr, texel);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* FIXME: respect static_state->min_mip_filter */;
|
||||
/* FIXME: respect static_state->mag_img_filter */;
|
||||
/* FIXME: respect static_state->prefilter */;
|
||||
|
||||
lp_build_sample_compare(&bld, p, texel);
|
||||
}
|
||||
@@ -41,31 +41,18 @@
|
||||
#include "lp_bld_struct.h"
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_struct_get_ptr(LLVMBuilderRef builder,
|
||||
LLVMValueRef ptr,
|
||||
unsigned member,
|
||||
const char *name)
|
||||
{
|
||||
LLVMValueRef indices[2];
|
||||
LLVMValueRef member_ptr;
|
||||
indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
indices[1] = LLVMConstInt(LLVMInt32Type(), member, 0);
|
||||
member_ptr = LLVMBuildGEP(builder, ptr, indices, Elements(indices), "");
|
||||
lp_build_name(member_ptr, "%s.%s_ptr", LLVMGetValueName(ptr), name);
|
||||
return member_ptr;
|
||||
}
|
||||
|
||||
|
||||
LLVMValueRef
|
||||
lp_build_struct_get(LLVMBuilderRef builder,
|
||||
LLVMValueRef ptr,
|
||||
unsigned member,
|
||||
const char *name)
|
||||
{
|
||||
LLVMValueRef indices[2];
|
||||
LLVMValueRef member_ptr;
|
||||
LLVMValueRef res;
|
||||
member_ptr = lp_build_struct_get_ptr(builder, ptr, member, name);
|
||||
indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
indices[1] = LLVMConstInt(LLVMInt32Type(), member, 0);
|
||||
member_ptr = LLVMBuildGEP(builder, ptr, indices, Elements(indices), "");
|
||||
res = LLVMBuildLoad(builder, member_ptr, "");
|
||||
lp_build_name(res, "%s.%s", LLVMGetValueName(ptr), name);
|
||||
return res;
|
||||
|
||||
@@ -53,18 +53,6 @@
|
||||
offsetof(_ctype, _cmember))
|
||||
|
||||
|
||||
/**
|
||||
* Get value pointer to a structure member.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_struct_get_ptr(LLVMBuilderRef builder,
|
||||
LLVMValueRef ptr,
|
||||
unsigned member,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* Get the value of a structure member.
|
||||
*/
|
||||
LLVMValueRef
|
||||
lp_build_struct_get(LLVMBuilderRef builder,
|
||||
LLVMValueRef ptr,
|
||||
|
||||
@@ -44,30 +44,14 @@ struct lp_build_context;
|
||||
struct lp_build_mask_context;
|
||||
|
||||
|
||||
/**
|
||||
* Sampler code generation interface.
|
||||
*
|
||||
* Although texture sampling is a requirement for TGSI translation, it is
|
||||
* a very different problem with several different approaches to it. This
|
||||
* structure establishes an interface for texture sampling code generation, so
|
||||
* that we can easily use different texture sampling strategies.
|
||||
*/
|
||||
struct lp_build_sampler_soa
|
||||
{
|
||||
void
|
||||
(*destroy)( struct lp_build_sampler_soa *sampler );
|
||||
|
||||
void
|
||||
(*emit_fetch_texel)( struct lp_build_sampler_soa *sampler,
|
||||
LLVMBuilderRef builder,
|
||||
union lp_type type,
|
||||
unsigned unit,
|
||||
unsigned num_coords,
|
||||
const LLVMValueRef *coords,
|
||||
LLVMValueRef lodbias,
|
||||
LLVMValueRef *texel);
|
||||
};
|
||||
|
||||
typedef void
|
||||
(*lp_emit_fetch_texel_soa_callback)( LLVMBuilderRef builder,
|
||||
void *context,
|
||||
unsigned unit,
|
||||
unsigned num_coords,
|
||||
const LLVMValueRef *coords,
|
||||
LLVMValueRef lodbias,
|
||||
LLVMValueRef *texel);
|
||||
|
||||
void
|
||||
lp_build_tgsi_soa(LLVMBuilderRef builder,
|
||||
@@ -78,7 +62,8 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
|
||||
const LLVMValueRef *pos,
|
||||
const LLVMValueRef (*inputs)[4],
|
||||
LLVMValueRef (*outputs)[4],
|
||||
struct lp_build_sampler_soa *sampler);
|
||||
lp_emit_fetch_texel_soa_callback emit_fetch_texel,
|
||||
void *emit_fetch_texel_context);
|
||||
|
||||
|
||||
#endif /* LP_BLD_TGSI_H */
|
||||
|
||||
@@ -88,7 +88,8 @@ struct lp_build_tgsi_soa_context
|
||||
const LLVMValueRef (*inputs)[NUM_CHANNELS];
|
||||
LLVMValueRef (*outputs)[NUM_CHANNELS];
|
||||
|
||||
struct lp_build_sampler_soa *sampler;
|
||||
lp_emit_fetch_texel_soa_callback emit_fetch_texel;
|
||||
void *emit_fetch_texel_context;
|
||||
|
||||
LLVMValueRef immediates[LP_MAX_IMMEDIATES][NUM_CHANNELS];
|
||||
LLVMValueRef temps[LP_MAX_TEMPS][NUM_CHANNELS];
|
||||
@@ -167,7 +168,6 @@ emit_fetch(
|
||||
break;
|
||||
|
||||
case TGSI_UTIL_SIGN_SET:
|
||||
/* TODO: Use bitwese OR for floating point */
|
||||
res = lp_build_abs( &bld->base, res );
|
||||
res = LLVMBuildNeg( bld->base.builder, res, "" );
|
||||
break;
|
||||
@@ -289,11 +289,8 @@ emit_tex( struct lp_build_tgsi_soa_context *bld,
|
||||
coords[i] = lp_build_mul(&bld->base, coords[i], oow);
|
||||
}
|
||||
|
||||
bld->sampler->emit_fetch_texel(bld->sampler,
|
||||
bld->base.builder,
|
||||
bld->base.type,
|
||||
unit, num_coords, coords, lodbias,
|
||||
texel);
|
||||
bld->emit_fetch_texel(bld->base.builder, bld->emit_fetch_texel_context,
|
||||
unit, num_coords, coords, lodbias, texel);
|
||||
|
||||
FOR_EACH_DST0_ENABLED_CHANNEL( inst, i ) {
|
||||
emit_store( bld, inst, 0, i, texel[i] );
|
||||
@@ -350,6 +347,14 @@ emit_kil(
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
emit_kilp(
|
||||
struct lp_build_tgsi_soa_context *bld )
|
||||
{
|
||||
/* XXX todo / fix me */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if inst src/dest regs use indirect addressing into temporary
|
||||
* register file.
|
||||
@@ -391,7 +396,6 @@ emit_instruction(
|
||||
switch (inst->Instruction.Opcode) {
|
||||
#if 0
|
||||
case TGSI_OPCODE_ARL:
|
||||
/* FIXME */
|
||||
FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
|
||||
tmp0 = emit_fetch( bld, inst, 0, chan_index );
|
||||
emit_flr(bld, 0, 0);
|
||||
@@ -680,7 +684,6 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_CND:
|
||||
/* FIXME */
|
||||
return 0;
|
||||
break;
|
||||
|
||||
@@ -844,11 +847,13 @@ emit_instruction(
|
||||
return 0;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case TGSI_OPCODE_KILP:
|
||||
/* predicated kill */
|
||||
/* FIXME */
|
||||
return 0;
|
||||
emit_kilp( bld );
|
||||
return 0; /* XXX fix me */
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TGSI_OPCODE_KIL:
|
||||
/* conditional kill */
|
||||
@@ -1278,7 +1283,8 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
|
||||
const LLVMValueRef *pos,
|
||||
const LLVMValueRef (*inputs)[NUM_CHANNELS],
|
||||
LLVMValueRef (*outputs)[NUM_CHANNELS],
|
||||
struct lp_build_sampler_soa *sampler)
|
||||
lp_emit_fetch_texel_soa_callback emit_fetch_texel,
|
||||
void *emit_fetch_texel_context)
|
||||
{
|
||||
struct lp_build_tgsi_soa_context bld;
|
||||
struct tgsi_parse_context parse;
|
||||
@@ -1293,7 +1299,8 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
|
||||
bld.inputs = inputs;
|
||||
bld.outputs = outputs;
|
||||
bld.consts_ptr = consts_ptr;
|
||||
bld.sampler = sampler;
|
||||
bld.emit_fetch_texel = emit_fetch_texel;
|
||||
bld.emit_fetch_texel_context = emit_fetch_texel_context;
|
||||
|
||||
tgsi_parse_init( &parse, tokens );
|
||||
|
||||
@@ -1302,7 +1309,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
|
||||
|
||||
switch( parse.FullToken.Token.Type ) {
|
||||
case TGSI_TOKEN_TYPE_DECLARATION:
|
||||
/* Inputs already interpolated */
|
||||
/* Input already interpolated */
|
||||
break;
|
||||
|
||||
case TGSI_TOKEN_TYPE_INSTRUCTION:
|
||||
|
||||
@@ -157,17 +157,6 @@ lp_build_int_vec_type(union lp_type type)
|
||||
}
|
||||
|
||||
|
||||
union lp_type
|
||||
lp_int_type(union lp_type type)
|
||||
{
|
||||
union lp_type int_type;
|
||||
int_type.value = 0;
|
||||
int_type.width = type.width;
|
||||
int_type.length = type.length;
|
||||
return int_type;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_build_context_init(struct lp_build_context *bld,
|
||||
LLVMBuilderRef builder,
|
||||
|
||||
@@ -165,10 +165,6 @@ LLVMTypeRef
|
||||
lp_build_int_vec_type(union lp_type type);
|
||||
|
||||
|
||||
union lp_type
|
||||
lp_int_type(union lp_type type);
|
||||
|
||||
|
||||
void
|
||||
lp_build_context_init(struct lp_build_context *bld,
|
||||
LLVMBuilderRef builder,
|
||||
|
||||
@@ -67,7 +67,6 @@ llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
|
||||
util_pack_color(rgba, ps->format, &cv);
|
||||
lp_tile_cache_clear(llvmpipe->cbuf_cache[i], rgba, cv);
|
||||
}
|
||||
llvmpipe->dirty_render_cache = TRUE;
|
||||
}
|
||||
|
||||
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
|
||||
|
||||
@@ -141,6 +141,8 @@ llvmpipe_is_texture_referenced( struct pipe_context *pipe,
|
||||
return PIPE_REFERENCED_FOR_WRITE;
|
||||
}
|
||||
|
||||
/* FIXME: we also need to do the same for the texture cache */
|
||||
|
||||
return PIPE_UNREFERENCED;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,47 +44,15 @@
|
||||
static void
|
||||
lp_jit_init_globals(struct llvmpipe_screen *screen)
|
||||
{
|
||||
LLVMTypeRef texture_type;
|
||||
|
||||
/* struct lp_jit_texture */
|
||||
{
|
||||
LLVMTypeRef elem_types[4];
|
||||
|
||||
elem_types[LP_JIT_TEXTURE_WIDTH] = LLVMInt32Type();
|
||||
elem_types[LP_JIT_TEXTURE_HEIGHT] = LLVMInt32Type();
|
||||
elem_types[LP_JIT_TEXTURE_STRIDE] = LLVMInt32Type();
|
||||
elem_types[LP_JIT_TEXTURE_DATA] = LLVMPointerType(LLVMInt8Type(), 0);
|
||||
|
||||
texture_type = LLVMStructType(elem_types, Elements(elem_types), 0);
|
||||
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, width,
|
||||
screen->target, texture_type,
|
||||
LP_JIT_TEXTURE_WIDTH);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, height,
|
||||
screen->target, texture_type,
|
||||
LP_JIT_TEXTURE_HEIGHT);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, stride,
|
||||
screen->target, texture_type,
|
||||
LP_JIT_TEXTURE_STRIDE);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, data,
|
||||
screen->target, texture_type,
|
||||
LP_JIT_TEXTURE_DATA);
|
||||
LP_CHECK_STRUCT_SIZE(struct lp_jit_texture,
|
||||
screen->target, texture_type);
|
||||
|
||||
LLVMAddTypeName(screen->module, "texture", texture_type);
|
||||
}
|
||||
|
||||
/* struct lp_jit_context */
|
||||
{
|
||||
LLVMTypeRef elem_types[5];
|
||||
LLVMTypeRef elem_types[4];
|
||||
LLVMTypeRef context_type;
|
||||
|
||||
elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */
|
||||
elem_types[1] = LLVMPointerType(LLVMInt8Type(), 0); /* samplers */
|
||||
elem_types[2] = LLVMFloatType(); /* alpha_ref_value */
|
||||
elem_types[3] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */
|
||||
elem_types[4] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
|
||||
|
||||
context_type = LLVMStructType(elem_types, Elements(elem_types), 0);
|
||||
|
||||
@@ -96,9 +64,6 @@ lp_jit_init_globals(struct llvmpipe_screen *screen)
|
||||
screen->target, context_type, 2);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color,
|
||||
screen->target, context_type, 3);
|
||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
|
||||
screen->target, context_type,
|
||||
LP_JIT_CONTEXT_TEXTURES_INDEX);
|
||||
LP_CHECK_STRUCT_SIZE(struct lp_jit_context,
|
||||
screen->target, context_type);
|
||||
|
||||
|
||||
@@ -38,31 +38,11 @@
|
||||
|
||||
#include "lp_bld_struct.h"
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
|
||||
struct tgsi_sampler;
|
||||
struct llvmpipe_screen;
|
||||
|
||||
|
||||
struct lp_jit_texture
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t stride;
|
||||
const void *data;
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
LP_JIT_TEXTURE_WIDTH = 0,
|
||||
LP_JIT_TEXTURE_HEIGHT,
|
||||
LP_JIT_TEXTURE_STRIDE,
|
||||
LP_JIT_TEXTURE_DATA
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This structure is passed directly to the generated fragment shader.
|
||||
*
|
||||
@@ -80,12 +60,11 @@ struct lp_jit_context
|
||||
|
||||
struct tgsi_sampler **samplers;
|
||||
|
||||
/* TODO: alpha reference value */
|
||||
float alpha_ref_value;
|
||||
|
||||
/* FIXME: store (also?) in floats */
|
||||
/* TODO: blend constant color */
|
||||
uint8_t *blend_color;
|
||||
|
||||
struct lp_jit_texture textures[PIPE_MAX_SAMPLERS];
|
||||
};
|
||||
|
||||
|
||||
@@ -101,11 +80,6 @@ struct lp_jit_context
|
||||
#define lp_jit_context_blend_color(_builder, _ptr) \
|
||||
lp_build_struct_get(_builder, _ptr, 3, "blend_color")
|
||||
|
||||
#define LP_JIT_CONTEXT_TEXTURES_INDEX 4
|
||||
|
||||
#define lp_jit_context_textures(_builder, _ptr) \
|
||||
lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures")
|
||||
|
||||
|
||||
typedef void
|
||||
(*lp_jit_frag_func)(struct lp_jit_context *context,
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#include "pipe/p_thread.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "lp_bld_debug.h"
|
||||
#include "lp_tile_cache.h"
|
||||
#include "lp_tile_soa.h"
|
||||
|
||||
@@ -163,12 +162,12 @@ shade_quads(struct llvmpipe_context *llvmpipe,
|
||||
else
|
||||
depth = NULL;
|
||||
|
||||
/* XXX: This will most likely fail on 32bit x86 without -mstackrealign */
|
||||
assert(lp_check_alignment(mask, 16));
|
||||
/* TODO: blend color */
|
||||
|
||||
assert(lp_check_alignment(depth, 16));
|
||||
assert(lp_check_alignment(color, 16));
|
||||
assert(lp_check_alignment(llvmpipe->jit_context.blend_color, 16));
|
||||
assert((((uintptr_t)mask) & 0xf) == 0);
|
||||
assert((((uintptr_t)depth) & 0xf) == 0);
|
||||
assert((((uintptr_t)color) & 0xf) == 0);
|
||||
assert((((uintptr_t)llvmpipe->jit_context.blend_color) & 0xf) == 0);
|
||||
|
||||
/* run shader */
|
||||
fs->current->jit_function( &llvmpipe->jit_context,
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "pipe/p_state.h"
|
||||
#include "tgsi/tgsi_scan.h"
|
||||
#include "lp_jit.h"
|
||||
#include "lp_bld_sample.h" /* for struct lp_sampler_static_state */
|
||||
|
||||
|
||||
#define LP_NEW_VIEWPORT 0x1
|
||||
@@ -58,20 +57,16 @@
|
||||
|
||||
struct tgsi_sampler;
|
||||
struct vertex_info;
|
||||
struct pipe_context;
|
||||
struct llvmpipe_context;
|
||||
|
||||
|
||||
struct lp_fragment_shader;
|
||||
|
||||
|
||||
struct lp_fragment_shader_variant_key
|
||||
{
|
||||
enum pipe_format zsbuf_format;
|
||||
struct pipe_depth_state depth;
|
||||
struct pipe_alpha_state alpha;
|
||||
struct pipe_blend_state blend;
|
||||
|
||||
struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -250,9 +250,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
||||
|
||||
if (llvmpipe->dirty & (LP_NEW_FS |
|
||||
LP_NEW_BLEND |
|
||||
LP_NEW_DEPTH_STENCIL_ALPHA |
|
||||
LP_NEW_SAMPLER |
|
||||
LP_NEW_TEXTURE))
|
||||
LP_NEW_DEPTH_STENCIL_ALPHA))
|
||||
llvmpipe_update_fs( llvmpipe );
|
||||
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@
|
||||
#include "lp_context.h"
|
||||
#include "lp_state.h"
|
||||
#include "lp_quad.h"
|
||||
#include "lp_tex_sample.h"
|
||||
|
||||
|
||||
static const unsigned char quad_offset_x[4] = {0, 1, 0, 1};
|
||||
@@ -131,8 +130,9 @@ generate_pos0(LLVMBuilderRef builder,
|
||||
* Generate the depth test.
|
||||
*/
|
||||
static void
|
||||
generate_depth(LLVMBuilderRef builder,
|
||||
const struct lp_fragment_shader_variant_key *key,
|
||||
generate_depth(struct llvmpipe_context *lp,
|
||||
LLVMBuilderRef builder,
|
||||
const struct pipe_depth_state *state,
|
||||
union lp_type src_type,
|
||||
struct lp_build_mask_context *mask,
|
||||
LLVMValueRef src,
|
||||
@@ -141,10 +141,10 @@ generate_depth(LLVMBuilderRef builder,
|
||||
const struct util_format_description *format_desc;
|
||||
union lp_type dst_type;
|
||||
|
||||
if(!key->depth.enabled)
|
||||
if(!lp->framebuffer.zsbuf)
|
||||
return;
|
||||
|
||||
format_desc = util_format_description(key->zsbuf_format);
|
||||
format_desc = util_format_description(lp->framebuffer.zsbuf->format);
|
||||
assert(format_desc);
|
||||
|
||||
/* Pick the depth type. */
|
||||
@@ -164,7 +164,7 @@ generate_depth(LLVMBuilderRef builder,
|
||||
#endif
|
||||
|
||||
lp_build_depth_test(builder,
|
||||
&key->depth,
|
||||
state,
|
||||
dst_type,
|
||||
format_desc,
|
||||
mask,
|
||||
@@ -173,6 +173,107 @@ generate_depth(LLVMBuilderRef builder,
|
||||
}
|
||||
|
||||
|
||||
struct build_fetch_texel_context
|
||||
{
|
||||
LLVMValueRef context_ptr;
|
||||
|
||||
LLVMValueRef samplers_ptr;
|
||||
|
||||
/** Coords/texels store */
|
||||
LLVMValueRef store_ptr;
|
||||
};
|
||||
|
||||
|
||||
void PIPE_CDECL
|
||||
lp_fetch_texel_soa( struct tgsi_sampler **samplers,
|
||||
uint32_t unit,
|
||||
float *store )
|
||||
{
|
||||
struct tgsi_sampler *sampler = samplers[unit];
|
||||
|
||||
#if 0
|
||||
uint j;
|
||||
|
||||
debug_printf("%s sampler: %p (%p) store: %p\n",
|
||||
__FUNCTION__,
|
||||
sampler, *sampler,
|
||||
store );
|
||||
|
||||
debug_printf("lodbias %f\n", store[12]);
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
debug_printf("sample %d texcoord %f %f\n",
|
||||
j,
|
||||
store[0+j],
|
||||
store[4+j]);
|
||||
#endif
|
||||
|
||||
{
|
||||
float rgba[NUM_CHANNELS][QUAD_SIZE];
|
||||
sampler->get_samples(sampler,
|
||||
&store[0],
|
||||
&store[4],
|
||||
&store[8],
|
||||
0.0f, /*store[12], lodbias */
|
||||
rgba);
|
||||
memcpy(store, rgba, sizeof rgba);
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (j = 0; j < 4; j++)
|
||||
debug_printf("sample %d result %f %f %f %f\n",
|
||||
j,
|
||||
store[0+j],
|
||||
store[4+j],
|
||||
store[8+j],
|
||||
store[12+j]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
emit_fetch_texel( LLVMBuilderRef builder,
|
||||
void *context,
|
||||
unsigned unit,
|
||||
unsigned num_coords,
|
||||
const LLVMValueRef *coords,
|
||||
LLVMValueRef lodbias,
|
||||
LLVMValueRef *texel)
|
||||
{
|
||||
struct build_fetch_texel_context *bld = context;
|
||||
LLVMTypeRef vec_type = LLVMTypeOf(coords[0]);
|
||||
LLVMValueRef args[3];
|
||||
unsigned i;
|
||||
|
||||
if(!bld->samplers_ptr)
|
||||
bld->samplers_ptr = lp_jit_context_samplers(builder, bld->context_ptr);
|
||||
|
||||
if(!bld->store_ptr)
|
||||
bld->store_ptr = LLVMBuildArrayAlloca(builder,
|
||||
vec_type,
|
||||
LLVMConstInt(LLVMInt32Type(), 4, 0),
|
||||
"texel_store");
|
||||
|
||||
for (i = 0; i < num_coords; i++) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
LLVMValueRef coord_ptr = LLVMBuildGEP(builder, bld->store_ptr, &index, 1, "");
|
||||
LLVMBuildStore(builder, coords[i], coord_ptr);
|
||||
}
|
||||
|
||||
args[0] = bld->samplers_ptr;
|
||||
args[1] = LLVMConstInt(LLVMInt32Type(), unit, 0);
|
||||
args[2] = bld->store_ptr;
|
||||
|
||||
lp_build_intrinsic(builder, "fetch_texel", LLVMVoidType(), args, 3);
|
||||
|
||||
for (i = 0; i < NUM_CHANNELS; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
LLVMValueRef texel_ptr = LLVMBuildGEP(builder, bld->store_ptr, &index, 1, "");
|
||||
texel[i] = LLVMBuildLoad(builder, texel_ptr, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the fragment shader, depth/stencil test, and alpha tests.
|
||||
*/
|
||||
@@ -185,7 +286,7 @@ generate_fs(struct llvmpipe_context *lp,
|
||||
LLVMValueRef context_ptr,
|
||||
unsigned i,
|
||||
const struct lp_build_interp_soa_context *interp,
|
||||
struct lp_build_sampler_soa *sampler,
|
||||
struct build_fetch_texel_context *sampler,
|
||||
LLVMValueRef *pmask,
|
||||
LLVMValueRef *color,
|
||||
LLVMValueRef depth_ptr)
|
||||
@@ -197,7 +298,6 @@ generate_fs(struct llvmpipe_context *lp,
|
||||
LLVMValueRef consts_ptr;
|
||||
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
|
||||
LLVMValueRef z = interp->pos[2];
|
||||
struct lp_build_flow_context *flow;
|
||||
struct lp_build_mask_context mask;
|
||||
boolean early_depth_test;
|
||||
unsigned attrib;
|
||||
@@ -209,35 +309,25 @@ generate_fs(struct llvmpipe_context *lp,
|
||||
|
||||
consts_ptr = lp_jit_context_constants(builder, context_ptr);
|
||||
|
||||
flow = lp_build_flow_create(builder);
|
||||
|
||||
memset(outputs, 0, sizeof outputs);
|
||||
|
||||
lp_build_flow_scope_begin(flow);
|
||||
|
||||
/* Declare the color and z variables */
|
||||
for(chan = 0; chan < NUM_CHANNELS; ++chan) {
|
||||
color[chan] = LLVMGetUndef(vec_type);
|
||||
lp_build_flow_scope_declare(flow, &color[chan]);
|
||||
}
|
||||
lp_build_flow_scope_declare(flow, &z);
|
||||
|
||||
lp_build_mask_begin(&mask, flow, type, *pmask);
|
||||
lp_build_mask_begin(&mask, builder, type, *pmask);
|
||||
|
||||
early_depth_test =
|
||||
key->depth.enabled &&
|
||||
!key->alpha.enabled &&
|
||||
!shader->info.uses_kill &&
|
||||
!shader->info.writes_z;
|
||||
lp->depth_stencil->depth.enabled &&
|
||||
lp->framebuffer.zsbuf &&
|
||||
!lp->depth_stencil->alpha.enabled &&
|
||||
!lp->fs->info.uses_kill &&
|
||||
!lp->fs->info.writes_z;
|
||||
|
||||
if(early_depth_test)
|
||||
generate_depth(builder, key,
|
||||
generate_depth(lp, builder, &key->depth,
|
||||
type, &mask,
|
||||
z, depth_ptr);
|
||||
|
||||
memset(outputs, 0, sizeof outputs);
|
||||
|
||||
lp_build_tgsi_soa(builder, tokens, type, &mask,
|
||||
consts_ptr, interp->pos, interp->inputs,
|
||||
outputs, sampler);
|
||||
outputs, emit_fetch_texel, sampler);
|
||||
|
||||
for (attrib = 0; attrib < shader->info.num_outputs; ++attrib) {
|
||||
for(chan = 0; chan < NUM_CHANNELS; ++chan) {
|
||||
@@ -278,16 +368,12 @@ generate_fs(struct llvmpipe_context *lp,
|
||||
}
|
||||
|
||||
if(!early_depth_test)
|
||||
generate_depth(builder, key,
|
||||
generate_depth(lp, builder, &key->depth,
|
||||
type, &mask,
|
||||
z, depth_ptr);
|
||||
|
||||
lp_build_mask_end(&mask);
|
||||
|
||||
lp_build_flow_scope_end(flow);
|
||||
|
||||
lp_build_flow_destroy(flow);
|
||||
|
||||
*pmask = mask.value;
|
||||
|
||||
}
|
||||
@@ -306,8 +392,6 @@ generate_blend(const struct pipe_blend_state *blend,
|
||||
LLVMValueRef dst_ptr)
|
||||
{
|
||||
struct lp_build_context bld;
|
||||
struct lp_build_flow_context *flow;
|
||||
struct lp_build_mask_context mask_ctx;
|
||||
LLVMTypeRef vec_type;
|
||||
LLVMTypeRef int_vec_type;
|
||||
LLVMValueRef const_ptr;
|
||||
@@ -316,14 +400,11 @@ generate_blend(const struct pipe_blend_state *blend,
|
||||
LLVMValueRef res[4];
|
||||
unsigned chan;
|
||||
|
||||
lp_build_context_init(&bld, builder, type);
|
||||
|
||||
flow = lp_build_flow_create(builder);
|
||||
lp_build_mask_begin(&mask_ctx, flow, type, mask);
|
||||
|
||||
vec_type = lp_build_vec_type(type);
|
||||
int_vec_type = lp_build_int_vec_type(type);
|
||||
|
||||
lp_build_context_init(&bld, builder, type);
|
||||
|
||||
const_ptr = lp_jit_context_blend_color(builder, context_ptr);
|
||||
const_ptr = LLVMBuildBitCast(builder, const_ptr,
|
||||
LLVMPointerType(vec_type, 0), "");
|
||||
@@ -341,16 +422,11 @@ generate_blend(const struct pipe_blend_state *blend,
|
||||
lp_build_blend_soa(builder, blend, type, src, dst, con, res);
|
||||
|
||||
for(chan = 0; chan < 4; ++chan) {
|
||||
if(blend->colormask & (1 << chan)) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0);
|
||||
lp_build_name(res[chan], "res.%c", "rgba"[chan]);
|
||||
res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]);
|
||||
LLVMBuildStore(builder, res[chan], LLVMBuildGEP(builder, dst_ptr, &index, 1, ""));
|
||||
}
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0);
|
||||
lp_build_name(res[chan], "res.%c", "rgba"[chan]);
|
||||
res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]);
|
||||
LLVMBuildStore(builder, res[chan], LLVMBuildGEP(builder, dst_ptr, &index, 1, ""));
|
||||
}
|
||||
|
||||
lp_build_mask_end(&mask_ctx);
|
||||
lp_build_flow_destroy(flow);
|
||||
}
|
||||
|
||||
|
||||
@@ -386,7 +462,7 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
LLVMBuilderRef builder;
|
||||
LLVMValueRef x0;
|
||||
LLVMValueRef y0;
|
||||
struct lp_build_sampler_soa *sampler;
|
||||
struct build_fetch_texel_context sampler;
|
||||
struct lp_build_interp_soa_context interp;
|
||||
LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH];
|
||||
LLVMValueRef fs_out_color[NUM_CHANNELS][LP_MAX_VECTOR_LENGTH];
|
||||
@@ -510,13 +586,8 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
a0_ptr, dadx_ptr, dady_ptr,
|
||||
x0, y0, 2, 0);
|
||||
|
||||
#if 0
|
||||
/* C texture sampling */
|
||||
sampler = lp_c_sampler_soa_create(context_ptr);
|
||||
#else
|
||||
/* code generated texture sampling */
|
||||
sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr);
|
||||
#endif
|
||||
memset(&sampler, 0, sizeof sampler);
|
||||
sampler.context_ptr = context_ptr;
|
||||
|
||||
for(i = 0; i < num_fs; ++i) {
|
||||
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
|
||||
@@ -535,7 +606,7 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
context_ptr,
|
||||
i,
|
||||
&interp,
|
||||
sampler,
|
||||
&sampler,
|
||||
&fs_mask[i],
|
||||
out_color,
|
||||
depth_ptr_i);
|
||||
@@ -544,8 +615,6 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
fs_out_color[chan][i] = out_color[chan];
|
||||
}
|
||||
|
||||
sampler->destroy(sampler);
|
||||
|
||||
/*
|
||||
* Convert the fs's output color and mask to fit to the blending type.
|
||||
*/
|
||||
@@ -696,45 +765,18 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe,
|
||||
*/
|
||||
static void
|
||||
make_variant_key(struct llvmpipe_context *lp,
|
||||
struct lp_fragment_shader *shader,
|
||||
struct lp_fragment_shader_variant_key *key)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
memset(key, 0, sizeof *key);
|
||||
|
||||
if(lp->framebuffer.zsbuf &&
|
||||
lp->depth_stencil->depth.enabled) {
|
||||
key->zsbuf_format = lp->framebuffer.zsbuf->format;
|
||||
memcpy(&key->depth, &lp->depth_stencil->depth, sizeof key->depth);
|
||||
}
|
||||
memcpy(&key->depth, &lp->depth_stencil->depth, sizeof key->depth);
|
||||
|
||||
key->alpha.enabled = lp->depth_stencil->alpha.enabled;
|
||||
if(key->alpha.enabled)
|
||||
key->alpha.func = lp->depth_stencil->alpha.func;
|
||||
/* alpha.ref_value is passed in jit_context */
|
||||
|
||||
if(lp->framebuffer.cbufs[0]) {
|
||||
const struct util_format_description *format_desc;
|
||||
unsigned chan;
|
||||
|
||||
memcpy(&key->blend, lp->blend, sizeof key->blend);
|
||||
|
||||
format_desc = util_format_description(lp->framebuffer.cbufs[0]->format);
|
||||
assert(format_desc->layout == UTIL_FORMAT_COLORSPACE_RGB ||
|
||||
format_desc->layout == UTIL_FORMAT_COLORSPACE_SRGB);
|
||||
|
||||
/* mask out color channels not present in the color buffer */
|
||||
for(chan = 0; chan < 4; ++chan) {
|
||||
enum util_format_swizzle swizzle = format_desc->swizzle[chan];
|
||||
if(swizzle > 4)
|
||||
key->blend.colormask &= ~(1 << chan);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < PIPE_MAX_SAMPLERS; ++i)
|
||||
if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i))
|
||||
lp_sampler_static_state(&key->sampler[i], lp->texture[i], lp->sampler[i]);
|
||||
memcpy(&key->blend, lp->blend, sizeof key->blend);
|
||||
}
|
||||
|
||||
|
||||
@@ -745,7 +787,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
|
||||
struct lp_fragment_shader_variant_key key;
|
||||
struct lp_fragment_shader_variant *variant;
|
||||
|
||||
make_variant_key(lp, shader, &key);
|
||||
make_variant_key(lp, &key);
|
||||
|
||||
variant = shader->variants;
|
||||
while(variant) {
|
||||
|
||||
@@ -98,16 +98,6 @@ llvmpipe_set_sampler_textures(struct pipe_context *pipe,
|
||||
|
||||
pipe_texture_reference(&llvmpipe->texture[i], tex);
|
||||
lp_tex_tile_cache_set_texture(llvmpipe->tex_cache[i], tex);
|
||||
|
||||
if(tex) {
|
||||
struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex);
|
||||
struct lp_jit_texture *jit_tex = &llvmpipe->jit_context.textures[i];
|
||||
jit_tex->width = tex->width[0];
|
||||
jit_tex->height = tex->height[0];
|
||||
jit_tex->stride = lp_tex->stride[0];
|
||||
if(!lp_tex->dt)
|
||||
jit_tex->data = lp_tex->data;
|
||||
}
|
||||
}
|
||||
|
||||
llvmpipe->num_textures = num;
|
||||
|
||||
@@ -119,7 +119,7 @@ add_load_rgba_test(LLVMModuleRef module,
|
||||
|
||||
lp_build_loop_begin(builder, LLVMConstInt(LLVMInt32Type(), 1, 0), &loop);
|
||||
|
||||
rgba = lp_build_load_rgba_aos(builder, format, ptr);
|
||||
rgba = lp_build_load_rgba(builder, format, ptr);
|
||||
LLVMBuildStore(builder, rgba, rgba_ptr);
|
||||
|
||||
lp_build_loop_end(builder, LLVMConstInt(LLVMInt32Type(), 4, 0), NULL, &loop);
|
||||
@@ -160,7 +160,7 @@ add_store_rgba_test(LLVMModuleRef module,
|
||||
|
||||
rgba = LLVMBuildLoad(builder, rgba_ptr, "");
|
||||
|
||||
lp_build_store_rgba_aos(builder, format, ptr, rgba);
|
||||
lp_build_store_rgba(builder, format, ptr, rgba);
|
||||
|
||||
LLVMBuildRetVoid(builder);
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ lp_tex_tile_cache_validate_texture(struct llvmpipe_tex_tile_cache *tc)
|
||||
if (lpt->timestamp != tc->timestamp) {
|
||||
/* texture was modified, invalidate all cached tiles */
|
||||
uint i;
|
||||
debug_printf("INV %d %d\n", tc->timestamp, lpt->timestamp);
|
||||
_debug_printf("INV %d %d\n", tc->timestamp, lpt->timestamp);
|
||||
for (i = 0; i < NUM_ENTRIES; i++) {
|
||||
tc->entries[i].addr.bits.invalid = 1;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user