Merge branch 'master' into r300-compiler

This commit is contained in:
Nicolai Hähnle 2009-10-03 19:30:48 +02:00
commit 6d25b9125e
460 changed files with 788562 additions and 16950 deletions

View file

@ -415,6 +415,12 @@ DEMO_FILES = \
$(DIRECTORY)/progs/demos/README \
$(DIRECTORY)/progs/fbdev/Makefile \
$(DIRECTORY)/progs/fbdev/glfbdevtest.c \
$(DIRECTORY)/progs/objviewer/*.[ch] \
$(DIRECTORY)/progs/objviewer/*.obj \
$(DIRECTORY)/progs/objviewer/*.mtl \
$(DIRECTORY)/progs/objviewer/*.rgb \
$(DIRECTORY)/progs/objviewer/Makefile \
$(DIRECTORY)/progs/objviewer/README.txt \
$(DIRECTORY)/progs/osdemos/Makefile \
$(DIRECTORY)/progs/osdemos/*.c \
$(DIRECTORY)/progs/xdemos/Makefile* \

View file

@ -87,14 +87,14 @@ SRC_DIRS = mesa gallium egl gallium/winsys glu glut/glx glew glw
GLU_DIRS = sgi
DRIVER_DIRS = x11 osmesa
# Which subdirs under $(TOP)/progs/ to enter:
PROGRAM_DIRS = demos redbook samples glsl xdemos
PROGRAM_DIRS = demos redbook samples glsl objviewer xdemos
# EGL directories
EGL_DRIVERS_DIRS = demo
# Gallium directories and
GALLIUM_DIRS = auxiliary drivers state_trackers
GALLIUM_AUXILIARY_DIRS = rbug draw translate cso_cache pipebuffer tgsi sct rtasm util indices
GALLIUM_AUXILIARY_DIRS = rbug draw translate cso_cache pipebuffer tgsi sct rtasm util indices vl
GALLIUM_AUXILIARIES = $(foreach DIR,$(GALLIUM_AUXILIARY_DIRS),$(TOP)/src/gallium/auxiliary/$(DIR)/lib$(DIR).a)
GALLIUM_DRIVERS_DIRS = softpipe i915simple failover trace identity
GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVERS_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a)

View file

@ -417,7 +417,7 @@ WINDOW_SYSTEM=""
GALLIUM_DIRS="auxiliary drivers state_trackers"
GALLIUM_WINSYS_DIRS=""
GALLIUM_WINSYS_DRM_DIRS=""
GALLIUM_AUXILIARY_DIRS="rbug draw translate cso_cache pipebuffer tgsi sct rtasm util indices"
GALLIUM_AUXILIARY_DIRS="rbug draw translate cso_cache pipebuffer tgsi sct rtasm util indices vl"
GALLIUM_DRIVERS_DIRS="softpipe failover trace identity"
GALLIUM_STATE_TRACKERS_DIRS=""

View file

@ -10,6 +10,17 @@
<H1>News</H1>
<h2>September 28, 2009</h2>
<p>
<a href="relnotes-7.6.html">Mesa 7.6</a> is released. This is a new feature
release. Those especially concerned about stability may want to wait for the
follow-on 7.6.1 bug-fix release.
</p>
<p>
<a href="relnotes-7.5.2.html">Mesa 7.5.2</a> is also released.
This is a stable release fixing bugs since the 7.5.1 release.
</p>
<h2>September 3, 2009</h2>
<p>

View file

@ -8,7 +8,7 @@
<body bgcolor="#eeeeee">
<H1>Mesa 7.5.2 Release Notes, (date tbd)</H1>
<H1>Mesa 7.5.2 Release Notes, 28 September 2009</H1>
<p>
Mesa 7.5.2 is a bug-fix release fixing issues found since the 7.5.1 release.
@ -31,7 +31,15 @@ for DRI hardware acceleration.
<h2>MD5 checksums</h2>
<pre>
tbd
43a90191dd9f76cd65dcc1ac91f3be70 MesaLib-7.5.2.tar.gz
94e47a499f1226803869c2e37a6a8e3a MesaLib-7.5.2.tar.bz2
1ecb822b567ad67a0617361d45206b67 MesaLib-7.5.2.zip
2718fdce7e075911d6147beb8f27104b MesaDemos-7.5.2.tar.gz
4e0f5ccd58afe21eddcd94327d926e86 MesaDemos-7.5.2.tar.bz2
f621f8c223b278d7c8e49a012d56ca25 MesaDemos-7.5.2.zip
83c16c1d6bcfcc3f97aab5d2fe430b4c MesaGLUT-7.5.2.tar.gz
e5d03bedae369ea3705783573bb33813 MesaGLUT-7.5.2.tar.bz2
e82ba28e00d653e6f437d32be8ca8481 MesaGLUT-7.5.2.zip
</pre>
@ -49,8 +57,11 @@ tbd
(such as bug 23946)
<li>glUseProgram() is now compiled into display lists (bug 23746).
<li>glUniform functions are now compiled into display lists
<li>Auto mipmap generation didn't work reliably with Gallium.
<li>Fixed random number usage in GLX code.
<li>Fixed invalid GL_OUT_OF_MEMORY error sometimes raised by glTexSubImage2D
when using Gallium.
</ul>
</body>
</html>

46
docs/relnotes-7.6.1.html Normal file
View file

@ -0,0 +1,46 @@
<HTML>
<TITLE>Mesa Release Notes</TITLE>
<head><link rel="stylesheet" type="text/css" href="mesa.css"></head>
<BODY>
<body bgcolor="#eeeeee">
<H1>Mesa 7.6.1 Release Notes, (date tbd)</H1>
<p>
Mesa 7.6.1 is a bug-fix release fixing issues since version 7.6.
</p>
<p>
Mesa 7.6.1 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>
</ul>
<h2>Bug fixes</h2>
<ul>
<li>Fixed crash caused by glXCopyContext() and glXDestroyContext(), bug 24217
<li>glXQueryContext(GLX_RENDER_TYPE) returned wrong values (bug 24211)
<li>GLSL sqrt(0) returned unpredictable results
</ul>
</body>
</html>

View file

@ -8,7 +8,7 @@
<body bgcolor="#eeeeee">
<H1>Mesa 7.6 Release Notes / date TBD</H1>
<H1>Mesa 7.6 Release Notes, 28 September 2009</H1>
<p>
Mesa 7.6 is a new development release.
@ -28,7 +28,15 @@ for DRI hardware acceleration.
<h2>MD5 checksums</h2>
<pre>
tbd
5ffa7d7abf8973f57a1bc4f813e6dade MesaLib-7.6.tar.gz
8c75f90cd0303cfac9e4b6d54f6759ca MesaLib-7.6.tar.bz2
27fcfd69708599c978cb34ba5cd363e1 MesaLib-7.6.zip
e7befb3ae604f591806194a4da445628 MesaDemos-7.6.tar.gz
0ede7adf217951acd90dbe4551210c07 MesaDemos-7.6.tar.bz2
ed9298409cf6613bc0964525ca4afc8a MesaDemos-7.6.zip
666955668e44ff14acf7d15dc78407d3 MesaGLUT-7.6.tar.gz
b8b59706f827d18d1b784a0ff98b4dc2 MesaGLUT-7.6.tar.bz2
c49c19c2bbef4f3b7f1389974dff25f4 MesaGLUT-7.6.zip
</pre>
@ -72,10 +80,5 @@ This was written by Zack Rusin at Tungsten Graphics.
buffers (GLSL uniforms)
</ul>
<h2>Changes</h2>
<ul>
</ul>
</body>
</html>

View file

@ -38,6 +38,7 @@ tbd
<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>
<li>GL_ARB_provoking_vertex (same as GL_EXT_provoking_vertex)</li>
<li>Wavefront .obj file loader/viewer demo (progs/demos/objviewer)
</ul>

View file

@ -14,6 +14,7 @@ The release notes summarize what's new or changed in each Mesa release.
<UL>
<LI><A HREF="relnotes-7.7.html">7.7 release notes</A>
<LI><A HREF="relnotes-7.6.1.html">7.6.1 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>

View file

@ -59,6 +59,8 @@ static GLboolean supportFBO = GL_FALSE;
static GLboolean supportSeamless = GL_FALSE;
static GLboolean seamless = GL_FALSE;
static GLuint TexObj = 0;
static GLint T0 = 0;
static GLint Frames = 0;
static struct {
@ -283,6 +285,20 @@ static void draw( void )
glPopMatrix();
glutSwapBuffers();
Frames++;
{
GLint t = glutGet(GLUT_ELAPSED_TIME);
if (t - T0 >= 5000) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps);
fflush(stdout);
T0 = t;
Frames = 0;
}
}
}

View file

@ -34,14 +34,9 @@ TestScreens(EGLDisplay dpy)
* Print table of all available configurations.
*/
static void
PrintConfigs(EGLDisplay d)
PrintConfigs(EGLDisplay d, EGLConfig *configs, EGLint numConfigs)
{
EGLConfig *configs;
EGLint numConfigs, i;
eglGetConfigs(d, NULL, 0, &numConfigs);
configs = malloc(sizeof(*configs) *numConfigs);
eglGetConfigs(d, configs, numConfigs, &numConfigs);
EGLint i;
printf("Configurations:\n");
printf(" bf lv d st colorbuffer dp st supported \n");
@ -83,7 +78,6 @@ PrintConfigs(EGLDisplay d)
red, green, blue, alpha,
depth, stencil, surfString);
}
free(configs);
}
@ -94,7 +88,8 @@ main(int argc, char *argv[])
int maj, min;
EGLContext ctx;
EGLSurface pbuffer;
EGLConfig configs[10];
EGLConfig *configs;
EGLint numConfigs;
EGLBoolean b;
const EGLint pbufAttribs[] = {
EGL_WIDTH, 500,
@ -102,10 +97,7 @@ main(int argc, char *argv[])
EGL_NONE
};
/*
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
*/
EGLDisplay d = eglGetDisplay((EGLNativeDisplayType) "!EGL_i915");
assert(d);
if (!eglInitialize(d, &maj, &min)) {
@ -116,7 +108,11 @@ main(int argc, char *argv[])
printf("EGL version = %d.%d\n", maj, min);
printf("EGL_VENDOR = %s\n", eglQueryString(d, EGL_VENDOR));
PrintConfigs(d);
eglGetConfigs(d, NULL, 0, &numConfigs);
configs = malloc(sizeof(*configs) *numConfigs);
eglGetConfigs(d, configs, numConfigs, &numConfigs);
PrintConfigs(d, configs, numConfigs);
ctx = eglCreateContext(d, configs[0], EGL_NO_CONTEXT, NULL);
if (ctx == EGL_NO_CONTEXT) {
@ -130,6 +126,8 @@ main(int argc, char *argv[])
return 0;
}
free(configs);
b = eglMakeCurrent(d, pbuffer, pbuffer, ctx);
if (!b) {
printf("make current failed\n");

View file

@ -7,6 +7,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <EGL/egl.h>
@ -119,10 +120,7 @@ main(int argc, char *argv[])
EGLScreenMESA screen;
EGLint count;
/*
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
*/
EGLDisplay d = eglGetDisplay((EGLNativeDisplayType) "!EGL_i915");
assert(d);
if (!eglInitialize(d, &maj, &min)) {
@ -132,6 +130,11 @@ main(int argc, char *argv[])
printf("EGL version = %d.%d\n", maj, min);
printf("EGL_VENDOR = %s\n", eglQueryString(d, EGL_VENDOR));
if (!strstr(eglQueryString(d, EGL_EXTENSIONS),
"EGL_MESA_screen_surface")) {
printf("EGL_MESA_screen_surface is not supported\n");
exit(1);
}
eglGetConfigs(d, configs, 10, &numConfigs);
printf("Got %d EGL configs:\n", numConfigs);

View file

@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -551,15 +552,6 @@ write_ppm(const char *filename, const GLubyte *buffer, int width, int height)
}
}
#include "../../src/egl/main/egldisplay.h"
typedef struct fb_display
{
_EGLDisplay Base; /* base class/object */
void *pFB;
} fbDisplay;
int
main(int argc, char *argv[])
{
@ -571,16 +563,14 @@ main(int argc, char *argv[])
EGLModeMESA mode;
EGLint numConfigs, count;
EGLBoolean b;
const GLubyte *bitmap;
const EGLint screenAttribs[] = {
EGL_WIDTH, 1024,
EGL_HEIGHT, 768,
EGL_NONE
};
/*
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
*/
EGLDisplay d = eglGetDisplay("!EGL_i915");
assert(d);
if (!eglInitialize(d, &maj, &min)) {
@ -590,6 +580,11 @@ main(int argc, char *argv[])
printf("EGL version = %d.%d\n", maj, min);
printf("EGL_VENDOR = %s\n", eglQueryString(d, EGL_VENDOR));
if (!strstr(eglQueryString(d, EGL_EXTENSIONS),
"EGL_MESA_screen_surface")) {
printf("EGL_MESA_screen_surface is not supported\n");
exit(1);
}
eglGetConfigs(d, configs, 10, &numConfigs);
eglGetScreensMESA(d, &screen, 1, &count);
@ -620,17 +615,24 @@ main(int argc, char *argv[])
Init();
Reshape(1024, 768);
/* some drivers crash when rendering to front buffer */
#if 0
glDrawBuffer( GL_FRONT );
glClearColor( 0, 1.0, 0, 1);
glClear( GL_COLOR_BUFFER_BIT );
#endif
doubleBuffer = 1;
glDrawBuffer( GL_BACK );
Draw(d, screen_surf);
sleep(2);
write_ppm("dump.ppm", ((struct fb_display *)_eglLookupDisplay(d))->pFB, 1024, 768);
/* TODO EGL_KHR_lock_surface */
bitmap = NULL;
if (bitmap)
write_ppm("dump.ppm", bitmap, 1024, 768);
eglDestroySurface(d, screen_surf);
eglDestroyContext(d, ctx);

View file

@ -388,7 +388,7 @@ main(int argc, char *argv[])
}
/* DBR : Create EGL context/surface etc */
d = eglGetDisplay((EGLNativeDisplayType)"!EGL_i915");
d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(d);
if (!eglInitialize(d, &maj, &min)) {

View file

@ -147,8 +147,7 @@ int
main(int argc, char *argv[])
{
int maj, min;
//EGLDisplay d = eglGetDisplay((EGLNativeDisplayType)"!EGL_i915");
EGLDisplay d = eglGetDisplay((EGLNativeDisplayType)"!EGL_i915");
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!eglInitialize(d, &maj, &min)) {
printf("eglinfo: eglInitialize failed\n");

View file

@ -55,7 +55,7 @@ main(int argc, char *argv[])
EGLint count, chosenMode;
EGLint width = 0, height = 0;
d = eglGetDisplay((EGLNativeDisplayType)"!EGL_i915");
d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(d);
if (!eglInitialize(d, &maj, &min)) {

View file

@ -130,9 +130,7 @@ static void run(EGLDisplay dpy, EGLSurface surf, int ttr)
while (ct - st < ttr)
{
double tt = current_time();
double dt = tt - ct;
ct = tt;
ct = current_time();
draw();
@ -174,7 +172,7 @@ int main(int argc, char *argv[])
}
/* DBR : Create EGL context/surface etc */
d = eglGetDisplay((EGLNativeDisplayType)"!EGL_i915");
d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(d);
if (!eglInitialize(d, &maj, &min)) {

View file

@ -385,7 +385,7 @@ main(int argc, char *argv[])
}
/* DBR : Create EGL context/surface etc */
d = eglGetDisplay((EGLNativeDisplayType)"!EGL_i915");
d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(d);
if (!eglInitialize(d, &major, &minor)) {

View file

@ -15,7 +15,7 @@ LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLEW_LIB) -l$(GLU_LIB) \
# using : to avoid APP_CC pointing to CC loop
CC := $(APP_CC)
CFLAGS += -I$(INCDIR)
CFLAGS := -I$(INCDIR) $(CFLAGS)
LDLIBS = $(LIBS)
PROG_SOURCES = \

View file

@ -0,0 +1,161 @@
# Exported from Wings 3D 0.99.03
# Top flaps
newmtl BottomWing
Ns 100.0
d 1.0
illum 2
Kd 1.0 0.0 0.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd TopBotMap.rgb
newmtl CompBall_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd CompBall_auv.rgb
newmtl EngMat1
Ns 100.0
d 1.0
illum 2
Kd 0.334 0.334 0.334
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl EngMat2
Ns 100.0
d 1.0
illum 2
Kd 0.78688 0.78688 0.78688
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Fuselage_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 0.0 0.0 0.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd SidesMap.rgb
newmtl Glass
Ns 100.0
d 0.5
illum 2
#Kd 0.5533333333333333 1.0 1.0
Kd 1.0 1.0 1.0
#Ka 0.37333333333333335 0.68 1.0
Ka 0.0 0.0 0.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Grip
Ns 100.0
d 1.0
illum 2
Kd 0.47386 0.47386 0.47386
Ka 0.6203799999999999 0.6203799999999999 0.6203799999999999
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Interior
Ns 100.0
d 1.0
illum 2
Kd 0.70696 0.70696 0.70696
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl Prop
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 0.6266666666666667
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd PropMap.rgb
# Rudder
newmtl Sides
Ns 100.0
d 1.0
illum 2
Kd 1.0 0.0 0.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd SidesMap.rgb
newmtl TailHoriz
Ns 100.0
d 1.0
illum 2
Kd 1.0 0.0 0.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd TopBotMap.rgb
# Top wing, bot wing, fuselage
newmtl TopWing
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd TopBotMap.rgb
newmtl Wheels
Ns 100.0
d 1.0
illum 2
Kd 0.0 0.0 0.0
Ka 0.0 0.0 0.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd WheelsMap.rgb
newmtl cylinder58_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd cylinder58_auv.rgb
newmtl default
Ns 100.0
d 1.0
illum 2
Kd 0.0 1.0 1.0
Ka 0.0 1.0 1.0
Ks 0.0 1.0 1.0
Ke 0.0 0.0 0.0
newmtl gage_auv
Ns 100.0
d 1.0
illum 2
Kd 1.0 1.0 1.0
Ka 1.0 1.0 1.0
Ks 1.0 1.0 1.0
Ke 0.0 0.0 0.0
map_Kd gage_auv.rgb

File diff suppressed because it is too large Load diff

83
progs/objviewer/Makefile Normal file
View file

@ -0,0 +1,83 @@
TOP = ../..
include $(TOP)/configs/current
INCDIR = $(TOP)/include
LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLEW_LIB) \
-l$(GLU_LIB) -l$(GL_LIB) $(APP_LIB_DEPS)
# using : to avoid APP_CC pointing to CC loop
CC := $(APP_CC)
CFLAGS := -I$(INCDIR) $(CFLAGS)
LDLIBS = $(LIBS)
SOURCES = \
glm.c \
glmdraw.c \
objview.c \
trackball.c \
skybox.c \
readtex.c \
shaderutil.c
HEADERS = \
extfuncs.h \
readtex.h \
shaderutil.h \
trackball.h
OBJS = $(SOURCES:.c=.o)
PROG = objview
.c.o:
$(CC) -c $(CFLAGS) $< -o $@
default: $(PROG)
$(PROG): $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
$(OBJS): $(HEADERS)
### Extra dependencies
extfuncs.h: $(TOP)/progs/util/extfuncs.h
cp $< .
readtex.c: $(TOP)/progs/util/readtex.c
cp $< .
readtex.h: $(TOP)/progs/util/readtex.h
cp $< .
shaderutil.c: $(TOP)/progs/util/shaderutil.c
cp $< .
shaderutil.h: $(TOP)/progs/util/shaderutil.h
cp $< .
trackball.c: $(TOP)/progs/util/trackball.c
cp $< .
trackball.h: $(TOP)/progs/util/trackball.h
cp $< .
clean:
-rm -f $(PROG) $(OBJS)
-rm -f *.o *~
-rm -f extfuncs.h
-rm -f shaderutil.*
-rm -f trackball.*
-rm -f readtex.*
depend: $(SOURCES)
@$(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(SOURCES) \
> /dev/null 2>/dev/null
-include depend

View file

@ -0,0 +1,23 @@
This .obj viewer is based on the "smooth" program by Nate Robins
found in the Kilgard GLUT package.
The alpine sky box textures come from http://www.hazelwhorley.com/skyboxtex3_bitmaps.html
The bunny.obj and buddha.obj models come from Stanford.
The GreatLakesBiplaneHP.obj model comes from http://www.sharecg.com/v/25978/3D-Model/Great-Lakes-Biplane-Model
The bobcat.obj model comes from http://www.sharecg.com/v/24771/3D-Model/Bobcat,3d-studio-and-wavefront-objects
The .obj file reader code in glm.c isn't perfect. Not all .obj files are
parsed correctly. There are often mistakes in material-to-triangle assignments.
Mouse:
Left = rotate
Middle = scale
Right = menu
Keyboard:
See pop-up menu for keyboard shortcuts, or press 'h'.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,72 @@
# Exported from Wings 3D 0.99.00b
newmtl black
Ns 48.6667
d 1.00000
illum 2
Kd 1.00000e-3 1.00000e-3 1.00000e-3
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl blanco
Ns 100.000
d 1.00000
illum 2
Kd 1.00000 1.00000 1.00000
Ka 0.620380 0.620380 0.620380
Ks 0.806860 0.806860 0.806860
Ke 1.00000e-3 1.00000e-3 1.00000e-3
newmtl blue
Ns 100.000
d 1.00000
illum 2
Kd 0.105111 0.125293 0.366667
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl default
Ns 100.000
d 1.00000
illum 2
Kd 1.00000 1.00000 1.00000
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.10000 0.10000 0.10000
Ks 0.50000 0.50000 0.500000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl gre
Ns 100.000
d 1.00000
illum 2
Kd 0.200800 0.200800 0.200800
Ka 1.00000 1.00000 1.00000
Ks 1.00000 1.00000 1.00000
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl red
Ns 100.000
d 1.00000
illum 2
Kd 0.460000 0.00000e+0 0.00000e+0
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 0.00000e+0 0.00000e+0 0.00000e+0
newmtl rojo
Ns 100.000
d 1.00000
illum 2
Kd 0.700000 0.00000e+0 0.00000e+0
Ka 0.00000 0.00000 0.00000
Ks 0.00000 0.00000 0.00000
Ke 1.00000e-3 1.00000e-3 1.00000e-3

9251
progs/objviewer/bobcat.obj Normal file

File diff suppressed because it is too large Load diff

149990
progs/objviewer/buddha.obj Normal file

File diff suppressed because it is too large Load diff

104501
progs/objviewer/bunny.obj Normal file

File diff suppressed because it is too large Load diff

1917
progs/objviewer/glm.c Normal file

File diff suppressed because it is too large Load diff

287
progs/objviewer/glm.h Normal file
View file

@ -0,0 +1,287 @@
/*
* GLM library. Wavefront .obj file format reader/writer/manipulator.
*
* Written by Nate Robins, 1997.
* email: ndr@pobox.com
* www: http://www.pobox.com/~ndr
*/
#ifndef GLM_H
#define GLM_H
typedef unsigned int uint;
#ifndef M_PI
#define M_PI 3.14159265
#endif
/* defines */
#define GLM_NONE (0) /* render with only vertices */
#define GLM_FLAT (1 << 0) /* render with facet normals */
#define GLM_SMOOTH (1 << 1) /* render with vertex normals */
#define GLM_TEXTURE (1 << 2) /* render with texture coords */
#define GLM_COLOR (1 << 3) /* render with colors */
#define GLM_MATERIAL (1 << 4) /* render with materials */
/* structs */
/* GLMmaterial: Structure that defines a material in a model.
*/
typedef struct _GLMmaterial
{
char* name; /* name of material */
float diffuse[4]; /* diffuse component */
float ambient[4]; /* ambient component */
float specular[4]; /* specular component */
float emmissive[4]; /* emmissive component */
float shininess; /* specular exponent */
char *map_kd; /* diffuse texture map file */
uint texture_kd; /* diffuse texture map */
uint texture_ks; /* specular texture map */
int uDiffuse, uAmbient, uSpecular, uShininess, uDiffTex, uSpecTex;
uint prog;
} GLMmaterial;
/* GLMtriangle: Structure that defines a triangle in a model.
*/
typedef struct {
uint vindices[3]; /* array of triangle vertex indices */
uint nindices[3]; /* array of triangle normal indices */
uint tindices[3]; /* array of triangle texcoord indices*/
uint findex; /* index of triangle facet normal */
} GLMtriangle;
/* GLMgroup: Structure that defines a group in a model.
*/
typedef struct _GLMgroup {
char* name; /* name of this group */
uint numtriangles; /* number of triangles in this group */
uint* triangles; /* array of triangle indices */
uint material; /* index to material for group */
uint * triIndexes;
uint minIndex, maxIndex;
struct _GLMgroup* next; /* pointer to next group in model */
} GLMgroup;
/* GLMmodel: Structure that defines a model.
*/
typedef struct {
char* pathname; /* path to this model */
char* mtllibname; /* name of the material library */
uint numvertices; /* number of vertices in model */
float* vertices; /* array of vertices */
uint numnormals; /* number of normals in model */
float* normals; /* array of normals */
uint numtexcoords; /* number of texcoords in model */
float* texcoords; /* array of texture coordinates */
uint numfacetnorms; /* number of facetnorms in model */
float* facetnorms; /* array of facetnorms */
uint numtriangles; /* number of triangles in model */
GLMtriangle* triangles; /* array of triangles */
uint nummaterials; /* number of materials in model */
GLMmaterial* materials; /* array of materials */
uint numgroups; /* number of groups in model */
GLMgroup* groups; /* linked list of groups */
float position[3]; /* position of the model */
float scale;
uint vbo; /* OpenGL VBO for vertex data */
uint vertexSize; /* number of floats per vertex */
uint posOffset; /* offset of position within vertex, in bytes */
uint normOffset; /* offset of normal within vertex, in bytes */
uint texOffset; /* offset of texcoord within vertex, in bytes */
} GLMmodel;
/* public functions */
/* glmUnitize: "unitize" a model by translating it to the origin and
* scaling it to fit in a unit cube around the origin. Returns the
* scalefactor used.
*
* model - properly initialized GLMmodel structure
*/
float
glmUnitize(GLMmodel* model);
/* glmDimensions: Calculates the dimensions (width, height, depth) of
* a model.
*
* model - initialized GLMmodel structure
* dimensions - array of 3 floats (float dimensions[3])
*/
void
glmDimensions(GLMmodel* model, float* dimensions);
/* glmScale: Scales a model by a given amount.
*
* model - properly initialized GLMmodel structure
* scale - scalefactor (0.5 = half as large, 2.0 = twice as large)
*/
void
glmScale(GLMmodel* model, float scale);
/* glmReverseWinding: Reverse the polygon winding for all polygons in
* this model. Default winding is counter-clockwise. Also changes
* the direction of the normals.
*
* model - properly initialized GLMmodel structure
*/
void
glmReverseWinding(GLMmodel* model);
/* glmFacetNormals: Generates facet normals for a model (by taking the
* cross product of the two vectors derived from the sides of each
* triangle). Assumes a counter-clockwise winding.
*
* model - initialized GLMmodel structure
*/
void
glmFacetNormals(GLMmodel* model);
/* glmVertexNormals: Generates smooth vertex normals for a model.
* First builds a list of all the triangles each vertex is in. Then
* loops through each vertex in the the list averaging all the facet
* normals of the triangles each vertex is in. Finally, sets the
* normal index in the triangle for the vertex to the generated smooth
* normal. If the dot product of a facet normal and the facet normal
* associated with the first triangle in the list of triangles the
* current vertex is in is greater than the cosine of the angle
* parameter to the function, that facet normal is not added into the
* average normal calculation and the corresponding vertex is given
* the facet normal. This tends to preserve hard edges. The angle to
* use depends on the model, but 90 degrees is usually a good start.
*
* model - initialized GLMmodel structure
* angle - maximum angle (in degrees) to smooth across
*/
void
glmVertexNormals(GLMmodel* model, float angle);
/* glmLinearTexture: Generates texture coordinates according to a
* linear projection of the texture map. It generates these by
* linearly mapping the vertices onto a square.
*
* model - pointer to initialized GLMmodel structure
*/
void
glmLinearTexture(GLMmodel* model);
/* glmSpheremapTexture: Generates texture coordinates according to a
* spherical projection of the texture map. Sometimes referred to as
* spheremap, or reflection map texture coordinates. It generates
* these by using the normal to calculate where that vertex would map
* onto a sphere. Since it is impossible to map something flat
* perfectly onto something spherical, there is distortion at the
* poles. This particular implementation causes the poles along the X
* axis to be distorted.
*
* model - pointer to initialized GLMmodel structure
*/
void
glmSpheremapTexture(GLMmodel* model);
/* glmDelete: Deletes a GLMmodel structure.
*
* model - initialized GLMmodel structure
*/
void
glmDelete(GLMmodel* model);
/* glmReadOBJ: Reads a model description from a Wavefront .OBJ file.
* Returns a pointer to the created object which should be free'd with
* glmDelete().
*
* filename - name of the file containing the Wavefront .OBJ format data.
*/
GLMmodel*
glmReadOBJ(char* filename);
/* glmWriteOBJ: Writes a model description in Wavefront .OBJ format to
* a file.
*
* model - initialized GLMmodel structure
* filename - name of the file to write the Wavefront .OBJ format data to
* mode - a bitwise or of values describing what is written to the file
* GLM_NONE - write only vertices
* GLM_FLAT - write facet normals
* GLM_SMOOTH - write vertex normals
* GLM_TEXTURE - write texture coords
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
void
glmWriteOBJ(GLMmodel* model, char* filename, uint mode);
/* glmDraw: Renders the model to the current OpenGL context using the
* mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
void
glmDraw(GLMmodel* model, uint mode);
/* glmList: Generates and returns a display list for the model using
* the mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
uint
glmList(GLMmodel* model, uint mode);
/* glmWeld: eliminate (weld) vectors that are within an epsilon of
* each other.
*
* model - initialized GLMmodel structure
* epsilon - maximum difference between vertices
* ( 0.00001 is a good start for a unitized model)
*
*/
void
glmWeld(GLMmodel* model, float epsilon);
void
glmReIndex(GLMmodel *model);
void
glmMakeVBOs(GLMmodel *model);
void
glmDrawVBO(GLMmodel *model);
void
glmPrint(const GLMmodel *model);
void
glmShaderMaterial(GLMmaterial *mat);
void
glmLoadTextures(GLMmodel *model);
void
glmSpecularTexture(GLMmodel *model, uint cubeTex);
#endif /* GLM_H */

455
progs/objviewer/glmdraw.c Normal file
View file

@ -0,0 +1,455 @@
/* */
#define GL_GLEXT_PROTOTYPES
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glm.h"
#include "readtex.h"
#include "shaderutil.h"
/* defines */
#define T(x) model->triangles[(x)]
/* glmDraw: Renders the model to the current OpenGL context using the
* mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_COLOR - render with colors (color material)
* GLM_MATERIAL - render with materials
* GLM_COLOR and GLM_MATERIAL should not both be specified.
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
GLvoid
glmDraw(GLMmodel* model, GLuint mode)
{
GLuint i;
GLMgroup* group;
assert(model);
assert(model->vertices);
/* do a bit of warning */
if (mode & GLM_FLAT && !model->facetnorms) {
printf("glmDraw() warning: flat render mode requested "
"with no facet normals defined.\n");
mode &= ~GLM_FLAT;
}
if (mode & GLM_SMOOTH && !model->normals) {
printf("glmDraw() warning: smooth render mode requested "
"with no normals defined.\n");
mode &= ~GLM_SMOOTH;
}
if (mode & GLM_TEXTURE && !model->texcoords) {
printf("glmDraw() warning: texture render mode requested "
"with no texture coordinates defined.\n");
mode &= ~GLM_TEXTURE;
}
if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
printf("glmDraw() warning: flat render mode requested "
"and smooth render mode requested (using smooth).\n");
mode &= ~GLM_FLAT;
}
if (mode & GLM_COLOR && !model->materials) {
printf("glmDraw() warning: color render mode requested "
"with no materials defined.\n");
mode &= ~GLM_COLOR;
}
if (mode & GLM_MATERIAL && !model->materials) {
printf("glmDraw() warning: material render mode requested "
"with no materials defined.\n");
mode &= ~GLM_MATERIAL;
}
if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
printf("glmDraw() warning: color and material render mode requested "
"using only material mode\n");
mode &= ~GLM_COLOR;
}
if (mode & GLM_COLOR)
glEnable(GL_COLOR_MATERIAL);
if (mode & GLM_MATERIAL)
glDisable(GL_COLOR_MATERIAL);
glPushMatrix();
glTranslatef(model->position[0], model->position[1], model->position[2]);
glBegin(GL_TRIANGLES);
group = model->groups;
while (group) {
if (mode & GLM_MATERIAL) {
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
model->materials[group->material].ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
model->materials[group->material].diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
model->materials[group->material].specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,
model->materials[group->material].shininess);
}
if (mode & GLM_COLOR) {
glColor3fv(model->materials[group->material].diffuse);
}
for (i = 0; i < group->numtriangles; i++) {
if (mode & GLM_FLAT)
glNormal3fv(&model->facetnorms[3 * T(group->triangles[i]).findex]);
if (mode & GLM_SMOOTH)
glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[0]]);
if (mode & GLM_TEXTURE)
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[0]]);
glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[0]]);
#if 0
printf("%f %f %f\n",
model->vertices[3 * T(group->triangles[i]).vindices[0] + X],
model->vertices[3 * T(group->triangles[i]).vindices[0] + Y],
model->vertices[3 * T(group->triangles[i]).vindices[0] + Z]);
#endif
if (mode & GLM_SMOOTH)
glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[1]]);
if (mode & GLM_TEXTURE)
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[1]]);
glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[1]]);
#if 0
printf("%f %f %f\n",
model->vertices[3 * T(group->triangles[i]).vindices[1] + X],
model->vertices[3 * T(group->triangles[i]).vindices[1] + Y],
model->vertices[3 * T(group->triangles[i]).vindices[1] + Z]);
#endif
if (mode & GLM_SMOOTH)
glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[2]]);
if (mode & GLM_TEXTURE)
glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[2]]);
glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[2]]);
#if 0
printf("%f %f %f\n",
model->vertices[3 * T(group->triangles[i]).vindices[2] + X],
model->vertices[3 * T(group->triangles[i]).vindices[2] + Y],
model->vertices[3 * T(group->triangles[i]).vindices[2] + Z]);
#endif
}
group = group->next;
}
glEnd();
glPopMatrix();
}
void
glmMakeVBOs(GLMmodel *model)
{
uint bytes, vertexFloats, i;
float *buffer;
vertexFloats = 3;
model->posOffset = 0;
if (model->numnormals > 0) {
assert(model->numnormals == model->numvertices);
model->normOffset = vertexFloats * sizeof(GLfloat);
vertexFloats += 3;
}
if (model->numtexcoords > 0) {
assert(model->numtexcoords == model->numvertices);
model->texOffset = vertexFloats * sizeof(GLfloat);
vertexFloats += 2;
}
model->vertexSize = vertexFloats;
bytes = (model->numvertices + 1) * vertexFloats * sizeof(float);
buffer = (float *) malloc(bytes);
for (i = 0; i < model->numvertices; i++) {
/* copy vertex pos */
uint j = 0;
buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 0];
buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 1];
buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 2];
if (model->numnormals > 0) {
buffer[i * vertexFloats + j++] = model->normals[i * 3 + 0];
buffer[i * vertexFloats + j++] = model->normals[i * 3 + 1];
buffer[i * vertexFloats + j++] = model->normals[i * 3 + 2];
}
if (model->numtexcoords > 0) {
buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 0];
buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 1];
}
}
glGenBuffersARB(1, &model->vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytes, buffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
free(buffer);
}
static void
_glmLoadTexture(GLMmaterial *mat)
{
if (mat->map_kd) {
GLint imgWidth, imgHeight;
GLenum imgFormat;
GLubyte *image = NULL;
glGenTextures(1, &mat->texture_kd);
image = LoadRGBImage( mat->map_kd, &imgWidth, &imgHeight, &imgFormat );
if (!image) {
/*fprintf(stderr, "Couldn't open texture %s\n", mat->map_kd);*/
free(mat->map_kd);
mat->map_kd = NULL;
mat->texture_kd = 0;
return;
}
if (0)
printf("load texture %s %d x %d\n", mat->map_kd, imgWidth, imgHeight);
glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
imgFormat, GL_UNSIGNED_BYTE, image);
free(image);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
}
void
glmLoadTextures(GLMmodel *model)
{
uint i;
for (i = 0; i < model->nummaterials; i++) {
GLMmaterial *mat = &model->materials[i];
_glmLoadTexture(mat);
}
}
void
glmDrawVBO(GLMmodel *model)
{
GLMgroup* group;
assert(model->vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
glVertexPointer(3, GL_FLOAT, model->vertexSize * sizeof(float),
(void *) model->posOffset);
glEnableClientState(GL_VERTEX_ARRAY);
if (model->numnormals > 0) {
glNormalPointer(GL_FLOAT, model->vertexSize * sizeof(float),
(void *) model->normOffset);
glEnableClientState(GL_NORMAL_ARRAY);
}
if (model->numtexcoords > 0) {
glTexCoordPointer(2, GL_FLOAT, model->vertexSize * sizeof(float),
(void *) model->texOffset);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glPushMatrix();
glTranslatef(model->position[0], model->position[1], model->position[2]);
glScalef(model->scale, model->scale, model->scale);
for (group = model->groups; group; group = group->next) {
if (group->numtriangles > 0) {
glmShaderMaterial(&model->materials[group->material]);
glDrawRangeElements(GL_TRIANGLES,
group->minIndex, group->maxIndex,
3 * group->numtriangles,
GL_UNSIGNED_INT, group->triIndexes);
}
}
glPopMatrix();
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
/* glmList: Generates and returns a display list for the model using
* the mode specified.
*
* model - initialized GLMmodel structure
* mode - a bitwise OR of values describing what is to be rendered.
* GLM_NONE - render with only vertices
* GLM_FLAT - render with facet normals
* GLM_SMOOTH - render with vertex normals
* GLM_TEXTURE - render with texture coords
* GLM_COLOR - render with colors (color material)
* GLM_MATERIAL - render with materials
* GLM_COLOR and GLM_MATERIAL should not both be specified.
* GLM_FLAT and GLM_SMOOTH should not both be specified.
*/
GLuint
glmList(GLMmodel* model, GLuint mode)
{
GLuint list;
list = glGenLists(1);
glNewList(list, GL_COMPILE);
glmDraw(model, mode);
glEndList();
return list;
}
static const char *VertexShader =
"varying vec3 normal; \n"
"void main() { \n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
" normal = gl_NormalMatrix * gl_Normal; \n"
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
"} \n";
/**
* Two %s substitutions:
* diffuse texture? true/false
* specular texture? true/false
*/
static const char *TexFragmentShader =
"uniform vec4 ambient, diffuse, specular; \n"
"uniform vec4 ambientLight, diffuseLight, specularLight; \n"
"uniform float shininess; \n"
"uniform sampler2D diffTex; \n"
"uniform samplerCube specTex; \n"
"varying vec3 normal; \n"
"\n"
"void main() \n"
"{ \n"
" vec4 diffTerm, specTerm; \n"
" float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
" normalize(normal)), 0.0);\n"
" float dotProd2 = max(dot(-gl_LightSource[0].position.xyz, \n"
" normalize(normal)), 0.0);\n"
" dotProd += dotProd2; \n"
" \n"
" diffTerm = diffuse * diffuseLight * dotProd; \n"
" if (%s) \n"
" diffTerm *= texture2D(diffTex, gl_TexCoord[0].st); \n"
" \n"
" specTerm = specular * specularLight * pow(dotProd, shininess); \n"
" if (%s) \n"
" specTerm *= textureCube(specTex, normal); \n"
" \n"
" gl_FragColor = ambient * ambientLight + diffTerm + specTerm; \n"
"} \n";
void
glmShaderMaterial(GLMmaterial *mat)
{
static const float ambientLight[4] = { 0.1, 0.1, 0.1, 0.0 };
static const float diffuseLight[4] = { 0.75, 0.75, 0.75, 1.0 };
static const float specularLight[4] = { 1.0, 1.0, 1.0, 0.0 };
if (!mat->prog) {
/* make shader now */
char newShader[10000];
GLuint vs, fs;
const char *diffuseTex = mat->texture_kd ? "true" : "false";
const char *specularTex = mat->texture_ks ? "true" : "false";
GLint uAmbientLight, uDiffuseLight, uSpecularLight;
/* replace %d with 0 or 1 */
sprintf(newShader, TexFragmentShader, diffuseTex, specularTex);
if (0)
printf("===== new shader =====\n%s\n============\n", newShader);
vs = CompileShaderText(GL_VERTEX_SHADER, VertexShader);
fs = CompileShaderText(GL_FRAGMENT_SHADER, newShader);
mat->prog = LinkShaders(vs, fs);
assert(mat->prog);
glUseProgram(mat->prog);
mat->uAmbient = glGetUniformLocation(mat->prog, "ambient");
mat->uDiffuse = glGetUniformLocation(mat->prog, "diffuse");
mat->uSpecular = glGetUniformLocation(mat->prog, "specular");
mat->uShininess = glGetUniformLocation(mat->prog, "shininess");
mat->uDiffTex = glGetUniformLocation(mat->prog, "diffTex");
mat->uSpecTex = glGetUniformLocation(mat->prog, "specTex");
uAmbientLight = glGetUniformLocation(mat->prog, "ambientLight");
uDiffuseLight = glGetUniformLocation(mat->prog, "diffuseLight");
uSpecularLight = glGetUniformLocation(mat->prog, "specularLight");
glUniform4fv(mat->uAmbient, 1, mat->ambient);
glUniform4fv(mat->uDiffuse, 1, mat->diffuse);
glUniform4fv(mat->uSpecular, 1, mat->specular);
glUniform1f(mat->uShininess, mat->shininess);
glUniform1i(mat->uDiffTex, 0);
glUniform1i(mat->uSpecTex, 1);
glUniform4fv(uAmbientLight, 1, ambientLight);
glUniform4fv(uDiffuseLight, 1, diffuseLight);
glUniform4fv(uSpecularLight, 1, specularLight);
}
glActiveTexture(GL_TEXTURE1);
if (mat->texture_ks)
glBindTexture(GL_TEXTURE_CUBE_MAP, mat->texture_ks);
else
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glActiveTexture(GL_TEXTURE0);
if (mat->texture_kd)
glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
else
glBindTexture(GL_TEXTURE_2D, 0);
if (mat->diffuse[3] < 1.0) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else {
glDisable(GL_BLEND);
}
glUseProgram(mat->prog);
}
void
glmSpecularTexture(GLMmodel *model, uint cubeTex)
{
uint i;
for (i = 0; i < model->nummaterials; i++) {
model->materials[i].texture_ks = cubeTex;
}
}

515
progs/objviewer/objview.c Normal file
View file

@ -0,0 +1,515 @@
/*
* .obj file viewer based on "smooth" by Nate Robins, 1997
*
* Brian Paul
* 1 Oct 2009
*/
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "glm.h"
#include "readtex.h"
#include "skybox.h"
#include "trackball.h"
static char *Model_file = NULL; /* name of the obect file */
static GLMmodel *Model;
static GLfloat Scale = 4.0; /* scaling factor */
static GLboolean Performance = GL_FALSE;
static GLboolean Stats = GL_FALSE;
static GLboolean Animate = GL_TRUE;
static GLuint SkyboxTex;
static GLboolean Skybox = GL_TRUE;
static GLboolean Cull = GL_TRUE;
static GLboolean WireFrame = GL_FALSE;
static GLenum FrontFace = GL_CCW;
static GLfloat Yrot = 0.0;
static GLint WinWidth = 1024, WinHeight = 768;
static GLuint NumInstances = 1;
typedef struct
{
float CurQuat[4];
float Distance;
/* When mouse is moving: */
GLboolean Rotating, Translating;
GLint StartX, StartY;
float StartDistance;
} ViewInfo;
static ViewInfo View;
static void
InitViewInfo(ViewInfo *view)
{
view->Rotating = GL_FALSE;
view->Translating = GL_FALSE;
view->StartX = view->StartY = 0;
view->Distance = 12.0;
view->StartDistance = 0.0;
view->CurQuat[0] = 0.0;
view->CurQuat[1] = 1.0;
view->CurQuat[2] = 0.0;
view->CurQuat[3] = 0.0;
}
/* text: general purpose text routine. draws a string according to
* format in a stroke font at x, y after scaling it by the scale
* specified (scale is in window-space (lower-left origin) pixels).
*
* x - position in x (in window-space)
* y - position in y (in window-space)
* scale - scale in pixels
* format - as in printf()
*/
static void
text(GLuint x, GLuint y, GLfloat scale, char* format, ...)
{
va_list args;
char buffer[255], *p;
GLfloat font_scale = 119.05 + 33.33;
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, glutGet(GLUT_WINDOW_WIDTH), 0, glutGet(GLUT_WINDOW_HEIGHT));
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glTranslatef(x, y, 0.0);
glScalef(scale/font_scale, scale/font_scale, scale/font_scale);
for(p = buffer; *p; p++)
glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);
glPopAttrib();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
static float
ComputeFPS(void)
{
static double t0 = -1.0;
static int frames = 0;
double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
static float fps = 0;
frames++;
if (t0 < 0.0) {
t0 = t;
fps = 0.0;
}
else if (t - t0 >= 4.0) {
fps = (frames / (t - t0) + 0.5);
t0 = t;
frames = 0;
return fps;
}
return 0.0;
}
static void
init_model(void)
{
float objScale;
/* read in the model */
Model = glmReadOBJ(Model_file);
objScale = glmUnitize(Model);
glmFacetNormals(Model);
if (Model->numnormals == 0) {
GLfloat smoothing_angle = 90.0;
printf("Generating normals.\n");
glmVertexNormals(Model, smoothing_angle);
}
glmLoadTextures(Model);
glmReIndex(Model);
glmMakeVBOs(Model);
if (0)
glmPrint(Model);
}
static void
init_skybox(void)
{
SkyboxTex = LoadSkyBoxCubeTexture("alpine_east.rgb",
"alpine_west.rgb",
"alpine_up.rgb",
"alpine_down.rgb",
"alpine_south.rgb",
"alpine_north.rgb");
glmSpecularTexture(Model, SkyboxTex);
}
static void
init_gfx(void)
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_NORMALIZE);
glClearColor(0.3, 0.3, 0.9, 0.0);
}
static void
reshape(int width, int height)
{
float ar = 0.5 * (float) width / (float) height;
WinWidth = width;
WinHeight = height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -0.5, 0.5, 1.0, 300.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -3.0);
}
static void
Idle(void)
{
float q[4];
trackball(q, 100, 0, 99.99, 0);
add_quats(q, View.CurQuat, View.CurQuat);
glutPostRedisplay();
}
static void
display(void)
{
GLfloat rot[4][4];
float fps;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0, 0.0, -View.Distance);
glRotatef(Yrot, 0, 1, 0);
build_rotmatrix(rot, View.CurQuat);
glMultMatrixf(&rot[0][0]);
glScalef(Scale, Scale, Scale );
glUseProgram(0);
if (Skybox)
DrawSkyBoxCubeTexture(SkyboxTex);
if (WireFrame)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (Cull)
glEnable(GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
if (NumInstances == 1) {
glmDrawVBO(Model);
}
else {
/* draw > 1 instance */
float dr = 360.0 / NumInstances;
float r;
for (r = 0.0; r < 360.0; r += dr) {
glPushMatrix();
glRotatef(r, 0, 1, 0);
glTranslatef(1.4, 0.0, 0.0);
glmDrawVBO(Model);
glPopMatrix();
}
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_CULL_FACE);
glPopMatrix();
if (Stats) {
glColor3f(1.0, 1.0, 1.0);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*1), 20, "%s",
Model->pathname);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*2), 20, "%d vertices",
Model->numvertices);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*3), 20, "%d triangles",
Model->numtriangles);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*4), 20, "%d normals",
Model->numnormals);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*5), 20, "%d texcoords",
Model->numtexcoords);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*6), 20, "%d groups",
Model->numgroups);
text(5, glutGet(GLUT_WINDOW_HEIGHT) - (5+20*7), 20, "%d materials",
Model->nummaterials);
}
glutSwapBuffers();
fps = ComputeFPS();
if (fps)
printf("%f FPS\n", fps);
}
static void
keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'h':
printf("help\n\n");
printf("a - Toggle animation\n");
printf("d/D - Decrease/Incrase number of models\n");
printf("w - Toggle wireframe/filled\n");
printf("c - Toggle culling\n");
printf("n - Toggle facet/smooth normal\n");
printf("r - Reverse polygon winding\n");
printf("p - Toggle performance indicator\n");
printf("s - Toggle skybox\n");
printf("z/Z - Scale model smaller/larger\n");
printf("i - Show model info/stats\n");
printf("q/escape - Quit\n\n");
break;
case 'a':
Animate = !Animate;
if (Animate)
glutIdleFunc(Idle);
else
glutIdleFunc(NULL);
break;
case 'd':
if (NumInstances > 1)
NumInstances--;
break;
case 'D':
NumInstances++;
break;
case 'i':
Stats = !Stats;
break;
case 'p':
Performance = !Performance;
break;
case 'w':
WireFrame = !WireFrame;
break;
case 'c':
Cull = !Cull;
printf("Polygon culling: %d\n", Cull);
break;
case 'r':
if (FrontFace == GL_CCW)
FrontFace = GL_CW;
else
FrontFace = GL_CCW;
glFrontFace(FrontFace);
printf("Front face:: %s\n", FrontFace == GL_CCW ? "CCW" : "CW");
break;
case 's':
Skybox = !Skybox;
if (Skybox)
glmSpecularTexture(Model, SkyboxTex);
else
glmSpecularTexture(Model, 0);
break;
case 'z':
Scale *= 0.9;
break;
case 'Z':
Scale *= 1.1;
break;
case 'q':
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
static void
menu(int item)
{
keyboard((unsigned char)item, 0, 0);
}
/**
* Handle mouse button.
*/
static void
Mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
View.StartX = x;
View.StartY = y;
View.Rotating = GL_TRUE;
}
else if (state == GLUT_UP) {
View.Rotating = GL_FALSE;
}
}
else if (button == GLUT_MIDDLE_BUTTON) {
if (state == GLUT_DOWN) {
View.StartX = x;
View.StartY = y;
View.StartDistance = View.Distance;
View.Translating = GL_TRUE;
}
else if (state == GLUT_UP) {
View.Translating = GL_FALSE;
}
}
}
/**
* Handle mouse motion
*/
static void
Motion(int x, int y)
{
int i;
if (View.Rotating) {
float x0 = (2.0 * View.StartX - WinWidth) / WinWidth;
float y0 = (WinHeight - 2.0 * View.StartY) / WinHeight;
float x1 = (2.0 * x - WinWidth) / WinWidth;
float y1 = (WinHeight - 2.0 * y) / WinHeight;
float q[4];
trackball(q, x0, y0, x1, y1);
View.StartX = x;
View.StartY = y;
for (i = 0; i < 1; i++)
add_quats(q, View.CurQuat, View.CurQuat);
glutPostRedisplay();
}
else if (View.Translating) {
float dz = 0.02 * (y - View.StartY);
View.Distance = View.StartDistance + dz;
glutPostRedisplay();
}
}
static void
DoFeatureChecks(void)
{
char *version = (char *) glGetString(GL_VERSION);
if (version[0] == '1') {
/* check for individual extensions */
if (!glutExtensionSupported("GL_ARB_texture_cube_map")) {
printf("Sorry, GL_ARB_texture_cube_map is required.\n");
exit(1);
}
if (!glutExtensionSupported("GL_ARB_vertex_shader")) {
printf("Sorry, GL_ARB_vertex_shader is required.\n");
exit(1);
}
if (!glutExtensionSupported("GL_ARB_fragment_shader")) {
printf("Sorry, GL_ARB_fragment_shader is required.\n");
exit(1);
}
if (!glutExtensionSupported("GL_ARB_vertex_buffer_object")) {
printf("Sorry, GL_ARB_vertex_buffer_object is required.\n");
exit(1);
}
}
}
int
main(int argc, char** argv)
{
glutInitWindowSize(WinWidth, WinHeight);
glutInit(&argc, argv);
if (argc > 1) {
Model_file = argv[1];
}
if (!Model_file) {
fprintf(stderr, "usage: objview file.obj\n");
fprintf(stderr, "(using default bunny.obj)\n");
Model_file = "bunny.obj";
}
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("objview");
glewInit();
DoFeatureChecks();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(Mouse);
glutMotionFunc(Motion);
if (Animate)
glutIdleFunc(Idle);
glutCreateMenu(menu);
glutAddMenuEntry("[a] Toggle animate", 'a');
glutAddMenuEntry("[d] Fewer models", 'd');
glutAddMenuEntry("[D] More models", 'D');
glutAddMenuEntry("[w] Toggle wireframe/filled", 'w');
glutAddMenuEntry("[c] Toggle culling on/off", 'c');
glutAddMenuEntry("[r] Reverse polygon winding", 'r');
glutAddMenuEntry("[z] Scale model smaller", 'z');
glutAddMenuEntry("[Z] Scale model larger", 'Z');
glutAddMenuEntry("[p] Toggle performance indicator", 'p');
glutAddMenuEntry("[i] Show model stats", 'i');
glutAddMenuEntry("", 0);
glutAddMenuEntry("[q] Quit", 27);
glutAttachMenu(GLUT_RIGHT_BUTTON);
InitViewInfo(&View);
init_model();
init_skybox();
init_gfx();
glutMainLoop();
return 0;
}

187
progs/objviewer/skybox.c Normal file
View file

@ -0,0 +1,187 @@
#include <assert.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include "readtex.h"
#include "skybox.h"
static int
load(GLenum target, const char *filename,
GLboolean flipTB, GLboolean flipLR)
{
GLint w, h;
GLenum format;
GLubyte *img = LoadRGBImage( filename, &w, &h, &format );
if (!img) {
printf("Error: couldn't load texture image %s\n", filename);
return 0;
}
assert(format == GL_RGB);
printf("Load cube face 0x%x: %s %d x %d\n", target, filename, w, h);
/* <sigh> the way the texture cube mapping works, we have to flip
* images to make things look right.
*/
if (flipTB) {
const int stride = 3 * w;
GLubyte temp[3*1024];
int i;
for (i = 0; i < h / 2; i++) {
memcpy(temp, img + i * stride, stride);
memcpy(img + i * stride, img + (h - i - 1) * stride, stride);
memcpy(img + (h - i - 1) * stride, temp, stride);
}
}
if (flipLR) {
const int stride = 3 * w;
GLubyte temp[3];
GLubyte *row;
int i, j;
for (i = 0; i < h; i++) {
row = img + i * stride;
for (j = 0; j < w / 2; j++) {
int k = w - j - 1;
temp[0] = row[j*3+0];
temp[1] = row[j*3+1];
temp[2] = row[j*3+2];
row[j*3+0] = row[k*3+0];
row[j*3+1] = row[k*3+1];
row[j*3+2] = row[k*3+2];
row[k*3+0] = temp[0];
row[k*3+1] = temp[1];
row[k*3+2] = temp[2];
}
}
}
gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img);
free(img);
return 1;
}
GLuint
LoadSkyBoxCubeTexture(const char *filePosX,
const char *fileNegX,
const char *filePosY,
const char *fileNegY,
const char *filePosZ,
const char *fileNegZ)
{
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST);
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_X, filePosX, GL_TRUE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, 1+GL_FALSE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, 1+GL_FALSE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
return 0;
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, fileNegZ, GL_TRUE, GL_TRUE))
return 0;
return tex;
}
#define eps1 0.99
#define br 20.0 /* box radius */
void
DrawSkyBoxCubeTexture(GLuint tex)
{
struct vertex {
float x, y, z, s, t, r;
};
static const struct vertex verts[24] = {
/* +X side */
{ br, -br, -br, 1.0, -eps1, -eps1 },
{ br, -br, br, 1.0, -eps1, eps1 },
{ br, br, br, 1.0, eps1, eps1 },
{ br, br, -br, 1.0, eps1, -eps1 },
/* -X side */
{ -br, br, -br, -1.0, eps1, -eps1 },
{ -br, br, br, -1.0, eps1, eps1 },
{ -br, -br, br, -1.0, -eps1, eps1 },
{ -br, -br, -br, -1.0, -eps1, -eps1 },
/* +Y side */
{ br, br, -br, eps1, 1.0, -eps1 },
{ br, br, br, eps1, 1.0, eps1 },
{ -br, br, br, -eps1, 1.0, eps1 },
{ -br, br, -br, -eps1, 1.0, -eps1 },
/* -Y side */
{ -br, -br, -br, -eps1, -1.0, -eps1 },
{ -br, -br, br, -eps1, -1.0, eps1 },
{ br, -br, br, eps1, -1.0, eps1 },
{ br, -br, -br, eps1, -1.0, -eps1 },
/* +Z side */
{ br, -br, br, eps1, -eps1, 1.0 },
{ -br, -br, br, -eps1, -eps1, 1.0 },
{ -br, br, br, -eps1, eps1, 1.0 },
{ br, br, br, eps1, eps1, 1.0 },
/* -Z side */
{ br, br, -br, eps1, eps1, -1.0 },
{ -br, br, -br, -eps1, eps1, -1.0 },
{ -br, -br, -br, -eps1, -eps1, -1.0 },
{ br, -br, -br, eps1, -eps1, -1.0 },
};
static GLuint vbo = 0;
if (!vbo ) {
glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
GL_STATIC_DRAW_ARB);
}
else {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
}
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glVertexPointer(3, GL_FLOAT, sizeof(struct vertex),
(void *) offsetof(struct vertex, x));
glTexCoordPointer(3, GL_FLOAT, sizeof(struct vertex),
(void *) offsetof(struct vertex, s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
glEnable(GL_TEXTURE_CUBE_MAP);
glDisable(GL_BLEND);
glDrawArrays(GL_QUADS, 0, 24);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}

18
progs/objviewer/skybox.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef SKYBOX_H
#define SKYBOX_H
extern GLuint
LoadSkyBoxCubeTexture(const char *filePosX,
const char *fileNegX,
const char *filePosY,
const char *fileNegY,
const char *filePosZ,
const char *fileNegZ);
extern void
DrawSkyBoxCubeTexture(GLuint tex);
#endif /* SKYBOX_H */

View file

@ -10,11 +10,17 @@ LIBS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLEW_LIB) \
# using : to avoid APP_CC pointing to CC loop
CC := $(APP_CC)
CFLAGS += -I$(INCDIR)
CFLAGS := -I$(INCDIR) $(CFLAGS)
LDLIBS = $(LIBS)
PROG_SOURCES = \
copytex.c \
drawoverhead.c \
fbobind.c \
fill.c \
genmipmap.c \
readpixels.c \
swapbuffers.c \
teximage.c \
vbo.c \
vertexrate.c \

View file

@ -8,7 +8,13 @@ env = env.Clone()
env.Prepend(LIBS = ['$GLUT_LIB'])
progs = [
'copytex',
'drawoverhead',
'fbobind',
'fill',
'genmipmap',
'readpixels',
'swapbuffers',
'teximage',
'vbo',
'vertexrate',

View file

@ -113,3 +113,21 @@ PerfMeasureRate(PerfRateFunc f)
}
/* Note static buffer, can only use once per printf.
*/
const char *
PerfHumanFloat( double d )
{
static char buf[80];
if (d > 1000000000.0)
snprintf(buf, sizeof(buf), "%.1f billion", d / 1000000000.0);
else if (d > 1000000.0)
snprintf(buf, sizeof(buf), "%.1f million", d / 1000000.0);
else if (d > 1000.0)
snprintf(buf, sizeof(buf), "%.1f thousand", d / 1000.0);
else
snprintf(buf, sizeof(buf), "%.1f", d);
return buf;
}

View file

@ -24,12 +24,17 @@
#define COMMON_H
#include <stddef.h> /* for offsetof() */
typedef void (*PerfRateFunc)(unsigned count);
extern double
PerfMeasureRate(PerfRateFunc f);
const char *
PerfHumanFloat( double d );
extern void
perf_printf(const char *format, ...);

214
progs/perf/copytex.c Normal file
View file

@ -0,0 +1,214 @@
/*
* Copyright (C) 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, 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
* VMWARE 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.
*/
/**
* Measure glCopyTex[Sub]Image() rate.
* Create a large, off-screen framebuffer object for rendering and
* copying the texture data from it since we can't make really large
* on-screen windows.
*
* Brian Paul
* 22 Sep 2009
*/
#include <string.h>
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO, FBO, RBO, Tex;
const GLsizei MinSize = 16, MaxSize = 4096;
static GLsizei TexSize;
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean TexSubImage4 = GL_FALSE;
struct vertex
{
GLfloat x, y, s, t;
};
static const struct vertex vertices[1] = {
{ 0.0, 0.0, 0.5, 0.5 },
};
#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
/** Called from test harness/main */
void
PerfInit(void)
{
const GLenum filter = GL_LINEAR;
GLenum stat;
if (!PerfExtensionSupported("GL_EXT_framebuffer_object")) {
perf_printf("copytex: GL_EXT_framebuffer_object not supported\n");
exit(0);
}
/* setup VBO */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices),
vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
/* setup texture */
glGenTextures(1, &Tex);
glBindTexture(GL_TEXTURE_2D, Tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glEnable(GL_TEXTURE_2D);
/* setup rbo */
glGenRenderbuffersEXT(1, &RBO);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBO);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, MaxSize, MaxSize);
/* setup fbo */
glGenFramebuffersEXT(1, &FBO);
glBindFramebufferEXT(GL_FRAMEBUFFER, FBO);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT, RBO);
stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (stat != GL_FRAMEBUFFER_COMPLETE_EXT) {
perf_printf("fboswitch: Error: incomplete FBO!\n");
exit(1);
}
/* clear the FBO */
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glViewport(0, 0, MaxSize, MaxSize);
glClear(GL_COLOR_BUFFER_BIT);
}
static void
CopyTexImage(unsigned count)
{
unsigned i;
for (i = 1; i < count; i++) {
/* draw something */
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
/* copy whole texture */
glCopyTexImage2D(GL_TEXTURE_2D, 0,
GL_RGBA, 0, 0, TexSize, TexSize, 0);
}
glFinish();
}
static void
CopyTexSubImage(unsigned count)
{
unsigned i;
for (i = 1; i < count; i++) {
/* draw something */
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
/* copy sub texture */
if (TexSubImage4) {
/* four sub-copies */
GLsizei half = TexSize / 2;
/* lower-left */
glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, 0, 0, half, half);
/* lower-right */
glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
half, 0, half, 0, half, half);
/* upper-left */
glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
0, half, 0, half, half, half);
/* upper-right */
glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
half, half, half, half, half, half);
}
else {
/* one big copy */
glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, 0, 0, TexSize, TexSize);
}
}
glFinish();
}
/** Called from test harness/main */
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate, mbPerSec;
GLint sub, maxTexSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
/* loop over whole/sub tex copy */
for (sub = 0; sub < 2; sub++) {
/* loop over texture sizes */
for (TexSize = MinSize; TexSize <= MaxSize; TexSize *= 4) {
if (TexSize <= maxTexSize) {
GLint bytesPerImage = 4 * TexSize * TexSize;
if (sub == 0)
rate = PerfMeasureRate(CopyTexImage);
else {
/* setup empty dest texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TexSize, TexSize, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
rate = PerfMeasureRate(CopyTexSubImage);
}
mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
}
else {
rate = 0.0;
mbPerSec = 0.0;
}
perf_printf(" glCopyTex%sImage(%d x %d): %.1f copies/sec, %.1f Mpixels/sec\n",
(sub ? "Sub" : ""), TexSize, TexSize, rate, mbPerSec);
}
}
exit(0);
}

View file

@ -27,7 +27,6 @@
* easily portable to other APIs.
*
* All the window-system stuff should be contained in glmain.c (or TBDmain.c).
* All the re-usable, generic code should be in common.c (XXX not done yet).
*
* Brian Paul
* 15 Sep 2009
@ -108,6 +107,10 @@ DrawStateChange(unsigned count)
glFinish();
}
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
@ -116,18 +119,18 @@ PerfDraw(void)
double rate0, rate1, rate2, overhead;
rate0 = PerfMeasureRate(DrawNoStateChange);
perf_printf(" Draw only: %.1f draws/second\n", rate0);
perf_printf(" Draw only: %s draws/second\n",
PerfHumanFloat(rate0));
rate1 = PerfMeasureRate(DrawNopStateChange);
overhead = 1000.0 * (1.0 / rate1 - 1.0 / rate0);
perf_printf(" Draw w/ nop state change: %.1f draws/sec (overhead: %f ms/draw)\n",
rate1, overhead);
perf_printf(" Draw w/ nop state change: %s draws/sec (overhead: %f ms/draw)\n",
PerfHumanFloat(rate1), overhead);
rate2 = PerfMeasureRate(DrawStateChange);
overhead = 1000.0 * (1.0 / rate2 - 1.0 / rate0);
perf_printf(" Draw w/ state change: %.1f draws/sec (overhead: %f ms/draw)\n",
rate2, overhead);
perf_printf(" Draw w/ state change: %s draws/sec (overhead: %f ms/draw)\n",
PerfHumanFloat(rate2), overhead);
exit(0);
}

153
progs/perf/fbobind.c Normal file
View file

@ -0,0 +1,153 @@
/*
* Copyright (C) 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, 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
* VMWARE 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.
*/
/**
* Measure rate of binding/switching between FBO targets.
* Create two framebuffer objects for rendering to two textures.
* Ping pong between texturing from one and drawing into the other.
*
* Brian Paul
* 22 Sep 2009
*/
#include <string.h>
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
static GLuint FBO[2], Tex[2];
static const GLsizei TexSize = 512;
static const GLboolean DrawPoint = GL_TRUE;
struct vertex
{
GLfloat x, y, s, t;
};
static const struct vertex vertices[1] = {
{ 0.0, 0.0, 0.5, 0.5 },
};
#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
/** Called from test harness/main */
void
PerfInit(void)
{
const GLenum filter = GL_LINEAR;
GLenum stat;
int i;
if (!PerfExtensionSupported("GL_EXT_framebuffer_object")) {
perf_printf("fboswitch: GL_EXT_framebuffer_object not supported\n");
exit(0);
}
/* setup VBO */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices),
vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glGenFramebuffersEXT(2, FBO);
glGenTextures(2, Tex);
for (i = 0; i < 2; i++) {
/* setup texture */
glBindTexture(GL_TEXTURE_2D, Tex[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TexSize, TexSize, 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);
/* setup fbo */
glBindFramebufferEXT(GL_FRAMEBUFFER, FBO[i]);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, Tex[i], 0/*level*/);
stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (stat != GL_FRAMEBUFFER_COMPLETE_EXT) {
perf_printf("fboswitch: Error: incomplete FBO!\n");
exit(1);
}
/* clear the FBO */
glClear(GL_COLOR_BUFFER_BIT);
}
glEnable(GL_TEXTURE_2D);
}
static void
FBOBind(unsigned count)
{
unsigned i;
for (i = 1; i < count; i++) {
const GLuint dst = i & 1;
const GLuint src = 1 - dst;
/* bind src texture */
glBindTexture(GL_TEXTURE_2D, Tex[src]);
/* bind dst fbo */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO[dst]);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
/* draw something */
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
/** Called from test harness/main */
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate;
rate = PerfMeasureRate(FBOBind);
perf_printf(" FBO Binding: %1.f binds/sec\n", rate);
exit(0);
}

248
progs/perf/fill.c Normal file
View file

@ -0,0 +1,248 @@
/*
* Copyright (C) 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, 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
* VMWARE 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.
*/
/**
* Measure fill rates.
*
* Brian Paul
* 21 Sep 2009
*/
#include "glmain.h"
#include "common.h"
int WinWidth = 1000, WinHeight = 1000;
static GLuint VBO, TexObj;
struct vertex
{
GLfloat x, y, s, t, r, g, b, a;
};
#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
static const struct vertex vertices[4] = {
/* x y s t r g b a */
{ -1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5 },
{ 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5 },
{ 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.5 },
{ -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.5 }
};
static const char *VertexShader =
"void main() \n"
"{ \n"
" gl_Position = ftransform(); \n"
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
" gl_FrontColor = gl_Color; \n"
"} \n";
/* simple fragment shader */
static const char *FragmentShader1 =
"uniform sampler2D Tex; \n"
"void main() \n"
"{ \n"
" vec4 t = texture2D(Tex, gl_TexCoord[0].xy); \n"
" gl_FragColor = vec4(1.0) - t * gl_Color; \n"
"} \n";
/**
* A more complex fragment shader (but equivalent to first shader).
* A good optimizer should catch some of these no-op operations, but
* probably not all of them.
*/
static const char *FragmentShader2 =
"uniform sampler2D Tex; \n"
"void main() \n"
"{ \n"
" // as above \n"
" vec4 t = texture2D(Tex, gl_TexCoord[0].xy); \n"
" t = vec4(1.0) - t * gl_Color; \n"
" vec4 u; \n"
" // no-op negate/swizzle \n"
" u = -t.wzyx; \n"
" t = -u.wzyx; \n"
" // no-op inverts \n"
" t = vec4(1.0) - t; \n"
" t = vec4(1.0) - t; \n"
" // no-op min/max \n"
" t = min(t, t); \n"
" t = max(t, t); \n"
" // no-op moves \n"
" u = t; \n"
" t = u; \n"
" u = t; \n"
" t = u; \n"
" // no-op add/mul \n"
" t = (t + t + t + t) * 0.25; \n"
" // no-op mul/sub \n"
" t = 3.0 * t - 2.0 * t; \n"
" // no-op negate/min/max \n"
" t = -min(-t, -t); \n"
" t = -max(-t, -t); \n"
" gl_FragColor = t; \n"
"} \n";
static GLuint ShaderProg1, ShaderProg2;
/** Called from test harness/main */
void
PerfInit(void)
{
GLint u;
/* setup VBO w/ vertex data */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
glColorPointer(4, GL_FLOAT, sizeof(struct vertex), VOFFSET(r));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
/* setup texture */
TexObj = PerfCheckerTexture(128, 128);
/* setup shaders */
ShaderProg1 = PerfShaderProgram(VertexShader, FragmentShader1);
glUseProgram(ShaderProg1);
u = glGetUniformLocation(ShaderProg1, "Tex");
glUniform1i(u, 0); /* texture unit 0 */
ShaderProg2 = PerfShaderProgram(VertexShader, FragmentShader2);
glUseProgram(ShaderProg2);
u = glGetUniformLocation(ShaderProg2, "Tex");
glUniform1i(u, 0); /* texture unit 0 */
glUseProgram(0);
}
static void
Ortho(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void
DrawQuad(unsigned count)
{
unsigned i;
glClear(GL_COLOR_BUFFER_BIT);
for (i = 0; i < count; i++) {
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
/* Avoid sending command buffers with huge numbers of fullscreen
* quads. Graphics schedulers don't always cope well with
* this...
*/
if (i % 128 == 0) {
PerfSwapBuffers();
glClear(GL_COLOR_BUFFER_BIT);
}
}
glFinish();
if (1)
PerfSwapBuffers();
}
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate;
double pixelsPerDraw = WinWidth * WinHeight;
Ortho();
/* simple fill */
rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw;
perf_printf(" Simple fill: %s pixels/second\n",
PerfHumanFloat(rate));
/* blended fill */
glEnable(GL_BLEND);
rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw;
glDisable(GL_BLEND);
perf_printf(" Blended fill: %s pixels/second\n",
PerfHumanFloat(rate));
/* textured fill */
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw;
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
perf_printf(" Textured fill: %s pixels/second\n",
PerfHumanFloat(rate));
/* shader1 fill */
glUseProgram(ShaderProg1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw;
glUseProgram(0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
perf_printf(" Shader1 fill: %s pixels/second\n",
PerfHumanFloat(rate));
/* shader2 fill */
glUseProgram(ShaderProg2);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
rate = PerfMeasureRate(DrawQuad) * pixelsPerDraw;
glUseProgram(0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
perf_printf(" Shader2 fill: %s pixels/second\n",
PerfHumanFloat(rate));
exit(0);
}

136
progs/perf/genmipmap.c Normal file
View file

@ -0,0 +1,136 @@
/*
* Copyright (C) 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, 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
* VMWARE 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.
*/
/**
* Measure glGenerateMipmap() speed.
*
* Brian Paul
* 24 Sep 2009
*/
#include <string.h>
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
static GLboolean DrawPoint = GL_TRUE;
static GLuint VBO;
static GLuint TexObj = 0;
static GLint BaseLevel, MaxLevel;
struct vertex
{
GLfloat x, y, s, t;
};
static const struct vertex vertices[1] = {
{ 0.0, 0.0, 0.5, 0.5 },
};
#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO w/ vertex data */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(x));
glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), VOFFSET(s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glGenTextures(1, &TexObj);
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnable(GL_TEXTURE_2D);
}
static void
GenMipmap(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
GLubyte texel[4];
texel[0] = texel[1] = texel[2] = texel[3] = i & 0xff;
/* dirty the base image */
glTexSubImage2D(GL_TEXTURE_2D, BaseLevel,
0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, texel);
glGenerateMipmap(GL_TEXTURE_2D);
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
/** Called from test harness/main */
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
PerfDraw(void)
{
const GLint NumLevels = 12;
const GLint TexWidth = 2048, TexHeight = 2048;
GLubyte *img;
double rate;
/* Make 2K x 2K texture */
img = (GLubyte *) malloc(TexWidth * TexHeight * 4);
memset(img, 128, TexWidth * TexHeight * 4);
glTexImage2D(GL_TEXTURE_2D, 0,
GL_RGBA, TexWidth, TexHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, img);
free(img);
perf_printf("Texture level[0] size: %d x %d, %d levels\n",
TexWidth, TexHeight, NumLevels);
/* loop over base levels 0, 2, 4 */
for (BaseLevel = 0; BaseLevel <= 4; BaseLevel += 2) {
/* loop over max level */
for (MaxLevel = NumLevels; MaxLevel > BaseLevel; MaxLevel--) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, BaseLevel);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel);
rate = PerfMeasureRate(GenMipmap);
perf_printf(" glGenerateMipmap(levels %d..%d): %.2f gens/sec\n",
BaseLevel + 1, MaxLevel, rate);
}
}
exit(0);
}

View file

@ -26,13 +26,13 @@
*/
#include <stdio.h>
#include "glmain.h"
#include <GL/glut.h>
static int Win;
static GLfloat Xrot = 0, Yrot = 0, Zrot = 0;
static GLboolean Anim = GL_FALSE;
/** Return time in seconds */
@ -50,13 +50,133 @@ PerfSwapBuffers(void)
}
/** make simple checkerboard texture object */
GLuint
PerfCheckerTexture(GLsizei width, GLsizei height)
{
const GLenum filter = GL_NEAREST;
GLubyte *img = (GLubyte *) malloc(width * height * 4);
GLint i, j, k;
GLuint obj;
k = 0;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
GLubyte color;
if (((i / 8) ^ (j / 8)) & 1) {
color = 0xff;
}
else {
color = 0x0;
}
img[k++] = color;
img[k++] = color;
img[k++] = color;
img[k++] = color;
}
}
glGenTextures(1, &obj);
glBindTexture(GL_TEXTURE_2D, obj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, img);
free(img);
return obj;
}
static GLuint
CompileShader(GLenum type, const char *shader)
{
GLuint sh;
GLint stat;
sh = glCreateShader(type);
glShaderSource(sh, 1, (const GLchar **) &shader, NULL);
glCompileShader(sh);
glGetShaderiv(sh, GL_COMPILE_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetShaderInfoLog(sh, 1000, &len, log);
fprintf(stderr, "Error: problem compiling shader: %s\n", log);
exit(1);
}
return sh;
}
/** Make shader program from given vert/frag shader text */
GLuint
PerfShaderProgram(const char *vertShader, const char *fragShader)
{
GLuint prog;
GLint stat;
{
const char *version = (const char *) glGetString(GL_VERSION);
if ((version[0] != '2' &&
version[0] != '3') || version[1] != '.') {
fprintf(stderr, "Error: GL version 2.x or better required\n");
exit(1);
}
}
prog = glCreateProgram();
if (vertShader) {
GLuint vs = CompileShader(GL_VERTEX_SHADER, vertShader);
glAttachShader(prog, vs);
}
if (fragShader) {
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragShader);
glAttachShader(prog, fs);
}
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetProgramInfoLog(prog, 1000, &len, log);
fprintf(stderr, "Shader link error:\n%s\n", log);
exit(1);
}
return prog;
}
int
PerfReshapeWindow( unsigned w, unsigned h )
{
if (glutGet(GLUT_SCREEN_WIDTH) < w ||
glutGet(GLUT_SCREEN_HEIGHT) < h)
return 0;
glutReshapeWindow( w, h );
glutPostRedisplay();
return 1;
}
GLboolean
PerfExtensionSupported(const char *ext)
{
return glutExtensionSupported(ext);
}
static void
Idle(void)
{
Xrot += 3.0;
Yrot += 4.0;
Zrot += 2.0;
glutPostRedisplay();
PerfNextRound();
}
@ -90,13 +210,6 @@ Key(unsigned char key, int x, int y)
(void) x;
(void) y;
switch (key) {
case 'a':
Anim = !Anim;
if (Anim)
glutIdleFunc(Idle);
else
glutIdleFunc(NULL);
break;
case 'z':
Zrot -= step;
break;
@ -141,15 +254,14 @@ main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(WinWidth, WinHeight);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
Win = glutCreateWindow(argv[0]);
glewInit();
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(SpecialKey);
glutDisplayFunc(Draw);
if (Anim)
glutIdleFunc(Idle);
glutIdleFunc(Idle);
PerfInit();
glutMainLoop();
return 0;

View file

@ -40,12 +40,27 @@ PerfGetTime(void);
extern void
PerfSwapBuffers(void);
extern GLuint
PerfCheckerTexture(GLsizei width, GLsizei height);
extern GLuint
PerfShaderProgram(const char *vertShader, const char *fragShader);
extern int
PerfReshapeWindow( unsigned w, unsigned h );
extern GLboolean
PerfExtensionSupported(const char *ext);
/** Test programs must implement these functions **/
extern void
PerfInit(void);
extern void
PerfNextRound(void);
extern void
PerfDraw(void);

169
progs/perf/readpixels.c Normal file
View file

@ -0,0 +1,169 @@
/*
* Copyright (C) 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, 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
* VMWARE 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.
*/
/**
* Measure glReadPixels speed.
* XXX also read into a PBO?
* XXX also read from FBOs?
*
* Brian Paul
* 23 Sep 2009
*/
#include <string.h>
#include <assert.h>
#include "glmain.h"
#include "common.h"
int WinWidth = 1000, WinHeight = 1000;
static GLuint VBO;
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean BufferSubDataInHalves = GL_TRUE;
static const GLfloat Vertex0[2] = { 0.0, 0.0 };
static GLenum HaveDepthStencil;
static GLenum ReadFormat, ReadType;
static GLint ReadWidth, ReadHeight;
static GLvoid *ReadBuffer;
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(Vertex0), Vertex0, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(Vertex0), (void *) 0);
glEnableClientState(GL_VERTEX_ARRAY);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
HaveDepthStencil = PerfExtensionSupported("GL_EXT_packed_depth_stencil");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
}
static void
ReadPixels(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
/* read from random pos */
GLint x, y;
x = WinWidth - ReadWidth;
y = WinHeight - ReadHeight;
if (x > 0)
x = rand() % x;
if (y > 0)
y = rand() % y;
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
glReadPixels(x, y, ReadWidth, ReadHeight,
ReadFormat, ReadType, ReadBuffer);
}
glFinish();
}
static const GLsizei Sizes[] = {
10,
100,
500,
1000,
0
};
static const struct {
GLenum format;
GLenum type;
const char *name;
GLuint pixel_size;
} DstFormats[] = {
{ GL_RGBA, GL_UNSIGNED_BYTE, "RGBA/ubyte", 4 },
{ GL_BGRA, GL_UNSIGNED_BYTE, "BGRA/ubyte", 4 },
{ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, "RGB/565", 2 },
{ GL_LUMINANCE, GL_UNSIGNED_BYTE, "L/ubyte", 1 },
{ GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, "Z/uint", 4 },
{ GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, "Z+S/uint", 4 },
{ 0, 0, NULL, 0 }
};
/** Called from test harness/main */
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate, mbPerSec;
int fmt, sz;
/* loop over formats */
for (fmt = 0; DstFormats[fmt].format; fmt++) {
ReadFormat = DstFormats[fmt].format;
ReadType = DstFormats[fmt].type;
/* loop over sizes */
for (sz = 0; Sizes[sz]; sz++) {
int imgSize;
ReadWidth = ReadHeight = Sizes[sz];
imgSize = ReadWidth * ReadHeight * DstFormats[fmt].pixel_size;
ReadBuffer = malloc(imgSize);
if (ReadFormat == GL_DEPTH_STENCIL_EXT && !HaveDepthStencil) {
rate = 0.0;
mbPerSec = 0.0;
}
else {
rate = PerfMeasureRate(ReadPixels);
mbPerSec = rate * imgSize / (1024.0 * 1024.0);
}
perf_printf("glReadPixels(%d x %d, %s): %.1f images/sec, %.1f Mpixels/sec\n",
ReadWidth, ReadHeight,
DstFormats[fmt].name, rate, mbPerSec);
free(ReadBuffer);
}
}
exit(0);
}

161
progs/perf/swapbuffers.c Normal file
View file

@ -0,0 +1,161 @@
/*
* Copyright (C) 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, 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
* VMWARE 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.
*/
/**
* Measure SwapBuffers.
*
* Keith Whitwell
* 22 Sep 2009
*/
#include "glmain.h"
#include "common.h"
int WinWidth = 100, WinHeight = 100;
int real_WinWidth, real_WinHeight; /* don't know whats going on here */
static GLuint VBO;
struct vertex
{
GLfloat x, y;
};
static const struct vertex vertices[4] = {
{ -1.0, -1.0 },
{ 1.0, -1.0 },
{ 1.0, 1.0 },
{ -1.0, 1.0 }
};
/** Called from test harness/main */
void
PerfInit(void)
{
/* setup VBO w/ vertex data */
glGenBuffersARB(1, &VBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,
sizeof(vertices), vertices, GL_STATIC_DRAW_ARB);
glVertexPointer(2, GL_FLOAT, sizeof(struct vertex), (void *) 0);
glEnableClientState(GL_VERTEX_ARRAY);
/* misc GL state */
glAlphaFunc(GL_ALWAYS, 0.0);
}
static void
SwapNaked(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
PerfSwapBuffers();
}
}
static void
SwapClear(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glClear(GL_COLOR_BUFFER_BIT);
PerfSwapBuffers();
}
}
static void
SwapClearPoint(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, 4);
PerfSwapBuffers();
}
}
static const struct {
unsigned w;
unsigned h;
} sizes[] = {
{ 320, 240 },
{ 640, 480 },
{ 1024, 768 },
{ 1200, 1024 },
{ 1600, 1200 }
};
void
PerfNextRound(void)
{
static unsigned i;
if (i < sizeof(sizes) / sizeof(sizes[0]) &&
PerfReshapeWindow( sizes[i].w, sizes[i].h ))
{
perf_printf("Reshape %dx%d\n", sizes[i].w, sizes[i].h);
real_WinWidth = sizes[i].w;
real_WinHeight = sizes[i].h;
i++;
}
else {
exit(0);
}
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate0;
rate0 = PerfMeasureRate(SwapNaked);
perf_printf(" Swapbuffers %dx%d: %s swaps/second",
real_WinWidth, real_WinHeight,
PerfHumanFloat(rate0));
perf_printf(" %s pixels/second\n",
PerfHumanFloat(rate0 * real_WinWidth * real_WinHeight));
rate0 = PerfMeasureRate(SwapClear);
perf_printf(" Swap/Clear %dx%d: %s swaps/second",
real_WinWidth, real_WinHeight,
PerfHumanFloat(rate0));
perf_printf(" %s pixels/second\n",
PerfHumanFloat(rate0 * real_WinWidth * real_WinHeight));
rate0 = PerfMeasureRate(SwapClearPoint);
perf_printf(" Swap/Clear/Draw %dx%d: %s swaps/second",
real_WinWidth, real_WinHeight,
PerfHumanFloat(rate0));
perf_printf(" %s pixels/second\n",
PerfHumanFloat(rate0 * real_WinWidth * real_WinHeight));
}

View file

@ -20,7 +20,7 @@
*/
/**
* Measure glTexSubImage2D rate
* Measure glTex[Sub]Image2D() and glGetTexImage() rate
*
* Brian Paul
* 16 Sep 2009
@ -36,10 +36,28 @@ static GLuint VBO;
static GLuint TexObj = 0;
static GLubyte *TexImage = NULL;
static GLsizei TexSize;
static GLenum TexSrcFormat, TexSrcType;
static GLenum TexIntFormat, TexSrcFormat, TexSrcType;
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean TexSubImage4 = GL_TRUE;
static const GLboolean TexSubImage4 = GL_FALSE;
enum {
MODE_CREATE_TEXIMAGE,
MODE_TEXIMAGE,
MODE_TEXSUBIMAGE,
MODE_GETTEXIMAGE,
MODE_COUNT
};
static const char *mode_name[MODE_COUNT] =
{
"Create_TexImage",
"TexImage",
"TexSubImage",
"GetTexImage"
};
struct vertex
{
@ -50,11 +68,8 @@ static const struct vertex vertices[1] = {
{ 0.0, 0.0, 0.5, 0.5 },
};
#if 0
#define VOFFSET(F) ((void *) offsetof(struct vertex, F))
#else
#define VOFFSET(F) ((void *) &((struct vertex *)NULL)->F)
#endif
/** Called from test harness/main */
void
@ -79,6 +94,32 @@ PerfInit(void)
}
static void
CreateUploadTexImage2D(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
if (TexObj)
glDeleteTextures(1, &TexObj);
glGenTextures(1, &TexObj);
glBindTexture(GL_TEXTURE_2D, TexObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, TexImage);
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
}
glFinish();
}
static void
UploadTexImage2D(unsigned count)
{
@ -89,7 +130,7 @@ UploadTexImage2D(unsigned count)
* in Mesa but may be optimized in other drivers. Note sure how
* much difference that might make.
*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, TexImage);
if (DrawPoint)
@ -132,8 +173,8 @@ UploadTexSubImage2D(unsigned count)
TexSrcFormat, TexSrcType, TexImage);
/* reset the unpacking state */
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
else {
/* replace whole texture image at once */
@ -148,17 +189,43 @@ UploadTexSubImage2D(unsigned count)
}
static void
GetTexImage2D(unsigned count)
{
unsigned i;
GLubyte *buf = (GLubyte *) malloc(TexSize * TexSize * 4);
for (i = 0; i < count; i++) {
glGetTexImage(GL_TEXTURE_2D, 0,
TexSrcFormat, TexSrcType, buf);
}
glFinish();
free(buf);
}
/* XXX any other formats to measure? */
static const struct {
GLenum format, type;
GLenum internal_format;
const char *name;
GLuint texel_size;
GLboolean full_test;
} SrcFormats[] = {
{ GL_RGBA, GL_UNSIGNED_BYTE, "GL_RGBA/GLubyte" },
{ GL_BGRA, GL_UNSIGNED_BYTE, "GL_BGRA/GLubyte" },
{ 0, 0, NULL }
{ GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA, "RGBA/ubyte", 4, GL_TRUE },
{ GL_RGB, GL_UNSIGNED_BYTE, GL_RGB, "RGB/ubyte", 3, GL_FALSE },
{ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB, "RGB/565", 2, GL_FALSE },
{ GL_BGRA, GL_UNSIGNED_BYTE, GL_RGBA, "BGRA/ubyte", 4, GL_FALSE },
{ GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE, "L/ubyte", 1, GL_FALSE },
{ 0, 0, 0, NULL, 0, 0 }
};
/** Called from test harness/main */
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
@ -166,46 +233,97 @@ PerfDraw(void)
{
GLint maxSize;
double rate;
GLint fmt, subImage;
GLint fmt, mode;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
/* loop over source data formats */
for (fmt = 0; SrcFormats[fmt].format; fmt++) {
TexIntFormat = SrcFormats[fmt].internal_format;
TexSrcFormat = SrcFormats[fmt].format;
TexSrcType = SrcFormats[fmt].type;
/* loop over glTexImage, glTexSubImage */
for (subImage = 0; subImage < 2; subImage++) {
for (mode = 0; mode < MODE_COUNT; mode++) {
GLuint minsz, maxsz;
/* loop over texture sizes */
for (TexSize = 16; TexSize <= maxSize; TexSize *= 2) {
GLint bytesPerImage;
if (SrcFormats[fmt].full_test) {
minsz = 16;
maxsz = 4096;
}
else {
minsz = maxsz = 256;
if (mode == MODE_CREATE_TEXIMAGE)
continue;
}
/* loop over a defined range of texture sizes, test only the
* ones which are legal for this driver.
*/
for (TexSize = minsz; TexSize <= maxsz; TexSize *= 4) {
double mbPerSec;
bytesPerImage = TexSize * TexSize * 4;
TexImage = malloc(bytesPerImage);
if (TexSize <= maxSize) {
GLint bytesPerImage;
bytesPerImage = TexSize * TexSize * SrcFormats[fmt].texel_size;
TexImage = malloc(bytesPerImage);
switch (mode) {
case MODE_TEXIMAGE:
rate = PerfMeasureRate(UploadTexImage2D);
break;
case MODE_CREATE_TEXIMAGE:
rate = PerfMeasureRate(CreateUploadTexImage2D);
break;
case MODE_TEXSUBIMAGE:
/* create initial, empty texture */
glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, NULL);
rate = PerfMeasureRate(UploadTexSubImage2D);
break;
case MODE_GETTEXIMAGE:
glTexImage2D(GL_TEXTURE_2D, 0, TexIntFormat,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, TexImage);
rate = PerfMeasureRate(GetTexImage2D);
break;
default:
exit(1);
}
mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
free(TexImage);
{
unsigned err;
err = glGetError();
if (err) {
perf_printf("non-zero glGetError() %d\n", err);
exit(1);
}
}
if (subImage) {
/* create initial, empty texture */
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
TexSize, TexSize, 0,
TexSrcFormat, TexSrcType, NULL);
rate = PerfMeasureRate(UploadTexSubImage2D);
}
else {
rate = PerfMeasureRate(UploadTexImage2D);
rate = 0;
mbPerSec = 0;
}
mbPerSec = rate * bytesPerImage / (1024.0 * 1024.0);
perf_printf(" glTex%sImage2D(%s %d x %d): "
perf_printf(" %s(%s %d x %d): "
"%.1f images/sec, %.1f MB/sec\n",
(subImage ? "Sub" : ""),
mode_name[mode],
SrcFormats[fmt].name, TexSize, TexSize, rate, mbPerSec);
free(TexImage);
}
if (SrcFormats[fmt].full_test)
perf_printf("\n");
}
}

View file

@ -31,13 +31,17 @@
#include "glmain.h"
#include "common.h"
/* Copy data out of a large array to avoid caching effects:
*/
#define DATA_SIZE (16*1024*1024)
int WinWidth = 100, WinHeight = 100;
static GLuint VBO;
static GLsizei VBOSize = 0;
static GLubyte *VBOData = NULL;
static GLsizei SubSize = 0;
static GLubyte *VBOData = NULL; /* array[DATA_SIZE] */
static const GLboolean DrawPoint = GL_TRUE;
static const GLboolean BufferSubDataInHalves = GL_TRUE;
@ -61,11 +65,23 @@ static void
UploadVBO(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
unsigned total = 0;
unsigned src = 0;
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
for (i = 0; i < count; i++) {
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData + src, GL_STREAM_DRAW_ARB);
glDrawArrays(GL_POINTS, 0, 1);
/* Throw in an occasional flush to work around a driver crash:
*/
total += VBOSize;
if (total >= 16*1024*1024) {
glFlush();
total = 0;
}
src += VBOSize;
src %= DATA_SIZE;
}
glFinish();
}
@ -75,18 +91,69 @@ static void
UploadSubVBO(unsigned count)
{
unsigned i;
unsigned src = 0;
for (i = 0; i < count; i++) {
if (BufferSubDataInHalves) {
GLsizei half = VBOSize / 2;
glBufferSubDataARB(GL_ARRAY_BUFFER, 0, half, VBOData);
glBufferSubDataARB(GL_ARRAY_BUFFER, half, half, VBOData + half);
}
else {
glBufferSubDataARB(GL_ARRAY_BUFFER, 0, VBOSize, VBOData);
unsigned offset = (i * SubSize) % VBOSize;
glBufferSubDataARB(GL_ARRAY_BUFFER, offset, SubSize, VBOData + src);
if (DrawPoint) {
glDrawArrays(GL_POINTS, offset / sizeof(Vertex0), 1);
}
if (DrawPoint)
glDrawArrays(GL_POINTS, 0, 1);
src += SubSize;
src %= DATA_SIZE;
}
glFinish();
}
/* Do multiple small SubData uploads, then call DrawArrays. This may be a
* fairer comparison to back-to-back BufferData calls:
*/
static void
BatchUploadSubVBO(unsigned count)
{
unsigned i = 0, j;
unsigned period = VBOSize / SubSize;
unsigned src = 0;
while (i < count) {
for (j = 0; j < period && i < count; j++, i++) {
unsigned offset = j * SubSize;
glBufferSubDataARB(GL_ARRAY_BUFFER, offset, SubSize, VBOData + src);
}
glDrawArrays(GL_POINTS, 0, 1);
src += SubSize;
src %= DATA_SIZE;
}
glFinish();
}
/**
* Test the sequence:
* create/load VBO
* draw
* destroy VBO
*/
static void
CreateDrawDestroyVBO(unsigned count)
{
unsigned i;
for (i = 0; i < count; i++) {
GLuint vbo;
/* create/load */
glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
/* draw */
glVertexPointer(2, GL_FLOAT, sizeof(Vertex0), (void *) 0);
glDrawArrays(GL_POINTS, 0, 1);
/* destroy */
glDeleteBuffersARB(1, &vbo);
}
glFinish();
}
@ -102,36 +169,77 @@ static const GLsizei Sizes[] = {
0 /* end of list */
};
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
PerfDraw(void)
{
double rate, mbPerSec;
int sub, sz;
int i, sz;
/* loop over whole/sub buffer upload */
for (sub = 0; sub < 2; sub++) {
/* Load VBOData buffer with duplicated Vertex0.
*/
VBOData = calloc(DATA_SIZE, 1);
/* loop over VBO sizes */
for (sz = 0; Sizes[sz]; sz++) {
VBOSize = Sizes[sz];
for (i = 0; i < DATA_SIZE / sizeof(Vertex0); i++) {
memcpy(VBOData + i * sizeof(Vertex0),
Vertex0,
sizeof(Vertex0));
}
VBOData = malloc(VBOSize);
memcpy(VBOData, Vertex0, sizeof(Vertex0));
/* glBufferDataARB()
*/
for (sz = 0; Sizes[sz]; sz++) {
SubSize = VBOSize = Sizes[sz];
rate = PerfMeasureRate(UploadVBO);
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
perf_printf(" glBufferDataARB(size = %d): %.1f MB/sec\n",
VBOSize, mbPerSec);
}
if (sub)
rate = PerfMeasureRate(UploadSubVBO);
else
rate = PerfMeasureRate(UploadVBO);
/* glBufferSubDataARB()
*/
for (sz = 0; Sizes[sz]; sz++) {
SubSize = VBOSize = Sizes[sz];
rate = PerfMeasureRate(UploadSubVBO);
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
perf_printf(" glBufferSubDataARB(size = %d): %.1f MB/sec\n",
VBOSize, mbPerSec);
}
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
/* Batch upload
*/
VBOSize = 1024 * 1024;
glBufferDataARB(GL_ARRAY_BUFFER, VBOSize, VBOData, GL_STREAM_DRAW_ARB);
perf_printf(" glBuffer%sDataARB(size = %d): %.1f MB/sec\n",
(sub ? "Sub" : ""), VBOSize, mbPerSec);
for (sz = 0; Sizes[sz] < VBOSize; sz++) {
SubSize = Sizes[sz];
rate = PerfMeasureRate(UploadSubVBO);
mbPerSec = rate * SubSize / (1024.0 * 1024.0);
perf_printf(" glBufferSubDataARB(size = %d, VBOSize = %d): %.1f MB/sec\n",
SubSize, VBOSize, mbPerSec);
}
free(VBOData);
}
for (sz = 0; Sizes[sz] < VBOSize; sz++) {
SubSize = Sizes[sz];
rate = PerfMeasureRate(BatchUploadSubVBO);
mbPerSec = rate * SubSize / (1024.0 * 1024.0);
perf_printf(" glBufferSubDataARB(size = %d, VBOSize = %d), batched: %.1f MB/sec\n",
SubSize, VBOSize, mbPerSec);
}
/* Create/Draw/Destroy
*/
for (sz = 0; Sizes[sz]; sz++) {
SubSize = VBOSize = Sizes[sz];
rate = PerfMeasureRate(CreateDrawDestroyVBO);
mbPerSec = rate * VBOSize / (1024.0 * 1024.0);
perf_printf(" VBO Create/Draw/Destroy(size = %d): %.1f MB/sec, %.1f draws/sec\n",
VBOSize, mbPerSec, rate);
}
exit(0);

View file

@ -228,6 +228,11 @@ DrawRangeElementsBO(unsigned count)
PerfSwapBuffers();
}
void
PerfNextRound(void)
{
}
/** Called from test harness/main */
void
@ -241,31 +246,31 @@ PerfDraw(void)
rate = PerfMeasureRate(DrawImmediate);
rate *= NumVerts;
perf_printf(" Immediate mode: %.1f verts/sec\n", rate);
perf_printf(" Immediate mode: %s verts/sec\n", PerfHumanFloat(rate));
rate = PerfMeasureRate(DrawArraysMem);
rate *= NumVerts;
perf_printf(" glDrawArrays: %.1f verts/sec\n", rate);
perf_printf(" glDrawArrays: %s verts/sec\n", PerfHumanFloat(rate));
rate = PerfMeasureRate(DrawArraysVBO);
rate *= NumVerts;
perf_printf(" VBO glDrawArrays: %.1f verts/sec\n", rate);
perf_printf(" VBO glDrawArrays: %s verts/sec\n", PerfHumanFloat(rate));
rate = PerfMeasureRate(DrawElementsMem);
rate *= NumVerts;
perf_printf(" glDrawElements: %.1f verts/sec\n", rate);
perf_printf(" glDrawElements: %s verts/sec\n", PerfHumanFloat(rate));
rate = PerfMeasureRate(DrawElementsBO);
rate *= NumVerts;
perf_printf(" VBO glDrawElements: %.1f verts/sec\n", rate);
perf_printf(" VBO glDrawElements: %s verts/sec\n", PerfHumanFloat(rate));
rate = PerfMeasureRate(DrawRangeElementsMem);
rate *= NumVerts;
perf_printf(" glDrawRangeElements: %.1f verts/sec\n", rate);
perf_printf(" glDrawRangeElements: %s verts/sec\n", PerfHumanFloat(rate));
rate = PerfMeasureRate(DrawRangeElementsBO);
rate *= NumVerts;
perf_printf(" VBO glDrawRangeElements: %.1f verts/sec\n", rate);
perf_printf(" VBO glDrawRangeElements: %s verts/sec\n", PerfHumanFloat(rate));
exit(0);
}

View file

@ -45,4 +45,4 @@ $(OBJECTS): %.o: %.c
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $(PROG_DEFINES) $< -o $@
$(PROGS): %: %.o
$(CC) $(LDFLAGS) $< $(LINKS) -o $@
$(CC) $(LDFLAGS) $< $(LINKS) -lm -o $@

View file

@ -77,15 +77,16 @@ InitValues(void)
}
static void MakeImage(int level, int width, int height, const GLubyte color[4])
static void
MakeImage(int level, int width, int height, const GLubyte color[4])
{
const int makeStripes = 0;
GLubyte img[512*512*3];
GLubyte img[512 * 512 * 3];
int i, j;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
int k = (i * width + j) * 3;
int p = (i/8) & makeStripes;
int p = (i / 8) & makeStripes;
if (p == 0) {
img[k + 0] = color[0];
img[k + 1] = color[1];
@ -104,7 +105,8 @@ static void MakeImage(int level, int width, int height, const GLubyte color[4])
}
static void makeImages(int image)
static void
makeImages(int image)
{
#define WIDTH 512
#define HEIGHT 512
@ -121,19 +123,20 @@ static void makeImages(int image)
if (width != WIDTH || height != HEIGHT) {
GLubyte *newImage = malloc(WIDTH * HEIGHT * 4);
gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image,
WIDTH, HEIGHT, GL_UNSIGNED_BYTE, newImage);
WIDTH, HEIGHT, GL_UNSIGNED_BYTE, newImage);
free(image);
image = newImage;
}
printf("Using GL_SGIS_generate_mipmap\n");
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, format, WIDTH, HEIGHT, 0,
format, GL_UNSIGNED_BYTE, image);
format, GL_UNSIGNED_BYTE, image);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
free(image);
/* make sure mipmap was really generated correctly */
width = WIDTH; height = HEIGHT;
width = WIDTH;
height = HEIGHT;
for (i = 0; i < 10; i++) {
GLint w, h;
glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w);
@ -142,18 +145,19 @@ static void makeImages(int image)
width /= 2;
height /= 2;
}
} else {
}
else {
static const GLubyte colors[10][3] = {
{128, 128, 128 },
{ 0, 255, 255 },
{ 255, 255, 0 },
{ 255, 0, 255 },
{ 255, 0, 0 },
{ 0, 255, 0 },
{ 0, 0, 255 },
{ 0, 255, 255 },
{ 255, 255, 0 },
{ 255, 255, 255 }
{128, 128, 128},
{0, 255, 255},
{255, 255, 0},
{255, 0, 255},
{255, 0, 0},
{0, 255, 0},
{0, 0, 255},
{0, 255, 255},
{255, 255, 0},
{255, 255, 255}
};
int i, sz = 512;
@ -165,7 +169,8 @@ static void makeImages(int image)
}
}
static void myinit(void)
static void
myinit(void)
{
InitValues();
@ -191,14 +196,16 @@ static void myinit(void)
glEnable(GL_TEXTURE_2D);
}
static void display(void)
static void
display(void)
{
GLfloat tcm = 1.0;
glBindTexture(GL_TEXTURE_2D, texCurrent);
printf("BASE_LEVEL=%d MAX_LEVEL=%d MIN_LOD=%.2g MAX_LOD=%.2g Bias=%.2g Filter=%s\n",
BaseLevel, MaxLevel, MinLod, MaxLod, LodBias,
NearestFilter ? "NEAREST" : "LINEAR");
printf
("BASE_LEVEL=%d MAX_LEVEL=%d MIN_LOD=%.2g MAX_LOD=%.2g Bias=%.2g Filter=%s\n",
BaseLevel, MaxLevel, MinLod, MaxLod, LodBias,
NearestFilter ? "NEAREST" : "LINEAR");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, BaseLevel);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel);
@ -208,103 +215,44 @@ static void display(void)
if (NearestFilter) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST_MIPMAP_NEAREST);
GL_NEAREST_MIPMAP_NEAREST);
}
else {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
GL_LINEAR_MIPMAP_LINEAR);
}
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, LodBias);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0);
glTexCoord2f(0.0, tcm); glVertex3f(-2.0, 1.0, 0.0);
glTexCoord2f(tcm * 3000.0, tcm); glVertex3f(3000.0, 1.0, -6000.0);
glTexCoord2f(tcm * 3000.0, 0.0); glVertex3f(3000.0, -1.0, -6000.0);
glTexCoord2f(0.0, 0.0);
glVertex3f(-2.0, -1.0, 0.0);
glTexCoord2f(0.0, tcm);
glVertex3f(-2.0, 1.0, 0.0);
glTexCoord2f(tcm * 3000.0, tcm);
glVertex3f(3000.0, 1.0, -6000.0);
glTexCoord2f(tcm * 3000.0, 0.0);
glVertex3f(3000.0, -1.0, -6000.0);
glEnd();
glFlush();
}
static void myReshape(int w, int h)
static void
myReshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, 1.0*(GLfloat)w/(GLfloat)h, 1.0, 30000.0);
gluPerspective(60.0, 1.0 * (GLfloat) w / (GLfloat) h, 1.0, 30000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void
key(unsigned char k, int x, int y)
{
(void) x;
(void) y;
switch (k) {
case 'b':
BaseLevel--;
if (BaseLevel < 0)
BaseLevel = 0;
break;
case 'B':
BaseLevel++;
if (BaseLevel > 10)
BaseLevel = 10;
break;
case 'm':
MaxLevel--;
if (MaxLevel < 0)
MaxLevel = 0;
break;
case 'M':
MaxLevel++;
if (MaxLevel > 10)
MaxLevel = 10;
break;
case 'l':
LodBias -= 0.25;
break;
case 'L':
LodBias += 0.25;
break;
case 'n':
MinLod -= 0.25;
break;
case 'N':
MinLod += 0.25;
break;
case 'x':
MaxLod -= 0.25;
break;
case 'X':
MaxLod += 0.25;
break;
case 'f':
NearestFilter = !NearestFilter;
break;
case 't':
if (texCurrent == texColor)
texCurrent = texImage;
else
texCurrent = texColor;
break;
case ' ':
InitValues();
break;
case 27: /* Escape */
exit(0);
break;
default:
return;
}
glutPostRedisplay();
}
static void usage(void)
usage(void)
{
printf("usage:\n");
printf(" b/B decrease/increase GL_TEXTURE_BASE_LEVEL\n");
@ -317,19 +265,88 @@ static void usage(void)
printf(" SPACE reset values\n");
}
int main(int argc, char** argv)
static void
key(unsigned char k, int x, int y)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (600, 600);
glutCreateWindow (argv[0]);
glewInit();
myinit();
glutReshapeFunc (myReshape);
glutDisplayFunc(display);
glutKeyboardFunc(key);
usage();
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
(void) x;
(void) y;
switch (k) {
case 'b':
BaseLevel--;
if (BaseLevel < 0)
BaseLevel = 0;
break;
case 'B':
BaseLevel++;
if (BaseLevel > 10)
BaseLevel = 10;
break;
case 'm':
MaxLevel--;
if (MaxLevel < 0)
MaxLevel = 0;
break;
case 'M':
MaxLevel++;
if (MaxLevel > 10)
MaxLevel = 10;
break;
case 'l':
LodBias -= 0.25;
break;
case 'L':
LodBias += 0.25;
break;
case 'n':
MinLod -= 0.25;
break;
case 'N':
MinLod += 0.25;
break;
case 'x':
MaxLod -= 0.25;
break;
case 'X':
MaxLod += 0.25;
break;
case 'f':
NearestFilter = !NearestFilter;
break;
case 't':
if (texCurrent == texColor)
texCurrent = texImage;
else
texCurrent = texColor;
break;
case ' ':
InitValues();
/* fall-through */
case 'u':
usage();
break;
case 27: /* Escape */
exit(0);
break;
default:
return;
}
glutPostRedisplay();
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutCreateWindow(argv[0]);
glewInit();
myinit();
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutKeyboardFunc(key);
usage();
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}

View file

@ -177,7 +177,7 @@ def generate(env):
# default in recent gcc versions
env.AppendUnique(CFLAGS = ['-gstabs'])
env.AppendUnique(LIBS = ['iberty'])
#env.AppendUnique(LIBS = ['iberty'])
env.AppendUnique(SHLINKFLAGS = ['-Wl,--enable-stdcall-fixup'])
#env.AppendUnique(SHLINKFLAGS = ['-Wl,--kill-at'])

View file

@ -177,7 +177,7 @@ demoCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, Nat
}
}
if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) {
if (GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) == 0) {
_eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface");
return NULL;
}

View file

@ -48,6 +48,7 @@
#include "glapi/glapi.h" /* for glapi functions */
#include "eglconfig.h"
#include "eglconfigutil.h"
#include "eglcontext.h"
#include "egldisplay.h"
#include "egldriver.h"
@ -104,6 +105,7 @@ struct xdri_egl_config
_EGLConfig Base; /**< base class */
const __GLcontextModes *mode; /**< corresponding GLX mode */
EGLint window_render_buffer;
};
@ -162,46 +164,76 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
}
static EGLBoolean
convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m)
{
static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
EGL_OPENGL_ES2_BIT |
EGL_OPENVG_BIT |
EGL_OPENGL_BIT);
EGLint val;
_eglInitConfig(conf, id);
if (!_eglConfigFromContextModesRec(conf, m, all_apis, all_apis))
return EGL_FALSE;
if (m->doubleBufferMode) {
/* pixmap and pbuffer surfaces are always single-buffered */
val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
val &= ~(EGL_PIXMAP_BIT | EGL_PBUFFER_BIT);
SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, val);
}
else {
/* EGL requires OpenGL ES context to be double-buffered */
val = GET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE);
val &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, val);
}
/* skip "empty" config */
if (!val)
return EGL_FALSE;
val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
if (!(val & EGL_PBUFFER_BIT)) {
/* bind-to-texture cannot be EGL_TRUE without pbuffer bit */
SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE);
SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE);
}
/* EGL_NATIVE_RENDERABLE is a boolean */
val = GET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE);
if (val != EGL_TRUE)
SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_FALSE);
return _eglValidateConfig(conf, EGL_FALSE);
}
/**
* Produce a set of EGL configs.
*/
static EGLint
create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id)
{
static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
EGL_OPENGL_ES2_BIT |
EGL_OPENVG_BIT |
EGL_OPENGL_BIT);
int id = first_id;
for (; m; m = m->next) {
/* add double buffered visual */
if (m->doubleBufferMode) {
struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config);
struct xdri_egl_config *xdri_conf;
_EGLConfig conf;
EGLint rb;
_eglInitConfig(&config->Base, id++);
if (!convert_config(&conf, id, m))
continue;
SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, m->rgbBits);
SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, m->redBits);
SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, m->greenBits);
SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, m->blueBits);
SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, m->alphaBits);
SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, m->depthBits);
SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, m->stencilBits);
SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, m->samples);
SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, m->sampleBuffers);
SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID);
SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType);
SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
rb = (m->doubleBufferMode) ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER;
/* XXX possibly other things to init... */
/* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
config->mode = m;
_eglAddConfig(disp, &config->Base);
xdri_conf = CALLOC_STRUCT(xdri_egl_config);
if (xdri_conf) {
memcpy(&xdri_conf->Base, &conf, sizeof(conf));
xdri_conf->mode = m;
xdri_conf->window_render_buffer = rb;
_eglAddConfig(disp, &xdri_conf->Base);
id++;
}
}
@ -363,6 +395,9 @@ xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
return NULL;
}
/* the config decides the render buffer for the context */
xdri_ctx->Base.WindowRenderBuffer = xdri_config->window_render_buffer;
xdri_ctx->driContext =
psc->driScreen->createContext(psc,
xdri_config->mode,

File diff suppressed because it is too large Load diff

View file

@ -2,27 +2,93 @@
#define EGLCONFIG_INCLUDED
#include <assert.h>
#include "egltypedefs.h"
#include <GLES/gl.h>
#define MAX_ATTRIBS 128
#define FIRST_ATTRIB EGL_BUFFER_SIZE
#define _EGL_CONFIG_FIRST_ATTRIB EGL_BUFFER_SIZE
#define _EGL_CONFIG_LAST_ATTRIB EGL_CONFORMANT
#define _EGL_CONFIG_NUM_ATTRIBS \
(_EGL_CONFIG_LAST_ATTRIB - _EGL_CONFIG_FIRST_ATTRIB + 1)
#define _EGL_CONFIG_STORAGE_SIZE _EGL_CONFIG_NUM_ATTRIBS
struct _egl_config
{
EGLConfig Handle; /* the public/opaque handle which names this config */
EGLint Attrib[MAX_ATTRIBS];
_EGLDisplay *Display;
EGLint Storage[_EGL_CONFIG_STORAGE_SIZE];
};
#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) \
assert((ATTR) - FIRST_ATTRIB < MAX_ATTRIBS); \
((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL)
#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) _eglSetConfigKey(CONF, ATTR, VAL)
#define GET_CONFIG_ATTRIB(CONF, ATTR) _eglGetConfigKey(CONF, ATTR)
#define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB])
/**
* Given a key, return an index into the storage of the config.
* Return -1 if the key is invalid.
*/
static INLINE EGLint
_eglIndexConfig(const _EGLConfig *conf, EGLint key)
{
(void) conf;
if (key >= _EGL_CONFIG_FIRST_ATTRIB &&
key < _EGL_CONFIG_FIRST_ATTRIB + _EGL_CONFIG_NUM_ATTRIBS)
return key - _EGL_CONFIG_FIRST_ATTRIB;
else
return -1;
}
/**
* Reset all keys in the config to a given value.
*/
static INLINE void
_eglResetConfigKeys(_EGLConfig *conf, EGLint val)
{
EGLint i;
for (i = 0; i < _EGL_CONFIG_NUM_ATTRIBS; i++)
conf->Storage[i] = val;
}
/**
* Update a config for a given key.
*/
static INLINE void
_eglSetConfigKey(_EGLConfig *conf, EGLint key, EGLint val)
{
EGLint idx = _eglIndexConfig(conf, key);
assert(idx >= 0);
conf->Storage[idx] = val;
}
/**
* Return the value for a given key.
*/
static INLINE EGLint
_eglGetConfigKey(const _EGLConfig *conf, EGLint key)
{
EGLint idx = _eglIndexConfig(conf, key);
assert(idx >= 0);
return conf->Storage[idx];
}
/**
* Set a given attribute.
*
* Because _eglGetConfigAttrib is already used as a fallback driver
* function, this function is not considered to have a good name.
* SET_CONFIG_ATTRIB is preferred over this function.
*/
static INLINE void
_eglSetConfigAttrib(_EGLConfig *conf, EGLint attr, EGLint val)
{
SET_CONFIG_ATTRIB(conf, attr, val);
}
extern void
@ -30,19 +96,76 @@ _eglInitConfig(_EGLConfig *config, EGLint id);
extern EGLConfig
_eglGetConfigHandle(_EGLConfig *config);
_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf);
extern _EGLConfig *
_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy);
extern _EGLConfig *
_eglAddConfig(_EGLDisplay *display, _EGLConfig *config);
#ifndef _EGL_SKIP_HANDLE_CHECK
extern EGLBoolean
_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list);
_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy);
#else
static INLINE EGLBoolean
_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
{
_EGLConfig *conf = (_EGLConfig *) config;
return (dpy && conf && conf->Display == dpy);
}
#endif /* _EGL_SKIP_HANDLE_CHECK */
/**
* Lookup a handle to find the linked config.
* Return NULL if the handle has no corresponding linked config.
*/
static INLINE _EGLConfig *
_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy)
{
_EGLConfig *conf = (_EGLConfig *) config;
if (!_eglCheckConfigHandle(config, dpy))
conf = NULL;
return conf;
}
/**
* Return the handle of a linked config, or NULL.
*/
static INLINE EGLConfig
_eglGetConfigHandle(_EGLConfig *conf)
{
return (EGLConfig) ((conf && conf->Display) ? conf : NULL);
}
extern EGLBoolean
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching);
extern EGLBoolean
_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria);
extern EGLBoolean
_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list);
extern EGLint
_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
const _EGLConfig *criteria, EGLBoolean compare_id);
extern void
_eglSortConfigs(const _EGLConfig **configs, EGLint count,
EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
void *),
void *priv_data);
extern EGLBoolean
@ -57,8 +180,4 @@ extern EGLBoolean
_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
extern void
_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val);
#endif /* EGLCONFIG_INCLUDED */

View file

@ -52,6 +52,78 @@ _eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
}
/**
* Convert a __GLcontextModes object to an _EGLConfig.
*/
EGLBoolean
_eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m,
EGLint conformant, EGLint renderable_type)
{
EGLint config_caveat, surface_type;
/* must be RGBA */
if (!m->rgbMode || !(m->renderType & GLX_RGBA_BIT))
return EGL_FALSE;
config_caveat = EGL_NONE;
if (m->visualRating == GLX_SLOW_CONFIG)
config_caveat = EGL_SLOW_CONFIG;
if (m->visualRating == GLX_NON_CONFORMANT_CONFIG)
conformant &= ~EGL_OPENGL_BIT;
if (!(conformant & EGL_OPENGL_ES_BIT))
config_caveat = EGL_NON_CONFORMANT_CONFIG;
surface_type = 0;
if (m->drawableType & GLX_WINDOW_BIT)
surface_type |= EGL_WINDOW_BIT;
if (m->drawableType & GLX_PIXMAP_BIT)
surface_type |= EGL_PIXMAP_BIT;
if (m->drawableType & GLX_PBUFFER_BIT)
surface_type |= EGL_PBUFFER_BIT;
SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, m->rgbBits);
SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, m->redBits);
SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, m->greenBits);
SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, m->blueBits);
SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, m->alphaBits);
SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, m->bindToTextureRgb);
SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, m->bindToTextureRgba);
SET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, config_caveat);
SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, conformant);
SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, m->depthBits);
SET_CONFIG_ATTRIB(conf, EGL_LEVEL, m->level);
SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, m->maxPbufferWidth);
SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, m->maxPbufferHeight);
SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, m->maxPbufferPixels);
SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, m->xRenderable);
SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, m->visualID);
SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, m->visualType);
SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, renderable_type);
SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, m->sampleBuffers);
SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, m->samples);
SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, m->stencilBits);
SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
/* what to do with GLX_TRANSPARENT_INDEX? */
if (m->transparentPixel == GLX_TRANSPARENT_RGB) {
SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB);
SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, m->transparentRed);
SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, m->transparentGreen);
SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, m->transparentBlue);
}
else {
SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_NONE);
}
return EGL_TRUE;
}
/**
* Creates a set of \c _EGLConfigs that a driver will expose.

View file

@ -1,18 +1,21 @@
#ifndef EGLCONFIGUTIL_INCLUDED
#define EGLCONFIGUTIL_INCLUDED
#include "eglconfig.h"
#include "GLES/gl.h"
#include "GL/internal/glcore.h"
#if (!defined(WIN32) && !defined(_WIN32_WCE))
#include "stdint.h"
#endif
#include "eglconfig.h"
extern void
_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
extern EGLBoolean
_eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m,
EGLint conformant, EGLint renderable_type);
extern EGLBoolean
_eglFillInConfigs( _EGLConfig *configs,
EGLenum fb_format, EGLenum fb_type,

View file

@ -45,6 +45,7 @@ _eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
ctx->DrawSurface = EGL_NO_SURFACE;
ctx->ReadSurface = EGL_NO_SURFACE;
ctx->ClientAPI = api;
ctx->WindowRenderBuffer = EGL_NONE;
return EGL_TRUE;
}
@ -87,6 +88,24 @@ _eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
}
#ifdef EGL_VERSION_1_2
static EGLint
_eglQueryContextRenderBuffer(_EGLContext *ctx)
{
_EGLSurface *surf = ctx->DrawSurface;
EGLint rb;
if (!surf)
return EGL_NONE;
if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
rb = ctx->WindowRenderBuffer;
else
rb = surf->RenderBuffer;
return rb;
}
#endif /* EGL_VERSION_1_2 */
EGLBoolean
_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
EGLint attribute, EGLint *value)
@ -94,22 +113,29 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
(void) drv;
(void) dpy;
if (!value)
return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
switch (attribute) {
case EGL_CONFIG_ID:
*value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
return EGL_TRUE;
break;
case EGL_CONTEXT_CLIENT_VERSION:
*value = c->ClientVersion;
break;
#ifdef EGL_VERSION_1_2
case EGL_CONTEXT_CLIENT_TYPE:
*value = c->ClientAPI;
return EGL_TRUE;
break;
case EGL_RENDER_BUFFER:
*value = _eglQueryContextRenderBuffer(c);
break;
#endif /* EGL_VERSION_1_2 */
case EGL_CONTEXT_CLIENT_VERSION:
*value = c->ClientVersion;
return EGL_TRUE;
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
return EGL_FALSE;
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
}
return EGL_TRUE;
}

View file

@ -24,6 +24,9 @@ struct _egl_context
EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */
EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */
/* The real render buffer when a window surface is bound */
EGLint WindowRenderBuffer;
};

View file

@ -44,6 +44,7 @@ struct _egl_display
EGLint NumScreens;
_EGLScreen **Screens; /* array [NumScreens] */
EGLint MaxConfigs;
EGLint NumConfigs;
_EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */

View file

@ -23,6 +23,7 @@ SConscript([
'auxiliary/pipebuffer/SConscript',
'auxiliary/indices/SConscript',
'auxiliary/rbug/SConscript',
'auxiliary/vl/SConscript',
])
for driver in env['drivers']:

View file

@ -104,7 +104,7 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
unsigned clipped = 0;
unsigned j;
if (0) debug_printf("%s\n");
if (0) debug_printf("%s\n", __FUNCTION__);
for (j = 0; j < count; j++) {
float *position = out->data[pos];

View file

@ -542,7 +542,7 @@ fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list)
debug_printf("%10p %7u %7u\n",
fenced_buf,
fenced_buf->base.base.size,
fenced_buf->base.base.reference.count);
p_atomic_read(&fenced_buf->base.base.reference.count));
curr = next;
next = curr->next;
}
@ -556,7 +556,7 @@ fenced_buffer_list_dump(struct fenced_buffer_list *fenced_list)
debug_printf("%10p %7u %7u %10p %s\n",
fenced_buf,
fenced_buf->base.base.size,
fenced_buf->base.base.reference.count,
p_atomic_read(&fenced_buf->base.base.reference.count),
fenced_buf->fence,
signaled == 0 ? "y" : "n");
curr = next;

View file

@ -350,7 +350,7 @@ pb_debug_manager_dump(struct pb_debug_manager *mgr)
buf = LIST_ENTRY(struct pb_debug_buffer, curr, head);
debug_printf("buffer = %p\n", buf);
debug_printf(" .size = %p\n", buf->base.base.size);
debug_printf(" .size = 0x%x\n", buf->base.base.size);
debug_backtrace_dump(buf->create_backtrace, PB_DEBUG_CREATE_BACKTRACE);
curr = next;

View file

@ -1445,11 +1445,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));
}
@ -1855,7 +1855,6 @@ emit_instruction(
break;
case TGSI_OPCODE_RCP:
/* TGSI_OPCODE_RECIP */
FETCH( func, *inst, 0, 0, CHAN_X );
emit_rcp( func, 0, 0 );
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
@ -1864,7 +1863,6 @@ emit_instruction(
break;
case TGSI_OPCODE_RSQ:
/* TGSI_OPCODE_RECIPSQRT */
FETCH( func, *inst, 0, 0, CHAN_X );
emit_abs( func, 0 );
emit_rsqrt( func, 1, 0 );
@ -1962,7 +1960,6 @@ emit_instruction(
break;
case TGSI_OPCODE_DP3:
/* TGSI_OPCODE_DOT3 */
FETCH( func, *inst, 0, 0, CHAN_X );
FETCH( func, *inst, 1, 1, CHAN_X );
emit_mul( func, 0, 1 );
@ -1980,7 +1977,6 @@ emit_instruction(
break;
case TGSI_OPCODE_DP4:
/* TGSI_OPCODE_DOT4 */
FETCH( func, *inst, 0, 0, CHAN_X );
FETCH( func, *inst, 1, 1, CHAN_X );
emit_mul( func, 0, 1 );
@ -2051,17 +2047,14 @@ emit_instruction(
break;
case TGSI_OPCODE_SLT:
/* TGSI_OPCODE_SETLT */
emit_setcc( func, inst, cc_LessThan );
break;
case TGSI_OPCODE_SGE:
/* TGSI_OPCODE_SETGE */
emit_setcc( func, inst, cc_NotLessThan );
break;
case TGSI_OPCODE_MAD:
/* TGSI_OPCODE_MADD */
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( func, *inst, 0, 0, chan_index );
FETCH( func, *inst, 1, 1, chan_index );
@ -2291,7 +2284,7 @@ emit_instruction(
break;
case TGSI_OPCODE_SEQ:
return 0;
emit_setcc( func, inst, cc_Equal );
break;
case TGSI_OPCODE_SFL:
@ -2299,7 +2292,7 @@ emit_instruction(
break;
case TGSI_OPCODE_SGT:
return 0;
emit_setcc( func, inst, cc_NotLessThanEqual );
break;
case TGSI_OPCODE_SIN:
@ -2311,11 +2304,11 @@ emit_instruction(
break;
case TGSI_OPCODE_SLE:
return 0;
emit_setcc( func, inst, cc_LessThanEqual );
break;
case TGSI_OPCODE_SNE:
return 0;
emit_setcc( func, inst, cc_NotEqual );
break;
case TGSI_OPCODE_STR:
@ -2379,7 +2372,6 @@ emit_instruction(
break;
case TGSI_OPCODE_SSG:
/* TGSI_OPCODE_SGN */
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( func, *inst, 0, 0, chan_index );
emit_sgn( func, 0, 0 );

View file

@ -10,6 +10,7 @@ C_SOURCES = \
u_debug_stack.c \
u_blit.c \
u_cache.c \
u_cpu_detect.c \
u_draw_quad.c \
u_format.c \
u_format_access.c \

View file

@ -24,6 +24,7 @@ util = env.ConvenienceLibrary(
'u_bitmask.c',
'u_blit.c',
'u_cache.c',
'u_cpu_detect.c',
'u_debug.c',
'u_debug_dump.c',
'u_debug_memory.c',

View file

@ -24,23 +24,21 @@
*
**************************************************************************/
/*
* Based on the work of Eric Anholt <anholt@FreeBSD.org>
/**
* @file
* CPU feature detection.
*
* @author Dennis Smit
* @author Based on the work of Eric Anholt <anholt@FreeBSD.org>
*/
/* FIXME: clean this entire file up */
#include "pipe/p_config.h"
#include "u_debug.h"
#include "u_cpu_detect.h"
#ifdef __linux__
#define OS_LINUX
#endif
#ifdef WIN32
#define OS_WIN32
#endif
#if defined(ARCH_POWERPC)
#if defined(OS_DARWIN)
#if defined(PIPE_ARCH_PPC)
#if defined(PIPE_OS_DARWIN)
#include <sys/sysctl.h>
#else
#include <signal.h>
@ -48,137 +46,140 @@
#endif
#endif
#if defined(OS_NETBSD) || defined(OS_OPENBSD)
#if defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
#endif
#if defined(OS_FREEBSD)
#if defined(PIPE_OS_FREEBSD)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#if defined(OS_LINUX)
#if defined(PIPE_OS_LINUX)
#include <signal.h>
#endif
#if defined(OS_WIN32)
#ifdef PIPE_OS_UNIX
#include <unistd.h>
#endif
#if defined(PIPE_OS_WINDOWS)
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
static struct cpu_detect_caps __cpu_detect_caps;
static int __cpu_detect_initialized = 0;
struct util_cpu_caps util_cpu_caps;
static int has_cpuid(void);
static int cpuid(unsigned int ax, unsigned int *p);
#if defined(PIPE_ARCH_X86)
/* The sigill handlers */
#if defined(ARCH_X86) /* x86 (linux katmai handler check thing) */
#if defined(OS_LINUX) && defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC)
static void sigill_handler_sse(int signal, struct sigcontext sc)
#if defined(PIPE_OS_LINUX) //&& defined(_POSIX_SOURCE) && defined(X86_FXSR_MAGIC)
static void
sigill_handler_sse(int signal, struct sigcontext sc)
{
/* Both the "xorps %%xmm0,%%xmm0" and "divps %xmm0,%%xmm1"
* instructions are 3 bytes long. We must increment the instruction
* pointer manually to avoid repeated execution of the offending
* instruction.
*
* If the SIGILL is caused by a divide-by-zero when unmasked
* exceptions aren't supported, the SIMD FPU status and control
* word will be restored at the end of the test, so we don't need
* to worry about doing it here. Besides, we may not be able to...
*/
sc.eip += 3;
/* Both the "xorps %%xmm0,%%xmm0" and "divps %xmm0,%%xmm1"
* instructions are 3 bytes long. We must increment the instruction
* pointer manually to avoid repeated execution of the offending
* instruction.
*
* If the SIGILL is caused by a divide-by-zero when unmasked
* exceptions aren't supported, the SIMD FPU status and control
* word will be restored at the end of the test, so we don't need
* to worry about doing it here. Besides, we may not be able to...
*/
sc.eip += 3;
__cpu_detect_caps.hasSSE=0;
util_cpu_caps.has_sse=0;
}
static void sigfpe_handler_sse(int signal, struct sigcontext sc)
static void
sigfpe_handler_sse(int signal, struct sigcontext sc)
{
if (sc.fpstate->magic != 0xffff) {
/* Our signal context has the extended FPU state, so reset the
* divide-by-zero exception mask and clear the divide-by-zero
* exception bit.
*/
sc.fpstate->mxcsr |= 0x00000200;
sc.fpstate->mxcsr &= 0xfffffffb;
} else {
/* If we ever get here, we're completely hosed.
*/
}
if (sc.fpstate->magic != 0xffff) {
/* Our signal context has the extended FPU state, so reset the
* divide-by-zero exception mask and clear the divide-by-zero
* exception bit.
*/
sc.fpstate->mxcsr |= 0x00000200;
sc.fpstate->mxcsr &= 0xfffffffb;
} else {
/* If we ever get here, we're completely hosed.
*/
}
}
#endif
#endif /* OS_LINUX && _POSIX_SOURCE && X86_FXSR_MAGIC */
#endif /* PIPE_OS_LINUX && _POSIX_SOURCE && X86_FXSR_MAGIC */
#if defined(OS_WIN32)
LONG CALLBACK win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
#if defined(PIPE_OS_WINDOWS)
static LONG CALLBACK
win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
{
if(ep->ExceptionRecord->ExceptionCode==EXCEPTION_ILLEGAL_INSTRUCTION){
ep->ContextRecord->Eip +=3;
__cpu_detect_caps.hasSSE=0;
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
if(ep->ExceptionRecord->ExceptionCode==EXCEPTION_ILLEGAL_INSTRUCTION){
ep->ContextRecord->Eip +=3;
util_cpu_caps.has_sse=0;
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
#endif /* OS_WIN32 */
#endif /* PIPE_OS_WINDOWS */
#endif /* PIPE_ARCH_X86 */
#if defined(ARCH_POWERPC) && !defined(OS_DARWIN)
#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_DARWIN)
static sigjmp_buf __lv_powerpc_jmpbuf;
static volatile sig_atomic_t __lv_powerpc_canjump = 0;
static void sigill_handler (int sig);
static void sigill_handler (int sig)
static void
sigill_handler(int sig)
{
if (!__lv_powerpc_canjump) {
signal (sig, SIG_DFL);
raise (sig);
}
if (!__lv_powerpc_canjump) {
signal (sig, SIG_DFL);
raise (sig);
}
__lv_powerpc_canjump = 0;
siglongjmp(__lv_powerpc_jmpbuf, 1);
__lv_powerpc_canjump = 0;
siglongjmp(__lv_powerpc_jmpbuf, 1);
}
static void check_os_altivec_support(void)
static void
check_os_altivec_support(void)
{
#if defined(OS_DARWIN)
int sels[2] = {CTL_HW, HW_VECTORUNIT};
int has_vu = 0;
int len = sizeof (has_vu);
int err;
#if defined(PIPE_OS_DARWIN)
int sels[2] = {CTL_HW, HW_VECTORUNIT};
int has_vu = 0;
int len = sizeof (has_vu);
int err;
err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
if (err == 0) {
if (has_vu != 0) {
__cpu_detect_caps.hasAltiVec = 1;
}
}
#else /* !OS_DARWIN */
/* no Darwin, do it the brute-force way */
/* this is borrowed from the libmpeg2 library */
signal(SIGILL, sigill_handler);
if (sigsetjmp(__lv_powerpc_jmpbuf, 1)) {
signal(SIGILL, SIG_DFL);
} else {
__lv_powerpc_canjump = 1;
if (err == 0) {
if (has_vu != 0) {
util_cpu_caps.has_altivec = 1;
}
}
#else /* !PIPE_OS_DARWIN */
/* no Darwin, do it the brute-force way */
/* this is borrowed from the libmpeg2 library */
signal(SIGILL, sigill_handler);
if (sigsetjmp(__lv_powerpc_jmpbuf, 1)) {
signal(SIGILL, SIG_DFL);
} else {
__lv_powerpc_canjump = 1;
__asm __volatile
("mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
:
: "r" (-1));
__asm __volatile
("mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
:
: "r" (-1));
signal(SIGILL, SIG_DFL);
__cpu_detect_caps.hasAltiVec = 1;
}
signal(SIGILL, SIG_DFL);
util_cpu_caps.has_altivec = 1;
}
#endif
}
#endif
@ -189,318 +190,312 @@ static void check_os_altivec_support(void)
* and RedHat patched 2.2 kernels that have broken exception handling
* support for user space apps that do SSE.
*/
static void check_os_katmai_support(void)
static void
check_os_katmai_support(void)
{
#if defined(ARCH_X86)
#if defined(OS_FREEBSD)
int has_sse=0, ret;
int len = sizeof (has_sse);
#if defined(PIPE_ARCH_X86)
#if defined(PIPE_OS_FREEBSD)
int has_sse=0, ret;
int len = sizeof (has_sse);
ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0);
if (ret || !has_sse)
__cpu_detect_caps.hasSSE=0;
ret = sysctlbyname("hw.instruction_sse", &has_sse, &len, NULL, 0);
if (ret || !has_sse)
util_cpu_caps.has_sse=0;
#elif defined(OS_NETBSD) || defined(OS_OPENBSD)
int has_sse, has_sse2, ret, mib[2];
int varlen;
#elif defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD)
int has_sse, has_sse2, ret, mib[2];
int varlen;
mib[0] = CTL_MACHDEP;
mib[1] = CPU_SSE;
varlen = sizeof (has_sse);
mib[0] = CTL_MACHDEP;
mib[1] = CPU_SSE;
varlen = sizeof (has_sse);
ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0);
if (ret < 0 || !has_sse) {
__cpu_detect_caps.hasSSE = 0;
} else {
__cpu_detect_caps.hasSSE = 1;
}
ret = sysctl(mib, 2, &has_sse, &varlen, NULL, 0);
if (ret < 0 || !has_sse) {
util_cpu_caps.has_sse = 0;
} else {
util_cpu_caps.has_sse = 1;
}
mib[1] = CPU_SSE2;
varlen = sizeof (has_sse2);
ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0);
if (ret < 0 || !has_sse2) {
__cpu_detect_caps.hasSSE2 = 0;
} else {
__cpu_detect_caps.hasSSE2 = 1;
}
__cpu_detect_caps.hasSSE = 0; /* FIXME ?!?!? */
mib[1] = CPU_SSE2;
varlen = sizeof (has_sse2);
ret = sysctl(mib, 2, &has_sse2, &varlen, NULL, 0);
if (ret < 0 || !has_sse2) {
util_cpu_caps.has_sse2 = 0;
} else {
util_cpu_caps.has_sse2 = 1;
}
util_cpu_caps.has_sse = 0; /* FIXME ?!?!? */
#elif defined(OS_WIN32)
LPTOP_LEVEL_EXCEPTION_FILTER exc_fil;
if (__cpu_detect_caps.hasSSE) {
exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse);
__asm __volatile ("xorps %xmm0, %xmm0");
SetUnhandledExceptionFilter(exc_fil);
}
#elif defined(OS_LINUX)
struct sigaction saved_sigill;
struct sigaction saved_sigfpe;
#elif defined(PIPE_OS_WINDOWS)
LPTOP_LEVEL_EXCEPTION_FILTER exc_fil;
if (util_cpu_caps.has_sse) {
exc_fil = SetUnhandledExceptionFilter(win32_sig_handler_sse);
#if defined(PIPE_CC_GCC)
__asm __volatile ("xorps %xmm0, %xmm0");
#elif defined(PIPE_CC_MSVC)
__asm {
xorps xmm0, xmm0 // executing SSE instruction
}
#else
#error Unsupported compiler
#endif
SetUnhandledExceptionFilter(exc_fil);
}
#elif defined(PIPE_OS_LINUX)
struct sigaction saved_sigill;
struct sigaction saved_sigfpe;
/* Save the original signal handlers.
*/
sigaction(SIGILL, NULL, &saved_sigill);
sigaction(SIGFPE, NULL, &saved_sigfpe);
/* Save the original signal handlers.
*/
sigaction(SIGILL, NULL, &saved_sigill);
sigaction(SIGFPE, NULL, &saved_sigfpe);
signal(SIGILL, (void (*)(int))sigill_handler_sse);
signal(SIGFPE, (void (*)(int))sigfpe_handler_sse);
signal(SIGILL, (void (*)(int))sigill_handler_sse);
signal(SIGFPE, (void (*)(int))sigfpe_handler_sse);
/* Emulate test for OSFXSR in CR4. The OS will set this bit if it
* supports the extended FPU save and restore required for SSE. If
* we execute an SSE instruction on a PIII and get a SIGILL, the OS
* doesn't support Streaming SIMD Exceptions, even if the processor
* does.
*/
if (__cpu_detect_caps.hasSSE) {
__asm __volatile ("xorps %xmm1, %xmm0");
}
/* Emulate test for OSFXSR in CR4. The OS will set this bit if it
* supports the extended FPU save and restore required for SSE. If
* we execute an SSE instruction on a PIII and get a SIGILL, the OS
* doesn't support Streaming SIMD Exceptions, even if the processor
* does.
*/
if (util_cpu_caps.has_sse) {
__asm __volatile ("xorps %xmm1, %xmm0");
}
/* Emulate test for OSXMMEXCPT in CR4. The OS will set this bit if
* it supports unmasked SIMD FPU exceptions. If we unmask the
* exceptions, do a SIMD divide-by-zero and get a SIGILL, the OS
* doesn't support unmasked SIMD FPU exceptions. If we get a SIGFPE
* as expected, we're okay but we need to clean up after it.
*
* Are we being too stringent in our requirement that the OS support
* unmasked exceptions? Certain RedHat 2.2 kernels enable SSE by
* setting CR4.OSFXSR but don't support unmasked exceptions. Win98
* doesn't even support them. We at least know the user-space SSE
* support is good in kernels that do support unmasked exceptions,
* and therefore to be safe I'm going to leave this test in here.
*/
if (__cpu_detect_caps.hasSSE) {
// test_os_katmai_exception_support();
}
/* Emulate test for OSXMMEXCPT in CR4. The OS will set this bit if
* it supports unmasked SIMD FPU exceptions. If we unmask the
* exceptions, do a SIMD divide-by-zero and get a SIGILL, the OS
* doesn't support unmasked SIMD FPU exceptions. If we get a SIGFPE
* as expected, we're okay but we need to clean up after it.
*
* Are we being too stringent in our requirement that the OS support
* unmasked exceptions? Certain RedHat 2.2 kernels enable SSE by
* setting CR4.OSFXSR but don't support unmasked exceptions. Win98
* doesn't even support them. We at least know the user-space SSE
* support is good in kernels that do support unmasked exceptions,
* and therefore to be safe I'm going to leave this test in here.
*/
if (util_cpu_caps.has_sse) {
// test_os_katmai_exception_support();
}
/* Restore the original signal handlers.
*/
sigaction(SIGILL, &saved_sigill, NULL);
sigaction(SIGFPE, &saved_sigfpe, NULL);
/* Restore the original signal handlers.
*/
sigaction(SIGILL, &saved_sigill, NULL);
sigaction(SIGFPE, &saved_sigfpe, NULL);
#else
/* We can't use POSIX signal handling to test the availability of
* SSE, so we disable it by default.
*/
__cpu_detect_caps.hasSSE = 0;
/* We can't use POSIX signal handling to test the availability of
* SSE, so we disable it by default.
*/
util_cpu_caps.has_sse = 0;
#endif /* __linux__ */
#endif
#if defined(PIPE_ARCH_X86_64)
util_cpu_caps.has_sse = 1;
#endif
}
static int has_cpuid(void)
{
#if defined(ARCH_X86)
int a, c;
#if defined(PIPE_ARCH_X86)
#if defined(PIPE_OS_GCC)
int a, c;
__asm __volatile
("pushf\n"
"popl %0\n"
"movl %0, %1\n"
"xorl $0x200000, %0\n"
"push %0\n"
"popf\n"
"pushf\n"
"popl %0\n"
: "=a" (a), "=c" (c)
:
: "cc");
__asm __volatile
("pushf\n"
"popl %0\n"
"movl %0, %1\n"
"xorl $0x200000, %0\n"
"push %0\n"
"popf\n"
"pushf\n"
"popl %0\n"
: "=a" (a), "=c" (c)
:
: "cc");
return a != c;
return a != c;
#else
return 0;
/* FIXME */
return 1;
#endif
#elif defined(PIPE_ARCH_X86_64)
return 1;
#else
return 0;
#endif
}
static int cpuid(unsigned int ax, unsigned int *p)
static INLINE int
cpuid(unsigned int ax, unsigned int *p)
{
#if defined(ARCH_X86)
unsigned int flags;
int ret = -1;
__asm __volatile
("movl %%ebx, %%esi\n\t"
"cpuid\n\t"
"xchgl %%ebx, %%esi"
: "=a" (p[0]), "=S" (p[1]),
"=c" (p[2]), "=d" (p[3])
: "0" (ax));
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
#if defined(PIPE_CC_GCC)
__asm __volatile
("movl %%ebx, %%esi\n\t"
"cpuid\n\t"
"xchgl %%ebx, %%esi"
: "=a" (p[0]), "=S" (p[1]),
"=c" (p[2]), "=d" (p[3])
: "0" (ax));
return 0;
#else
return -1;
ret = 0;
#elif defined(PIPE_CC_MSVC)
__cpuid(ax, p);
ret = 0;
#endif
}
void cpu_detect_initialize()
{
unsigned int regs[4];
unsigned int regs2[4];
int mib[2], ncpu;
int len;
memset(&__cpu_detect_caps, 0, sizeof (struct cpu_detect_caps));
/* Check for arch type */
#if defined(ARCH_MIPS)
__cpu_detect_caps.type = CPU_DETECT_TYPE_MIPS;
#elif defined(ARCH_ALPHA)
__cpu_detect_caps.type = CPU_DETECT_TYPE_ALPHA;
#elif defined(ARCH_SPARC)
__cpu_detect_caps.type = CPU_DETECT_TYPE_SPARC;
#elif defined(ARCH_X86)
__cpu_detect_caps.type = CPU_DETECT_TYPE_X86;
#elif defined(ARCH_POWERPC)
__cpu_detect_caps.type = CPU_DETECT_TYPE_POWERPC;
#else
__cpu_detect_caps.type = CPU_DETECT_TYPE_OTHER;
#endif
/* Count the number of CPUs in system */
#if !defined(OS_WIN32) && !defined(OS_UNKNOWN) && defined(_SC_NPROCESSORS_ONLN)
__cpu_detect_caps.nrcpu = sysconf(_SC_NPROCESSORS_ONLN);
if (__cpu_detect_caps.nrcpu == -1)
__cpu_detect_caps.nrcpu = 1;
return ret;
}
#elif defined(OS_NETBSD) || defined(OS_FREEBSD) || defined(OS_OPENBSD)
void
util_cpu_detect(void)
{
static boolean util_cpu_detect_initialized = FALSE;
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
if(util_cpu_detect_initialized)
return;
len = sizeof (ncpu);
sysctl(mib, 2, &ncpu, &len, NULL, 0);
__cpu_detect_caps.nrcpu = ncpu;
memset(&util_cpu_caps, 0, sizeof util_cpu_caps);
/* Check for arch type */
#if defined(PIPE_ARCH_MIPS)
util_cpu_caps.arch = UTIL_CPU_ARCH_MIPS;
#elif defined(PIPE_ARCH_ALPHA)
util_cpu_caps.arch = UTIL_CPU_ARCH_ALPHA;
#elif defined(PIPE_ARCH_SPARC)
util_cpu_caps.arch = UTIL_CPU_ARCH_SPARC;
#elif defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
util_cpu_caps.arch = UTIL_CPU_ARCH_X86;
#elif defined(PIPE_ARCH_PPC)
util_cpu_caps.arch = UTIL_CPU_ARCH_POWERPC;
#else
__cpu_detect_caps.nrcpu = 1;
util_cpu_caps.arch = UTIL_CPU_ARCH_UNKNOWN;
#endif
#if defined(ARCH_X86)
/* No cpuid, old 486 or lower */
if (has_cpuid() == 0)
return;
/* Count the number of CPUs in system */
#if !defined(PIPE_OS_WINDOWS) && !defined(PIPE_OS_UNKNOWN) && defined(_SC_NPROCESSORS_ONLN)
util_cpu_caps.nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if (util_cpu_caps.nr_cpus == -1)
util_cpu_caps.nr_cpus = 1;
__cpu_detect_caps.cacheline = 32;
#elif defined(PIPE_OS_NETBSD) || defined(PIPE_OS_FREEBSD) || defined(PIPE_OS_OPENBSD)
{
int mib[2], ncpu;
int len;
/* Get max cpuid level */
cpuid(0x00000000, regs);
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
if (regs[0] >= 0x00000001) {
unsigned int cacheline;
cpuid (0x00000001, regs2);
__cpu_detect_caps.x86cpuType = (regs2[0] >> 8) & 0xf;
if (__cpu_detect_caps.x86cpuType == 0xf)
__cpu_detect_caps.x86cpuType = 8 + ((regs2[0] >> 20) & 255); /* use extended family (P4, IA64) */
/* general feature flags */
__cpu_detect_caps.hasTSC = (regs2[3] & (1 << 8 )) >> 8; /* 0x0000010 */
__cpu_detect_caps.hasMMX = (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */
__cpu_detect_caps.hasSSE = (regs2[3] & (1 << 25 )) >> 25; /* 0x2000000 */
__cpu_detect_caps.hasSSE2 = (regs2[3] & (1 << 26 )) >> 26; /* 0x4000000 */
__cpu_detect_caps.hasSSE3 = (regs2[2] & (1)); /* 0x0000001 */
__cpu_detect_caps.hasSSSE3 = (regs2[2] & (1 << 9 )) >> 9; /* 0x0000020 */
__cpu_detect_caps.hasMMX2 = __cpu_detect_caps.hasSSE; /* SSE cpus supports mmxext too */
cacheline = ((regs2[1] >> 8) & 0xFF) * 8;
if (cacheline > 0)
__cpu_detect_caps.cacheline = cacheline;
}
cpuid(0x80000000, regs);
if (regs[0] >= 0x80000001) {
cpuid(0x80000001, regs2);
__cpu_detect_caps.hasMMX |= (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */
__cpu_detect_caps.hasMMX2 |= (regs2[3] & (1 << 22 )) >> 22; /* 0x400000 */
__cpu_detect_caps.has3DNow = (regs2[3] & (1 << 31 )) >> 31; /* 0x80000000 */
__cpu_detect_caps.has3DNowExt = (regs2[3] & (1 << 30 )) >> 30;
}
if (regs[0] >= 0x80000006) {
cpuid(0x80000006, regs2);
__cpu_detect_caps.cacheline = regs2[2] & 0xFF;
}
#if defined(OS_LINUX) || defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_CYGWIN) || defined(OS_OPENBSD)
if (__cpu_detect_caps.hasSSE)
check_os_katmai_support();
if (!__cpu_detect_caps.hasSSE) {
__cpu_detect_caps.hasSSE2 = 0;
__cpu_detect_caps.hasSSE3 = 0;
__cpu_detect_caps.hasSSSE3 = 0;
}
len = sizeof (ncpu);
sysctl(mib, 2, &ncpu, &len, NULL, 0);
util_cpu_caps.nr_cpus = ncpu;
}
#else
__cpu_detect_caps.hasSSE = 0;
__cpu_detect_caps.hasSSE2 = 0;
__cpu_detect_caps.hasSSE3 = 0;
__cpu_detect_caps.hasSSSE3 = 0;
util_cpu_caps.nr_cpus = 1;
#endif
#endif /* ARCH_X86 */
#if defined(ARCH_POWERPC)
check_os_altivec_support();
#endif /* ARCH_POWERPC */
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
if (has_cpuid()) {
unsigned int regs[4];
unsigned int regs2[4];
__cpu_detect_initialized = 1;
util_cpu_caps.cacheline = 32;
/* Get max cpuid level */
cpuid(0x00000000, regs);
if (regs[0] >= 0x00000001) {
unsigned int cacheline;
cpuid (0x00000001, regs2);
util_cpu_caps.x86_cpu_type = (regs2[0] >> 8) & 0xf;
if (util_cpu_caps.x86_cpu_type == 0xf)
util_cpu_caps.x86_cpu_type = 8 + ((regs2[0] >> 20) & 255); /* use extended family (P4, IA64) */
/* general feature flags */
util_cpu_caps.has_tsc = (regs2[3] & (1 << 8 )) >> 8; /* 0x0000010 */
util_cpu_caps.has_mmx = (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */
util_cpu_caps.has_sse = (regs2[3] & (1 << 25 )) >> 25; /* 0x2000000 */
util_cpu_caps.has_sse2 = (regs2[3] & (1 << 26 )) >> 26; /* 0x4000000 */
util_cpu_caps.has_sse3 = (regs2[2] & (1)); /* 0x0000001 */
util_cpu_caps.has_ssse3 = (regs2[2] & (1 << 9 )) >> 9; /* 0x0000020 */
util_cpu_caps.has_sse4_1 = (regs2[2] & (1 << 19)) >> 19;
util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */
cacheline = ((regs2[1] >> 8) & 0xFF) * 8;
if (cacheline > 0)
util_cpu_caps.cacheline = cacheline;
}
cpuid(0x80000000, regs);
if (regs[0] >= 0x80000001) {
cpuid(0x80000001, regs2);
util_cpu_caps.has_mmx |= (regs2[3] & (1 << 23 )) >> 23; /* 0x0800000 */
util_cpu_caps.has_mmx2 |= (regs2[3] & (1 << 22 )) >> 22; /* 0x400000 */
util_cpu_caps.has_3dnow = (regs2[3] & (1 << 31 )) >> 31; /* 0x80000000 */
util_cpu_caps.has_3dnow_ext = (regs2[3] & (1 << 30 )) >> 30;
}
if (regs[0] >= 0x80000006) {
cpuid(0x80000006, regs2);
util_cpu_caps.cacheline = regs2[2] & 0xFF;
}
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_FREEBSD) || defined(PIPE_OS_NETBSD) || defined(PIPE_OS_CYGWIN) || defined(PIPE_OS_OPENBSD)
if (util_cpu_caps.has_sse)
check_os_katmai_support();
if (!util_cpu_caps.has_sse) {
util_cpu_caps.has_sse2 = 0;
util_cpu_caps.has_sse3 = 0;
util_cpu_caps.has_ssse3 = 0;
}
#else
util_cpu_caps.has_sse = 0;
util_cpu_caps.has_sse2 = 0;
util_cpu_caps.has_sse3 = 0;
util_cpu_caps.has_ssse3 = 0;
#endif
}
#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */
#if defined(PIPE_ARCH_PPC)
check_os_altivec_support();
#endif /* PIPE_ARCH_PPC */
#ifdef DEBUG
debug_printf("util_cpu_caps.arch = %i\n", util_cpu_caps.arch);
debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus);
debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type);
debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline);
debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc);
debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx);
debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2);
debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse);
debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2);
debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3);
debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3);
debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1);
debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow);
debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext);
debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec);
#endif
util_cpu_detect_initialized = TRUE;
}
struct cpu_detect_caps *cpu_detect_get_caps()
{
return &__cpu_detect_caps;
}
/* The getters and setters for feature flags */
int cpu_detect_get_tsc()
{
return __cpu_detect_caps.hasTSC;
}
int cpu_detect_get_mmx()
{
return __cpu_detect_caps.hasMMX;
}
int cpu_detect_get_mmx2()
{
return __cpu_detect_caps.hasMMX2;
}
int cpu_detect_get_sse()
{
return __cpu_detect_caps.hasSSE;
}
int cpu_detect_get_sse2()
{
return __cpu_detect_caps.hasSSE2;
}
int cpu_detect_get_sse3()
{
return __cpu_detect_caps.hasSSE3;
}
int cpu_detect_get_ssse3()
{
return __cpu_detect_caps.hasSSSE3;
}
int cpu_detect_get_3dnow()
{
return __cpu_detect_caps.has3DNow;
}
int cpu_detect_get_3dnow2()
{
return __cpu_detect_caps.has3DNowExt;
}
int cpu_detect_get_altivec()
{
return __cpu_detect_caps.hasAltiVec;
}

View file

@ -24,55 +24,53 @@
*
***************************************************************************/
/*
* Based on the work of Eric Anholt <anholt@FreeBSD.org>
/**
* @file
* CPU feature detection.
*
* @author Dennis Smit
* @author Based on the work of Eric Anholt <anholt@FreeBSD.org>
*/
#ifndef _CPU_DETECT_H
#define _CPU_DETECT_H
#ifndef _UTIL_CPU_DETECT_H
#define _UTIL_CPU_DETECT_H
typedef enum {
CPU_DETECT_TYPE_MIPS,
CPU_DETECT_TYPE_ALPHA,
CPU_DETECT_TYPE_SPARC,
CPU_DETECT_TYPE_X86,
CPU_DETECT_TYPE_POWERPC,
CPU_DETECT_TYPE_OTHER
} cpu_detect_type;
#include "pipe/p_compiler.h"
struct cpu_detect_caps {
cpu_detect_type type;
int nrcpu;
/* Feature flags */
int x86cpuType;
int cacheline;
int hasTSC;
int hasMMX;
int hasMMX2;
int hasSSE;
int hasSSE2;
int hasSSE3;
int hasSSSE3;
int has3DNow;
int has3DNowExt;
int hasAltiVec;
enum util_cpu_arch {
UTIL_CPU_ARCH_UNKNOWN = 0,
UTIL_CPU_ARCH_MIPS,
UTIL_CPU_ARCH_ALPHA,
UTIL_CPU_ARCH_SPARC,
UTIL_CPU_ARCH_X86,
UTIL_CPU_ARCH_POWERPC
};
/* prototypes */
void cpu_detect_initialize(void);
struct cpu_detect_caps *cpu_detect_get_caps(void);
struct util_cpu_caps {
enum util_cpu_arch arch;
unsigned nr_cpus;
int cpu_detect_get_tsc(void);
int cpu_detect_get_mmx(void);
int cpu_detect_get_mmx2(void);
int cpu_detect_get_sse(void);
int cpu_detect_get_sse2(void);
int cpu_detect_get_sse3(void);
int cpu_detect_get_ssse3(void);
int cpu_detect_get_3dnow(void);
int cpu_detect_get_3dnow2(void);
int cpu_detect_get_altivec(void);
/* Feature flags */
int x86_cpu_type;
unsigned cacheline;
#endif /* _CPU_DETECT_H */
unsigned has_tsc:1;
unsigned has_mmx:1;
unsigned has_mmx2:1;
unsigned has_sse:1;
unsigned has_sse2:1;
unsigned has_sse3:1;
unsigned has_ssse3:1;
unsigned has_sse4_1:1;
unsigned has_3dnow:1;
unsigned has_3dnow_ext:1;
unsigned has_altivec:1;
};
extern struct util_cpu_caps
util_cpu_caps;
void util_cpu_detect(void);
#endif /* _UTIL_CPU_DETECT_H */

View file

@ -65,6 +65,11 @@ extern "C" {
#define __FUNCTION__ "???"
#endif
#if defined(__GNUC__)
#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
#else
#define _util_printf_format(fmt, list)
#endif
void _debug_vprintf(const char *format, va_list ap);
@ -82,13 +87,16 @@ _debug_printf(const char *format, ...)
/**
* Print debug messages.
*
* The actual channel used to output debug message is platform specific. To
* avoid misformating or truncation, follow these rules of thumb:
* The actual channel used to output debug message is platform specific. To
* avoid misformating or truncation, follow these rules of thumb:
* - output whole lines
* - avoid outputing large strings (512 bytes is the current maximum length
* - avoid outputing large strings (512 bytes is the current maximum length
* that is guaranteed to be printed in all platforms)
*/
#if !defined(PIPE_OS_HAIKU)
static INLINE void
debug_printf(const char *format, ...) _util_printf_format(1,2);
static INLINE void
debug_printf(const char *format, ...)
{

View file

@ -1515,6 +1515,17 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
uint zslice = 0;
uint offset;
/* The texture object should have room for the levels which we're
* about to generate.
*/
assert(lastLevel <= pt->last_level);
/* If this fails, why are we here? */
assert(lastLevel > baseLevel);
assert(filter == PIPE_TEX_FILTER_LINEAR ||
filter == PIPE_TEX_FILTER_NEAREST);
/* check if we can render in the texture's format */
if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {

View file

@ -283,6 +283,14 @@ util_fast_pow(float x, float y)
return util_fast_exp2(util_fast_log2(x) * y);
}
/* Note that this counts zero as a power of two.
*/
static INLINE boolean
util_is_power_of_two( unsigned v )
{
return (v & (v-1)) == 0;
}
/**
* Floor(x), returned as int.
@ -462,6 +470,26 @@ util_logbase2(unsigned n)
}
/**
* Returns the smallest power of two >= x
*/
static INLINE unsigned
util_next_power_of_two(unsigned x)
{
unsigned i;
if (x == 0)
return 1;
--x;
for (i = 1; i < sizeof(unsigned) * 8; i <<= 1)
x |= x >> i;
return x + 1;
}
/**
* Clamp X to [MIN, MAX].
* This is a macro to allow float, int, uint, etc. types.

View file

@ -6,7 +6,7 @@
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# include <winsock2.h>
# include <windows.h>
#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_BSD)
# include <sys/socket.h>
# include <netinet/in.h>
# include <unistd.h>
@ -54,7 +54,7 @@ u_socket_close(int s)
if (s < 0)
return;
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_BSD)
shutdown(s, SHUT_RDWR);
close(s);
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
@ -169,7 +169,7 @@ u_socket_listen_on_port(uint16_t portnum)
void
u_socket_block(int s, boolean block)
{
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_BSD)
int old = fcntl(s, F_GETFL, 0);
if (old == -1)
return;

View file

@ -6,7 +6,7 @@
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# define PIPE_HAVE_SOCKETS
#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU)
#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_BSD)
# define PIPE_HAVE_SOCKETS
#endif

View file

@ -1452,7 +1452,7 @@ pipe_put_tile_z(struct pipe_transfer *pt,
case PIPE_FORMAT_S8Z24_UNORM:
{
uint *pDest = (uint *) (map + y * pt->stride + x*4);
assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit Z to 24-bit Z, preserve stencil */
@ -1479,7 +1479,7 @@ pipe_put_tile_z(struct pipe_transfer *pt,
case PIPE_FORMAT_Z24S8_UNORM:
{
uint *pDest = (uint *) (map + y * pt->stride + x*4);
assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit Z to 24-bit Z, preserve stencil */

View file

@ -0,0 +1,13 @@
TOP = ../../../..
include $(TOP)/configs/current
LIBNAME = vl
C_SOURCES = \
vl_bitstream_parser.c \
vl_mpeg12_mc_renderer.c \
vl_compositor.c \
vl_csc.c \
vl_shader_build.c
include ../../Makefile.template

View file

@ -0,0 +1,13 @@
Import('*')
vl = env.ConvenienceLibrary(
target = 'vl',
source = [
'vl_bitstream_parser.c',
'vl_mpeg12_mc_renderer.c',
'vl_compositor.c',
'vl_csc.c',
'vl_shader_build.c',
])
auxiliaries.insert(0, vl)

View file

@ -0,0 +1,167 @@
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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 TUNGSTEN GRAPHICS 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 "vl_bitstream_parser.h"
#include <assert.h>
#include <limits.h>
#include <util/u_memory.h>
static unsigned
grab_bits(unsigned cursor, unsigned how_many_bits, unsigned bitstream_elt)
{
unsigned excess_bits = sizeof(unsigned) * CHAR_BIT - how_many_bits - cursor;
assert(cursor < sizeof(unsigned) * CHAR_BIT);
assert(how_many_bits > 0 && how_many_bits <= sizeof(unsigned) * CHAR_BIT);
assert(cursor + how_many_bits <= sizeof(unsigned) * CHAR_BIT);
return (bitstream_elt << excess_bits) >> (excess_bits + cursor);
}
static unsigned
show_bits(unsigned cursor, unsigned how_many_bits, const unsigned *bitstream)
{
unsigned cur_int = cursor / (sizeof(unsigned) * CHAR_BIT);
unsigned cur_bit = cursor % (sizeof(unsigned) * CHAR_BIT);
assert(bitstream);
if (cur_bit + how_many_bits > sizeof(unsigned) * CHAR_BIT) {
unsigned lower = grab_bits(cur_bit, sizeof(unsigned) * CHAR_BIT - cur_bit,
bitstream[cur_int]);
unsigned upper = grab_bits(0, cur_bit + how_many_bits - sizeof(unsigned) * CHAR_BIT,
bitstream[cur_int + 1]);
return lower | upper << (sizeof(unsigned) * CHAR_BIT - cur_bit);
}
else
return grab_bits(cur_bit, how_many_bits, bitstream[cur_int]);
}
bool vl_bitstream_parser_init(struct vl_bitstream_parser *parser,
unsigned num_bitstreams,
const void **bitstreams,
const unsigned *sizes)
{
assert(parser);
assert(num_bitstreams);
assert(bitstreams);
assert(sizes);
parser->num_bitstreams = num_bitstreams;
parser->bitstreams = (const unsigned**)bitstreams;
parser->sizes = sizes;
parser->cur_bitstream = 0;
parser->cursor = 0;
return true;
}
void vl_bitstream_parser_cleanup(struct vl_bitstream_parser *parser)
{
assert(parser);
}
unsigned
vl_bitstream_parser_get_bits(struct vl_bitstream_parser *parser,
unsigned how_many_bits)
{
unsigned bits;
assert(parser);
bits = vl_bitstream_parser_show_bits(parser, how_many_bits);
vl_bitstream_parser_forward(parser, how_many_bits);
return bits;
}
unsigned
vl_bitstream_parser_show_bits(struct vl_bitstream_parser *parser,
unsigned how_many_bits)
{
unsigned bits = 0;
unsigned shift = 0;
unsigned cursor;
unsigned cur_bitstream;
assert(parser);
cursor = parser->cursor;
cur_bitstream = parser->cur_bitstream;
while (1) {
unsigned bits_left = parser->sizes[cur_bitstream] * CHAR_BIT - cursor;
unsigned bits_to_show = how_many_bits > bits_left ? bits_left : how_many_bits;
bits |= show_bits(cursor, bits_to_show,
parser->bitstreams[cur_bitstream]) << shift;
if (how_many_bits > bits_to_show) {
how_many_bits -= bits_to_show;
cursor = 0;
++cur_bitstream;
shift += bits_to_show;
}
else
break;
}
return bits;
}
void vl_bitstream_parser_forward(struct vl_bitstream_parser *parser,
unsigned how_many_bits)
{
assert(parser);
assert(how_many_bits);
parser->cursor += how_many_bits;
while (parser->cursor > parser->sizes[parser->cur_bitstream] * CHAR_BIT) {
parser->cursor -= parser->sizes[parser->cur_bitstream++] * CHAR_BIT;
assert(parser->cur_bitstream < parser->num_bitstreams);
}
}
void vl_bitstream_parser_rewind(struct vl_bitstream_parser *parser,
unsigned how_many_bits)
{
signed c;
assert(parser);
assert(how_many_bits);
c = parser->cursor - how_many_bits;
while (c < 0) {
c += parser->sizes[parser->cur_bitstream--] * CHAR_BIT;
assert(parser->cur_bitstream < parser->num_bitstreams);
}
parser->cursor = (unsigned)c;
}

View file

@ -1,8 +1,8 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
*
* Copyright 2009 Younes Manton.
* 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
@ -10,11 +10,11 @@
* 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.
@ -22,52 +22,42 @@
* 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 STW_PUBLIC_H
#define STW_PUBLIC_H
#ifndef vl_bitstream_parser_h
#define vl_bitstream_parser_h
#include <windows.h>
#include "pipe/p_compiler.h"
BOOL stw_copy_context( UINT_PTR hglrcSrc,
UINT_PTR hglrcDst,
UINT mask );
struct vl_bitstream_parser
{
unsigned num_bitstreams;
const unsigned **bitstreams;
const unsigned *sizes;
unsigned cur_bitstream;
unsigned cursor;
};
UINT_PTR stw_create_layer_context( HDC hdc,
int iLayerPlane );
bool vl_bitstream_parser_init(struct vl_bitstream_parser *parser,
unsigned num_bitstreams,
const void **bitstreams,
const unsigned *sizes);
BOOL stw_share_lists( UINT_PTR hglrc1, UINT_PTR hglrc2 );
void vl_bitstream_parser_cleanup(struct vl_bitstream_parser *parser);
BOOL stw_delete_context( UINT_PTR hglrc );
unsigned
vl_bitstream_parser_get_bits(struct vl_bitstream_parser *parser,
unsigned how_many_bits);
BOOL
stw_release_context( UINT_PTR dhglrc );
unsigned
vl_bitstream_parser_show_bits(struct vl_bitstream_parser *parser,
unsigned how_many_bits);
UINT_PTR stw_get_current_context( void );
void vl_bitstream_parser_forward(struct vl_bitstream_parser *parser,
unsigned how_many_bits);
HDC stw_get_current_dc( void );
void vl_bitstream_parser_rewind(struct vl_bitstream_parser *parser,
unsigned how_many_bits);
BOOL stw_make_current( HDC hdc, UINT_PTR hglrc );
BOOL stw_swap_buffers( HDC hdc );
BOOL
stw_swap_layer_buffers( HDC hdc, UINT fuPlanes );
PROC stw_get_proc_address( LPCSTR lpszProc );
int stw_pixelformat_describe( HDC hdc,
int iPixelFormat,
UINT nBytes,
LPPIXELFORMATDESCRIPTOR ppfd );
int stw_pixelformat_get( HDC hdc );
BOOL stw_pixelformat_set( HDC hdc,
int iPixelFormat );
int stw_pixelformat_choose( HDC hdc,
CONST PIXELFORMATDESCRIPTOR *ppfd );
#endif
#endif /* vl_bitstream_parser_h */

View file

@ -0,0 +1,532 @@
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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 TUNGSTEN GRAPHICS 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 "vl_compositor.h"
#include <assert.h>
#include <pipe/p_context.h>
#include <pipe/p_inlines.h>
#include <tgsi/tgsi_parse.h>
#include <tgsi/tgsi_build.h>
#include <util/u_memory.h>
#include "vl_csc.h"
#include "vl_shader_build.h"
struct vertex2f
{
float x, y;
};
struct vertex4f
{
float x, y, z, w;
};
struct vertex_shader_consts
{
struct vertex4f dst_scale;
struct vertex4f dst_trans;
struct vertex4f src_scale;
struct vertex4f src_trans;
};
struct fragment_shader_consts
{
float matrix[16];
};
/*
* Represents 2 triangles in a strip in normalized coords.
* Used to render the surface onto the frame buffer.
*/
static const struct vertex2f surface_verts[4] =
{
{0.0f, 0.0f},
{0.0f, 1.0f},
{1.0f, 0.0f},
{1.0f, 1.0f}
};
/*
* Represents texcoords for the above. We can use the position values directly.
* TODO: Duplicate these in the shader, no need to create a buffer.
*/
static const struct vertex2f *surface_texcoords = surface_verts;
static void
create_vert_shader(struct vl_compositor *c)
{
const unsigned max_tokens = 50;
struct pipe_shader_state vs;
struct tgsi_token *tokens;
struct tgsi_header *header;
struct tgsi_full_declaration decl;
struct tgsi_full_instruction inst;
unsigned ti;
unsigned i;
assert(c);
tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token));
*(struct tgsi_version*)&tokens[0] = tgsi_build_version();
header = (struct tgsi_header*)&tokens[1];
*header = tgsi_build_header();
*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
ti = 3;
/*
* decl i0 ; Vertex pos
* decl i1 ; Vertex texcoords
*/
for (i = 0; i < 2; i++) {
decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
}
/*
* decl c0 ; Scaling vector to scale vertex pos rect to destination size
* decl c1 ; Translation vector to move vertex pos rect into position
* decl c2 ; Scaling vector to scale texcoord rect to source size
* decl c3 ; Translation vector to move texcoord rect into position
*/
decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
/*
* decl o0 ; Vertex pos
* decl o1 ; Vertex texcoords
*/
for (i = 0; i < 2; i++) {
decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
}
/* decl t0, t1 */
decl = vl_decl_temps(0, 1);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
/*
* mad o0, i0, c0, c1 ; Scale and translate unit output rect to destination size and pos
* mad o1, i1, c2, c3 ; Scale and translate unit texcoord rect to source size and pos
*/
for (i = 0; i < 2; ++i) {
inst = vl_inst4(TGSI_OPCODE_MAD, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i, TGSI_FILE_CONSTANT, i * 2, TGSI_FILE_CONSTANT, i * 2 + 1);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
}
/* end */
inst = vl_end();
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
assert(ti <= max_tokens);
vs.tokens = tokens;
c->vertex_shader = c->pipe->create_vs_state(c->pipe, &vs);
FREE(tokens);
}
static void
create_frag_shader(struct vl_compositor *c)
{
const unsigned max_tokens = 50;
struct pipe_shader_state fs;
struct tgsi_token *tokens;
struct tgsi_header *header;
struct tgsi_full_declaration decl;
struct tgsi_full_instruction inst;
unsigned ti;
unsigned i;
assert(c);
tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token));
*(struct tgsi_version*)&tokens[0] = tgsi_build_version();
header = (struct tgsi_header*)&tokens[1];
*header = tgsi_build_header();
*(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
ti = 3;
/* decl i0 ; Texcoords for s0 */
decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
/*
* decl c0-c3 ; CSC matrix c0-c3
*/
decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
/* decl o0 ; Fragment color */
decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
/* decl t0 */
decl = vl_decl_temps(0, 0);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
/* decl s0 ; Sampler for tex containing picture to display */
decl = vl_decl_samplers(0, 0);
ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
/* tex2d t0, i0, s0 ; Read src pixel */
inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0);
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
/*
* dp4 o0.x, t0, c0 ; Multiply pixel by the color conversion matrix
* dp4 o0.y, t0, c1
* dp4 o0.z, t0, c2
* dp4 o0.w, t0, c3
*/
for (i = 0; i < 4; ++i) {
inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i);
inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
}
/* end */
inst = vl_end();
ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
assert(ti <= max_tokens);
fs.tokens = tokens;
c->fragment_shader = c->pipe->create_fs_state(c->pipe, &fs);
FREE(tokens);
}
static bool
init_pipe_state(struct vl_compositor *c)
{
struct pipe_sampler_state sampler;
assert(c);
c->fb_state.nr_cbufs = 1;
c->fb_state.zsbuf = NULL;
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
/*sampler.prefilter = ;*/
/*sampler.lod_bias = ;*/
/*sampler.min_lod = ;*/
/*sampler.max_lod = ;*/
/*sampler.border_color[i] = ;*/
/*sampler.max_anisotropy = ;*/
c->sampler = c->pipe->create_sampler_state(c->pipe, &sampler);
return true;
}
static void cleanup_pipe_state(struct vl_compositor *c)
{
assert(c);
c->pipe->delete_sampler_state(c->pipe, c->sampler);
}
static bool
init_shaders(struct vl_compositor *c)
{
assert(c);
create_vert_shader(c);
create_frag_shader(c);
return true;
}
static void cleanup_shaders(struct vl_compositor *c)
{
assert(c);
c->pipe->delete_vs_state(c->pipe, c->vertex_shader);
c->pipe->delete_fs_state(c->pipe, c->fragment_shader);
}
static bool
init_buffers(struct vl_compositor *c)
{
struct fragment_shader_consts fsc;
assert(c);
/*
* Create our vertex buffer and vertex buffer element
* VB contains 4 vertices that render a quad covering the entire window
* to display a rendered surface
* Quad is rendered as a tri strip
*/
c->vertex_bufs[0].stride = sizeof(struct vertex2f);
c->vertex_bufs[0].max_index = 3;
c->vertex_bufs[0].buffer_offset = 0;
c->vertex_bufs[0].buffer = pipe_buffer_create
(
c->pipe->screen,
1,
PIPE_BUFFER_USAGE_VERTEX,
sizeof(struct vertex2f) * 4
);
memcpy
(
pipe_buffer_map(c->pipe->screen, c->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
surface_verts,
sizeof(struct vertex2f) * 4
);
pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[0].buffer);
c->vertex_elems[0].src_offset = 0;
c->vertex_elems[0].vertex_buffer_index = 0;
c->vertex_elems[0].nr_components = 2;
c->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
/*
* Create our texcoord buffer and texcoord buffer element
* Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices
*/
c->vertex_bufs[1].stride = sizeof(struct vertex2f);
c->vertex_bufs[1].max_index = 3;
c->vertex_bufs[1].buffer_offset = 0;
c->vertex_bufs[1].buffer = pipe_buffer_create
(
c->pipe->screen,
1,
PIPE_BUFFER_USAGE_VERTEX,
sizeof(struct vertex2f) * 4
);
memcpy
(
pipe_buffer_map(c->pipe->screen, c->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
surface_texcoords,
sizeof(struct vertex2f) * 4
);
pipe_buffer_unmap(c->pipe->screen, c->vertex_bufs[1].buffer);
c->vertex_elems[1].src_offset = 0;
c->vertex_elems[1].vertex_buffer_index = 1;
c->vertex_elems[1].nr_components = 2;
c->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
/*
* Create our vertex shader's constant buffer
* Const buffer contains scaling and translation vectors
*/
c->vs_const_buf.buffer = pipe_buffer_create
(
c->pipe->screen,
1,
PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD,
sizeof(struct vertex_shader_consts)
);
/*
* Create our fragment shader's constant buffer
* Const buffer contains the color conversion matrix and bias vectors
*/
c->fs_const_buf.buffer = pipe_buffer_create
(
c->pipe->screen,
1,
PIPE_BUFFER_USAGE_CONSTANT,
sizeof(struct fragment_shader_consts)
);
vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, fsc.matrix);
vl_compositor_set_csc_matrix(c, fsc.matrix);
return true;
}
static void
cleanup_buffers(struct vl_compositor *c)
{
unsigned i;
assert(c);
for (i = 0; i < 2; ++i)
pipe_buffer_reference(&c->vertex_bufs[i].buffer, NULL);
pipe_buffer_reference(&c->vs_const_buf.buffer, NULL);
pipe_buffer_reference(&c->fs_const_buf.buffer, NULL);
}
bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe)
{
assert(compositor);
memset(compositor, 0, sizeof(struct vl_compositor));
compositor->pipe = pipe;
if (!init_pipe_state(compositor))
return false;
if (!init_shaders(compositor)) {
cleanup_pipe_state(compositor);
return false;
}
if (!init_buffers(compositor)) {
cleanup_shaders(compositor);
cleanup_pipe_state(compositor);
return false;
}
return true;
}
void vl_compositor_cleanup(struct vl_compositor *compositor)
{
assert(compositor);
cleanup_buffers(compositor);
cleanup_shaders(compositor);
cleanup_pipe_state(compositor);
}
void vl_compositor_render(struct vl_compositor *compositor,
/*struct pipe_texture *backround,
struct pipe_video_rect *backround_area,*/
struct pipe_texture *src_surface,
enum pipe_mpeg12_picture_type picture_type,
/*unsigned num_past_surfaces,
struct pipe_texture *past_surfaces,
unsigned num_future_surfaces,
struct pipe_texture *future_surfaces,*/
struct pipe_video_rect *src_area,
struct pipe_texture *dst_surface,
struct pipe_video_rect *dst_area,
/*unsigned num_layers,
struct pipe_texture *layers,
struct pipe_video_rect *layer_src_areas,
struct pipe_video_rect *layer_dst_areas*/
struct pipe_fence_handle **fence)
{
struct vertex_shader_consts *vs_consts;
assert(compositor);
assert(src_surface);
assert(src_area);
assert(dst_surface);
assert(dst_area);
assert(picture_type == PIPE_MPEG12_PICTURE_TYPE_FRAME);
compositor->fb_state.width = dst_surface->width[0];
compositor->fb_state.height = dst_surface->height[0];
compositor->fb_state.cbufs[0] = compositor->pipe->screen->get_tex_surface
(
compositor->pipe->screen,
dst_surface,
0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE
);
compositor->viewport.scale[0] = compositor->fb_state.width;
compositor->viewport.scale[1] = compositor->fb_state.height;
compositor->viewport.scale[2] = 1;
compositor->viewport.scale[3] = 1;
compositor->viewport.translate[0] = 0;
compositor->viewport.translate[1] = 0;
compositor->viewport.translate[2] = 0;
compositor->viewport.translate[3] = 0;
compositor->pipe->set_framebuffer_state(compositor->pipe, &compositor->fb_state);
compositor->pipe->set_viewport_state(compositor->pipe, &compositor->viewport);
compositor->pipe->bind_sampler_states(compositor->pipe, 1, &compositor->sampler);
compositor->pipe->set_sampler_textures(compositor->pipe, 1, &src_surface);
compositor->pipe->bind_vs_state(compositor->pipe, compositor->vertex_shader);
compositor->pipe->bind_fs_state(compositor->pipe, compositor->fragment_shader);
compositor->pipe->set_vertex_buffers(compositor->pipe, 2, compositor->vertex_bufs);
compositor->pipe->set_vertex_elements(compositor->pipe, 2, compositor->vertex_elems);
compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_VERTEX, 0, &compositor->vs_const_buf);
compositor->pipe->set_constant_buffer(compositor->pipe, PIPE_SHADER_FRAGMENT, 0, &compositor->fs_const_buf);
vs_consts = pipe_buffer_map
(
compositor->pipe->screen,
compositor->vs_const_buf.buffer,
PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
);
vs_consts->dst_scale.x = dst_area->w / (float)compositor->fb_state.cbufs[0]->width;
vs_consts->dst_scale.y = dst_area->h / (float)compositor->fb_state.cbufs[0]->height;
vs_consts->dst_scale.z = 1;
vs_consts->dst_scale.w = 1;
vs_consts->dst_trans.x = dst_area->x / (float)compositor->fb_state.cbufs[0]->width;
vs_consts->dst_trans.y = dst_area->y / (float)compositor->fb_state.cbufs[0]->height;
vs_consts->dst_trans.z = 0;
vs_consts->dst_trans.w = 0;
vs_consts->src_scale.x = src_area->w / (float)src_surface->width[0];
vs_consts->src_scale.y = src_area->h / (float)src_surface->height[0];
vs_consts->src_scale.z = 1;
vs_consts->src_scale.w = 1;
vs_consts->src_trans.x = src_area->x / (float)src_surface->width[0];
vs_consts->src_trans.y = src_area->y / (float)src_surface->height[0];
vs_consts->src_trans.z = 0;
vs_consts->src_trans.w = 0;
pipe_buffer_unmap(compositor->pipe->screen, compositor->vs_const_buf.buffer);
compositor->pipe->draw_arrays(compositor->pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
compositor->pipe->flush(compositor->pipe, PIPE_FLUSH_RENDER_CACHE, fence);
pipe_surface_reference(&compositor->fb_state.cbufs[0], NULL);
}
void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat)
{
assert(compositor);
memcpy
(
pipe_buffer_map(compositor->pipe->screen, compositor->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
mat,
sizeof(struct fragment_shader_consts)
);
pipe_buffer_unmap(compositor->pipe->screen, compositor->fs_const_buf.buffer);
}

View file

@ -0,0 +1,76 @@
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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 TUNGSTEN GRAPHICS 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.
*
**************************************************************************/
#ifndef vl_compositor_h
#define vl_compositor_h
#include <pipe/p_compiler.h>
#include <pipe/p_state.h>
#include <pipe/p_video_state.h>
struct pipe_context;
struct pipe_texture;
struct vl_compositor
{
struct pipe_context *pipe;
struct pipe_framebuffer_state fb_state;
void *sampler;
void *vertex_shader;
void *fragment_shader;
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_bufs[2];
struct pipe_vertex_element vertex_elems[2];
struct pipe_constant_buffer vs_const_buf, fs_const_buf;
};
bool vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe);
void vl_compositor_cleanup(struct vl_compositor *compositor);
void vl_compositor_render(struct vl_compositor *compositor,
/*struct pipe_texture *backround,
struct pipe_video_rect *backround_area,*/
struct pipe_texture *src_surface,
enum pipe_mpeg12_picture_type picture_type,
/*unsigned num_past_surfaces,
struct pipe_texture *past_surfaces,
unsigned num_future_surfaces,
struct pipe_texture *future_surfaces,*/
struct pipe_video_rect *src_area,
struct pipe_texture *dst_surface,
struct pipe_video_rect *dst_area,
/*unsigned num_layers,
struct pipe_texture *layers,
struct pipe_video_rect *layer_src_areas,
struct pipe_video_rect *layer_dst_areas,*/
struct pipe_fence_handle **fence);
void vl_compositor_set_csc_matrix(struct vl_compositor *compositor, const float *mat);
#endif /* vl_compositor_h */

View file

@ -0,0 +1,206 @@
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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 TUNGSTEN GRAPHICS 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 "vl_csc.h"
#include <util/u_math.h>
#include <util/u_debug.h>
/*
* Color space conversion formulas
*
* To convert YCbCr to RGB,
* vec4 ycbcr, rgb
* mat44 csc
* rgb = csc * ycbcr
*
* To calculate the color space conversion matrix csc with ProcAmp adjustments,
* mat44 csc, cstd, procamp, bias
* csc = cstd * (procamp * bias)
*
* Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc)
* adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full),
* bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full)
*
* To calculate procamp,
* mat44 procamp, hue, saturation, brightness, contrast
* procamp = brightness * (saturation * (contrast * hue))
* Alternatively,
* procamp = saturation * (brightness * (contrast * hue))
*
* contrast
* [ c, 0, 0, 0]
* [ 0, c, 0, 0]
* [ 0, 0, c, 0]
* [ 0, 0, 0, 1]
*
* brightness
* [ 1, 0, 0, b]
* [ 0, 1, 0, 0]
* [ 0, 0, 1, 0]
* [ 0, 0, 0, 1]
*
* saturation
* [ 1, 0, 0, 0]
* [ 0, s, 0, 0]
* [ 0, 0, s, 0]
* [ 0, 0, 0, 1]
*
* hue
* [ 1, 0, 0, 0]
* [ 0, cos(h), sin(h), 0]
* [ 0, -sin(h), cos(h), 0]
* [ 0, 0, 0, 1]
*
* procamp
* [ c, 0, 0, b]
* [ 0, c*s*cos(h), c*s*sin(h), 0]
* [ 0, -c*s*sin(h), c*s*cos(h), 0]
* [ 0, 0, 0, 1]
*
* bias
* [ 1, 0, 0, ybias]
* [ 0, 1, 0, cbbias]
* [ 0, 0, 1, crbias]
* [ 0, 0, 0, 1]
*
* csc
* [ c*cstd[ 0], c*cstd[ 1]*s*cos(h) - c*cstd[ 2]*s*sin(h), c*cstd[ 2]*s*cos(h) + c*cstd[ 1]*s*sin(h), cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 2]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
* [ c*cstd[ 4], c*cstd[ 5]*s*cos(h) - c*cstd[ 6]*s*sin(h), c*cstd[ 6]*s*cos(h) + c*cstd[ 5]*s*sin(h), cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 6]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
* [ c*cstd[ 8], c*cstd[ 9]*s*cos(h) - c*cstd[10]*s*sin(h), c*cstd[10]*s*cos(h) + c*cstd[ 9]*s*sin(h), cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[10]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
* [ c*cstd[12], c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h), c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h), cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
*/
/*
* Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [16,235]
*/
static const float bt_601[16] =
{
1.0f, 0.0f, 1.371f, 0.0f,
1.0f, -0.336f, -0.698f, 0.0f,
1.0f, 1.732f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
/*
* Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [0,255]
*/
static const float bt_601_full[16] =
{
1.164f, 0.0f, 1.596f, 0.0f,
1.164f, -0.391f, -0.813f, 0.0f,
1.164f, 2.018f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
/*
* Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [16,235]
*/
static const float bt_709[16] =
{
1.0f, 0.0f, 1.540f, 0.0f,
1.0f, -0.183f, -0.459f, 0.0f,
1.0f, 1.816f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
/*
* Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [0,255]
*/
static const float bt_709_full[16] =
{
1.164f, 0.0f, 1.793f, 0.0f,
1.164f, -0.213f, -0.534f, 0.0f,
1.164f, 2.115f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
static const float identity[16] =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
struct vl_procamp *procamp,
bool full_range,
float *matrix)
{
float ybias = full_range ? -16.0f/255.0f : 0.0f;
float cbbias = -128.0f/255.0f;
float crbias = -128.0f/255.0f;
float c = procamp ? procamp->contrast : 1.0f;
float s = procamp ? procamp->saturation : 1.0f;
float b = procamp ? procamp->brightness : 0.0f;
float h = procamp ? procamp->hue : 0.0f;
const float *cstd;
assert(matrix);
switch (cs) {
case VL_CSC_COLOR_STANDARD_BT_601:
cstd = full_range ? &bt_601_full[0] : &bt_601[0];
break;
case VL_CSC_COLOR_STANDARD_BT_709:
cstd = full_range ? &bt_709_full[0] : &bt_709[0];
break;
case VL_CSC_COLOR_STANDARD_IDENTITY:
default:
assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY);
memcpy(matrix, &identity[0], sizeof(float) * 16);
return;
}
matrix[ 0] = c*cstd[ 0];
matrix[ 1] = c*cstd[ 1]*s*cosf(h) - c*cstd[ 2]*s*sinf(h);
matrix[ 2] = c*cstd[ 2]*s*cosf(h) + c*cstd[ 1]*s*sinf(h);
matrix[ 3] = cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 2]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h));
matrix[ 4] = c*cstd[ 4];
matrix[ 5] = c*cstd[ 5]*s*cosf(h) - c*cstd[ 6]*s*sinf(h);
matrix[ 6] = c*cstd[ 6]*s*cosf(h) + c*cstd[ 5]*s*sinf(h);
matrix[ 7] = cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[ 6]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h));
matrix[ 8] = c*cstd[ 8];
matrix[ 9] = c*cstd[ 9]*s*cosf(h) - c*cstd[10]*s*sinf(h);
matrix[10] = c*cstd[10]*s*cosf(h) + c*cstd[ 9]*s*sinf(h);
matrix[11] = cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cosf(h) + c*crbias*s*sinf(h)) + cstd[10]*(c*crbias*s*cosf(h) - c*cbbias*s*sinf(h));
matrix[12] = c*cstd[12];
matrix[13] = c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h);
matrix[14] = c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h);
matrix[15] = cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h));
}

View file

@ -1,8 +1,8 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
*
* Copyright 2009 Younes Manton.
* 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
@ -10,11 +10,11 @@
* 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.
@ -22,44 +22,32 @@
* 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 STW_WINSYS_H
#define STW_WINSYS_H
#ifndef vl_csc_h
#define vl_csc_h
#include <windows.h> /* for HDC */
#include <pipe/p_compiler.h>
#include "pipe/p_compiler.h"
struct pipe_screen;
struct pipe_context;
struct pipe_surface;
struct stw_winsys
struct vl_procamp
{
struct pipe_screen *
(*create_screen)( void );
struct pipe_context *
(*create_context)( struct pipe_screen *screen );
void
(*flush_frontbuffer)( struct pipe_screen *screen,
struct pipe_surface *surf,
HDC hDC );
float brightness;
float contrast;
float saturation;
float hue;
};
boolean
stw_init(const struct stw_winsys *stw_winsys);
enum VL_CSC_COLOR_STANDARD
{
VL_CSC_COLOR_STANDARD_IDENTITY,
VL_CSC_COLOR_STANDARD_BT_601,
VL_CSC_COLOR_STANDARD_BT_709
};
boolean
stw_init_thread(void);
void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
struct vl_procamp *procamp,
bool full_range,
float *matrix);
void
stw_cleanup_thread(void);
void
stw_cleanup(void);
#endif /* STW_WINSYS_H */
#endif /* vl_csc_h */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,120 @@
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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 TUNGSTEN GRAPHICS 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.
*
**************************************************************************/
#ifndef vl_mpeg12_mc_renderer_h
#define vl_mpeg12_mc_renderer_h
#include <pipe/p_compiler.h>
#include <pipe/p_state.h>
#include <pipe/p_video_state.h>
struct pipe_context;
struct pipe_video_surface;
struct pipe_macroblock;
/* A slice is video-width (rounded up to a multiple of macroblock width) x macroblock height */
enum VL_MPEG12_MC_RENDERER_BUFFER_MODE
{
VL_MPEG12_MC_RENDERER_BUFFER_SLICE, /* Saves memory at the cost of smaller batches */
VL_MPEG12_MC_RENDERER_BUFFER_PICTURE /* Larger batches, more memory */
};
enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK
{
VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL, /* Waste of memory bandwidth */
VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE, /* Can only do point-filtering when interpolating subsampled chroma channels */
VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE /* Needs conditional texel fetch! */
};
struct vl_mpeg12_mc_renderer
{
struct pipe_context *pipe;
unsigned picture_width;
unsigned picture_height;
enum pipe_video_chroma_format chroma_format;
enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode;
enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling;
bool pot_buffers;
unsigned macroblocks_per_batch;
struct pipe_viewport_state viewport;
struct pipe_constant_buffer vs_const_buf;
struct pipe_constant_buffer fs_const_buf;
struct pipe_framebuffer_state fb_state;
struct pipe_vertex_element vertex_elems[8];
union
{
void *all[5];
struct { void *y, *cb, *cr, *ref[2]; } individual;
} samplers;
void *i_vs, *p_vs[2], *b_vs[2];
void *i_fs, *p_fs[2], *b_fs[2];
union
{
struct pipe_texture *all[5];
struct { struct pipe_texture *y, *cb, *cr, *ref[2]; } individual;
} textures;
union
{
struct pipe_vertex_buffer all[3];
struct { struct pipe_vertex_buffer ycbcr, ref[2]; } individual;
} vertex_bufs;
struct pipe_texture *surface, *past, *future;
struct pipe_fence_handle **fence;
unsigned num_macroblocks;
struct pipe_mpeg12_macroblock *macroblock_buf;
struct pipe_transfer *tex_transfer[3];
short *texels[3];
struct { float x, y; } surface_tex_inv_size;
struct { float x, y; } zero_block[3];
};
bool vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
struct pipe_context *pipe,
unsigned picture_width,
unsigned picture_height,
enum pipe_video_chroma_format chroma_format,
enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
bool pot_buffers);
void vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer);
void vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer *renderer,
struct pipe_texture *surface,
struct pipe_texture *past,
struct pipe_texture *future,
unsigned num_macroblocks,
struct pipe_mpeg12_macroblock *mpeg12_macroblocks,
struct pipe_fence_handle **fence);
#endif /* vl_mpeg12_mc_renderer_h */

View file

@ -0,0 +1,242 @@
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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 TUNGSTEN GRAPHICS 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 "vl_shader_build.h"
#include <assert.h>
#include <tgsi/tgsi_parse.h>
#include <tgsi/tgsi_build.h>
struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
{
struct tgsi_full_declaration decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = name;
decl.Semantic.SemanticIndex = index;
decl.DeclarationRange.First = first;
decl.DeclarationRange.Last = last;
return decl;
}
struct tgsi_full_declaration vl_decl_interpolated_input
(
unsigned int name,
unsigned int index,
unsigned int first,
unsigned int last,
int interpolation
)
{
struct tgsi_full_declaration decl = tgsi_default_full_declaration();
assert
(
interpolation == TGSI_INTERPOLATE_CONSTANT ||
interpolation == TGSI_INTERPOLATE_LINEAR ||
interpolation == TGSI_INTERPOLATE_PERSPECTIVE
);
decl.Declaration.File = TGSI_FILE_INPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = name;
decl.Semantic.SemanticIndex = index;
decl.Declaration.Interpolate = interpolation;;
decl.DeclarationRange.First = first;
decl.DeclarationRange.Last = last;
return decl;
}
struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
{
struct tgsi_full_declaration decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_CONSTANT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = name;
decl.Semantic.SemanticIndex = index;
decl.DeclarationRange.First = first;
decl.DeclarationRange.Last = last;
return decl;
}
struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last)
{
struct tgsi_full_declaration decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_OUTPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.SemanticName = name;
decl.Semantic.SemanticIndex = index;
decl.DeclarationRange.First = first;
decl.DeclarationRange.Last = last;
return decl;
}
struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last)
{
struct tgsi_full_declaration decl = tgsi_default_full_declaration();
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
decl.DeclarationRange.First = first;
decl.DeclarationRange.Last = last;
return decl;
}
struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last)
{
struct tgsi_full_declaration decl = tgsi_default_full_declaration();
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
decl.DeclarationRange.First = first;
decl.DeclarationRange.Last = last;
return decl;
}
struct tgsi_full_instruction vl_inst2
(
int opcode,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src_file,
unsigned int src_index
)
{
struct tgsi_full_instruction inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = opcode;
inst.Instruction.NumDstRegs = 1;
inst.FullDstRegisters[0].DstRegister.File = dst_file;
inst.FullDstRegisters[0].DstRegister.Index = dst_index;
inst.Instruction.NumSrcRegs = 1;
inst.FullSrcRegisters[0].SrcRegister.File = src_file;
inst.FullSrcRegisters[0].SrcRegister.Index = src_index;
return inst;
}
struct tgsi_full_instruction vl_inst3
(
int opcode,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src1_file,
unsigned int src1_index,
enum tgsi_file_type src2_file,
unsigned int src2_index
)
{
struct tgsi_full_instruction inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = opcode;
inst.Instruction.NumDstRegs = 1;
inst.FullDstRegisters[0].DstRegister.File = dst_file;
inst.FullDstRegisters[0].DstRegister.Index = dst_index;
inst.Instruction.NumSrcRegs = 2;
inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
return inst;
}
struct tgsi_full_instruction vl_tex
(
int tex,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src1_file,
unsigned int src1_index,
enum tgsi_file_type src2_file,
unsigned int src2_index
)
{
struct tgsi_full_instruction inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = TGSI_OPCODE_TEX;
inst.Instruction.NumDstRegs = 1;
inst.FullDstRegisters[0].DstRegister.File = dst_file;
inst.FullDstRegisters[0].DstRegister.Index = dst_index;
inst.Instruction.NumSrcRegs = 2;
inst.InstructionExtTexture.Texture = tex;
inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
return inst;
}
struct tgsi_full_instruction vl_inst4
(
int opcode,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src1_file,
unsigned int src1_index,
enum tgsi_file_type src2_file,
unsigned int src2_index,
enum tgsi_file_type src3_file,
unsigned int src3_index
)
{
struct tgsi_full_instruction inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = opcode;
inst.Instruction.NumDstRegs = 1;
inst.FullDstRegisters[0].DstRegister.File = dst_file;
inst.FullDstRegisters[0].DstRegister.Index = dst_index;
inst.Instruction.NumSrcRegs = 3;
inst.FullSrcRegisters[0].SrcRegister.File = src1_file;
inst.FullSrcRegisters[0].SrcRegister.Index = src1_index;
inst.FullSrcRegisters[1].SrcRegister.File = src2_file;
inst.FullSrcRegisters[1].SrcRegister.Index = src2_index;
inst.FullSrcRegisters[2].SrcRegister.File = src3_file;
inst.FullSrcRegisters[2].SrcRegister.Index = src3_index;
return inst;
}
struct tgsi_full_instruction vl_end(void)
{
struct tgsi_full_instruction inst = tgsi_default_full_instruction();
inst.Instruction.Opcode = TGSI_OPCODE_END;
inst.Instruction.NumDstRegs = 0;
inst.Instruction.NumSrcRegs = 0;
return inst;
}

View file

@ -0,0 +1,88 @@
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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 TUNGSTEN GRAPHICS 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.
*
**************************************************************************/
#ifndef vl_shader_build_h
#define vl_shader_build_h
#include <pipe/p_shader_tokens.h>
struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
struct tgsi_full_declaration vl_decl_interpolated_input
(
unsigned int name,
unsigned int index,
unsigned int first,
unsigned int last,
int interpolation
);
struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last);
struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last);
struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last);
struct tgsi_full_instruction vl_inst2
(
int opcode,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src_file,
unsigned int src_index
);
struct tgsi_full_instruction vl_inst3
(
int opcode,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src1_file,
unsigned int src1_index,
enum tgsi_file_type src2_file,
unsigned int src2_index
);
struct tgsi_full_instruction vl_tex
(
int tex,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src1_file,
unsigned int src1_index,
enum tgsi_file_type src2_file,
unsigned int src2_index
);
struct tgsi_full_instruction vl_inst4
(
int opcode,
enum tgsi_file_type dst_file,
unsigned int dst_index,
enum tgsi_file_type src1_file,
unsigned int src1_index,
enum tgsi_file_type src2_file,
unsigned int src2_index,
enum tgsi_file_type src3_file,
unsigned int src3_index
);
struct tgsi_full_instruction vl_end(void);
#endif

View file

@ -41,7 +41,7 @@
static const char *
cell_get_vendor(struct pipe_screen *screen)
{
return "Tungsten Graphics, Inc.";
return "VMware, Inc.";
}

View file

@ -389,22 +389,14 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
const uint texWidth = pt->width[level];
const uint texHeight = pt->height[level];
const uint stride = ct->stride[level];
unsigned flags = 0x0;
unsigned size;
assert(transfer->texture);
if (transfer->usage != PIPE_TRANSFER_READ) {
flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
}
if (transfer->usage != PIPE_TRANSFER_WRITE) {
flags |= PIPE_BUFFER_USAGE_CPU_READ;
}
if (!ct->mapped) {
/* map now */
ct->mapped = pipe_buffer_map(screen, ct->buffer, flags);
ct->mapped = pipe_buffer_map(screen, ct->buffer,
pipe_transfer_buffer_flags(transfer));
}
/*
@ -417,8 +409,7 @@ cell_transfer_map(struct pipe_screen *screen, struct pipe_transfer *transfer)
if (!ctrans->map)
return NULL; /* out of memory */
if (transfer->usage == PIPE_TRANSFER_READ ||
transfer->usage == PIPE_TRANSFER_READ_WRITE) {
if (transfer->usage & PIPE_TRANSFER_READ) {
/* need to untwiddle the texture to make a linear version */
const uint bpp = pf_get_size(ct->base.format);
if (bpp == 4) {
@ -459,8 +450,7 @@ cell_transfer_unmap(struct pipe_screen *screen,
PIPE_BUFFER_USAGE_CPU_READ);
}
if (transfer->usage == PIPE_TRANSFER_WRITE ||
transfer->usage == PIPE_TRANSFER_READ_WRITE) {
if (transfer->usage & PIPE_TRANSFER_WRITE) {
/* The user wrote new texture data into the mapped buffer.
* We need to convert the new linear data into the twiddled/tiled format.
*/

View file

@ -175,12 +175,19 @@ i915_is_buffer_referenced(struct pipe_context *pipe,
static void i915_destroy(struct pipe_context *pipe)
{
struct i915_context *i915 = i915_context(pipe);
int i;
draw_destroy(i915->draw);
if(i915->batch)
i915->iws->batchbuffer_destroy(i915->batch);
/* unbind framebuffer */
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
pipe_surface_reference(&i915->framebuffer.cbufs[i], NULL);
}
pipe_surface_reference(&i915->framebuffer.zsbuf, NULL);
FREE(i915);
}

View file

@ -198,7 +198,7 @@ i915_vbuf_render_map_vertices(struct vbuf_render *render)
struct intel_winsys *iws = i915->iws;
if (i915->vbo_flushed)
debug_printf("%s bad vbo flush occured stalling on hw\n");
debug_printf("%s bad vbo flush occured stalling on hw\n", __FUNCTION__);
i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE);
@ -389,14 +389,43 @@ i915_vbuf_render_draw_arrays(struct vbuf_render *render,
uint nr)
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
struct i915_context *i915 = i915_render->i915;
if (i915_render->fallback) {
draw_arrays_fallback(render, start, nr);
return;
}
/* JB: TODO submit direct cmds */
draw_arrays_fallback(render, start, nr);
if (i915->dirty)
i915_update_derived(i915);
if (i915->hardware_dirty)
i915_emit_hardware_state(i915);
if (!BEGIN_BATCH(2, 0)) {
FLUSH_BATCH(NULL);
/* Make sure state is re-emitted after a flush:
*/
i915_update_derived(i915);
i915_emit_hardware_state(i915);
i915->vbo_flushed = 1;
if (!BEGIN_BATCH(2, 0)) {
assert(0);
goto out;
}
}
OUT_BATCH(_3DPRIMITIVE |
PRIM_INDIRECT |
PRIM_INDIRECT_SEQUENTIAL |
i915_render->hwprim |
nr);
OUT_BATCH(start); /* Beginning vertex index */
out:
return;
}
/**

View file

@ -46,7 +46,7 @@
static const char *
i915_get_vendor(struct pipe_screen *screen)
{
return "Tungsten Graphics, Inc.";
return "VMware, Inc.";
}
static const char *

View file

@ -588,9 +588,17 @@ static void i915_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct i915_context *i915 = i915_context(pipe);
int i;
draw_flush(i915->draw);
i915->framebuffer = *fb; /* struct copy */
i915->framebuffer.width = fb->width;
i915->framebuffer.height = fb->height;
i915->framebuffer.nr_cbufs = fb->nr_cbufs;
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
pipe_surface_reference(&i915->framebuffer.cbufs[i], fb->cbufs[i]);
}
pipe_surface_reference(&i915->framebuffer.zsbuf, fb->zsbuf);
i915->dirty |= I915_NEW_FRAMEBUFFER;
}

Some files were not shown because too many files have changed in this diff Show more