Compare commits
245 Commits
mesa-17.0.
...
texman_0_1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ecd83f6cd | ||
|
|
cff7e025ed | ||
|
|
3de9a9bd1d | ||
|
|
e6cae6e6f6 | ||
|
|
9cf5945b83 | ||
|
|
d6ddc33f07 | ||
|
|
ec32d129b7 | ||
|
|
cd41c27446 | ||
|
|
af6a480117 | ||
|
|
14e9700621 | ||
|
|
7fb177c367 | ||
|
|
d65cda4ce3 | ||
|
|
460a375d85 | ||
|
|
c3c5652602 | ||
|
|
e1998baef8 | ||
|
|
3e980901b0 | ||
|
|
14fe63a12b | ||
|
|
fbd147c0b5 | ||
|
|
7b7c54e94c | ||
|
|
84dd9c8112 | ||
|
|
bba85343e7 | ||
|
|
6484b373c3 | ||
|
|
245a3c54c7 | ||
|
|
1266e633cc | ||
|
|
86042f53f2 | ||
|
|
068062f997 | ||
|
|
c62af8e3b7 | ||
|
|
8e5650d7f4 | ||
|
|
65f1cf2cbf | ||
|
|
f04f5e990a | ||
|
|
1854ebe77e | ||
|
|
3500f2e3c4 | ||
|
|
cfeefc9b81 | ||
|
|
3ad6adfb57 | ||
|
|
8a126f1166 | ||
|
|
6315aabcf2 | ||
|
|
a8c2344364 | ||
|
|
2929b2569b | ||
|
|
f14790d7b0 | ||
|
|
8fb2e61801 | ||
|
|
b3c94f9d9d | ||
|
|
5b889f7f2d | ||
|
|
0f531b5b48 | ||
|
|
c6482c0d41 | ||
|
|
b71748efd1 | ||
|
|
1c4b9edc41 | ||
|
|
2b464d93d1 | ||
|
|
497f80ac34 | ||
|
|
2be748769b | ||
|
|
45a1083ee7 | ||
|
|
3a45baa70d | ||
|
|
0bc3a7ac2e | ||
|
|
08f0579176 | ||
|
|
d689cd0715 | ||
|
|
e957f39f67 | ||
|
|
416f09d3e6 | ||
|
|
40cc5d36fd | ||
|
|
62f9613dbc | ||
|
|
7f31255eb2 | ||
|
|
78382b4bbe | ||
|
|
bd8e90857c | ||
|
|
b7cc448ff8 | ||
|
|
0ea582acbe | ||
|
|
05c824db87 | ||
|
|
829f6909bd | ||
|
|
34f1ebc72f | ||
|
|
c6e586ee0c | ||
|
|
9180d932c6 | ||
|
|
95df1b67a2 | ||
|
|
bc400c3f30 | ||
|
|
3a3db0e9ec | ||
|
|
613e395ab8 | ||
|
|
86c5de8b85 | ||
|
|
44c8c42ab9 | ||
|
|
31a82a663c | ||
|
|
dafdf6512e | ||
|
|
9caacb015a | ||
|
|
2887770534 | ||
|
|
fb440c9f82 | ||
|
|
576c9c310f | ||
|
|
ec1db9db1f | ||
|
|
e1f70cf5e2 | ||
|
|
a7cdbf5c38 | ||
|
|
fe37adfde3 | ||
|
|
315396ac6c | ||
|
|
a7252f42ae | ||
|
|
bffc66109e | ||
|
|
0089c7f4ee | ||
|
|
54f435340b | ||
|
|
66d887d605 | ||
|
|
c6dc5cc8ab | ||
|
|
e0412bb726 | ||
|
|
cc5cbd1bca | ||
|
|
93fbfa5781 | ||
|
|
30709caad6 | ||
|
|
a647198f65 | ||
|
|
7ad6ea6ff2 | ||
|
|
ceee2c45cd | ||
|
|
26dc161fde | ||
|
|
b176ef05f2 | ||
|
|
6d6e7a08c7 | ||
|
|
eb75ec2349 | ||
|
|
2a8bd4e329 | ||
|
|
c247268499 | ||
|
|
b2cb8920c2 | ||
|
|
af4d93f256 | ||
|
|
c8dd839acb | ||
|
|
e43c3c38fb | ||
|
|
9194782fdc | ||
|
|
ec36d5b537 | ||
|
|
6e5da1a860 | ||
|
|
21f6e8a2d0 | ||
|
|
18772c9e88 | ||
|
|
5df4283b53 | ||
|
|
6734bab3b2 | ||
|
|
0a5fea5f96 | ||
|
|
9b2762d7b9 | ||
|
|
571bf7a71b | ||
|
|
4ab3b9aa76 | ||
|
|
88c018ee47 | ||
|
|
cead52ef68 | ||
|
|
9cf0ed6059 | ||
|
|
2c1c8dccf7 | ||
|
|
b87f9f6056 | ||
|
|
427bf0171d | ||
|
|
98c5445c75 | ||
|
|
15ffb3bbab | ||
|
|
97b570b999 | ||
|
|
e8e6374a16 | ||
|
|
d9f31f16c0 | ||
|
|
1173198f51 | ||
|
|
01a56d23e6 | ||
|
|
bf050799ac | ||
|
|
3697eca493 | ||
|
|
de2b3506ea | ||
|
|
bfbe2eb6e9 | ||
|
|
8bd395f601 | ||
|
|
735925d15b | ||
|
|
448a3456a9 | ||
|
|
e176b11b74 | ||
|
|
cdc8771893 | ||
|
|
789399d3f4 | ||
|
|
dfa8624e83 | ||
|
|
36b64bbd4f | ||
|
|
651985f813 | ||
|
|
9f2b49a7b3 | ||
|
|
05c6361b0b | ||
|
|
9621817253 | ||
|
|
7e2e4a6b1a | ||
|
|
656c71ca3f | ||
|
|
6ce7055dcc | ||
|
|
c848a65b5e | ||
|
|
1ff99fcd50 | ||
|
|
67342052d2 | ||
|
|
ccf52b6784 | ||
|
|
78aa58c914 | ||
|
|
4291f24abd | ||
|
|
f4211722f1 | ||
|
|
71380a1325 | ||
|
|
33e55c6a7d | ||
|
|
cd32164cc6 | ||
|
|
7c1348ac8f | ||
|
|
2560061cfe | ||
|
|
0c047b8847 | ||
|
|
c64a08c286 | ||
|
|
bb409e88d8 | ||
|
|
af69eefcba | ||
|
|
d9c071adec | ||
|
|
833d19c21d | ||
|
|
7245757174 | ||
|
|
3d96cb7d48 | ||
|
|
f565ab2dd5 | ||
|
|
7ad0c51f48 | ||
|
|
fea684c533 | ||
|
|
4e8845fc0c | ||
|
|
ffcc1cdb41 | ||
|
|
afc90075ba | ||
|
|
79acea2708 | ||
|
|
a12063a540 | ||
|
|
9826d83439 | ||
|
|
84f7ded925 | ||
|
|
59dd8ad752 | ||
|
|
4afd26982e | ||
|
|
17e4a7ea17 | ||
|
|
3d67655cce | ||
|
|
b5d7c69884 | ||
|
|
b6759e2be7 | ||
|
|
af853b0da7 | ||
|
|
8d349798da | ||
|
|
4aea628194 | ||
|
|
008ddf628a | ||
|
|
716496f263 | ||
|
|
b3b325e560 | ||
|
|
382ce985ac | ||
|
|
54b7eca7a0 | ||
|
|
f74e06bf11 | ||
|
|
9c02649d18 | ||
|
|
2c34704e41 | ||
|
|
85d0041ff0 | ||
|
|
67ff8b354e | ||
|
|
08e7957571 | ||
|
|
9c1f7089d8 | ||
|
|
5381ac5f11 | ||
|
|
a6f78d4eee | ||
|
|
ae695e3566 | ||
|
|
c82c3335e1 | ||
|
|
f8246f504b | ||
|
|
499458bcdb | ||
|
|
37a53fd6a0 | ||
|
|
5ec38fb2ea | ||
|
|
11c0215bf8 | ||
|
|
6a13b6c346 | ||
|
|
a103097ee5 | ||
|
|
7efad0d84c | ||
|
|
42c88cd072 | ||
|
|
2541c54e79 | ||
|
|
33529e3d8e | ||
|
|
84c1b82081 | ||
|
|
a97a1439ae | ||
|
|
2fd2910010 | ||
|
|
fbbda155e0 | ||
|
|
a49c3c0fae | ||
|
|
baf5998d59 | ||
|
|
4c5acef241 | ||
|
|
9839e272cf | ||
|
|
b57e79ff14 | ||
|
|
43824acb4e | ||
|
|
d8f509e749 | ||
|
|
eb91c93c2e | ||
|
|
79de983b6f | ||
|
|
fdb3acf016 | ||
|
|
2807d1f58a | ||
|
|
93f913926e | ||
|
|
33ca04f379 | ||
|
|
398cb30c72 | ||
|
|
f67bb30314 | ||
|
|
4578d7b9f0 | ||
|
|
dcdfc154c3 | ||
|
|
696ba32779 | ||
|
|
dcfe55539f | ||
|
|
ff84b1f1b2 | ||
|
|
3bca9c47f4 | ||
|
|
d4d7fdb43b | ||
|
|
d65dab5777 | ||
|
|
638ca019ef |
@@ -10,9 +10,6 @@ MESA_MAJOR=6
|
||||
MESA_MINOR=5
|
||||
MESA_TINY=0
|
||||
|
||||
# external projects. This should be useless now that we use libdrm.
|
||||
DRM_SOURCE_PATH=$(TOP)/../drm
|
||||
|
||||
# Compiler and flags
|
||||
CC = cc
|
||||
CXX = CC
|
||||
|
||||
@@ -9,11 +9,12 @@ CONFIG_NAME = linux-dri
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
|
||||
MKDEP = /usr/X11R6/bin/makedepend
|
||||
#MKDEP = /usr/X11R6/bin/makedepend
|
||||
#MKDEP = gcc -M
|
||||
#MKDEP_OPTIONS = -MF depend
|
||||
|
||||
OPT_FLAGS = -g
|
||||
#OPT_FLAGS = -g -march=pentium4 -fprefetch-loop-arrays
|
||||
OPT_FLAGS = -O2
|
||||
PIC_FLAGS = -fPIC
|
||||
|
||||
# Add '-DGLX_USE_TLS' to ARCH_FLAGS to enable TLS support.
|
||||
@@ -22,6 +23,7 @@ ARCH_FLAGS ?=
|
||||
DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \
|
||||
-D_BSD_SOURCE -D_GNU_SOURCE \
|
||||
-DPTHREADS -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER \
|
||||
-DDEBUG \
|
||||
-DGLX_DIRECT_RENDERING -DHAVE_ALIAS
|
||||
|
||||
X11_INCLUDES = -I/usr/X11R6/include
|
||||
@@ -63,5 +65,7 @@ WINDOW_SYSTEM=dri
|
||||
|
||||
# gamma are missing because they have not been converted to use the new
|
||||
# interface.
|
||||
DRI_DIRS = i810 i830 i915 mach64 mga r128 r200 r300 radeon s3v \
|
||||
DRI_DIRS = i915 mach64 mga r128 r200 r300 radeon s3v \
|
||||
savage sis tdfx trident unichrome ffb
|
||||
|
||||
DRI_DIRS = i915
|
||||
|
||||
@@ -2260,6 +2260,28 @@ typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pnam
|
||||
|
||||
|
||||
|
||||
#ifndef GL_EXT_framebuffer_blit
|
||||
#define GL_EXT_framebuffer_blit 1
|
||||
|
||||
#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
|
||||
#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
|
||||
#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
|
||||
#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
|
||||
|
||||
GLAPI void GLAPIENTRY
|
||||
glBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter);
|
||||
|
||||
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC)
|
||||
(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter);
|
||||
|
||||
#endif /* GL_EXT_framebuffer_blit */
|
||||
|
||||
|
||||
|
||||
#ifndef GL_EXT_packed_depth_stencil
|
||||
#define GL_EXT_packed_depth_stencil 1
|
||||
|
||||
|
||||
@@ -20,11 +20,14 @@ PROGS = \
|
||||
clearspd \
|
||||
cubemap \
|
||||
drawpix \
|
||||
copypix \
|
||||
drawpix_pbo \
|
||||
fire \
|
||||
fogcoord \
|
||||
fplight \
|
||||
gamma \
|
||||
gears \
|
||||
gearbox \
|
||||
geartrain \
|
||||
glinfo \
|
||||
gloss \
|
||||
@@ -51,7 +54,7 @@ PROGS = \
|
||||
terrain \
|
||||
tessdemo \
|
||||
texcyl \
|
||||
texdown \
|
||||
texdown-pool \
|
||||
texenv \
|
||||
texobj \
|
||||
trispd \
|
||||
@@ -73,9 +76,8 @@ PROGS = \
|
||||
|
||||
##### TARGETS #####
|
||||
|
||||
default: $(PROGS)
|
||||
default: readtex.o $(PROGS)
|
||||
|
||||
$(PROGS): readtex.o
|
||||
|
||||
readtex.c: $(TOP)/progs/util/readtex.c
|
||||
cp $< .
|
||||
|
||||
364
progs/demos/copypix.c
Normal file
364
progs/demos/copypix.c
Normal file
@@ -0,0 +1,364 @@
|
||||
|
||||
/*
|
||||
* glDrawPixels demo/test/benchmark
|
||||
*
|
||||
* Brian Paul September 25, 1997 This file is in the public domain.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
#include "readtex.h"
|
||||
|
||||
#define IMAGE_FILE "../images/girl.rgb"
|
||||
|
||||
static int ImgWidth, ImgHeight;
|
||||
static GLenum ImgFormat;
|
||||
static GLubyte *Image = NULL;
|
||||
|
||||
static int Xpos, Ypos;
|
||||
static int SkipPixels, SkipRows;
|
||||
static int DrawWidth, DrawHeight;
|
||||
static int Scissor = 0;
|
||||
static int Fog = 0;
|
||||
static GLfloat Zpos = -1.0;
|
||||
static float Xzoom, Yzoom;
|
||||
static GLboolean DrawFront = GL_FALSE;
|
||||
static GLboolean Dither = GL_TRUE;
|
||||
|
||||
|
||||
static void Reset( void )
|
||||
{
|
||||
Xpos = Ypos = 20;
|
||||
DrawWidth = ImgWidth;
|
||||
DrawHeight = ImgHeight;
|
||||
SkipPixels = SkipRows = 0;
|
||||
Scissor = 0;
|
||||
Fog = 0;
|
||||
Zpos = -1.0;
|
||||
Xzoom = Yzoom = 1.0;
|
||||
}
|
||||
|
||||
|
||||
static void Display( void )
|
||||
{
|
||||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
|
||||
glRasterPos2i(10, 10);
|
||||
glPixelZoom( 1, 1 );
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_FOG);
|
||||
glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image);
|
||||
|
||||
#if 0
|
||||
glRasterPos2i(Xpos, Ypos);
|
||||
#else
|
||||
/* This allows negative raster positions: */
|
||||
glRasterPos3f(0, 0, Zpos);
|
||||
glBitmap(0, 0, 0, 0, Xpos, Ypos, NULL);
|
||||
#endif
|
||||
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
|
||||
|
||||
glPixelZoom( Xzoom, Yzoom );
|
||||
|
||||
if (Scissor)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
if (Fog)
|
||||
glEnable(GL_FOG);
|
||||
|
||||
glCopyPixels(10, 10, ImgWidth, ImgHeight, GL_COLOR);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_FOG);
|
||||
|
||||
if (DrawFront)
|
||||
glFinish();
|
||||
else
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
|
||||
static void Benchmark( void )
|
||||
{
|
||||
int startTime, endTime;
|
||||
int draws = 500;
|
||||
double seconds, pixelsPerSecond;
|
||||
|
||||
printf("Benchmarking...\n");
|
||||
/* GL set-up */
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
|
||||
glPixelZoom( Xzoom, Yzoom );
|
||||
if (Scissor)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
if (Fog)
|
||||
glEnable(GL_FOG);
|
||||
|
||||
if (DrawFront)
|
||||
glDrawBuffer(GL_FRONT);
|
||||
else
|
||||
glDrawBuffer(GL_BACK);
|
||||
|
||||
/* Run timing test */
|
||||
draws = 0;
|
||||
startTime = glutGet(GLUT_ELAPSED_TIME);
|
||||
do {
|
||||
glCopyPixels(10, 10, ImgWidth, ImgHeight, GL_COLOR);
|
||||
draws++;
|
||||
endTime = glutGet(GLUT_ELAPSED_TIME);
|
||||
} while (endTime - startTime < 4000); /* 4 seconds */
|
||||
|
||||
/* GL clean-up */
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_FOG);
|
||||
|
||||
/* Results */
|
||||
seconds = (double) (endTime - startTime) / 1000.0;
|
||||
pixelsPerSecond = draws * DrawWidth * DrawHeight / seconds;
|
||||
printf("Result: %d draws in %f seconds = %f pixels/sec\n",
|
||||
draws, seconds, pixelsPerSecond);
|
||||
}
|
||||
|
||||
|
||||
static void Reshape( int width, int height )
|
||||
{
|
||||
glViewport( 0, 0, width, height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glOrtho( 0.0, width, 0.0, height, 0.0, 2.0 );
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
glScissor(width/4, height/4, width/2, height/2);
|
||||
}
|
||||
|
||||
|
||||
static void Key( unsigned char key, int x, int y )
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case ' ':
|
||||
Reset();
|
||||
break;
|
||||
case 'd':
|
||||
Dither = !Dither;
|
||||
if (Dither)
|
||||
glEnable(GL_DITHER);
|
||||
else
|
||||
glDisable(GL_DITHER);
|
||||
break;
|
||||
case 'w':
|
||||
if (DrawWidth > 0)
|
||||
DrawWidth--;
|
||||
break;
|
||||
case 'W':
|
||||
DrawWidth++;
|
||||
break;
|
||||
case 'h':
|
||||
if (DrawHeight > 0)
|
||||
DrawHeight--;
|
||||
break;
|
||||
case 'H':
|
||||
DrawHeight++;
|
||||
break;
|
||||
case 'p':
|
||||
if (SkipPixels > 0)
|
||||
SkipPixels--;
|
||||
break;
|
||||
case 'P':
|
||||
SkipPixels++;
|
||||
break;
|
||||
case 'r':
|
||||
if (SkipRows > 0)
|
||||
SkipRows--;
|
||||
break;
|
||||
case 'R':
|
||||
SkipRows++;
|
||||
break;
|
||||
case 's':
|
||||
Scissor = !Scissor;
|
||||
break;
|
||||
case 'x':
|
||||
Xzoom -= 0.1;
|
||||
break;
|
||||
case 'X':
|
||||
Xzoom += 0.1;
|
||||
break;
|
||||
case 'y':
|
||||
Yzoom -= 0.1;
|
||||
break;
|
||||
case 'Y':
|
||||
Yzoom += 0.1;
|
||||
break;
|
||||
case 'z':
|
||||
Zpos -= 0.1;
|
||||
printf("RasterPos Z = %g\n", Zpos);
|
||||
break;
|
||||
case 'Z':
|
||||
Zpos += 0.1;
|
||||
printf("RasterPos Z = %g\n", Zpos);
|
||||
break;
|
||||
case 'b':
|
||||
Benchmark();
|
||||
break;
|
||||
case 'F':
|
||||
Fog = !Fog;
|
||||
printf("Fog %d\n", Fog);
|
||||
break;
|
||||
case 'f':
|
||||
DrawFront = !DrawFront;
|
||||
if (DrawFront)
|
||||
glDrawBuffer(GL_FRONT);
|
||||
else
|
||||
glDrawBuffer(GL_BACK);
|
||||
printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK");
|
||||
break;
|
||||
case 27:
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void SpecialKey( int key, int x, int y )
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case GLUT_KEY_UP:
|
||||
Ypos += 1;
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
Ypos -= 1;
|
||||
break;
|
||||
case GLUT_KEY_LEFT:
|
||||
Xpos -= 1;
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
Xpos += 1;
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void Init( GLboolean ciMode, const char *filename )
|
||||
{
|
||||
static const GLfloat fogColor[4] = {0, 1, 0, 0};
|
||||
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
|
||||
Image = LoadRGBImage( filename, &ImgWidth, &ImgHeight, &ImgFormat );
|
||||
if (!Image) {
|
||||
printf("Couldn't read %s\n", filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (ciMode) {
|
||||
/* Convert RGB image to grayscale */
|
||||
GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight );
|
||||
GLint i;
|
||||
for (i=0; i<ImgWidth*ImgHeight; i++) {
|
||||
int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2];
|
||||
indexImage[i] = gray / 3;
|
||||
}
|
||||
free(Image);
|
||||
Image = indexImage;
|
||||
ImgFormat = GL_COLOR_INDEX;
|
||||
|
||||
for (i=0;i<255;i++) {
|
||||
float g = i / 255.0;
|
||||
glutSetColor(i, g, g, g);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Loaded %d by %d image\n", ImgWidth, ImgHeight );
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth);
|
||||
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
glFogf(GL_FOG_START, 0);
|
||||
glFogf(GL_FOG_END, 2);
|
||||
glFogfv(GL_FOG_COLOR, fogColor);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
static void Usage(void)
|
||||
{
|
||||
printf("Keys:\n");
|
||||
printf(" SPACE Reset Parameters\n");
|
||||
printf(" Up/Down Move image up/down\n");
|
||||
printf(" Left/Right Move image left/right\n");
|
||||
printf(" x Decrease X-axis PixelZoom\n");
|
||||
printf(" X Increase X-axis PixelZoom\n");
|
||||
printf(" y Decrease Y-axis PixelZoom\n");
|
||||
printf(" Y Increase Y-axis PixelZoom\n");
|
||||
printf(" w Decrease glDrawPixels width*\n");
|
||||
printf(" W Increase glDrawPixels width*\n");
|
||||
printf(" h Decrease glDrawPixels height*\n");
|
||||
printf(" H Increase glDrawPixels height*\n");
|
||||
printf(" p Decrease GL_UNPACK_SKIP_PIXELS*\n");
|
||||
printf(" P Increase GL_UNPACK_SKIP_PIXELS*\n");
|
||||
printf(" r Decrease GL_UNPACK_SKIP_ROWS*\n");
|
||||
printf(" R Increase GL_UNPACK_SKIP_ROWS*\n");
|
||||
printf(" s Toggle GL_SCISSOR_TEST\n");
|
||||
printf(" F Toggle GL_FOG\n");
|
||||
printf(" z Decrease RasterPos Z\n");
|
||||
printf(" Z Increase RasterPos Z\n");
|
||||
|
||||
printf(" f Toggle front/back buffer drawing\n");
|
||||
printf(" b Benchmark test\n");
|
||||
printf(" ESC Exit\n");
|
||||
printf("* Warning: no limits are imposed on these parameters so it's\n");
|
||||
printf(" possible to cause a segfault if you go too far.\n");
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
GLboolean ciMode = GL_FALSE;
|
||||
const char *filename = IMAGE_FILE;
|
||||
int i = 1;
|
||||
|
||||
if (argc > i && strcmp(argv[i], "-ci")==0) {
|
||||
ciMode = GL_TRUE;
|
||||
i++;
|
||||
}
|
||||
if (argc > i) {
|
||||
filename = argv[i];
|
||||
}
|
||||
|
||||
glutInit( &argc, argv );
|
||||
glutInitWindowPosition( 0, 0 );
|
||||
glutInitWindowSize( 500, 400 );
|
||||
|
||||
if (ciMode)
|
||||
glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE );
|
||||
else
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
|
||||
|
||||
glutCreateWindow(argv[0]);
|
||||
|
||||
Init(ciMode, filename);
|
||||
Usage();
|
||||
|
||||
glutReshapeFunc( Reshape );
|
||||
glutKeyboardFunc( Key );
|
||||
glutSpecialFunc( SpecialKey );
|
||||
glutDisplayFunc( Display );
|
||||
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
376
progs/demos/drawpix_pbo.c
Normal file
376
progs/demos/drawpix_pbo.c
Normal file
@@ -0,0 +1,376 @@
|
||||
|
||||
/*
|
||||
* glDrawPixels demo/test/benchmark
|
||||
*
|
||||
* Brian Paul September 25, 1997 This file is in the public domain.
|
||||
*/
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
#include "readtex.h"
|
||||
|
||||
#define IMAGE_FILE "../images/tree2.rgba"
|
||||
|
||||
static int ImgWidth, ImgHeight;
|
||||
static GLenum ImgFormat;
|
||||
static GLenum ImgType = GL_UNSIGNED_BYTE;
|
||||
static GLubyte *Image = NULL;
|
||||
|
||||
static int Xpos, Ypos;
|
||||
static int SkipPixels, SkipRows;
|
||||
static int DrawWidth, DrawHeight;
|
||||
static int Scissor = 0;
|
||||
static int Fog = 0;
|
||||
static GLfloat Zpos = -1.0;
|
||||
static float Xzoom, Yzoom;
|
||||
static GLboolean DrawFront = GL_FALSE;
|
||||
static GLboolean Dither = GL_TRUE;
|
||||
|
||||
|
||||
static GLuint DrawPBO;
|
||||
|
||||
|
||||
static void Reset( void )
|
||||
{
|
||||
Xpos = Ypos = 20;
|
||||
DrawWidth = ImgWidth;
|
||||
DrawHeight = ImgHeight;
|
||||
SkipPixels = SkipRows = 0;
|
||||
Scissor = 0;
|
||||
Fog = 0;
|
||||
Zpos = -1.0;
|
||||
Xzoom = Yzoom = 1.0;
|
||||
}
|
||||
|
||||
|
||||
static void Display( void )
|
||||
{
|
||||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
|
||||
#if 0
|
||||
glRasterPos2i(Xpos, Ypos);
|
||||
#else
|
||||
/* This allows negative raster positions: */
|
||||
glRasterPos3f(0, 0, Zpos);
|
||||
glBitmap(0, 0, 0, 0, Xpos, Ypos, NULL);
|
||||
#endif
|
||||
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
|
||||
|
||||
glPixelZoom( Xzoom, Yzoom );
|
||||
|
||||
if (Scissor)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
if (Fog)
|
||||
glEnable(GL_FOG);
|
||||
|
||||
/*** Draw from the DrawPBO */
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
|
||||
glDrawPixels(DrawWidth, DrawHeight, ImgFormat, ImgType, NULL);
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_FOG);
|
||||
|
||||
if (DrawFront)
|
||||
glFinish();
|
||||
else
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
|
||||
static void Benchmark( void )
|
||||
{
|
||||
int startTime, endTime;
|
||||
int draws = 500;
|
||||
double seconds, pixelsPerSecond;
|
||||
|
||||
printf("Benchmarking...\n");
|
||||
/* GL set-up */
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels);
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows);
|
||||
glPixelZoom( Xzoom, Yzoom );
|
||||
if (Scissor)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
if (Fog)
|
||||
glEnable(GL_FOG);
|
||||
|
||||
if (DrawFront)
|
||||
glDrawBuffer(GL_FRONT);
|
||||
else
|
||||
glDrawBuffer(GL_BACK);
|
||||
|
||||
/* Run timing test */
|
||||
draws = 0;
|
||||
startTime = glutGet(GLUT_ELAPSED_TIME);
|
||||
do {
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
|
||||
glDrawPixels(DrawWidth, DrawHeight, ImgFormat, ImgType, NULL);
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||
draws++;
|
||||
endTime = glutGet(GLUT_ELAPSED_TIME);
|
||||
} while (endTime - startTime < 4000); /* 4 seconds */
|
||||
|
||||
/* GL clean-up */
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_FOG);
|
||||
|
||||
/* Results */
|
||||
seconds = (double) (endTime - startTime) / 1000.0;
|
||||
pixelsPerSecond = draws * DrawWidth * DrawHeight / seconds;
|
||||
printf("Result: %d draws in %f seconds = %f pixels/sec\n",
|
||||
draws, seconds, pixelsPerSecond);
|
||||
}
|
||||
|
||||
|
||||
static void Reshape( int width, int height )
|
||||
{
|
||||
glViewport( 0, 0, width, height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glOrtho( 0.0, width, 0.0, height, 0.0, 2.0 );
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
glScissor(width/4, height/4, width/2, height/2);
|
||||
}
|
||||
|
||||
|
||||
static void Key( unsigned char key, int x, int y )
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case ' ':
|
||||
Reset();
|
||||
break;
|
||||
case 'd':
|
||||
Dither = !Dither;
|
||||
if (Dither)
|
||||
glEnable(GL_DITHER);
|
||||
else
|
||||
glDisable(GL_DITHER);
|
||||
break;
|
||||
case 'w':
|
||||
if (DrawWidth > 0)
|
||||
DrawWidth--;
|
||||
break;
|
||||
case 'W':
|
||||
DrawWidth++;
|
||||
break;
|
||||
case 'h':
|
||||
if (DrawHeight > 0)
|
||||
DrawHeight--;
|
||||
break;
|
||||
case 'H':
|
||||
DrawHeight++;
|
||||
break;
|
||||
case 'p':
|
||||
if (SkipPixels > 0)
|
||||
SkipPixels--;
|
||||
break;
|
||||
case 'P':
|
||||
SkipPixels++;
|
||||
break;
|
||||
case 'r':
|
||||
if (SkipRows > 0)
|
||||
SkipRows--;
|
||||
break;
|
||||
case 'R':
|
||||
SkipRows++;
|
||||
break;
|
||||
case 's':
|
||||
Scissor = !Scissor;
|
||||
break;
|
||||
case 'x':
|
||||
Xzoom -= 0.1;
|
||||
break;
|
||||
case 'X':
|
||||
Xzoom += 0.1;
|
||||
break;
|
||||
case 'y':
|
||||
Yzoom -= 0.1;
|
||||
break;
|
||||
case 'Y':
|
||||
Yzoom += 0.1;
|
||||
break;
|
||||
case 'z':
|
||||
Zpos -= 0.1;
|
||||
printf("RasterPos Z = %g\n", Zpos);
|
||||
break;
|
||||
case 'Z':
|
||||
Zpos += 0.1;
|
||||
printf("RasterPos Z = %g\n", Zpos);
|
||||
break;
|
||||
case 'b':
|
||||
Benchmark();
|
||||
break;
|
||||
case 'F':
|
||||
Fog = !Fog;
|
||||
printf("Fog %d\n", Fog);
|
||||
break;
|
||||
case 'f':
|
||||
DrawFront = !DrawFront;
|
||||
if (DrawFront)
|
||||
glDrawBuffer(GL_FRONT);
|
||||
else
|
||||
glDrawBuffer(GL_BACK);
|
||||
printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK");
|
||||
break;
|
||||
case 27:
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void SpecialKey( int key, int x, int y )
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case GLUT_KEY_UP:
|
||||
Ypos += 1;
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
Ypos -= 1;
|
||||
break;
|
||||
case GLUT_KEY_LEFT:
|
||||
Xpos -= 1;
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
Xpos += 1;
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void Init( GLboolean ciMode, const char *filename )
|
||||
{
|
||||
static const GLfloat fogColor[4] = {0, 1, 0, 0};
|
||||
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
|
||||
Image = LoadRGBImage( filename, &ImgWidth, &ImgHeight, &ImgFormat );
|
||||
if (!Image) {
|
||||
printf("Couldn't read %s\n", filename);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (ciMode) {
|
||||
/* Convert RGB image to grayscale */
|
||||
GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight );
|
||||
GLint i;
|
||||
for (i=0; i<ImgWidth*ImgHeight; i++) {
|
||||
int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2];
|
||||
indexImage[i] = gray / 3;
|
||||
}
|
||||
free(Image);
|
||||
Image = indexImage;
|
||||
ImgFormat = GL_COLOR_INDEX;
|
||||
|
||||
for (i=0;i<255;i++) {
|
||||
float g = i / 255.0;
|
||||
glutSetColor(i, g, g, g);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Loaded %d by %d image\n", ImgWidth, ImgHeight );
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth);
|
||||
|
||||
|
||||
/* put image into DrawPBO */
|
||||
glGenBuffersARB(1, &DrawPBO);
|
||||
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, DrawPBO);
|
||||
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
|
||||
ImgWidth * ImgHeight * 4, Image, GL_STATIC_DRAW);
|
||||
|
||||
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
glFogf(GL_FOG_START, 0);
|
||||
glFogf(GL_FOG_END, 2);
|
||||
glFogfv(GL_FOG_COLOR, fogColor);
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
static void Usage(void)
|
||||
{
|
||||
printf("Keys:\n");
|
||||
printf(" SPACE Reset Parameters\n");
|
||||
printf(" Up/Down Move image up/down\n");
|
||||
printf(" Left/Right Move image left/right\n");
|
||||
printf(" x Decrease X-axis PixelZoom\n");
|
||||
printf(" X Increase X-axis PixelZoom\n");
|
||||
printf(" y Decrease Y-axis PixelZoom\n");
|
||||
printf(" Y Increase Y-axis PixelZoom\n");
|
||||
printf(" w Decrease glDrawPixels width*\n");
|
||||
printf(" W Increase glDrawPixels width*\n");
|
||||
printf(" h Decrease glDrawPixels height*\n");
|
||||
printf(" H Increase glDrawPixels height*\n");
|
||||
printf(" p Decrease GL_UNPACK_SKIP_PIXELS*\n");
|
||||
printf(" P Increase GL_UNPACK_SKIP_PIXELS*\n");
|
||||
printf(" r Decrease GL_UNPACK_SKIP_ROWS*\n");
|
||||
printf(" R Increase GL_UNPACK_SKIP_ROWS*\n");
|
||||
printf(" s Toggle GL_SCISSOR_TEST\n");
|
||||
printf(" F Toggle GL_FOG\n");
|
||||
printf(" z Decrease RasterPos Z\n");
|
||||
printf(" Z Increase RasterPos Z\n");
|
||||
|
||||
printf(" f Toggle front/back buffer drawing\n");
|
||||
printf(" b Benchmark test\n");
|
||||
printf(" ESC Exit\n");
|
||||
printf("* Warning: no limits are imposed on these parameters so it's\n");
|
||||
printf(" possible to cause a segfault if you go too far.\n");
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
GLboolean ciMode = GL_FALSE;
|
||||
const char *filename = IMAGE_FILE;
|
||||
int i = 1;
|
||||
|
||||
if (argc > i && strcmp(argv[i], "-ci")==0) {
|
||||
ciMode = GL_TRUE;
|
||||
i++;
|
||||
}
|
||||
if (argc > i) {
|
||||
filename = argv[i];
|
||||
}
|
||||
|
||||
glutInit( &argc, argv );
|
||||
glutInitWindowPosition( 0, 0 );
|
||||
glutInitWindowSize( 500, 400 );
|
||||
|
||||
if (ciMode)
|
||||
glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE );
|
||||
else
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
|
||||
|
||||
glutCreateWindow(argv[0]);
|
||||
|
||||
Init(ciMode, filename);
|
||||
Usage();
|
||||
|
||||
glutReshapeFunc( Reshape );
|
||||
glutKeyboardFunc( Key );
|
||||
glutSpecialFunc( SpecialKey );
|
||||
glutDisplayFunc( Display );
|
||||
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
486
progs/demos/gearbox.c
Normal file
486
progs/demos/gearbox.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Use glCopyTexSubImage2D to draw animated gears on the sides of a box.
|
||||
*
|
||||
* Brian Paul
|
||||
* 27 January 2006
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265
|
||||
#endif
|
||||
|
||||
static GLint WinWidth = 800, WinHeight = 500;
|
||||
static GLint TexWidth, TexHeight;
|
||||
static GLuint TexObj = 1;
|
||||
static GLenum IntFormat = GL_RGBA;
|
||||
|
||||
static GLboolean WireFrame = GL_FALSE;
|
||||
|
||||
static GLint T0 = 0;
|
||||
static GLint Frames = 0;
|
||||
static GLint Win = 0;
|
||||
|
||||
static GLfloat ViewRotX = 20.0, ViewRotY = 30.0, ViewRotZ = 0.0;
|
||||
static GLint Gear1, Gear2, Gear3;
|
||||
static GLfloat GearRot = 0.0;
|
||||
static GLfloat CubeRot = 0.0;
|
||||
|
||||
|
||||
/**
|
||||
Draw a gear wheel. You'll probably want to call this function when
|
||||
building a display list since we do a lot of trig here.
|
||||
|
||||
Input: inner_radius - radius of hole at center
|
||||
outer_radius - radius at center of teeth
|
||||
width - width of gear
|
||||
teeth - number of teeth
|
||||
tooth_depth - depth of tooth
|
||||
**/
|
||||
static void
|
||||
gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
|
||||
GLint teeth, GLfloat tooth_depth)
|
||||
{
|
||||
GLint i;
|
||||
GLfloat r0, r1, r2;
|
||||
GLfloat angle, da;
|
||||
GLfloat u, v, len;
|
||||
|
||||
r0 = inner_radius;
|
||||
r1 = outer_radius - tooth_depth / 2.0;
|
||||
r2 = outer_radius + tooth_depth / 2.0;
|
||||
|
||||
da = 2.0 * M_PI / teeth / 4.0;
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
glNormal3f(0.0, 0.0, 1.0);
|
||||
|
||||
/* draw front face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i <= teeth; i++) {
|
||||
angle = i * 2.0 * M_PI / teeth;
|
||||
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
||||
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
||||
if (i < teeth) {
|
||||
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
||||
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw front sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = 2.0 * M_PI / teeth / 4.0;
|
||||
for (i = 0; i < teeth; i++) {
|
||||
angle = i * 2.0 * M_PI / teeth;
|
||||
|
||||
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
||||
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
||||
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
|
||||
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
|
||||
/* draw back face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i <= teeth; i++) {
|
||||
angle = i * 2.0 * M_PI / teeth;
|
||||
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
||||
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
||||
if (i < teeth) {
|
||||
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
||||
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw back sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = 2.0 * M_PI / teeth / 4.0;
|
||||
for (i = 0; i < teeth; i++) {
|
||||
angle = i * 2.0 * M_PI / teeth;
|
||||
|
||||
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
||||
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
|
||||
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
||||
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw outward faces of teeth */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i < teeth; i++) {
|
||||
angle = i * 2.0 * M_PI / teeth;
|
||||
|
||||
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
||||
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
||||
u = r2 * cos(angle + da) - r1 * cos(angle);
|
||||
v = r2 * sin(angle + da) - r1 * sin(angle);
|
||||
len = sqrt(u * u + v * v);
|
||||
u /= len;
|
||||
v /= len;
|
||||
glNormal3f(v, -u, 0.0);
|
||||
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
||||
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
||||
glNormal3f(cos(angle), sin(angle), 0.0);
|
||||
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
|
||||
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
|
||||
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
|
||||
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
|
||||
glNormal3f(v, -u, 0.0);
|
||||
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
|
||||
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
|
||||
glNormal3f(cos(angle), sin(angle), 0.0);
|
||||
}
|
||||
|
||||
glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
|
||||
glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
|
||||
|
||||
glEnd();
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
/* draw inside radius cylinder */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i = 0; i <= teeth; i++) {
|
||||
angle = i * 2.0 * M_PI / teeth;
|
||||
glNormal3f(-cos(angle), -sin(angle), 0.0);
|
||||
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
||||
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(void)
|
||||
{
|
||||
glDeleteTextures(1, &TexObj);
|
||||
glDeleteLists(Gear1, 1);
|
||||
glDeleteLists(Gear2, 1);
|
||||
glDeleteLists(Gear3, 1);
|
||||
glutDestroyWindow(Win);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DrawGears(void)
|
||||
{
|
||||
if (WireFrame) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(20/*ViewRotX*/, 1.0, 0.0, 0.0);
|
||||
glRotatef(ViewRotY, 0.0, 1.0, 0.0);
|
||||
glRotatef(ViewRotZ, 0.0, 0.0, 1.0);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.0, -2.0, 0.0);
|
||||
glRotatef(GearRot, 0.0, 0.0, 1.0);
|
||||
glCallList(Gear1);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(3.1, -2.0, 0.0);
|
||||
glRotatef(-2.0 * GearRot - 9.0, 0.0, 0.0, 1.0);
|
||||
glCallList(Gear2);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.1, 4.2, 0.0);
|
||||
glRotatef(-2.0 * GearRot - 25.0, 0.0, 0.0, 1.0);
|
||||
glCallList(Gear3);
|
||||
glPopMatrix();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DrawCube(void)
|
||||
{
|
||||
static const GLfloat texcoords[4][2] = {
|
||||
{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
|
||||
};
|
||||
static const GLfloat vertices[4][2] = {
|
||||
{ -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
|
||||
};
|
||||
static const GLfloat xforms[6][4] = {
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 90, 0, 1, 0 },
|
||||
{ 180, 0, 1, 0 },
|
||||
{ 270, 0, 1, 0 },
|
||||
{ 90, 1, 0, 0 },
|
||||
{ -90, 1, 0, 0 }
|
||||
};
|
||||
static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
|
||||
GLint i, j;
|
||||
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(ViewRotX, 1.0, 0.0, 0.0);
|
||||
glRotatef(15, 1, 0, 0);
|
||||
glRotatef(CubeRot, 0, 1, 0);
|
||||
glScalef(4, 4, 4);
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
glPushMatrix();
|
||||
glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
|
||||
glTranslatef(0, 0, 1.1);
|
||||
glBegin(GL_POLYGON);
|
||||
glNormal3f(0, 0, 1);
|
||||
for (j = 0; j < 4; j++) {
|
||||
glTexCoord2fv(texcoords[j]);
|
||||
glVertex2fv(vertices[j]);
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draw(void)
|
||||
{
|
||||
float ar;
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -40.0);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
/* draw gears */
|
||||
glViewport(0, 0, TexWidth, TexHeight);
|
||||
glScissor(0, 0, TexWidth, TexHeight);
|
||||
glClearColor(0.5, 0.5, 0.8, 0.0);
|
||||
glClearColor(1, 1, 1, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 60.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
DrawGears();
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
|
||||
|
||||
/* draw textured cube */
|
||||
glViewport(TexWidth, 0, WinWidth - TexWidth, WinHeight);
|
||||
glScissor(TexWidth, 0, WinWidth - TexWidth, WinHeight);
|
||||
glClearColor(0.5, 0.5, 0.8, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
ar = (float) (WinWidth - TexWidth) / WinHeight;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
DrawCube();
|
||||
|
||||
/* finish up */
|
||||
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);
|
||||
T0 = t;
|
||||
Frames = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
idle(void)
|
||||
{
|
||||
static double t0 = -1.;
|
||||
double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
||||
if (t0 < 0.0)
|
||||
t0 = t;
|
||||
dt = t - t0;
|
||||
t0 = t;
|
||||
|
||||
GearRot += 70.0 * dt; /* 70 degrees per second */
|
||||
GearRot = fmod(GearRot, 360.0); /* prevents eventual overflow */
|
||||
|
||||
CubeRot += 15.0 * dt;
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
/* change view angle, exit upon ESC */
|
||||
static void
|
||||
key(unsigned char k, int x, int y)
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (k) {
|
||||
case 'w':
|
||||
WireFrame = !WireFrame;
|
||||
break;
|
||||
case 'z':
|
||||
ViewRotZ += 5.0;
|
||||
break;
|
||||
case 'Z':
|
||||
ViewRotZ -= 5.0;
|
||||
break;
|
||||
case 27: /* Escape */
|
||||
cleanup();
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
/* change view angle */
|
||||
static void
|
||||
special(int k, int x, int y)
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (k) {
|
||||
case GLUT_KEY_UP:
|
||||
ViewRotX += 5.0;
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
ViewRotX -= 5.0;
|
||||
break;
|
||||
case GLUT_KEY_LEFT:
|
||||
ViewRotY += 5.0;
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
ViewRotY -= 5.0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
reshape(int width, int height)
|
||||
{
|
||||
WinWidth = width;
|
||||
WinHeight = height;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init(int argc, char *argv[])
|
||||
{
|
||||
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
|
||||
static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
|
||||
static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
|
||||
static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
|
||||
GLint i;
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
#if 0
|
||||
glEnable(GL_CULL_FACE);
|
||||
#endif
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
/* make the gears */
|
||||
Gear1 = glGenLists(1);
|
||||
glNewList(Gear1, GL_COMPILE);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
|
||||
gear(1.0, 4.0, 1.0, 20, 0.7);
|
||||
glEndList();
|
||||
|
||||
Gear2 = glGenLists(1);
|
||||
glNewList(Gear2, GL_COMPILE);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
|
||||
gear(0.5, 2.0, 2.0, 10, 0.7);
|
||||
glEndList();
|
||||
|
||||
Gear3 = glGenLists(1);
|
||||
glNewList(Gear3, GL_COMPILE);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
|
||||
gear(1.3, 2.0, 0.5, 10, 0.7);
|
||||
glEndList();
|
||||
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
/* xxx make size dynamic */
|
||||
TexWidth = 256;
|
||||
TexHeight = 256;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, TexObj);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
|
||||
for ( i=1; i<argc; i++ ) {
|
||||
if (strcmp(argv[i], "-info")==0) {
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
visible(int vis)
|
||||
{
|
||||
if (vis == GLUT_VISIBLE)
|
||||
glutIdleFunc(idle);
|
||||
else
|
||||
glutIdleFunc(NULL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
|
||||
|
||||
glutInitWindowSize(WinWidth, WinHeight);
|
||||
Win = glutCreateWindow("gearbox");
|
||||
init(argc, argv);
|
||||
|
||||
glutDisplayFunc(draw);
|
||||
glutReshapeFunc(reshape);
|
||||
glutKeyboardFunc(key);
|
||||
glutSpecialFunc(special);
|
||||
glutVisibilityFunc(visible);
|
||||
|
||||
glutMainLoop();
|
||||
return 0; /* ANSI C requires main to return int. */
|
||||
}
|
||||
@@ -38,8 +38,8 @@
|
||||
#include <GL/glut.h>
|
||||
|
||||
|
||||
static GLsizei MaxSize = 1024;
|
||||
static GLsizei TexWidth = 256, TexHeight = 256, TexBorder = 0;
|
||||
static GLsizei MaxSize = 2048;
|
||||
static GLsizei TexWidth = 1024, TexHeight = 1024, TexBorder = 0;
|
||||
static GLboolean ScaleAndBias = GL_FALSE;
|
||||
static GLboolean SubImage = GL_FALSE;
|
||||
static GLdouble DownloadRate = 0.0; /* texels/sec */
|
||||
@@ -47,6 +47,32 @@ static GLdouble DownloadRate = 0.0; /* texels/sec */
|
||||
static GLuint Mode = 0;
|
||||
|
||||
|
||||
/* Try and avoid L2 cache effects by cycling through a small number of
|
||||
* textures.
|
||||
*
|
||||
* At the initial size of 1024x1024x4 == 4mbyte, say 8 textures will
|
||||
* keep us out of most caches at 32mb total.
|
||||
*
|
||||
* This turns into a fairly interesting question of what exactly you
|
||||
* expect to be in cache in normal usage, and what you think should be
|
||||
* outside. There's no rules for this, no reason to favour one usage
|
||||
* over another except what the application you care about happens to
|
||||
* resemble most closely.
|
||||
*
|
||||
* - Should the client texture image be in L2 cache? Has it just been
|
||||
* generated or read from disk?
|
||||
* - Does the application really use >1 texture, or is it constantly
|
||||
* updating one image in-place?
|
||||
*
|
||||
* Different answers will favour different texture upload mechanisms.
|
||||
* To upload an image that is purely outside of cache, a DMA-based
|
||||
* upload will probably win, whereas for small, in-cache textures,
|
||||
* copying looks good.
|
||||
*/
|
||||
#define NR_TEXOBJ 4
|
||||
static GLuint TexObj[NR_TEXOBJ];
|
||||
|
||||
|
||||
struct FormatRec {
|
||||
GLenum Format;
|
||||
GLenum Type;
|
||||
@@ -116,25 +142,57 @@ TypeStr(GLenum type)
|
||||
}
|
||||
}
|
||||
|
||||
/* On x86, there is a performance cliff for memcpy to texture memory
|
||||
* for sources below 64 byte alignment. We do our best with this in
|
||||
* the driver, but it is better if the images are correctly aligned to
|
||||
* start with:
|
||||
*/
|
||||
#define ALIGN (1<<12)
|
||||
|
||||
static unsigned align(unsigned value, unsigned a)
|
||||
{
|
||||
return (value + a - 1) & ~(a-1);
|
||||
}
|
||||
|
||||
static int MIN2(int a, int b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
static void
|
||||
MeasureDownloadRate(void)
|
||||
{
|
||||
const int w = TexWidth + 2 * TexBorder;
|
||||
const int h = TexHeight + 2 * TexBorder;
|
||||
const int bytes = w * h * BytesPerTexel(Format);
|
||||
const int image_bytes = align(w * h * BytesPerTexel(Format), ALIGN);
|
||||
const int bytes = image_bytes * NR_TEXOBJ;
|
||||
GLubyte *orig_texImage, *orig_getImage;
|
||||
GLubyte *texImage, *getImage;
|
||||
GLdouble t0, t1, time;
|
||||
int count;
|
||||
int i;
|
||||
int offset = 0;
|
||||
GLdouble total = 0; /* ints will tend to overflow */
|
||||
|
||||
texImage = (GLubyte *) malloc(bytes);
|
||||
getImage = (GLubyte *) malloc(bytes);
|
||||
if (!texImage || !getImage) {
|
||||
printf("allocating %d bytes for %d %dx%d images\n",
|
||||
bytes, NR_TEXOBJ, w, h);
|
||||
|
||||
orig_texImage = (GLubyte *) malloc(bytes + ALIGN);
|
||||
orig_getImage = (GLubyte *) malloc(image_bytes + ALIGN);
|
||||
if (!orig_texImage || !orig_getImage) {
|
||||
DownloadRate = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
printf("alloc %p %p\n", orig_texImage, orig_getImage);
|
||||
|
||||
texImage = (GLubyte *)align((unsigned)orig_texImage, ALIGN);
|
||||
getImage = (GLubyte *)align((unsigned)orig_getImage, ALIGN);
|
||||
|
||||
for (i = 1; !(((unsigned)texImage) & i); i<<=1)
|
||||
;
|
||||
printf("texture image alignment: %d bytes (%p)\n", i, texImage);
|
||||
|
||||
for (i = 0; i < bytes; i++) {
|
||||
texImage[i] = i & 0xff;
|
||||
}
|
||||
@@ -166,51 +224,80 @@ MeasureDownloadRate(void)
|
||||
count = 0;
|
||||
t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
|
||||
do {
|
||||
int img = count%NR_TEXOBJ;
|
||||
GLubyte *img_ptr = texImage + img * image_bytes;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, TexObj[img]);
|
||||
|
||||
if (SubImage && count > 0) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, -TexBorder, -TexBorder, w, h,
|
||||
/* Only update a portion of the image each iteration. This
|
||||
* is presumably why you'd want to use texsubimage, otherwise
|
||||
* you may as well just call teximage again.
|
||||
*
|
||||
* A bigger question is whether to use a pointer that moves
|
||||
* with each call, ie does the incoming data come from L2
|
||||
* cache under normal circumstances, or is it pulled from
|
||||
* uncached memory?
|
||||
*
|
||||
* There's a good argument to say L2 cache, ie you'd expect
|
||||
* the data to have been recently generated. It's possible
|
||||
* that it could have come from a file read, which may or may
|
||||
* not have gone through the cpu.
|
||||
*/
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
-TexBorder,
|
||||
-TexBorder + offset * h/8,
|
||||
w,
|
||||
h/8,
|
||||
FormatTable[Format].Format,
|
||||
FormatTable[Format].Type, texImage);
|
||||
FormatTable[Format].Type,
|
||||
#if 1
|
||||
texImage /* likely in L2$ */
|
||||
#else
|
||||
img_ptr + offset * bytes/8 /* unlikely in L2$ */
|
||||
#endif
|
||||
);
|
||||
offset += 1;
|
||||
offset %= 8;
|
||||
total += w * h / 8;
|
||||
}
|
||||
else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
FormatTable[Format].IntFormat, w, h, TexBorder,
|
||||
FormatTable[Format].Format,
|
||||
FormatTable[Format].Type, texImage);
|
||||
FormatTable[Format].Type,
|
||||
img_ptr);
|
||||
total += w*h;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* Render a texture, but not necessarily the one just uploaded.
|
||||
*/
|
||||
/* glBindTexture(GL_TEXTURE_2D, TexObj[(img + NR_TEXOBJ/2)%NR_TEXOBJ]); */
|
||||
|
||||
/* draw a tiny polygon to force texture into texram */
|
||||
glBegin(GL_TRIANGLES);
|
||||
glTexCoord2f(0, 0); glVertex2f(1, 1);
|
||||
glTexCoord2f(1, 0); glVertex2f(3, 1);
|
||||
glTexCoord2f(0.5, 1); glVertex2f(2, 3);
|
||||
glEnd();
|
||||
/* glFinish(); */
|
||||
#endif
|
||||
|
||||
t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
|
||||
time = t1 - t0;
|
||||
count++;
|
||||
/* printf("total %f count %d\n", total, count); */
|
||||
} while (time < 3.0);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
printf("w*h=%d count=%d time=%f\n", w*h, count, time);
|
||||
DownloadRate = w * h * count / time;
|
||||
printf("total texels=%f time=%f\n", total, time);
|
||||
DownloadRate = total / time;
|
||||
|
||||
#if 0
|
||||
if (!ScaleAndBias) {
|
||||
/* verify texture readback */
|
||||
glGetTexImage(GL_TEXTURE_2D, 0,
|
||||
FormatTable[Format].Format,
|
||||
FormatTable[Format].Type, getImage);
|
||||
for (i = 0; i < w * h; i++) {
|
||||
if (texImage[i] != getImage[i]) {
|
||||
printf("[%d] %d != %d\n", i, texImage[i], getImage[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
free(texImage);
|
||||
free(getImage);
|
||||
free(orig_texImage);
|
||||
free(orig_getImage);
|
||||
|
||||
{
|
||||
GLint err = glGetError();
|
||||
@@ -29,6 +29,7 @@ SOURCES = antialias.c \
|
||||
dinoshade.c \
|
||||
floattex.c \
|
||||
fbotest1.c \
|
||||
fbotest2.c \
|
||||
fbotexture.c \
|
||||
fog.c \
|
||||
fogcoord.c \
|
||||
@@ -47,6 +48,7 @@ SOURCES = antialias.c \
|
||||
sharedtex.c \
|
||||
stencilwrap.c \
|
||||
stencil_wrap.c \
|
||||
subtexrate.c \
|
||||
tex1d.c \
|
||||
texfilt.c \
|
||||
texline.c \
|
||||
|
||||
204
progs/tests/fbotest2.c
Normal file
204
progs/tests/fbotest2.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Test GL_EXT_framebuffer_object
|
||||
*
|
||||
* Brian Paul
|
||||
* 19 Mar 2006
|
||||
*/
|
||||
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
static int Width = 400, Height = 400;
|
||||
static GLuint MyFB, ColorRb, DepthRb;
|
||||
static GLboolean Animate = GL_FALSE;
|
||||
static GLfloat Rotation = 0.0;
|
||||
|
||||
|
||||
static void
|
||||
CheckError(int line)
|
||||
{
|
||||
GLenum err = glGetError();
|
||||
if (err) {
|
||||
printf("fbotest1: GL Error 0x%x at line %d\n", (int) err, line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Display( void )
|
||||
{
|
||||
GLubyte *buffer = malloc(Width * Height * 4);
|
||||
GLenum status;
|
||||
|
||||
printf("Drawing\n");
|
||||
|
||||
CheckError(__LINE__);
|
||||
|
||||
/* draw to user framebuffer */
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
||||
|
||||
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
printf("fbotest1: Error: Framebuffer is incomplete!!!\n");
|
||||
}
|
||||
|
||||
CheckError(__LINE__);
|
||||
|
||||
glClearColor(0.5, 0.5, 1.0, 0.0);
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(30.0, 1, 0, 0);
|
||||
glRotatef(Rotation, 0, 1, 0);
|
||||
glutSolidTeapot(2.0);
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
/* read from user framebuffer */
|
||||
glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
/* draw to window */
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glWindowPos2iARB(0, 0);
|
||||
glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
free(buffer);
|
||||
glutSwapBuffers();
|
||||
CheckError(__LINE__);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Reshape( int width, int height )
|
||||
{
|
||||
float ar = (float) width / (float) height;
|
||||
|
||||
glViewport( 0, 0, width, height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
glFrustum( -ar, ar, -1.0, 1.0, 5.0, 25.0 );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glTranslatef( 0.0, 0.0, -15.0 );
|
||||
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRb);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
|
||||
width, height);
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
CleanUp(void)
|
||||
{
|
||||
glDeleteFramebuffersEXT(1, &MyFB);
|
||||
glDeleteRenderbuffersEXT(1, &ColorRb);
|
||||
glDeleteRenderbuffersEXT(1, &DepthRb);
|
||||
assert(!glIsFramebufferEXT(MyFB));
|
||||
assert(!glIsRenderbufferEXT(ColorRb));
|
||||
assert(!glIsRenderbufferEXT(DepthRb));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Idle(void)
|
||||
{
|
||||
Rotation = glutGet(GLUT_ELAPSED_TIME) * 0.1;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Key( unsigned char key, int x, int y )
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case 'a':
|
||||
Animate = !Animate;
|
||||
if (Animate)
|
||||
glutIdleFunc(Idle);
|
||||
else
|
||||
glutIdleFunc(NULL);
|
||||
break;
|
||||
case 27:
|
||||
CleanUp();
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Init( void )
|
||||
{
|
||||
if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
|
||||
printf("fbotest1: GL_EXT_framebuffer_object not found!\n");
|
||||
exit(0);
|
||||
}
|
||||
printf("fbotest1: GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
|
||||
glGenFramebuffersEXT(1, &MyFB);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
|
||||
assert(glIsFramebufferEXT(MyFB));
|
||||
|
||||
/* set color buffer */
|
||||
glGenRenderbuffersEXT(1, &ColorRb);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb);
|
||||
assert(glIsRenderbufferEXT(ColorRb));
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
|
||||
GL_RENDERBUFFER_EXT, ColorRb);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
|
||||
|
||||
/* setup depth buffer */
|
||||
glGenRenderbuffersEXT(1, &DepthRb);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRb);
|
||||
assert(glIsRenderbufferEXT(DepthRb));
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, DepthRb);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, Width, Height);
|
||||
|
||||
CheckError(__LINE__);
|
||||
|
||||
/* restore to default */
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
CheckError(__LINE__);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main( int argc, char *argv[] )
|
||||
{
|
||||
glutInit( &argc, argv );
|
||||
glutInitWindowPosition( 0, 0 );
|
||||
glutInitWindowSize(Width, Height);
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
|
||||
glutCreateWindow(argv[0]);
|
||||
glutReshapeFunc( Reshape );
|
||||
glutKeyboardFunc( Key );
|
||||
glutDisplayFunc( Display );
|
||||
if (Animate)
|
||||
glutIdleFunc(Idle);
|
||||
Init();
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* For debug */
|
||||
#define DEPTH 1
|
||||
#define STENCIL 1
|
||||
|
||||
|
||||
static int Width = 400, Height = 400;
|
||||
static int TexWidth = 512, TexHeight = 512;
|
||||
@@ -76,10 +80,14 @@ RenderTexture(void)
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
CheckError(__LINE__);
|
||||
|
||||
#if DEPTH
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
#if STENCIL
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_NEVER, 1, ~0);
|
||||
glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
|
||||
#endif
|
||||
|
||||
CheckError(__LINE__);
|
||||
|
||||
@@ -93,10 +101,13 @@ RenderTexture(void)
|
||||
glEnd();
|
||||
|
||||
/* draw teapot where stencil != 1 */
|
||||
#if STENCIL
|
||||
glStencilFunc(GL_NOTEQUAL, 1, ~0);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
#endif
|
||||
|
||||
CheckError(__LINE__);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
glBegin(GL_POLYGON);
|
||||
@@ -184,9 +195,13 @@ Reshape(int width, int height)
|
||||
static void
|
||||
CleanUp(void)
|
||||
{
|
||||
#if DEPTH
|
||||
glDeleteRenderbuffersEXT(1, &DepthRB);
|
||||
#endif
|
||||
#if STENCIL
|
||||
if (!UsePackedDepthStencil)
|
||||
glDeleteRenderbuffersEXT(1, &StencilRB);
|
||||
#endif
|
||||
glDeleteFramebuffersEXT(1, &MyFB);
|
||||
|
||||
glDeleteTextures(1, &TexObj);
|
||||
@@ -253,6 +268,7 @@ Init(int argc, char *argv[])
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
|
||||
assert(i == MyFB);
|
||||
|
||||
#if DEPTH
|
||||
/* make depth renderbuffer */
|
||||
glGenRenderbuffersEXT(1, &DepthRB);
|
||||
assert(DepthRB);
|
||||
@@ -275,9 +291,11 @@ Init(int argc, char *argv[])
|
||||
/* attach DepthRB to MyFB */
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, DepthRB);
|
||||
#endif
|
||||
|
||||
CheckError(__LINE__);
|
||||
|
||||
#if STENCIL
|
||||
if (UsePackedDepthStencil) {
|
||||
/* DepthRb is a combined depth/stencil renderbuffer */
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
|
||||
@@ -303,7 +321,7 @@ Init(int argc, char *argv[])
|
||||
CheckError(__LINE__);
|
||||
printf("Stencil renderbuffer size = %d bits\n", i);
|
||||
assert(i > 0);
|
||||
|
||||
#endif
|
||||
|
||||
/* bind regular framebuffer */
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "../util/readtex.c" /* a hack, I know */
|
||||
|
||||
#define IMAGE_FILE "../images/girl.rgb"
|
||||
#define IMAGE_FILE "../images/tree2.rgba"
|
||||
|
||||
static int ImgWidth, ImgHeight;
|
||||
static GLenum ImgFormat;
|
||||
@@ -32,8 +32,8 @@ static GLboolean Benchmark = GL_FALSE;
|
||||
static GLuint DrawPBO, TempPBO;
|
||||
|
||||
|
||||
static GLenum ReadFormat = GL_RGBA;
|
||||
static GLenum ReadType = GL_UNSIGNED_BYTE;
|
||||
static GLenum ReadFormat = GL_BGRA;
|
||||
static GLenum ReadType = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
|
||||
|
||||
|
||||
|
||||
378
progs/tests/subtexrate.c
Normal file
378
progs/tests/subtexrate.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Measure glTexSubImage and glCopyTexSubImage speed
|
||||
*
|
||||
* Brian Paul
|
||||
* 26 Jan 2006
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
static GLint WinWidth = 1024, WinHeight = 512;
|
||||
static GLint TexWidth = 512, TexHeight = 512;
|
||||
|
||||
static GLuint TexObj = 1;
|
||||
|
||||
static GLenum IntFormat = GL_RGBA;
|
||||
static GLenum ReadFormat = GL_BGRA; /* for glReadPixels */
|
||||
|
||||
static GLboolean DrawQuad = GL_TRUE;
|
||||
|
||||
|
||||
/**
|
||||
* draw teapot image, size TexWidth by TexHeight
|
||||
*/
|
||||
static void
|
||||
DrawTestImage(void)
|
||||
{
|
||||
GLfloat ar;
|
||||
|
||||
glViewport(0, 0, TexWidth, TexHeight);
|
||||
glScissor(0, 0, TexWidth, TexHeight);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glClearColor(0.5, 0.5, 0.5, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
ar = (float) TexWidth / TexHeight;
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glFrontFace(GL_CW);
|
||||
glPushMatrix();
|
||||
glRotatef(45, 1, 0, 0);
|
||||
glRotatef(45, 0, 1, 0);
|
||||
glutSolidTeapot(2.3);
|
||||
glPopMatrix();
|
||||
glFrontFace(GL_CCW);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glViewport(0, 0, WinWidth, WinHeight);
|
||||
glFinish();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do glCopyTexSubImage2D call (update texture with framebuffer data)
|
||||
* If doSubRect is true, do the copy in four pieces instead of all at once.
|
||||
*/
|
||||
static void
|
||||
DoCopyTex(GLboolean doSubRect)
|
||||
{
|
||||
if (doSubRect) {
|
||||
/* copy in four parts */
|
||||
int w = TexWidth / 2, h = TexHeight / 2;
|
||||
int x0 = 0, y0 = 0;
|
||||
int x1 = w, y1 = h;
|
||||
#if 0
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x0, y0, w, h);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x1, y0, w, h);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x0, y1, w, h);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x1, y1, w, h);
|
||||
#else
|
||||
/* scramble */
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x1, y1, w, h);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x0, y1, w, h);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x1, y0, w, h);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x0, y0, w, h);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do glTexSubImage2D (update texture w/ user data)
|
||||
* If doSubRect, do update in four pieces, else all at once.
|
||||
*/
|
||||
static void
|
||||
SubTex(GLboolean doSubRect, const GLubyte *image)
|
||||
{
|
||||
if (doSubRect) {
|
||||
/* four pieces */
|
||||
int w = TexWidth / 2, h = TexHeight / 2;
|
||||
int x0 = 0, y0 = 0;
|
||||
int x1 = w, y1 = h;
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, TexWidth);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei( GL_PACK_INVERT_MESA, GL_TRUE );
|
||||
|
||||
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, w, h,
|
||||
ReadFormat, GL_UNSIGNED_BYTE, image);
|
||||
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, w, h,
|
||||
ReadFormat, GL_UNSIGNED_BYTE, image);
|
||||
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, w, h,
|
||||
ReadFormat, GL_UNSIGNED_BYTE, image);
|
||||
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */
|
||||
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, w, h,
|
||||
ReadFormat, GL_UNSIGNED_BYTE, image);
|
||||
glPixelStorei( GL_PACK_INVERT_MESA, GL_FALSE );
|
||||
|
||||
}
|
||||
else {
|
||||
/* all at once */
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexWidth, TexHeight,
|
||||
ReadFormat, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Measure gl[Copy]TexSubImage rate.
|
||||
* This actually also includes time to render a quad and SwapBuffers.
|
||||
*/
|
||||
static void
|
||||
RunTest(GLboolean copyTex, GLboolean doSubRect)
|
||||
{
|
||||
double t0, t1;
|
||||
int iters = 0;
|
||||
float copyRate, mbRate;
|
||||
float rot = 0.0;
|
||||
int bpp, r, g, b, a;
|
||||
int w, h;
|
||||
GLubyte *image = NULL;
|
||||
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b);
|
||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a);
|
||||
bpp = (r + g + b + a) / 8;
|
||||
|
||||
if (!copyTex) {
|
||||
/* read image from frame buffer */
|
||||
image = (GLubyte *) malloc(TexWidth * TexHeight * bpp);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(0, 0, TexWidth, TexHeight,
|
||||
ReadFormat, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glViewport(WinWidth / 2, 0, WinWidth / 2, WinHeight);
|
||||
|
||||
t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
||||
|
||||
if (!DrawQuad)
|
||||
glDrawBuffer(GL_FRONT);
|
||||
|
||||
do {
|
||||
if (copyTex)
|
||||
/* Framebuffer -> Texture */
|
||||
DoCopyTex(doSubRect);
|
||||
else {
|
||||
/* Main Mem -> Texture */
|
||||
SubTex(doSubRect, image);
|
||||
}
|
||||
|
||||
/* draw textured quad */
|
||||
if (DrawQuad) {
|
||||
glPushMatrix();
|
||||
glRotatef(rot, 0, 0, 1);
|
||||
glTranslatef(1, 0, 0);
|
||||
glBegin(GL_POLYGON);
|
||||
glTexCoord2f(0, 0); glVertex2f(-1, -1);
|
||||
glTexCoord2f(1, 0); glVertex2f( 1, -1);
|
||||
glTexCoord2f(1, 1); glVertex2f( 1, 1);
|
||||
glTexCoord2f(0, 1); glVertex2f(-1, 1);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
glutSwapBuffers();
|
||||
}
|
||||
else {
|
||||
/* Draw something tiny to ensure that the texture is really
|
||||
* uploaded:
|
||||
*/
|
||||
glPushMatrix();
|
||||
glRotatef(rot, 0, 0, 1);
|
||||
glTranslatef(1, 0, 0);
|
||||
glBegin(GL_POLYGON);
|
||||
glTexCoord2f(0, 0); glVertex2f(-.01, -.01);
|
||||
glTexCoord2f(.01, 0); glVertex2f( .01, -.01);
|
||||
glTexCoord2f(.01, .01); glVertex2f( .01, .01);
|
||||
glTexCoord2f(0, .01); glVertex2f(-.01, .01);
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
glFlush();
|
||||
}
|
||||
|
||||
iters++;
|
||||
rot += 2.0;
|
||||
|
||||
t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
||||
} while (t1 - t0 < 2.0);
|
||||
|
||||
/* Make sure everything is done before taking the final timing:
|
||||
*/
|
||||
glFinish();
|
||||
t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
||||
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if (image)
|
||||
free(image);
|
||||
|
||||
if (doSubRect) {
|
||||
w = TexWidth / 2;
|
||||
h = TexHeight / 2;
|
||||
iters *= 4;
|
||||
}
|
||||
else {
|
||||
w = TexWidth;
|
||||
h = TexHeight;
|
||||
}
|
||||
|
||||
copyRate = iters / (t1 - t0);
|
||||
mbRate = w * h * bpp * copyRate / (1024 * 1024);
|
||||
|
||||
if (copyTex)
|
||||
printf("glCopyTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
|
||||
else
|
||||
printf("glTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp);
|
||||
printf(" %d calls in %.2f = %.2f calls/sec, %.2f MB/s\n",
|
||||
iters, t1-t0, copyRate, mbRate);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Draw(void)
|
||||
{
|
||||
glClearColor(0.2, 0.2, 0.8, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
DrawTestImage();
|
||||
if (!DrawQuad) {
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
RunTest(GL_FALSE, GL_FALSE);
|
||||
RunTest(GL_FALSE, GL_TRUE);
|
||||
RunTest(GL_TRUE, GL_FALSE);
|
||||
RunTest(GL_TRUE, GL_TRUE);
|
||||
|
||||
glutSwapBuffers();
|
||||
|
||||
/* printf("exiting\n"); */
|
||||
/* exit(0); */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Reshape(int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -15.0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Key(unsigned char key, int x, int y)
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case 27:
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SpecialKey(int key, int x, int y)
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (key) {
|
||||
case GLUT_KEY_UP:
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
break;
|
||||
case GLUT_KEY_LEFT:
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Init(void)
|
||||
{
|
||||
/* create initial, empty teximage */
|
||||
glBindTexture(GL_TEXTURE_2D, TexObj);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
ParseArgs(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-nodraw") == 0)
|
||||
DrawQuad = GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH;
|
||||
glutInit(&argc, argv);
|
||||
|
||||
ParseArgs(argc, argv);
|
||||
|
||||
glutInitWindowPosition(0, 0);
|
||||
glutInitWindowSize(WinWidth, WinHeight);
|
||||
glutInitDisplayMode(mode);
|
||||
glutCreateWindow(argv[0]);
|
||||
glutReshapeFunc(Reshape);
|
||||
glutKeyboardFunc(Key);
|
||||
glutSpecialFunc(SpecialKey);
|
||||
glutDisplayFunc(Draw);
|
||||
|
||||
printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
|
||||
Init();
|
||||
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
@@ -687,4 +687,15 @@ extern int __glXGetInternalVersion(void);
|
||||
/* Get the unadjusted system time */
|
||||
extern int __glXGetUST( int64_t * ust );
|
||||
|
||||
/* KW: Temporary hacks to coalesce multiple opens of the same drm
|
||||
* instance. These should be renamed or moved to libdrm, or the
|
||||
* behaviour of drmOpen/drmClose should change.
|
||||
*/
|
||||
int drmOpenOnce(void *unused,
|
||||
const char *BusID,
|
||||
int *newlyopened);
|
||||
|
||||
void drmCloseOnce(int fd);
|
||||
|
||||
|
||||
#endif /* !__GLX_client_h__ */
|
||||
|
||||
@@ -702,6 +702,68 @@ static const __DRIinterfaceMethods interface_methods = {
|
||||
glXGetMscRateOML,
|
||||
};
|
||||
|
||||
#define DRM_MAX_FDS 16
|
||||
static struct {
|
||||
char *BusID;
|
||||
int fd;
|
||||
int refcount;
|
||||
} connection[DRM_MAX_FDS];
|
||||
|
||||
static int nr_fds = 0;
|
||||
|
||||
int drmOpenOnce(void *unused,
|
||||
const char *BusID,
|
||||
int *newlyopened)
|
||||
{
|
||||
int i;
|
||||
int fd;
|
||||
|
||||
for (i = 0; i < nr_fds; i++)
|
||||
if (strcmp(BusID, connection[i].BusID) == 0) {
|
||||
connection[i].refcount++;
|
||||
*newlyopened = 0;
|
||||
return connection[i].fd;
|
||||
}
|
||||
|
||||
fd = drmOpen(unused, BusID);
|
||||
if (fd <= 0 || nr_fds == DRM_MAX_FDS)
|
||||
return fd;
|
||||
|
||||
connection[nr_fds].BusID = strdup(BusID);
|
||||
connection[nr_fds].fd = fd;
|
||||
connection[nr_fds].refcount = 1;
|
||||
*newlyopened = 1;
|
||||
|
||||
fprintf(stderr, "saved connection %d for %s %d\n",
|
||||
nr_fds, connection[nr_fds].BusID,
|
||||
strcmp(BusID, connection[nr_fds].BusID));
|
||||
|
||||
nr_fds++;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void drmCloseOnce(int fd)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
|
||||
for (i = 0; i < nr_fds; i++) {
|
||||
if (fd == connection[i].fd) {
|
||||
if (--connection[i].refcount == 0) {
|
||||
drmClose(connection[i].fd);
|
||||
free(connection[i].BusID);
|
||||
|
||||
if (i < --nr_fds)
|
||||
connection[i] = connection[nr_fds];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform the required libGL-side initialization and call the client-side
|
||||
@@ -753,7 +815,8 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
|
||||
framebuffer.dev_priv = NULL;
|
||||
|
||||
if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
|
||||
fd = drmOpen(NULL,BusID);
|
||||
int newlyopened;
|
||||
fd = drmOpenOnce(NULL,BusID, &newlyopened);
|
||||
Xfree(BusID); /* No longer needed */
|
||||
|
||||
err_msg = "open DRM";
|
||||
@@ -780,7 +843,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
|
||||
}
|
||||
|
||||
err_msg = "XF86DRIAuthConnection";
|
||||
if (XF86DRIAuthConnection(dpy, scrn, magic)) {
|
||||
if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) {
|
||||
char *driverName;
|
||||
|
||||
/*
|
||||
@@ -884,7 +947,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
|
||||
}
|
||||
|
||||
if ( fd >= 0 ) {
|
||||
(void)drmClose(fd);
|
||||
(void)drmCloseOnce(fd);
|
||||
}
|
||||
|
||||
(void)XF86DRICloseConnection(dpy, scrn);
|
||||
|
||||
@@ -206,10 +206,15 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
|
||||
#if FEATURE_EXT_framebuffer_object
|
||||
driver->NewFramebuffer = _mesa_new_framebuffer;
|
||||
driver->NewRenderbuffer = _mesa_new_soft_renderbuffer;
|
||||
driver->RenderbufferTexture = _mesa_renderbuffer_texture;
|
||||
driver->RenderTexture = _mesa_render_texture;
|
||||
driver->FinishRenderTexture = _mesa_finish_render_texture;
|
||||
driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
|
||||
#endif
|
||||
|
||||
#if FEATURE_EXT_framebuffer_blit
|
||||
driver->BlitFramebuffer = _swrast_BlitFramebuffer;
|
||||
#endif
|
||||
|
||||
/* query objects */
|
||||
driver->NewQueryObject = _mesa_new_query_object;
|
||||
driver->BeginQuery = NULL;
|
||||
|
||||
@@ -89,7 +89,7 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME)
|
||||
depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
|
||||
touch depend
|
||||
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \
|
||||
> /dev/null
|
||||
>& /dev/null
|
||||
|
||||
|
||||
# Emacs tags
|
||||
|
||||
@@ -829,7 +829,7 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv
|
||||
(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
|
||||
(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
|
||||
_mesa_free(psp->pDevPriv);
|
||||
(void)drmClose(psp->fd);
|
||||
(void)drmCloseOnce(psp->fd);
|
||||
if ( psp->modes != NULL ) {
|
||||
(*dri_interface->destroyContextModes)( psp->modes );
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ driNewRenderbuffer(GLenum format, GLvoid *addr,
|
||||
driRenderbuffer *drb;
|
||||
|
||||
assert(format == GL_RGBA ||
|
||||
format == GL_RGB5 ||
|
||||
format == GL_RGBA8 ||
|
||||
format == GL_DEPTH_COMPONENT16 ||
|
||||
format == GL_DEPTH_COMPONENT24 ||
|
||||
format == GL_DEPTH_COMPONENT32 ||
|
||||
@@ -75,7 +77,7 @@ driNewRenderbuffer(GLenum format, GLvoid *addr,
|
||||
|
||||
drb->Base.InternalFormat = format;
|
||||
|
||||
if (format == GL_RGBA) {
|
||||
if (format == GL_RGBA || format == GL_RGB5 || format == GL_RGBA8) {
|
||||
/* Color */
|
||||
drb->Base._BaseFormat = GL_RGBA;
|
||||
drb->Base.DataType = GL_UNSIGNED_BYTE;
|
||||
@@ -94,7 +96,7 @@ driNewRenderbuffer(GLenum format, GLvoid *addr,
|
||||
}
|
||||
else {
|
||||
/* Stencil */
|
||||
ASSERT(format == GL_STENCIL_INDEX8);
|
||||
ASSERT(format == GL_STENCIL_INDEX8_EXT);
|
||||
drb->Base._BaseFormat = GL_STENCIL_INDEX;
|
||||
drb->Base.DataType = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,6 @@ include $(TOP)/configs/current
|
||||
LIBNAME = i915_dri.so
|
||||
|
||||
DRIVER_SOURCES = \
|
||||
i915_context.c \
|
||||
i915_debug.c \
|
||||
i915_fragprog.c \
|
||||
i915_metaops.c \
|
||||
i915_program.c \
|
||||
i915_state.c \
|
||||
i915_tex.c \
|
||||
i915_texprog.c \
|
||||
i915_texstate.c \
|
||||
i915_vtbl.c \
|
||||
i830_context.c \
|
||||
i830_metaops.c \
|
||||
i830_state.c \
|
||||
@@ -22,16 +12,45 @@ DRIVER_SOURCES = \
|
||||
i830_tex.c \
|
||||
i830_texstate.c \
|
||||
i830_vtbl.c \
|
||||
intel_render.c \
|
||||
intel_regions.c \
|
||||
intel_buffer_objects.c \
|
||||
intel_batchbuffer.c \
|
||||
intel_mipmap_tree.c \
|
||||
i915_tex_layout.c \
|
||||
intel_tex_image.c \
|
||||
intel_tex_subimage.c \
|
||||
intel_tex_copy.c \
|
||||
intel_tex_validate.c \
|
||||
intel_tex_format.c \
|
||||
intel_tex.c \
|
||||
intel_pixel.c \
|
||||
intel_pixel_copy.c \
|
||||
intel_pixel_read.c \
|
||||
intel_pixel_draw.c \
|
||||
intel_buffers.c \
|
||||
intel_blit.c \
|
||||
i915_tex.c \
|
||||
i915_texstate.c \
|
||||
i915_context.c \
|
||||
i915_debug.c \
|
||||
i915_fragprog.c \
|
||||
i915_metaops.c \
|
||||
i915_program.c \
|
||||
i915_state.c \
|
||||
i915_texprog.c \
|
||||
i915_vtbl.c \
|
||||
intel_context.c \
|
||||
intel_ioctl.c \
|
||||
intel_pixel.c \
|
||||
intel_render.c \
|
||||
intel_screen.c \
|
||||
intel_span.c \
|
||||
intel_state.c \
|
||||
intel_tex.c \
|
||||
intel_tris.c
|
||||
intel_tris.c \
|
||||
intel_fbo.c \
|
||||
intel_depthstencil.c \
|
||||
intel_bufmgr.c
|
||||
|
||||
|
||||
|
||||
C_SOURCES = \
|
||||
$(COMMON_SOURCES) \
|
||||
|
||||
@@ -58,8 +58,8 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
|
||||
void *sharedContextPrivate)
|
||||
{
|
||||
struct dd_function_table functions;
|
||||
i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context);
|
||||
intelContextPtr intel = &i830->intel;
|
||||
struct i830_context *i830 = CALLOC_STRUCT(i830_context);
|
||||
struct intel_context *intel = &i830->intel;
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
if (!i830) return GL_FALSE;
|
||||
|
||||
@@ -76,33 +76,14 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
|
||||
intel->ctx.Const.MaxTextureImageUnits = I830_TEX_UNITS;
|
||||
intel->ctx.Const.MaxTextureCoordUnits = I830_TEX_UNITS;
|
||||
|
||||
intel->nr_heaps = 1;
|
||||
intel->texture_heaps[0] =
|
||||
driCreateTextureHeap( 0, intel,
|
||||
intel->intelScreen->tex.size,
|
||||
12,
|
||||
I830_NR_TEX_REGIONS,
|
||||
intel->sarea->texList,
|
||||
& intel->sarea->texAge,
|
||||
& intel->swapped,
|
||||
sizeof( struct i830_texture_object ),
|
||||
(destroy_texture_object_t *)intelDestroyTexObj );
|
||||
|
||||
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly
|
||||
* FIXME: packed, but they're not in Intel graphics hardware.
|
||||
/* Advertise the full hardware capabilities. The new memory
|
||||
* manager should cope much better with overload situations:
|
||||
*/
|
||||
intel->ctx.Const.MaxTextureUnits = 1;
|
||||
driCalculateMaxTextureLevels( intel->texture_heaps,
|
||||
intel->nr_heaps,
|
||||
&intel->ctx.Const,
|
||||
4,
|
||||
11, /* max 2D texture size is 2048x2048 */
|
||||
8, /* max 3D texture size is 256^3 */
|
||||
10, /* max CUBE texture size is 1024x1024 */
|
||||
11, /* max RECT. supported */
|
||||
12,
|
||||
GL_FALSE );
|
||||
intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS;
|
||||
ctx->Const.MaxTextureLevels = 12;
|
||||
ctx->Const.Max3DTextureLevels = 9;
|
||||
ctx->Const.MaxCubeTextureLevels = 11;
|
||||
ctx->Const.MaxTextureRectSize = (1<<11);
|
||||
ctx->Const.MaxTextureUnits = I830_TEX_UNITS;
|
||||
|
||||
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
|
||||
18 * sizeof(GLfloat) );
|
||||
@@ -112,7 +93,7 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
|
||||
driInitExtensions( ctx, i830_extensions, GL_FALSE );
|
||||
|
||||
i830InitState( i830 );
|
||||
|
||||
i830InitMetaFuncs( i830 );
|
||||
|
||||
_tnl_allow_vertex_fog( ctx, 1 );
|
||||
_tnl_allow_pixel_fog( ctx, 0 );
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#define I830_UPLOAD_CTX 0x1
|
||||
#define I830_UPLOAD_BUFFERS 0x2
|
||||
#define I830_UPLOAD_STIPPLE 0x4
|
||||
#define I830_UPLOAD_INVARIENT 0x8
|
||||
#define I830_UPLOAD_TEX(i) (0x10<<(i))
|
||||
#define I830_UPLOAD_TEXBLEND(i) (0x100<<(i))
|
||||
#define I830_UPLOAD_TEX_ALL (0x0f0)
|
||||
@@ -48,17 +49,15 @@
|
||||
*/
|
||||
#define I830_DESTREG_CBUFADDR0 0
|
||||
#define I830_DESTREG_CBUFADDR1 1
|
||||
#define I830_DESTREG_CBUFADDR2 2
|
||||
#define I830_DESTREG_DBUFADDR0 3
|
||||
#define I830_DESTREG_DBUFADDR1 4
|
||||
#define I830_DESTREG_DBUFADDR2 5
|
||||
#define I830_DESTREG_DV0 6
|
||||
#define I830_DESTREG_DV1 7
|
||||
#define I830_DESTREG_SENABLE 8
|
||||
#define I830_DESTREG_SR0 9
|
||||
#define I830_DESTREG_SR1 10
|
||||
#define I830_DESTREG_SR2 11
|
||||
#define I830_DEST_SETUP_SIZE 12
|
||||
#define I830_DESTREG_DBUFADDR0 2
|
||||
#define I830_DESTREG_DBUFADDR1 3
|
||||
#define I830_DESTREG_DV0 4
|
||||
#define I830_DESTREG_DV1 5
|
||||
#define I830_DESTREG_SENABLE 6
|
||||
#define I830_DESTREG_SR0 7
|
||||
#define I830_DESTREG_SR1 8
|
||||
#define I830_DESTREG_SR2 9
|
||||
#define I830_DEST_SETUP_SIZE 10
|
||||
|
||||
#define I830_CTXREG_STATE1 0
|
||||
#define I830_CTXREG_STATE2 1
|
||||
@@ -84,14 +83,13 @@
|
||||
#define I830_STP_SETUP_SIZE 2
|
||||
|
||||
#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */
|
||||
#define I830_TEXREG_TM0S0 1
|
||||
#define I830_TEXREG_TM0S1 2
|
||||
#define I830_TEXREG_TM0S2 3
|
||||
#define I830_TEXREG_TM0S3 4
|
||||
#define I830_TEXREG_TM0S4 5
|
||||
#define I830_TEXREG_MCS 6 /* _3DSTATE_MAP_COORD_SETS */
|
||||
#define I830_TEXREG_CUBE 7 /* _3DSTATE_MAP_SUBE */
|
||||
#define I830_TEX_SETUP_SIZE 8
|
||||
#define I830_TEXREG_TM0S1 1
|
||||
#define I830_TEXREG_TM0S2 2
|
||||
#define I830_TEXREG_TM0S3 3
|
||||
#define I830_TEXREG_TM0S4 4
|
||||
#define I830_TEXREG_MCS 5 /* _3DSTATE_MAP_COORD_SETS */
|
||||
#define I830_TEXREG_CUBE 6 /* _3DSTATE_MAP_SUBE */
|
||||
#define I830_TEX_SETUP_SIZE 7
|
||||
|
||||
#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */
|
||||
|
||||
@@ -110,6 +108,17 @@ struct i830_hw_state {
|
||||
GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE];
|
||||
GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE];
|
||||
GLuint TexBlendWordsUsed[I830_TEX_UNITS];
|
||||
|
||||
struct intel_region *draw_region;
|
||||
struct intel_region *depth_region;
|
||||
|
||||
/* Regions aren't actually that appropriate here as the memory may
|
||||
* be from a PBO or FBO. Just use the buffer id. Will have to do
|
||||
* this for draw and depth for FBO's...
|
||||
*/
|
||||
GLuint tex_buffer[I830_TEX_UNITS];
|
||||
GLuint tex_offset[I830_TEX_UNITS];
|
||||
|
||||
GLuint emitted; /* I810_UPLOAD_* */
|
||||
GLuint active;
|
||||
};
|
||||
@@ -118,15 +127,12 @@ struct i830_context
|
||||
{
|
||||
struct intel_context intel;
|
||||
|
||||
GLuint lodbias_tm0s3[MAX_TEXTURE_UNITS];
|
||||
GLuint last_index;
|
||||
|
||||
struct i830_hw_state meta, initial, state, *current;
|
||||
};
|
||||
|
||||
typedef struct i830_context *i830ContextPtr;
|
||||
typedef struct i830_texture_object *i830TextureObjectPtr;
|
||||
|
||||
#define I830_CONTEXT(ctx) ((i830ContextPtr)(ctx))
|
||||
|
||||
|
||||
|
||||
@@ -148,7 +154,7 @@ do { \
|
||||
/* i830_vtbl.c
|
||||
*/
|
||||
extern void
|
||||
i830InitVtbl( i830ContextPtr i830 );
|
||||
i830InitVtbl( struct i830_context *i830 );
|
||||
|
||||
/* i830_context.c
|
||||
*/
|
||||
@@ -160,22 +166,19 @@ i830CreateContext( const __GLcontextModes *mesaVis,
|
||||
/* i830_tex.c, i830_texstate.c
|
||||
*/
|
||||
extern void
|
||||
i830UpdateTextureState( intelContextPtr intel );
|
||||
i830UpdateTextureState( struct intel_context *intel );
|
||||
|
||||
extern void
|
||||
i830InitTextureFuncs( struct dd_function_table *functions );
|
||||
|
||||
extern intelTextureObjectPtr
|
||||
i830AllocTexObj( struct gl_texture_object *tObj );
|
||||
|
||||
/* i830_texblend.c
|
||||
*/
|
||||
extern GLuint i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
extern GLuint i830SetTexEnvCombine(struct i830_context *i830,
|
||||
const struct gl_tex_env_combine_state * combine, GLint blendUnit,
|
||||
GLuint texel_op, GLuint *state, const GLfloat *factor );
|
||||
|
||||
extern void
|
||||
i830EmitTextureBlend( i830ContextPtr i830 );
|
||||
i830EmitTextureBlend( struct i830_context *i830 );
|
||||
|
||||
|
||||
/* i830_state.c
|
||||
@@ -184,32 +187,25 @@ extern void
|
||||
i830InitStateFuncs( struct dd_function_table *functions );
|
||||
|
||||
extern void
|
||||
i830EmitState( i830ContextPtr i830 );
|
||||
i830EmitState( struct i830_context *i830 );
|
||||
|
||||
extern void
|
||||
i830InitState( i830ContextPtr i830 );
|
||||
i830InitState( struct i830_context *i830 );
|
||||
|
||||
/* i830_metaops.c
|
||||
*/
|
||||
extern GLboolean
|
||||
i830TryTextureReadPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels );
|
||||
|
||||
extern GLboolean
|
||||
i830TryTextureDrawPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels );
|
||||
|
||||
extern void
|
||||
i830ClearWithTris( intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
|
||||
i830InitMetaFuncs( struct i830_context *i830 );
|
||||
|
||||
/*======================================================================
|
||||
* Inline conversion functions. These are better-typed than the
|
||||
* macros used previously:
|
||||
*/
|
||||
static INLINE struct i830_context *
|
||||
i830_context( GLcontext *ctx )
|
||||
{
|
||||
return (struct i830_context *)ctx;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -34,16 +34,18 @@
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
#include "i830_context.h"
|
||||
#include "i830_reg.h"
|
||||
|
||||
/* A large amount of state doesn't need to be uploaded.
|
||||
*/
|
||||
#define ACTIVE (I830_UPLOAD_TEXBLEND(0) | \
|
||||
I830_UPLOAD_STIPPLE | \
|
||||
#define ACTIVE (I830_UPLOAD_INVARIENT | \
|
||||
I830_UPLOAD_CTX | \
|
||||
I830_UPLOAD_BUFFERS | \
|
||||
I830_UPLOAD_STIPPLE | \
|
||||
I830_UPLOAD_TEXBLEND(0) | \
|
||||
I830_UPLOAD_TEX(0))
|
||||
|
||||
|
||||
@@ -54,20 +56,11 @@ do { \
|
||||
i830->current->emitted &= ~ACTIVE; \
|
||||
} while (0)
|
||||
|
||||
/* Operations where the 3D engine is decoupled temporarily from the
|
||||
* current GL state and used for other purposes than simply rendering
|
||||
* incoming triangles.
|
||||
*/
|
||||
static void set_initial_state( i830ContextPtr i830 )
|
||||
{
|
||||
memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
|
||||
i830->meta.active = ACTIVE;
|
||||
i830->meta.emitted = 0;
|
||||
}
|
||||
|
||||
|
||||
static void set_no_depth_stencil_write( i830ContextPtr i830 )
|
||||
static void set_no_stencil_write( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
|
||||
*/
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
|
||||
@@ -75,6 +68,12 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 )
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
|
||||
|
||||
i830->meta.emitted &= ~I830_UPLOAD_CTX;
|
||||
}
|
||||
|
||||
static void set_no_depth_write( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
|
||||
*/
|
||||
@@ -86,25 +85,43 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 )
|
||||
i830->meta.emitted &= ~I830_UPLOAD_CTX;
|
||||
}
|
||||
|
||||
/* Set depth unit to replace.
|
||||
*/
|
||||
static void set_depth_replace( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
|
||||
* ctx->Driver.DepthMask( ctx, GL_TRUE )
|
||||
*/
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE;
|
||||
|
||||
/* ctx->Driver.DepthFunc( ctx, GL_ALWAYS )
|
||||
*/
|
||||
i830->meta.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK;
|
||||
i830->meta.Ctx[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC |
|
||||
DEPTH_TEST_FUNC(COMPAREFUNC_ALWAYS));
|
||||
|
||||
i830->meta.emitted &= ~I830_UPLOAD_CTX;
|
||||
}
|
||||
|
||||
|
||||
/* Set stencil unit to replace always with the reference value.
|
||||
*/
|
||||
static void set_stencil_replace( i830ContextPtr i830,
|
||||
static void set_stencil_replace( struct intel_context *intel,
|
||||
GLuint s_mask,
|
||||
GLuint s_clear)
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE )
|
||||
*/
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
|
||||
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
|
||||
*/
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
|
||||
|
||||
/* ctx->Driver.StencilMask( ctx, s_mask )
|
||||
*/
|
||||
i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
|
||||
@@ -140,8 +157,10 @@ static void set_stencil_replace( i830ContextPtr i830,
|
||||
}
|
||||
|
||||
|
||||
static void set_color_mask( i830ContextPtr i830, GLboolean state )
|
||||
static void set_color_mask( struct intel_context *intel, GLboolean state )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) |
|
||||
(1 << WRITEMASK_GREEN_SHIFT) |
|
||||
(1 << WRITEMASK_BLUE_SHIFT) |
|
||||
@@ -161,8 +180,9 @@ static void set_color_mask( i830ContextPtr i830, GLboolean state )
|
||||
/* Installs a one-stage passthrough texture blend pipeline. Is there
|
||||
* more that can be done to turn off texturing?
|
||||
*/
|
||||
static void set_no_texture( i830ContextPtr i830 )
|
||||
static void set_no_texture( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
static const struct gl_tex_env_combine_state comb = {
|
||||
GL_NONE, GL_NONE,
|
||||
{ GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, },
|
||||
@@ -181,13 +201,13 @@ static void set_no_texture( i830ContextPtr i830 )
|
||||
/* Set up a single element blend stage for 'replace' texturing with no
|
||||
* funny ops.
|
||||
*/
|
||||
static void enable_texture_blend_replace( i830ContextPtr i830,
|
||||
GLenum format )
|
||||
static void set_texture_blend_replace( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
static const struct gl_tex_env_combine_state comb = {
|
||||
GL_REPLACE, GL_REPLACE,
|
||||
{ GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, },
|
||||
{ GL_SRC_COLOR, 0, 0 }, { GL_SRC_ALPHA, 0, 0 },
|
||||
{ GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, }, { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, },
|
||||
{ GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR }, { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA },
|
||||
0, 0, 1, 1
|
||||
};
|
||||
|
||||
@@ -207,31 +227,90 @@ static void enable_texture_blend_replace( i830ContextPtr i830,
|
||||
/* Set up an arbitary piece of memory as a rectangular texture
|
||||
* (including the front or back buffer).
|
||||
*/
|
||||
static void set_tex_rect_source( i830ContextPtr i830,
|
||||
GLuint offset,
|
||||
GLuint width,
|
||||
GLuint height,
|
||||
GLuint pitch,
|
||||
GLuint textureFormat )
|
||||
static GLboolean set_tex_rect_source( struct intel_context *intel,
|
||||
GLuint buffer,
|
||||
GLuint offset,
|
||||
GLuint pitch,
|
||||
GLuint height,
|
||||
GLenum format,
|
||||
GLenum type)
|
||||
{
|
||||
GLint numLevels = 1;
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
GLuint *setup = i830->meta.Tex[0];
|
||||
GLint numLevels = 1;
|
||||
GLuint textureFormat;
|
||||
GLuint cpp;
|
||||
|
||||
pitch *= i830->intel.intelScreen->cpp;
|
||||
/* A full implementation of this would do the upload through
|
||||
* glTexImage2d, and get all the conversion operations at that
|
||||
* point. We are restricted, but still at least have access to the
|
||||
* fragment program swizzle.
|
||||
*/
|
||||
switch (format) {
|
||||
case GL_BGRA:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
|
||||
cpp = 4;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case GL_RGBA:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
|
||||
cpp = 4;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case GL_BGR:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_SHORT_5_6_5_REV:
|
||||
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
|
||||
cpp = 2;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case GL_RGB:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
|
||||
cpp = 2;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
|
||||
/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
i830->meta.tex_buffer[0] = buffer;
|
||||
i830->meta.tex_offset[0] = offset;
|
||||
|
||||
setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
|
||||
(LOAD_TEXTURE_MAP0 << 0) | 4);
|
||||
setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
|
||||
setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
|
||||
((width - 1) << TM0S1_WIDTH_SHIFT) |
|
||||
((pitch - 1) << TM0S1_WIDTH_SHIFT) |
|
||||
textureFormat);
|
||||
setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));
|
||||
setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
|
||||
setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
|
||||
setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
|
||||
setup[I830_TEXREG_TM0S2] = (((((pitch * cpp) / 4) - 1) << TM0S2_PITCH_SHIFT) |
|
||||
TM0S2_CUBE_FACE_ENA_MASK);
|
||||
|
||||
setup[I830_TEXREG_TM0S3] = ( (((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT) |
|
||||
(FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT) |
|
||||
(MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT) |
|
||||
(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT));
|
||||
|
||||
setup[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(0));
|
||||
|
||||
setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
|
||||
MAP_UNIT(0) |
|
||||
@@ -244,40 +323,17 @@ static void set_tex_rect_source( i830ContextPtr i830,
|
||||
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
|
||||
|
||||
i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Select between front and back draw buffers.
|
||||
*/
|
||||
static void set_draw_offset( i830ContextPtr i830,
|
||||
GLuint offset )
|
||||
{
|
||||
i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset;
|
||||
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
|
||||
}
|
||||
|
||||
/* Setup an arbitary draw format, useful for targeting
|
||||
* texture or agp memory.
|
||||
*/
|
||||
static void set_draw_format( i830ContextPtr i830,
|
||||
GLuint format,
|
||||
GLuint depth_format)
|
||||
{
|
||||
i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
|
||||
DSTORG_VERT_BIAS(0x8) | /* .5 */
|
||||
format |
|
||||
DEPTH_IS_Z |
|
||||
depth_format);
|
||||
}
|
||||
|
||||
|
||||
static void set_vertex_format( i830ContextPtr i830 )
|
||||
static void set_vertex_format( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
i830->meta.Ctx[I830_CTXREG_VF] = (_3DSTATE_VFT0_CMD |
|
||||
VFT0_TEX_COUNT(1) |
|
||||
VFT0_DIFFUSE |
|
||||
VFT0_SPEC |
|
||||
VFT0_XYZW);
|
||||
VFT0_XYZ);
|
||||
i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD |
|
||||
VFT1_TEX0_FMT(TEXCOORDFMT_2D) |
|
||||
VFT1_TEX1_FMT(TEXCOORDFMT_2D) |
|
||||
@@ -287,446 +343,127 @@ static void set_vertex_format( i830ContextPtr i830 )
|
||||
}
|
||||
|
||||
|
||||
static void draw_quad(i830ContextPtr i830,
|
||||
GLfloat x0, GLfloat x1,
|
||||
GLfloat y0, GLfloat y1,
|
||||
GLubyte red, GLubyte green,
|
||||
GLubyte blue, GLubyte alpha,
|
||||
GLfloat s0, GLfloat s1,
|
||||
GLfloat t0, GLfloat t1 )
|
||||
static void meta_import_pixel_state( struct intel_context *intel )
|
||||
{
|
||||
GLuint vertex_size = 8;
|
||||
GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,
|
||||
PRIM3D_TRIFAN,
|
||||
4*vertex_size,
|
||||
vertex_size );
|
||||
intelVertex tmp;
|
||||
int i;
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
i830->meta.Ctx[I830_CTXREG_STATE1] = i830->state.Ctx[I830_CTXREG_STATE1];
|
||||
i830->meta.Ctx[I830_CTXREG_STATE2] = i830->state.Ctx[I830_CTXREG_STATE2];
|
||||
i830->meta.Ctx[I830_CTXREG_STATE3] = i830->state.Ctx[I830_CTXREG_STATE3];
|
||||
i830->meta.Ctx[I830_CTXREG_STATE4] = i830->state.Ctx[I830_CTXREG_STATE4];
|
||||
i830->meta.Ctx[I830_CTXREG_STATE5] = i830->state.Ctx[I830_CTXREG_STATE5];
|
||||
i830->meta.Ctx[I830_CTXREG_IALPHAB] = i830->state.Ctx[I830_CTXREG_IALPHAB];
|
||||
i830->meta.Ctx[I830_CTXREG_STENCILTST] = i830->state.Ctx[I830_CTXREG_STENCILTST];
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_1] = i830->state.Ctx[I830_CTXREG_ENABLES_1];
|
||||
i830->meta.Ctx[I830_CTXREG_ENABLES_2] = i830->state.Ctx[I830_CTXREG_ENABLES_2];
|
||||
i830->meta.Ctx[I830_CTXREG_AA] = i830->state.Ctx[I830_CTXREG_AA];
|
||||
i830->meta.Ctx[I830_CTXREG_FOGCOLOR] = i830->state.Ctx[I830_CTXREG_FOGCOLOR];
|
||||
i830->meta.Ctx[I830_CTXREG_BLENDCOLOR0] = i830->state.Ctx[I830_CTXREG_BLENDCOLOR0];
|
||||
i830->meta.Ctx[I830_CTXREG_BLENDCOLOR1] = i830->state.Ctx[I830_CTXREG_BLENDCOLOR1];
|
||||
i830->meta.Ctx[I830_CTXREG_MCSB0] = i830->state.Ctx[I830_CTXREG_MCSB0];
|
||||
i830->meta.Ctx[I830_CTXREG_MCSB1] = i830->state.Ctx[I830_CTXREG_MCSB1];
|
||||
|
||||
/* fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */
|
||||
/* __FUNCTION__, */
|
||||
/* x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */
|
||||
|
||||
i830->meta.Ctx[I830_CTXREG_STATE3] &= ~CULLMODE_MASK;
|
||||
i830->meta.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
|
||||
i830->meta.emitted &= ~I830_UPLOAD_CTX;
|
||||
|
||||
|
||||
/* initial vertex, left bottom */
|
||||
tmp.v.x = x0;
|
||||
tmp.v.y = y0;
|
||||
tmp.v.z = 1.0;
|
||||
tmp.v.w = 1.0;
|
||||
tmp.v.color.red = red;
|
||||
tmp.v.color.green = green;
|
||||
tmp.v.color.blue = blue;
|
||||
tmp.v.color.alpha = alpha;
|
||||
tmp.v.specular.red = 0;
|
||||
tmp.v.specular.green = 0;
|
||||
tmp.v.specular.blue = 0;
|
||||
tmp.v.specular.alpha = 0;
|
||||
tmp.v.u0 = s0;
|
||||
tmp.v.v0 = t0;
|
||||
for (i = 0 ; i < 8 ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
/* right bottom */
|
||||
vb += 8;
|
||||
tmp.v.x = x1;
|
||||
tmp.v.u0 = s1;
|
||||
for (i = 0 ; i < 8 ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
/* right top */
|
||||
vb += 8;
|
||||
tmp.v.y = y1;
|
||||
tmp.v.v0 = t1;
|
||||
for (i = 0 ; i < 8 ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
/* left top */
|
||||
vb += 8;
|
||||
tmp.v.x = x0;
|
||||
tmp.v.u0 = s0;
|
||||
for (i = 0 ; i < 8 ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
/* fprintf(stderr, "%s: DV1: %x\n", */
|
||||
/* __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */
|
||||
}
|
||||
|
||||
void
|
||||
i830ClearWithTris(intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT( intel );
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
int x0, y0, x1, y1;
|
||||
|
||||
|
||||
SET_STATE( i830, meta );
|
||||
set_initial_state( i830 );
|
||||
set_no_texture( i830 );
|
||||
set_vertex_format( i830 );
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
if(!all) {
|
||||
x0 = cx;
|
||||
y0 = cy;
|
||||
x1 = x0 + cw;
|
||||
y1 = y0 + ch;
|
||||
} else {
|
||||
x0 = 0;
|
||||
y0 = 0;
|
||||
x1 = x0 + dPriv->w;
|
||||
y1 = y0 + dPriv->h;
|
||||
}
|
||||
|
||||
/* Don't do any clipping to screen - these are window coordinates.
|
||||
* The active cliprects will be applied as for any other geometry.
|
||||
*/
|
||||
|
||||
if(mask & BUFFER_BIT_FRONT_LEFT) {
|
||||
set_no_depth_stencil_write( i830 );
|
||||
set_color_mask( i830, GL_TRUE );
|
||||
set_draw_offset( i830, screen->front.offset );
|
||||
draw_quad(i830, x0, x1, y0, y1,
|
||||
intel->clear_red, intel->clear_green,
|
||||
intel->clear_blue, intel->clear_alpha,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(mask & BUFFER_BIT_BACK_LEFT) {
|
||||
set_no_depth_stencil_write( i830 );
|
||||
set_color_mask( i830, GL_TRUE );
|
||||
set_draw_offset( i830, screen->back.offset );
|
||||
|
||||
draw_quad(i830, x0, x1, y0, y1,
|
||||
intel->clear_red, intel->clear_green,
|
||||
intel->clear_blue, intel->clear_alpha,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(mask & BUFFER_BIT_STENCIL) {
|
||||
set_stencil_replace( i830,
|
||||
intel->ctx.Stencil.WriteMask[0],
|
||||
intel->ctx.Stencil.Clear);
|
||||
|
||||
set_color_mask( i830, GL_FALSE );
|
||||
set_draw_offset( i830, screen->front.offset );
|
||||
draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
SET_STATE( i830, state );
|
||||
i830->meta.Buffer[I830_DESTREG_SENABLE] = i830->state.Buffer[I830_DESTREG_SENABLE];
|
||||
i830->meta.Buffer[I830_DESTREG_SR1] = i830->state.Buffer[I830_DESTREG_SR1];
|
||||
i830->meta.Buffer[I830_DESTREG_SR2] = i830->state.Buffer[I830_DESTREG_SR2];
|
||||
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GLboolean
|
||||
i830TryTextureReadPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels )
|
||||
/* Select between front and back draw buffers.
|
||||
*/
|
||||
static void meta_draw_region( struct intel_context *intel,
|
||||
struct intel_region *draw_region,
|
||||
struct intel_region *depth_region )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
intelScreenPrivate *screen = i830->intel.intelScreen;
|
||||
GLint pitch = pack->RowLength ? pack->RowLength : width;
|
||||
__DRIdrawablePrivate *dPriv = i830->intel.driDrawable;
|
||||
int textureFormat;
|
||||
GLenum glTextureFormat;
|
||||
int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
|
||||
int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels);
|
||||
int destFormat, depthFormat, destPitch;
|
||||
drm_clip_rect_t tmp;
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
GLuint format;
|
||||
GLuint depth_format = DEPTH_FRMT_16_FIXED;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
|
||||
if ( ctx->_ImageTransferState ||
|
||||
pack->SwapBytes ||
|
||||
pack->LsbFirst ||
|
||||
!pack->Invert) {
|
||||
fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
switch (screen->fbFormat) {
|
||||
case DV_PF_565:
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
|
||||
glTextureFormat = GL_RGB;
|
||||
break;
|
||||
case DV_PF_555:
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
|
||||
glTextureFormat = GL_RGBA;
|
||||
break;
|
||||
case DV_PF_8888:
|
||||
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
|
||||
glTextureFormat = GL_RGBA;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__,
|
||||
screen->fbFormat);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
if (format != GL_RGB) return GL_FALSE;
|
||||
destFormat = COLR_BUF_RGB565;
|
||||
depthFormat = DEPTH_FRMT_16_FIXED;
|
||||
destPitch = pitch * 2;
|
||||
break;
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
if (format != GL_BGRA) return GL_FALSE;
|
||||
destFormat = COLR_BUF_ARGB8888;
|
||||
depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER;
|
||||
destPitch = pitch * 4;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(type));
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
destFormat |= (0x02<<24);
|
||||
|
||||
/* fprintf(stderr, "type: %s destFormat: %x\n", */
|
||||
/* _mesa_lookup_enum_by_nr(type), */
|
||||
/* destFormat); */
|
||||
|
||||
intelFlush( ctx );
|
||||
|
||||
SET_STATE( i830, meta );
|
||||
set_initial_state( i830 );
|
||||
set_no_depth_stencil_write( i830 );
|
||||
|
||||
LOCK_HARDWARE( intel );
|
||||
{
|
||||
intelWaitForIdle( intel ); /* required by GL */
|
||||
|
||||
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
SET_STATE(i830, state);
|
||||
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* FIXME -- Just emit the correct state
|
||||
*/
|
||||
if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,
|
||||
destPitch) != 0) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
SET_STATE(i830, state);
|
||||
fprintf(stderr, "%s: setparam failed\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
y = dPriv->h - y - height;
|
||||
x += dPriv->x;
|
||||
y += dPriv->y;
|
||||
|
||||
|
||||
/* Set the frontbuffer up as a large rectangular texture.
|
||||
*/
|
||||
set_tex_rect_source( i830,
|
||||
src_offset,
|
||||
screen->width,
|
||||
screen->height,
|
||||
screen->front.pitch,
|
||||
textureFormat );
|
||||
intel_region_release(intel, &i830->meta.draw_region);
|
||||
intel_region_reference(&i830->meta.draw_region, draw_region);
|
||||
|
||||
|
||||
enable_texture_blend_replace( i830, glTextureFormat );
|
||||
intel_region_release(intel, &i830->meta.depth_region);
|
||||
intel_region_reference(&i830->meta.depth_region, depth_region);
|
||||
|
||||
/* XXX FBO: grab code from i915 meta_draw_region */
|
||||
|
||||
/* Set the 3d engine to draw into the agp memory
|
||||
*/
|
||||
/* XXX: 555 support?
|
||||
*/
|
||||
if (draw_region->cpp == 2)
|
||||
format = DV_PF_565;
|
||||
else
|
||||
format = DV_PF_8888;
|
||||
|
||||
set_draw_offset( i830, destOffset );
|
||||
set_draw_format( i830, destFormat, depthFormat );
|
||||
|
||||
|
||||
/* Draw a single quad, no cliprects:
|
||||
*/
|
||||
i830->intel.numClipRects = 1;
|
||||
i830->intel.pClipRects = &tmp;
|
||||
i830->intel.pClipRects[0].x1 = 0;
|
||||
i830->intel.pClipRects[0].y1 = 0;
|
||||
i830->intel.pClipRects[0].x2 = width;
|
||||
i830->intel.pClipRects[0].y2 = height;
|
||||
|
||||
draw_quad( i830,
|
||||
0, width, 0, height,
|
||||
0, 255, 0, 0,
|
||||
x, x+width, y, y+height );
|
||||
|
||||
intelWindowMoved( intel );
|
||||
if (depth_region) {
|
||||
if (depth_region->cpp == 2)
|
||||
depth_format = DEPTH_FRMT_16_FIXED;
|
||||
else
|
||||
depth_format = DEPTH_FRMT_24_FIXED_8_OTHER;
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
intelFinish( ctx ); /* required by GL */
|
||||
|
||||
SET_STATE( i830, state );
|
||||
return GL_TRUE;
|
||||
i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
|
||||
DSTORG_VERT_BIAS(0x8) | /* .5 */
|
||||
format |
|
||||
DEPTH_IS_Z |
|
||||
depth_format);
|
||||
|
||||
i830->meta.emitted &= ~I830_UPLOAD_BUFFERS;
|
||||
}
|
||||
|
||||
|
||||
GLboolean
|
||||
i830TryTextureDrawPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
/* Operations where the 3D engine is decoupled temporarily from the
|
||||
* current GL state and used for other purposes than simply rendering
|
||||
* incoming triangles.
|
||||
*/
|
||||
static void install_meta_state( struct intel_context *intel )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
int textureFormat;
|
||||
GLenum glTextureFormat;
|
||||
int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2];
|
||||
int src_offset = intelAgpOffsetFromVirtual( intel, pixels );
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) );
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
i830->meta.active = ACTIVE;
|
||||
i830->meta.emitted = 0;
|
||||
|
||||
/* Todo -- upload images that aren't in agp space, then texture
|
||||
* from them.
|
||||
*/
|
||||
SET_STATE(i830, meta);
|
||||
set_vertex_format(intel);
|
||||
set_no_texture(intel);
|
||||
}
|
||||
|
||||
if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) {
|
||||
fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Todo -- don't want to clobber all the drawing state like we do
|
||||
* for readpixels -- most of this state can be handled just fine.
|
||||
*/
|
||||
if ( ctx->_ImageTransferState ||
|
||||
unpack->SwapBytes ||
|
||||
unpack->LsbFirst ||
|
||||
ctx->Color.AlphaEnabled ||
|
||||
ctx->Depth.Test ||
|
||||
ctx->Fog.Enabled ||
|
||||
ctx->Scissor.Enabled ||
|
||||
ctx->Stencil.Enabled ||
|
||||
!ctx->Color.ColorMask[0] ||
|
||||
!ctx->Color.ColorMask[1] ||
|
||||
!ctx->Color.ColorMask[2] ||
|
||||
!ctx->Color.ColorMask[3] ||
|
||||
ctx->Color.ColorLogicOpEnabled ||
|
||||
ctx->Texture._EnabledUnits) {
|
||||
fprintf(stderr, "%s: other tests failed\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Todo -- remove these restrictions:
|
||||
*/
|
||||
if (ctx->Pixel.ZoomX != 1.0F ||
|
||||
ctx->Pixel.ZoomY != -1.0F)
|
||||
return GL_FALSE;
|
||||
|
||||
|
||||
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
|
||||
if (format != GL_BGRA) return GL_FALSE;
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
|
||||
glTextureFormat = GL_RGBA;
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
if (format != GL_RGB) return GL_FALSE;
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
|
||||
glTextureFormat = GL_RGB;
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT_8_8_MESA:
|
||||
if (format != GL_YCBCR_MESA) return GL_FALSE;
|
||||
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY
|
||||
/* | TM0S1_COLORSPACE_CONVERSION */
|
||||
);
|
||||
glTextureFormat = GL_YCBCR_MESA;
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT_8_8_REV_MESA:
|
||||
if (format != GL_YCBCR_MESA) return GL_FALSE;
|
||||
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL
|
||||
/* | TM0S1_COLORSPACE_CONVERSION */
|
||||
);
|
||||
glTextureFormat = GL_YCBCR_MESA;
|
||||
break;
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
if (format != GL_BGRA) return GL_FALSE;
|
||||
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
|
||||
glTextureFormat = GL_RGBA;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
intelFlush( ctx );
|
||||
|
||||
SET_STATE( i830, meta );
|
||||
|
||||
LOCK_HARDWARE( intel );
|
||||
{
|
||||
intelWaitForIdle( intel ); /* required by GL */
|
||||
|
||||
y -= height; /* cope with pixel zoom */
|
||||
|
||||
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
SET_STATE(i830, state);
|
||||
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
y = dPriv->h - y - height;
|
||||
|
||||
set_initial_state( i830 );
|
||||
|
||||
/* Set the pixel image up as a rectangular texture.
|
||||
*/
|
||||
set_tex_rect_source( i830,
|
||||
src_offset,
|
||||
width,
|
||||
height,
|
||||
pitch, /* XXXX!!!! -- /2 sometimes */
|
||||
textureFormat );
|
||||
|
||||
|
||||
enable_texture_blend_replace( i830, glTextureFormat );
|
||||
|
||||
|
||||
/* Draw to the current draw buffer:
|
||||
*/
|
||||
set_draw_offset( i830, dst_offset );
|
||||
|
||||
/* Draw a quad, use regular cliprects
|
||||
*/
|
||||
/* fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */
|
||||
|
||||
draw_quad( i830,
|
||||
x, x+width, y, y+height,
|
||||
0, 255, 0, 0,
|
||||
0, width, 0, height );
|
||||
|
||||
intelWindowMoved( intel );
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
intelFinish( ctx ); /* required by GL */
|
||||
|
||||
static void leave_meta_state( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
intel_region_release(intel, &i830->meta.draw_region);
|
||||
intel_region_release(intel, &i830->meta.depth_region);
|
||||
/* intel_region_release(intel, &i830->meta.tex_region[0]); */
|
||||
SET_STATE(i830, state);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i830InitMetaFuncs( struct i830_context *i830 )
|
||||
{
|
||||
i830->intel.vtbl.install_meta_state = install_meta_state;
|
||||
i830->intel.vtbl.leave_meta_state = leave_meta_state;
|
||||
i830->intel.vtbl.meta_no_depth_write = set_no_depth_write;
|
||||
i830->intel.vtbl.meta_no_stencil_write = set_no_stencil_write;
|
||||
i830->intel.vtbl.meta_stencil_replace = set_stencil_replace;
|
||||
i830->intel.vtbl.meta_depth_replace = set_depth_replace;
|
||||
i830->intel.vtbl.meta_color_mask = set_color_mask;
|
||||
i830->intel.vtbl.meta_no_texture = set_no_texture;
|
||||
i830->intel.vtbl.meta_texture_blend_replace = set_texture_blend_replace;
|
||||
i830->intel.vtbl.meta_tex_rect_source = set_tex_rect_source;
|
||||
i830->intel.vtbl.meta_draw_region = meta_draw_region;
|
||||
i830->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -407,10 +407,10 @@
|
||||
#define LOGICOP_SET 0xf
|
||||
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
|
||||
#define ENABLE_STENCIL_TEST_MASK (1<<17)
|
||||
#define STENCIL_TEST_MASK(x) ((x)<<8)
|
||||
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8)
|
||||
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
|
||||
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
|
||||
#define STENCIL_WRITE_MASK(x) (x)
|
||||
#define STENCIL_WRITE_MASK(x) ((x)&0xff)
|
||||
|
||||
/* _3DSTATE_MODES_5, p196 */
|
||||
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_fbo.h"
|
||||
|
||||
#include "i830_context.h"
|
||||
#include "i830_reg.h"
|
||||
@@ -44,7 +45,7 @@ static void
|
||||
i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
GLuint mask)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int test = intel_translate_compare_func(func);
|
||||
|
||||
mask = mask & 0xff;
|
||||
@@ -69,7 +70,7 @@ i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
static void
|
||||
i830StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask);
|
||||
@@ -86,7 +87,7 @@ static void
|
||||
i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
GLenum zpass)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int fop, dfop, dpop;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -193,7 +194,7 @@ i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
|
||||
static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int test = intel_translate_compare_func(func);
|
||||
GLubyte refByte;
|
||||
GLuint refInt;
|
||||
@@ -221,7 +222,7 @@ static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
*/
|
||||
static void i830EvalLogicOpBlendState(GLcontext *ctx)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
|
||||
@@ -245,7 +246,7 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx)
|
||||
|
||||
static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
GLubyte r, g, b, a;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -268,7 +269,7 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
*/
|
||||
static void i830_set_blend_state( GLcontext * ctx )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int funcA;
|
||||
int funcRGB;
|
||||
int eqnA;
|
||||
@@ -406,7 +407,7 @@ static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
|
||||
|
||||
static void i830DepthFunc(GLcontext *ctx, GLenum func)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int test = intel_translate_compare_func(func);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -420,7 +421,7 @@ static void i830DepthFunc(GLcontext *ctx, GLenum func)
|
||||
|
||||
static void i830DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag);
|
||||
@@ -443,7 +444,7 @@ static void i830DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
*/
|
||||
static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
const GLubyte *m = mask;
|
||||
GLubyte p[4];
|
||||
int i,j,k;
|
||||
@@ -496,15 +497,14 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
GLsizei w, GLsizei h)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
intelScreenPrivate *screen = i830->intel.intelScreen;
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
if (!i830->intel.driDrawable)
|
||||
if (!ctx->DrawBuffer)
|
||||
return;
|
||||
|
||||
x1 = x;
|
||||
y1 = i830->intel.driDrawable->h - (y + h);
|
||||
y1 = ctx->DrawBuffer->Height - (y + h);
|
||||
x2 = x + w - 1;
|
||||
y2 = y1 + h - 1;
|
||||
|
||||
@@ -512,16 +512,10 @@ static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
|
||||
x, y, w, h);
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 < 0) x2 = 0;
|
||||
if (y2 < 0) y2 = 0;
|
||||
|
||||
if (x2 >= screen->width) x2 = screen->width-1;
|
||||
if (y2 >= screen->height) y2 = screen->height-1;
|
||||
if (x1 >= screen->width) x1 = screen->width-1;
|
||||
if (y1 >= screen->height) y1 = screen->height-1;
|
||||
|
||||
x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
|
||||
y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
|
||||
x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
|
||||
y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
|
||||
i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
|
||||
@@ -530,7 +524,7 @@ static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
|
||||
static void i830LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int tmp = intel_translate_logic_op( opcode );
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -545,7 +539,7 @@ static void i830LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
|
||||
static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
GLuint mode;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -573,7 +567,7 @@ static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
|
||||
static void i830LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT( ctx );
|
||||
struct i830_context *i830 = i830_context( ctx );
|
||||
int width;
|
||||
int state5;
|
||||
|
||||
@@ -594,7 +588,7 @@ static void i830LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
|
||||
static void i830PointSize(GLcontext *ctx, GLfloat size)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
GLint point_size = (int)size;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -616,7 +610,7 @@ static void i830ColorMask(GLcontext *ctx,
|
||||
GLboolean r, GLboolean g,
|
||||
GLboolean b, GLboolean a)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT( ctx );
|
||||
struct i830_context *i830 = i830_context( ctx );
|
||||
GLuint tmp = 0;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -638,7 +632,7 @@ static void i830ColorMask(GLcontext *ctx,
|
||||
|
||||
static void update_specular( GLcontext *ctx )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT( ctx );
|
||||
struct i830_context *i830 = i830_context( ctx );
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK;
|
||||
@@ -664,7 +658,7 @@ static void i830LightModelfv(GLcontext *ctx, GLenum pname,
|
||||
*/
|
||||
static void i830ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
|
||||
|
||||
@@ -690,7 +684,7 @@ static void i830ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
*/
|
||||
static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
@@ -710,7 +704,7 @@ static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
|
||||
static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
|
||||
switch(cap) {
|
||||
case GL_LIGHTING:
|
||||
@@ -806,20 +800,28 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
break;
|
||||
|
||||
case GL_STENCIL_TEST:
|
||||
if (i830->intel.hw_stencil) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
{
|
||||
GLboolean hw_stencil = GL_FALSE;
|
||||
if (ctx->DrawBuffer) {
|
||||
struct intel_renderbuffer *irbStencil
|
||||
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
|
||||
hw_stencil = (irbStencil && irbStencil->region);
|
||||
}
|
||||
if (hw_stencil) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
|
||||
if (state) {
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
|
||||
} else {
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
|
||||
}
|
||||
} else {
|
||||
FALLBACK( &i830->intel, I830_FALLBACK_STENCIL, state );
|
||||
if (state) {
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
|
||||
} else {
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
|
||||
}
|
||||
} else {
|
||||
FALLBACK( &i830->intel, I830_FALLBACK_STENCIL, state );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -844,7 +846,7 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
}
|
||||
|
||||
|
||||
static void i830_init_packets( i830ContextPtr i830 )
|
||||
static void i830_init_packets( struct i830_context *i830 )
|
||||
{
|
||||
intelScreenPrivate *screen = i830->intel.intelScreen;
|
||||
|
||||
@@ -902,6 +904,7 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
DISABLE_COLOR_BLEND |
|
||||
DISABLE_DEPTH_TEST);
|
||||
|
||||
#if 000 /* XXX all the stencil enable state is set in i830Enable(), right? */
|
||||
if (i830->intel.hw_stencil) {
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD |
|
||||
ENABLE_STENCIL_WRITE |
|
||||
@@ -911,7 +914,9 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
/* set no color comps disabled */
|
||||
ENABLE_COLOR_WRITE |
|
||||
ENABLE_DEPTH_WRITE);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD |
|
||||
DISABLE_STENCIL_WRITE |
|
||||
ENABLE_TEX_CACHE |
|
||||
@@ -1010,15 +1015,14 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH |
|
||||
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) |
|
||||
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | /* XXX FBO fix */
|
||||
BUF_3D_USE_FENCE);
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset;
|
||||
/* i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; */
|
||||
|
||||
|
||||
i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
|
||||
|
||||
switch (screen->fbFormat) {
|
||||
case DV_PF_555:
|
||||
case DV_PF_565:
|
||||
i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
|
||||
DSTORG_VERT_BIAS(0x8) | /* .5 */
|
||||
@@ -1068,7 +1072,7 @@ void i830InitStateFuncs( struct dd_function_table *functions )
|
||||
functions->StencilOpSeparate = i830StencilOpSeparate;
|
||||
}
|
||||
|
||||
void i830InitState( i830ContextPtr i830 )
|
||||
void i830InitState( struct i830_context *i830 )
|
||||
{
|
||||
GLcontext *ctx = &i830->intel.ctx;
|
||||
|
||||
@@ -1080,7 +1084,8 @@ void i830InitState( i830ContextPtr i830 )
|
||||
|
||||
i830->current = &i830->state;
|
||||
i830->state.emitted = 0;
|
||||
i830->state.active = (I830_UPLOAD_TEXBLEND(0) |
|
||||
i830->state.active = (I830_UPLOAD_INVARIENT |
|
||||
I830_UPLOAD_TEXBLEND(0) |
|
||||
I830_UPLOAD_STIPPLE |
|
||||
I830_UPLOAD_CTX |
|
||||
I830_UPLOAD_BUFFERS);
|
||||
|
||||
@@ -45,261 +45,12 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the texture wrap modes.
|
||||
*
|
||||
* The i830M (and related graphics cores) do not support GL_CLAMP. The Intel
|
||||
* drivers for "other operating systems" implement GL_CLAMP as
|
||||
* GL_CLAMP_TO_EDGE, so the same is done here.
|
||||
*
|
||||
* \param t Texture object whose wrap modes are to be set
|
||||
* \param swrap Wrap mode for the \a s texture coordinate
|
||||
* \param twrap Wrap mode for the \a t texture coordinate
|
||||
*/
|
||||
static void i830SetTexWrapping(i830TextureObjectPtr tex,
|
||||
GLenum swrap,
|
||||
GLenum twrap)
|
||||
{
|
||||
tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK);
|
||||
|
||||
switch( swrap ) {
|
||||
case GL_REPEAT:
|
||||
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP);
|
||||
break;
|
||||
case GL_CLAMP:
|
||||
case GL_CLAMP_TO_EDGE:
|
||||
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP);
|
||||
break;
|
||||
case GL_CLAMP_TO_BORDER:
|
||||
tex->Setup[I830_TEXREG_MCS] |=
|
||||
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER);
|
||||
break;
|
||||
case GL_MIRRORED_REPEAT:
|
||||
tex->Setup[I830_TEXREG_MCS] |=
|
||||
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch( twrap ) {
|
||||
case GL_REPEAT:
|
||||
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP);
|
||||
break;
|
||||
case GL_CLAMP:
|
||||
case GL_CLAMP_TO_EDGE:
|
||||
tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP);
|
||||
break;
|
||||
case GL_CLAMP_TO_BORDER:
|
||||
tex->Setup[I830_TEXREG_MCS] |=
|
||||
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER);
|
||||
break;
|
||||
case GL_MIRRORED_REPEAT:
|
||||
tex->Setup[I830_TEXREG_MCS] |=
|
||||
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the texture magnification and minification modes.
|
||||
*
|
||||
* \param t Texture whose filter modes are to be set
|
||||
* \param minf Texture minification mode
|
||||
* \param magf Texture magnification mode
|
||||
* \param bias LOD bias for this texture unit.
|
||||
*/
|
||||
|
||||
static void i830SetTexFilter( i830TextureObjectPtr t, GLenum minf, GLenum magf,
|
||||
GLfloat maxanisotropy )
|
||||
{
|
||||
int minFilt = 0, mipFilt = 0, magFilt = 0;
|
||||
|
||||
if(INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
if ( maxanisotropy > 1.0 ) {
|
||||
minFilt = FILTER_ANISOTROPIC;
|
||||
magFilt = FILTER_ANISOTROPIC;
|
||||
}
|
||||
else {
|
||||
switch (minf) {
|
||||
case GL_NEAREST:
|
||||
minFilt = FILTER_NEAREST;
|
||||
mipFilt = MIPFILTER_NONE;
|
||||
break;
|
||||
case GL_LINEAR:
|
||||
minFilt = FILTER_LINEAR;
|
||||
mipFilt = MIPFILTER_NONE;
|
||||
break;
|
||||
case GL_NEAREST_MIPMAP_NEAREST:
|
||||
minFilt = FILTER_NEAREST;
|
||||
mipFilt = MIPFILTER_NEAREST;
|
||||
break;
|
||||
case GL_LINEAR_MIPMAP_NEAREST:
|
||||
minFilt = FILTER_LINEAR;
|
||||
mipFilt = MIPFILTER_NEAREST;
|
||||
break;
|
||||
case GL_NEAREST_MIPMAP_LINEAR:
|
||||
minFilt = FILTER_NEAREST;
|
||||
mipFilt = MIPFILTER_LINEAR;
|
||||
break;
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
minFilt = FILTER_LINEAR;
|
||||
mipFilt = MIPFILTER_LINEAR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (magf) {
|
||||
case GL_NEAREST:
|
||||
magFilt = FILTER_NEAREST;
|
||||
break;
|
||||
case GL_LINEAR:
|
||||
magFilt = FILTER_LINEAR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_FILTER_MASK;
|
||||
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIP_FILTER_MASK;
|
||||
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAG_FILTER_MASK;
|
||||
t->Setup[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
|
||||
(mipFilt << TM0S3_MIP_FILTER_SHIFT) |
|
||||
(magFilt << TM0S3_MAG_FILTER_SHIFT));
|
||||
}
|
||||
|
||||
static void i830SetTexBorderColor(i830TextureObjectPtr t, GLubyte color[4])
|
||||
{
|
||||
if(INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
t->Setup[I830_TEXREG_TM0S4] =
|
||||
INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocate space for and load the mesa images into the texture memory block.
|
||||
* This will happen before drawing with a new texture, or drawing with a
|
||||
* texture after it was swapped out or teximaged again.
|
||||
*/
|
||||
|
||||
intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj )
|
||||
{
|
||||
i830TextureObjectPtr t = CALLOC_STRUCT( i830_texture_object );
|
||||
if ( !t )
|
||||
return NULL;
|
||||
|
||||
texObj->DriverData = t;
|
||||
t->intel.base.tObj = texObj;
|
||||
t->intel.dirty = I830_UPLOAD_TEX_ALL;
|
||||
make_empty_list( &t->intel.base );
|
||||
|
||||
t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */
|
||||
t->Setup[I830_TEXREG_TM0S0] = 0;
|
||||
t->Setup[I830_TEXREG_TM0S1] = 0;
|
||||
t->Setup[I830_TEXREG_TM0S2] = 0;
|
||||
t->Setup[I830_TEXREG_TM0S3] = 0;
|
||||
t->Setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
|
||||
MAP_UNIT(0) |
|
||||
ENABLE_TEXCOORD_PARAMS |
|
||||
TEXCOORDS_ARE_NORMAL |
|
||||
TEXCOORDTYPE_CARTESIAN |
|
||||
ENABLE_ADDR_V_CNTL |
|
||||
TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
|
||||
ENABLE_ADDR_U_CNTL |
|
||||
TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));
|
||||
|
||||
|
||||
i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
|
||||
i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter,
|
||||
texObj->MaxAnisotropy );
|
||||
i830SetTexBorderColor( t, texObj->_BorderChan );
|
||||
|
||||
return &t->intel;
|
||||
}
|
||||
|
||||
|
||||
static void i830TexParameter( GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *tObj,
|
||||
GLenum pname, const GLfloat *params )
|
||||
{
|
||||
i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
i830SetTexFilter( t, tObj->MinFilter, tObj->MagFilter,
|
||||
tObj->MaxAnisotropy);
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_WRAP_S:
|
||||
case GL_TEXTURE_WRAP_T:
|
||||
i830SetTexWrapping( t, tObj->WrapS, tObj->WrapT );
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_BORDER_COLOR:
|
||||
i830SetTexBorderColor( t, tObj->_BorderChan );
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_BASE_LEVEL:
|
||||
case GL_TEXTURE_MAX_LEVEL:
|
||||
case GL_TEXTURE_MIN_LOD:
|
||||
case GL_TEXTURE_MAX_LOD:
|
||||
/* The i830 and its successors can do a lot of this without
|
||||
* reloading the textures. A project for someone?
|
||||
*/
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( (driTextureObject *) t );
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
t->intel.dirty = I830_UPLOAD_TEX_ALL;
|
||||
}
|
||||
|
||||
|
||||
static void i830TexEnv( GLcontext *ctx, GLenum target,
|
||||
GLenum pname, const GLfloat *param )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT( ctx );
|
||||
GLuint unit = ctx->Texture.CurrentUnit;
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_ENV_COLOR:
|
||||
#if 0
|
||||
{
|
||||
GLubyte r, g, b, a;
|
||||
GLuint col;
|
||||
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(r, param[RCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(g, param[GCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(b, param[BCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(a, param[ACOMP]);
|
||||
|
||||
col = ((a << 24) | (r << 16) | (g << 8) | b);
|
||||
|
||||
if (col != i830->state.TexEnv[unit][I830_TEXENVREG_COL1]) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEXENV);
|
||||
i830->state.TexEnv[unit][I830_TEXENVREG_COL1] = col;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case GL_TEXTURE_ENV_MODE:
|
||||
case GL_COMBINE_RGB:
|
||||
case GL_COMBINE_ALPHA:
|
||||
@@ -320,13 +71,13 @@ static void i830TexEnv( GLcontext *ctx, GLenum target,
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_LOD_BIAS: {
|
||||
struct i830_context *i830 = i830_context( ctx );
|
||||
GLuint unit = ctx->Texture.CurrentUnit;
|
||||
int b = (int) ((*param) * 16.0);
|
||||
if (b > 63) b = 63;
|
||||
if (b < -64) b = -64;
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK;
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S3] |=
|
||||
((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
|
||||
i830->lodbias_tm0s3[unit] = ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -341,5 +92,4 @@ static void i830TexEnv( GLcontext *ctx, GLenum target,
|
||||
void i830InitTextureFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
functions->TexEnv = i830TexEnv;
|
||||
functions->TexParameter = i830TexParameter;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count,
|
||||
}
|
||||
|
||||
|
||||
static __inline__ GLuint GetTexelOp(GLint unit)
|
||||
static INLINE GLuint GetTexelOp(GLint unit)
|
||||
{
|
||||
switch(unit) {
|
||||
case 0: return TEXBLENDARG_TEXEL0;
|
||||
@@ -132,7 +132,7 @@ static __inline__ GLuint GetTexelOp(GLint unit)
|
||||
* partial support for the extension?
|
||||
*/
|
||||
GLuint
|
||||
i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
i830SetTexEnvCombine(struct i830_context *i830,
|
||||
const struct gl_tex_env_combine_state * combine,
|
||||
GLint blendUnit,
|
||||
GLuint texel_op,
|
||||
@@ -394,7 +394,7 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
}
|
||||
|
||||
|
||||
static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit,
|
||||
static void emit_texblend( struct i830_context *i830, GLuint unit, GLuint blendUnit,
|
||||
GLboolean last_stage )
|
||||
{
|
||||
struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit];
|
||||
@@ -423,7 +423,7 @@ static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit,
|
||||
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), GL_TRUE);
|
||||
}
|
||||
|
||||
static void emit_passthrough( i830ContextPtr i830 )
|
||||
static void emit_passthrough( struct i830_context *i830 )
|
||||
{
|
||||
GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
|
||||
GLuint unit = 0;
|
||||
@@ -442,7 +442,7 @@ static void emit_passthrough( i830ContextPtr i830 )
|
||||
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), GL_TRUE);
|
||||
}
|
||||
|
||||
void i830EmitTextureBlend( i830ContextPtr i830 )
|
||||
void i830EmitTextureBlend( struct i830_context *i830 )
|
||||
{
|
||||
GLcontext *ctx = &i830->intel.ctx;
|
||||
GLuint unit, last_stage = 0, blendunit = 0;
|
||||
|
||||
@@ -38,441 +38,274 @@
|
||||
#include "intel_screen.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
#include "i830_context.h"
|
||||
#include "i830_reg.h"
|
||||
|
||||
static const GLint initial_offsets[6][2] = { {0,0},
|
||||
{0,2},
|
||||
{1,0},
|
||||
{1,2},
|
||||
{1,1},
|
||||
{1,3} };
|
||||
|
||||
static const GLint step_offsets[6][2] = { {0,2},
|
||||
{0,2},
|
||||
{-1,2},
|
||||
{-1,2},
|
||||
{-1,1},
|
||||
{-1,1} };
|
||||
|
||||
#define I830_TEX_UNIT_ENABLED(unit) (1<<unit)
|
||||
|
||||
static GLboolean i830SetTexImages( i830ContextPtr i830,
|
||||
struct gl_texture_object *tObj )
|
||||
static GLuint translate_texture_format( GLuint mesa_format )
|
||||
{
|
||||
GLuint total_height, pitch, i, textureFormat;
|
||||
i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData;
|
||||
const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
|
||||
GLint firstLevel, lastLevel, numLevels;
|
||||
|
||||
switch( baseImage->TexFormat->MesaFormat ) {
|
||||
switch (mesa_format) {
|
||||
case MESA_FORMAT_L8:
|
||||
t->intel.texelBytes = 1;
|
||||
textureFormat = MAPSURF_8BIT | MT_8BIT_L8;
|
||||
break;
|
||||
|
||||
return MAPSURF_8BIT | MT_8BIT_L8;
|
||||
case MESA_FORMAT_I8:
|
||||
t->intel.texelBytes = 1;
|
||||
textureFormat = MAPSURF_8BIT | MT_8BIT_I8;
|
||||
break;
|
||||
|
||||
return MAPSURF_8BIT | MT_8BIT_I8;
|
||||
case MESA_FORMAT_A8:
|
||||
t->intel.texelBytes = 1;
|
||||
textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */
|
||||
break;
|
||||
|
||||
return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */
|
||||
case MESA_FORMAT_AL88:
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_AY88;
|
||||
break;
|
||||
|
||||
return MAPSURF_16BIT | MT_16BIT_AY88;
|
||||
case MESA_FORMAT_RGB565:
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
|
||||
break;
|
||||
|
||||
return MAPSURF_16BIT | MT_16BIT_RGB565;
|
||||
case MESA_FORMAT_ARGB1555:
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555;
|
||||
break;
|
||||
|
||||
return MAPSURF_16BIT | MT_16BIT_ARGB1555;
|
||||
case MESA_FORMAT_ARGB4444:
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444;
|
||||
break;
|
||||
|
||||
return MAPSURF_16BIT | MT_16BIT_ARGB4444;
|
||||
case MESA_FORMAT_ARGB8888:
|
||||
t->intel.texelBytes = 4;
|
||||
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
|
||||
break;
|
||||
|
||||
return MAPSURF_32BIT | MT_32BIT_ARGB8888;
|
||||
case MESA_FORMAT_YCBCR_REV:
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL |
|
||||
TM0S1_COLORSPACE_CONVERSION);
|
||||
break;
|
||||
|
||||
return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
|
||||
case MESA_FORMAT_YCBCR:
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */
|
||||
TM0S1_COLORSPACE_CONVERSION);
|
||||
break;
|
||||
|
||||
return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
|
||||
case MESA_FORMAT_RGB_FXT1:
|
||||
case MESA_FORMAT_RGBA_FXT1:
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = MAPSURF_COMPRESSED | MT_COMPRESS_FXT1;
|
||||
break;
|
||||
|
||||
return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
|
||||
case MESA_FORMAT_RGBA_DXT1:
|
||||
case MESA_FORMAT_RGB_DXT1:
|
||||
/*
|
||||
* DXTn pitches are Width/4 * blocksize in bytes
|
||||
* for DXT1: blocksize=8 so Width/4*8 = Width * 2
|
||||
* for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
|
||||
*/
|
||||
t->intel.texelBytes = 2;
|
||||
textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
|
||||
break;
|
||||
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
|
||||
case MESA_FORMAT_RGBA_DXT3:
|
||||
t->intel.texelBytes = 4;
|
||||
textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
|
||||
break;
|
||||
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
|
||||
case MESA_FORMAT_RGBA_DXT5:
|
||||
t->intel.texelBytes = 4;
|
||||
textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
|
||||
break;
|
||||
|
||||
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
|
||||
default:
|
||||
fprintf(stderr, "%s: bad image format\n", __FUNCTION__);
|
||||
fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__,
|
||||
mesa_format);
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute which mipmap levels we really want to send to the hardware.
|
||||
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
|
||||
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
|
||||
* Yes, this looks overly complicated, but it's all needed.
|
||||
*/
|
||||
driCalculateTextureFirstLastLevel( (driTextureObject *) t );
|
||||
|
||||
|
||||
/* Figure out the amount of memory required to hold all the mipmap
|
||||
* levels. Choose the smallest pitch to accomodate the largest
|
||||
* mipmap:
|
||||
*/
|
||||
firstLevel = t->intel.base.firstLevel;
|
||||
lastLevel = t->intel.base.lastLevel;
|
||||
numLevels = lastLevel - firstLevel + 1;
|
||||
|
||||
|
||||
/* All images must be loaded at this pitch. Count the number of
|
||||
* lines required:
|
||||
*/
|
||||
switch (tObj->Target) {
|
||||
case GL_TEXTURE_CUBE_MAP: {
|
||||
const GLuint dim = tObj->Image[0][firstLevel]->Width;
|
||||
GLuint face;
|
||||
|
||||
pitch = dim * t->intel.texelBytes;
|
||||
pitch *= 2; /* double pitch for cube layouts */
|
||||
pitch = (pitch + 3) & ~3;
|
||||
|
||||
total_height = dim * 4;
|
||||
|
||||
for ( face = 0 ; face < 6 ; face++) {
|
||||
GLuint x = initial_offsets[face][0] * dim;
|
||||
GLuint y = initial_offsets[face][1] * dim;
|
||||
GLuint d = dim;
|
||||
|
||||
t->intel.base.dirty_images[face] = ~0;
|
||||
|
||||
assert(tObj->Image[face][firstLevel]->Width == dim);
|
||||
assert(tObj->Image[face][firstLevel]->Height == dim);
|
||||
|
||||
for (i = 0; i < numLevels; i++) {
|
||||
t->intel.image[face][i].image = tObj->Image[face][firstLevel + i];
|
||||
if (!t->intel.image[face][i].image) {
|
||||
fprintf(stderr, "no image %d %d\n", face, i);
|
||||
break; /* can't happen */
|
||||
}
|
||||
|
||||
t->intel.image[face][i].offset =
|
||||
y * pitch + x * t->intel.texelBytes;
|
||||
t->intel.image[face][i].internalFormat = baseImage->_BaseFormat;
|
||||
|
||||
d >>= 1;
|
||||
x += step_offsets[face][0] * d;
|
||||
y += step_offsets[face][1] * d;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes;
|
||||
pitch = (pitch + 3) & ~3;
|
||||
t->intel.base.dirty_images[0] = ~0;
|
||||
|
||||
for ( total_height = i = 0 ; i < numLevels ; i++ ) {
|
||||
t->intel.image[0][i].image = tObj->Image[0][firstLevel + i];
|
||||
if (!t->intel.image[0][i].image)
|
||||
break;
|
||||
|
||||
t->intel.image[0][i].offset = total_height * pitch;
|
||||
t->intel.image[0][i].internalFormat = baseImage->_BaseFormat;
|
||||
if (t->intel.image[0][i].image->IsCompressed)
|
||||
{
|
||||
if (t->intel.image[0][i].image->Height > 4)
|
||||
total_height += t->intel.image[0][i].image->Height/4;
|
||||
else
|
||||
total_height += 1;
|
||||
}
|
||||
else
|
||||
total_height += MAX2(2, t->intel.image[0][i].image->Height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
t->intel.Pitch = pitch;
|
||||
t->intel.base.totalSize = total_height*pitch;
|
||||
t->intel.max_level = i-1;
|
||||
t->Setup[I830_TEXREG_TM0S1] =
|
||||
(((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) |
|
||||
((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) |
|
||||
textureFormat);
|
||||
t->Setup[I830_TEXREG_TM0S2] =
|
||||
(((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) |
|
||||
TM0S2_CUBE_FACE_ENA_MASK;
|
||||
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
|
||||
t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
|
||||
t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;
|
||||
t->intel.dirty = I830_UPLOAD_TEX_ALL;
|
||||
|
||||
return intelUploadTexImages( &i830->intel, &t->intel, 0 );
|
||||
}
|
||||
|
||||
|
||||
static void i830_import_tex_unit( i830ContextPtr i830,
|
||||
i830TextureObjectPtr t,
|
||||
GLuint unit )
|
||||
{
|
||||
if(INTEL_DEBUG&DEBUG_TEXTURE)
|
||||
fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
|
||||
|
||||
if (i830->intel.CurrentTexObj[unit])
|
||||
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
|
||||
|
||||
i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
|
||||
t->intel.base.bound |= (1 << unit);
|
||||
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
|
||||
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
|
||||
(LOAD_TEXTURE_MAP0 << unit) | 4);
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE |
|
||||
t->intel.TextureOffset);
|
||||
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1];
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2];
|
||||
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK;
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] &
|
||||
~TM0S3_LOD_BIAS_MASK);
|
||||
|
||||
i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4];
|
||||
i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] &
|
||||
~MAP_UNIT_MASK);
|
||||
i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE];
|
||||
i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit);
|
||||
|
||||
t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
|
||||
|
||||
/* The i915 (and related graphics cores) do not support GL_CLAMP. The
|
||||
* Intel drivers for "other operating systems" implement GL_CLAMP as
|
||||
* GL_CLAMP_TO_EDGE, so the same is done here.
|
||||
*/
|
||||
static GLuint translate_wrap_mode( GLenum wrap )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
|
||||
struct gl_texture_object *tObj = texUnit->_Current;
|
||||
i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
|
||||
switch( wrap ) {
|
||||
case GL_REPEAT:
|
||||
return TEXCOORDMODE_WRAP;
|
||||
case GL_CLAMP:
|
||||
case GL_CLAMP_TO_EDGE:
|
||||
return TEXCOORDMODE_CLAMP; /* not really correct */
|
||||
case GL_CLAMP_TO_BORDER:
|
||||
return TEXCOORDMODE_CLAMP_BORDER;
|
||||
case GL_MIRRORED_REPEAT:
|
||||
return TEXCOORDMODE_MIRROR;
|
||||
default:
|
||||
return TEXCOORDMODE_WRAP;
|
||||
}
|
||||
}
|
||||
|
||||
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
/* Fallback if there's a texture border */
|
||||
if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
|
||||
fprintf(stderr, "Texture border\n");
|
||||
return GL_FALSE;
|
||||
/* Recalculate all state from scratch. Perhaps not the most
|
||||
* efficient, but this has gotten complex enough that we need
|
||||
* something which is understandable and reliable.
|
||||
*/
|
||||
static GLboolean i830_update_tex_unit( struct intel_context *intel,
|
||||
GLuint unit,
|
||||
GLuint ss3 )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
|
||||
struct intel_texture_object *intelObj = intel_texture_object(tObj);
|
||||
struct gl_texture_image *firstImage;
|
||||
GLuint *state = i830->state.Tex[unit];
|
||||
|
||||
memset(state, 0, sizeof(state));
|
||||
|
||||
if (!intel_finalize_mipmap_tree(intel, unit))
|
||||
return GL_FALSE;
|
||||
|
||||
/* Get first image here, since intelObj->firstLevel will get set in
|
||||
* the intel_finalize_mipmap_tree() call above.
|
||||
*/
|
||||
firstImage = tObj->Image[0][intelObj->firstLevel];
|
||||
|
||||
i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
|
||||
i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0,
|
||||
intelObj->firstLevel);
|
||||
|
||||
|
||||
state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
|
||||
(LOAD_TEXTURE_MAP0 << unit) | 4);
|
||||
|
||||
/* state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */
|
||||
/* t->intel.TextureOffset); */
|
||||
|
||||
|
||||
state[I830_TEXREG_TM0S1] =
|
||||
(((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
|
||||
((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) |
|
||||
translate_texture_format( firstImage->TexFormat->MesaFormat));
|
||||
|
||||
state[I830_TEXREG_TM0S2] =
|
||||
(((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) - 1) << TM0S2_PITCH_SHIFT) |
|
||||
TM0S2_CUBE_FACE_ENA_MASK);
|
||||
|
||||
{
|
||||
if (tObj->Target == GL_TEXTURE_CUBE_MAP)
|
||||
state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
|
||||
CUBE_NEGX_ENABLE |
|
||||
CUBE_POSX_ENABLE |
|
||||
CUBE_NEGY_ENABLE |
|
||||
CUBE_POSY_ENABLE |
|
||||
CUBE_NEGZ_ENABLE |
|
||||
CUBE_POSZ_ENABLE);
|
||||
else
|
||||
state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
|
||||
}
|
||||
|
||||
/* Upload teximages (not pipelined)
|
||||
*/
|
||||
if (t->intel.base.dirty_images[0]) {
|
||||
if (!i830SetTexImages( i830, tObj )) {
|
||||
|
||||
|
||||
|
||||
{
|
||||
GLuint minFilt, mipFilt, magFilt;
|
||||
|
||||
switch (tObj->MinFilter) {
|
||||
case GL_NEAREST:
|
||||
minFilt = FILTER_NEAREST;
|
||||
mipFilt = MIPFILTER_NONE;
|
||||
break;
|
||||
case GL_LINEAR:
|
||||
minFilt = FILTER_LINEAR;
|
||||
mipFilt = MIPFILTER_NONE;
|
||||
break;
|
||||
case GL_NEAREST_MIPMAP_NEAREST:
|
||||
minFilt = FILTER_NEAREST;
|
||||
mipFilt = MIPFILTER_NEAREST;
|
||||
break;
|
||||
case GL_LINEAR_MIPMAP_NEAREST:
|
||||
minFilt = FILTER_LINEAR;
|
||||
mipFilt = MIPFILTER_NEAREST;
|
||||
break;
|
||||
case GL_NEAREST_MIPMAP_LINEAR:
|
||||
minFilt = FILTER_NEAREST;
|
||||
mipFilt = MIPFILTER_LINEAR;
|
||||
break;
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
minFilt = FILTER_LINEAR;
|
||||
mipFilt = MIPFILTER_LINEAR;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if ( tObj->MaxAnisotropy > 1.0 ) {
|
||||
minFilt = FILTER_ANISOTROPIC;
|
||||
magFilt = FILTER_ANISOTROPIC;
|
||||
}
|
||||
else {
|
||||
switch (tObj->MagFilter) {
|
||||
case GL_NEAREST:
|
||||
magFilt = FILTER_NEAREST;
|
||||
break;
|
||||
case GL_LINEAR:
|
||||
magFilt = FILTER_LINEAR;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit];
|
||||
|
||||
#if 0
|
||||
/* YUV conversion:
|
||||
*/
|
||||
if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
|
||||
firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
|
||||
state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
|
||||
#endif
|
||||
|
||||
state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -
|
||||
intelObj->firstLevel)*4) << TM0S3_MIN_MIP_SHIFT;
|
||||
|
||||
state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
|
||||
(mipFilt << TM0S3_MIP_FILTER_SHIFT) |
|
||||
(magFilt << TM0S3_MAG_FILTER_SHIFT));
|
||||
}
|
||||
|
||||
/* Update state if this is a different texture object to last
|
||||
* time.
|
||||
*/
|
||||
if (i830->intel.CurrentTexObj[unit] != &t->intel ||
|
||||
(t->intel.dirty & I830_UPLOAD_TEX(unit))) {
|
||||
i830_import_tex_unit( i830, t, unit);
|
||||
{
|
||||
GLenum ws = tObj->WrapS;
|
||||
GLenum wt = tObj->WrapT;
|
||||
|
||||
|
||||
/* 3D textures not available on i830
|
||||
*/
|
||||
if (tObj->Target == GL_TEXTURE_3D)
|
||||
return GL_FALSE;
|
||||
|
||||
state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
|
||||
MAP_UNIT(unit) |
|
||||
ENABLE_TEXCOORD_PARAMS |
|
||||
ss3 |
|
||||
ENABLE_ADDR_V_CNTL |
|
||||
TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt)) |
|
||||
ENABLE_ADDR_U_CNTL |
|
||||
TEXCOORD_ADDR_U_MODE(translate_wrap_mode(ws)));
|
||||
}
|
||||
|
||||
|
||||
state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
|
||||
tObj->_BorderChan[1],
|
||||
tObj->_BorderChan[2],
|
||||
tObj->_BorderChan[3]);
|
||||
|
||||
|
||||
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
|
||||
|
||||
mcs &= ~TEXCOORDS_ARE_NORMAL;
|
||||
mcs |= TEXCOORDS_ARE_IN_TEXELUNITS;
|
||||
|
||||
if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
|
||||
|| (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
|
||||
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
|
||||
i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
|
||||
|
||||
mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
|
||||
mcs |= TEXCOORDS_ARE_NORMAL;
|
||||
|
||||
if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
|
||||
|| (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
|
||||
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
|
||||
i830->state.Tex[unit][I830_TEXREG_CUBE] = 0;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
|
||||
struct gl_texture_object *tObj = texUnit->_Current;
|
||||
i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData;
|
||||
GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS];
|
||||
const GLuint cube = CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE
|
||||
| CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE
|
||||
| CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE;
|
||||
GLuint face;
|
||||
|
||||
mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS;
|
||||
mcs |= TEXCOORDS_ARE_NORMAL;
|
||||
|
||||
if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS])
|
||||
|| (cube != i830->state.Tex[unit][I830_TEXREG_CUBE])) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
|
||||
i830->state.Tex[unit][I830_TEXREG_MCS] = mcs;
|
||||
i830->state.Tex[unit][I830_TEXREG_CUBE] = cube;
|
||||
}
|
||||
|
||||
/* Upload teximages (not pipelined)
|
||||
/* memcmp was already disabled, but definitely won't work as the
|
||||
* region might now change and that wouldn't be detected:
|
||||
*/
|
||||
if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] ||
|
||||
t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] ||
|
||||
t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) {
|
||||
i830SetTexImages( i830, tObj );
|
||||
}
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* upload (per face) */
|
||||
for (face = 0; face < 6; face++) {
|
||||
if (t->intel.base.dirty_images[face]) {
|
||||
if (!intelUploadTexImages( &i830->intel, &t->intel, face )) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i830UpdateTextureState( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
GLboolean ok = GL_TRUE;
|
||||
GLuint i;
|
||||
|
||||
for (i = 0 ; i < I830_TEX_UNITS && ok ; i++) {
|
||||
switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
|
||||
case TEXTURE_1D_BIT:
|
||||
case TEXTURE_2D_BIT:
|
||||
case TEXTURE_CUBE_BIT:
|
||||
ok = i830_update_tex_unit( intel, i, TEXCOORDS_ARE_NORMAL );
|
||||
break;
|
||||
case TEXTURE_RECT_BIT:
|
||||
ok = i830_update_tex_unit( intel, i, TEXCOORDS_ARE_IN_TEXELUNITS );
|
||||
break;
|
||||
case 0:
|
||||
if (i830->state.active & I830_UPLOAD_TEX(i))
|
||||
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE);
|
||||
break;
|
||||
case TEXTURE_3D_BIT:
|
||||
default:
|
||||
ok = GL_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
|
||||
/* This is happening too often. I need to conditionally send diffuse
|
||||
* state to the card. Perhaps a diffuse dirty flag of some kind.
|
||||
* Will need to change this logic if more than 2 texture units are
|
||||
* used. We need to only do this up to the last unit enabled, or unit
|
||||
* one if nothing is enabled.
|
||||
*/
|
||||
|
||||
if ( i830->intel.CurrentTexObj[unit] != NULL ) {
|
||||
/* The old texture is no longer bound to this texture unit.
|
||||
* Mark it as such.
|
||||
*/
|
||||
|
||||
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0);
|
||||
i830->intel.CurrentTexObj[unit] = NULL;
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit )
|
||||
{
|
||||
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
|
||||
|
||||
if (texUnit->_ReallyEnabled &&
|
||||
INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024)
|
||||
return GL_FALSE;
|
||||
|
||||
switch(texUnit->_ReallyEnabled) {
|
||||
case TEXTURE_1D_BIT:
|
||||
case TEXTURE_2D_BIT:
|
||||
return (enable_tex_common( ctx, unit ) &&
|
||||
enable_tex_2d( ctx, unit ));
|
||||
case TEXTURE_RECT_BIT:
|
||||
return (enable_tex_common( ctx, unit ) &&
|
||||
enable_tex_rect( ctx, unit ));
|
||||
case TEXTURE_CUBE_BIT:
|
||||
return (enable_tex_common( ctx, unit ) &&
|
||||
enable_tex_cube( ctx, unit ));
|
||||
case 0:
|
||||
return disable_tex( ctx, unit );
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i830UpdateTextureState( intelContextPtr intel )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
GLboolean ok;
|
||||
|
||||
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE);
|
||||
|
||||
ok = (i830UpdateTexUnit( ctx, 0 ) &&
|
||||
i830UpdateTexUnit( ctx, 1 ) &&
|
||||
i830UpdateTexUnit( ctx, 2 ) &&
|
||||
i830UpdateTexUnit( ctx, 3 ));
|
||||
|
||||
FALLBACK( intel, I830_FALLBACK_TEXTURE, !ok );
|
||||
|
||||
if (ok)
|
||||
@@ -481,3 +314,8 @@ void i830UpdateTextureState( intelContextPtr intel )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -30,11 +30,12 @@
|
||||
#include "i830_reg.h"
|
||||
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
#include "tnl/t_context.h"
|
||||
#include "tnl/t_vertex.h"
|
||||
|
||||
static GLboolean i830_check_vertex_size( intelContextPtr intel,
|
||||
static GLboolean i830_check_vertex_size( struct intel_context *intel,
|
||||
GLuint expected );
|
||||
|
||||
#define SZ_TO_HW(sz) ((sz-2)&0x3)
|
||||
@@ -59,10 +60,10 @@ do { \
|
||||
#define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
|
||||
#define TEXBIND_SET(n, x) ((x)<<((n)*4))
|
||||
|
||||
static void i830_render_start( intelContextPtr intel )
|
||||
static void i830_render_start( struct intel_context *intel )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
GLuint index = tnl->render_inputs;
|
||||
@@ -163,6 +164,7 @@ static void i830_render_start( intelContextPtr intel )
|
||||
v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
|
||||
mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
|
||||
index != i830->last_index) {
|
||||
int k;
|
||||
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_CTX );
|
||||
|
||||
@@ -182,14 +184,15 @@ static void i830_render_start( intelContextPtr intel )
|
||||
i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
|
||||
i830->last_index = index;
|
||||
|
||||
assert(i830_check_vertex_size( intel, intel->vertex_size ));
|
||||
k = i830_check_vertex_size( intel, intel->vertex_size );
|
||||
assert(k);
|
||||
}
|
||||
}
|
||||
|
||||
static void i830_reduced_primitive_state( intelContextPtr intel,
|
||||
static void i830_reduced_primitive_state( struct intel_context *intel,
|
||||
GLenum rprim )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
GLuint st1 = i830->state.Stipple[I830_STPREG_ST1];
|
||||
|
||||
st1 &= ~ST1_ENABLE;
|
||||
@@ -217,10 +220,10 @@ static void i830_reduced_primitive_state( intelContextPtr intel,
|
||||
/* Pull apart the vertex format registers and figure out how large a
|
||||
* vertex is supposed to be.
|
||||
*/
|
||||
static GLboolean i830_check_vertex_size( intelContextPtr intel,
|
||||
static GLboolean i830_check_vertex_size( struct intel_context *intel,
|
||||
GLuint expected )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
int vft0 = i830->current->Ctx[I830_CTXREG_VF];
|
||||
int vft1 = i830->current->Ctx[I830_CTXREG_VF2];
|
||||
int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT;
|
||||
@@ -257,16 +260,11 @@ static GLboolean i830_check_vertex_size( intelContextPtr intel,
|
||||
return sz == expected;
|
||||
}
|
||||
|
||||
static void i830_emit_invarient_state( intelContextPtr intel )
|
||||
static void i830_emit_invarient_state( struct intel_context *intel )
|
||||
{
|
||||
BATCH_LOCALS;
|
||||
|
||||
BEGIN_BATCH( 200 );
|
||||
|
||||
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0));
|
||||
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1));
|
||||
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2));
|
||||
OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3));
|
||||
BEGIN_BATCH(200, 0);
|
||||
|
||||
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
|
||||
OUT_BATCH(0);
|
||||
@@ -330,13 +328,6 @@ static void i830_emit_invarient_state( intelContextPtr intel )
|
||||
TRI_FAN_PROVOKE_VRTX(2) |
|
||||
TRI_STRIP_PROVOKE_VRTX(2));
|
||||
|
||||
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
DISABLE_SCISSOR_RECT);
|
||||
|
||||
OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(0);
|
||||
|
||||
OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
|
||||
OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
|
||||
|
||||
@@ -355,18 +346,20 @@ static void i830_emit_invarient_state( intelContextPtr intel )
|
||||
#define emit( intel, state, size ) \
|
||||
do { \
|
||||
int k; \
|
||||
BEGIN_BATCH( size / sizeof(GLuint)); \
|
||||
for (k = 0 ; k < size / sizeof(GLuint) ; k++) \
|
||||
BEGIN_BATCH(size / sizeof(GLuint), 0); \
|
||||
for (k = 0 ; k < size / sizeof(GLuint) ; k++) { \
|
||||
if (0) _mesa_printf(" 0x%08x\n", state[k]); \
|
||||
OUT_BATCH(state[k]); \
|
||||
} \
|
||||
ADVANCE_BATCH(); \
|
||||
} while (0);
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Push the state into the sarea and/or texture memory.
|
||||
*/
|
||||
static void i830_emit_state( intelContextPtr intel )
|
||||
static void i830_emit_state( struct intel_context *intel )
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
struct i830_hw_state *state = i830->current;
|
||||
int i;
|
||||
GLuint dirty;
|
||||
@@ -374,29 +367,79 @@ static void i830_emit_state( intelContextPtr intel )
|
||||
|
||||
dirty = state->active & ~state->emitted;
|
||||
|
||||
if (dirty & I830_UPLOAD_INVARIENT) {
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr, "I830_UPLOAD_INVARIENT:\n");
|
||||
i830_emit_invarient_state( intel );
|
||||
}
|
||||
|
||||
if (dirty & I830_UPLOAD_CTX) {
|
||||
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n");
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr, "I830_UPLOAD_CTX:\n");
|
||||
emit( i830, state->Ctx, sizeof(state->Ctx) );
|
||||
|
||||
}
|
||||
|
||||
if (dirty & I830_UPLOAD_BUFFERS) {
|
||||
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");
|
||||
emit( i830, state->Buffer, sizeof(state->Buffer) );
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");
|
||||
BEGIN_BATCH(I830_DEST_SETUP_SIZE+2, 0);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]);
|
||||
OUT_RELOC(state->draw_region->buffer, DRM_MM_TT|DRM_MM_WRITE, 0);
|
||||
|
||||
if (state->depth_region) {
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]);
|
||||
OUT_RELOC(state->depth_region->buffer, DRM_MM_TT |DRM_MM_WRITE, 0);
|
||||
}
|
||||
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_DV0]);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_DV1]);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_SENABLE]);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_SR0]);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_SR1]);
|
||||
OUT_BATCH(state->Buffer[I830_DESTREG_SR2]);
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
if (dirty & I830_UPLOAD_STIPPLE) {
|
||||
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");
|
||||
emit( i830, state->Stipple, sizeof(state->Stipple) );
|
||||
}
|
||||
|
||||
for (i = 0; i < I830_TEX_UNITS; i++) {
|
||||
if ((dirty & I830_UPLOAD_TEX(i))) {
|
||||
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);
|
||||
emit( i830, state->Tex[i], sizeof(state->Tex[i]));
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);
|
||||
|
||||
BEGIN_BATCH(I830_TEX_SETUP_SIZE+1, 0);
|
||||
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0LI]);
|
||||
|
||||
if (state->tex_buffer[i]) {
|
||||
OUT_RELOC(state->tex_buffer[i],
|
||||
DRM_MM_TT|DRM_MM_READ,
|
||||
state->tex_offset[i] | TM0S0_USE_FENCE);
|
||||
}
|
||||
else {
|
||||
assert(i == 0);
|
||||
assert(state == &i830->meta);
|
||||
OUT_BATCH(0);
|
||||
}
|
||||
|
||||
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S1]);
|
||||
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S2]);
|
||||
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S3]);
|
||||
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]);
|
||||
OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]);
|
||||
OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]);
|
||||
}
|
||||
|
||||
if (dirty & I830_UPLOAD_TEXBLEND(i)) {
|
||||
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d):\n", i);
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d): %d words\n", i,
|
||||
state->TexBlendWordsUsed[i]);
|
||||
emit( i830, state->TexBlend[i],
|
||||
state->TexBlendWordsUsed[i] * 4 );
|
||||
}
|
||||
@@ -405,52 +448,54 @@ static void i830_emit_state( intelContextPtr intel )
|
||||
state->emitted |= dirty;
|
||||
}
|
||||
|
||||
static void i830_destroy_context( intelContextPtr intel )
|
||||
static void i830_destroy_context( struct intel_context *intel )
|
||||
{
|
||||
_tnl_free_vertices(&intel->ctx);
|
||||
}
|
||||
|
||||
static void i830_set_draw_offset( intelContextPtr intel, int offset )
|
||||
static void i830_set_draw_region( struct intel_context *intel,
|
||||
struct intel_region *draw_region,
|
||||
struct intel_region *depth_region)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
intel_region_release(intel, &i830->state.draw_region);
|
||||
intel_region_release(intel, &i830->state.depth_region);
|
||||
intel_region_reference(&i830->state.draw_region, draw_region);
|
||||
intel_region_reference(&i830->state.depth_region, depth_region);
|
||||
|
||||
/* XXX FBO: Need code from i915_set_draw_region() */
|
||||
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset;
|
||||
}
|
||||
|
||||
/* This isn't really handled at the moment.
|
||||
*/
|
||||
static void i830_lost_hardware( intelContextPtr intel )
|
||||
static void i830_lost_hardware( struct intel_context *intel )
|
||||
{
|
||||
I830_CONTEXT(intel)->state.emitted = 0;
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
i830->state.emitted = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void i830_emit_flush( intelContextPtr intel )
|
||||
static GLuint i830_flush_cmd( void )
|
||||
{
|
||||
BATCH_LOCALS;
|
||||
|
||||
BEGIN_BATCH(2);
|
||||
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );
|
||||
OUT_BATCH( 0 );
|
||||
ADVANCE_BATCH();
|
||||
return MI_FLUSH | FLUSH_MAP_CACHE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void i830InitVtbl( i830ContextPtr i830 )
|
||||
void i830InitVtbl( struct i830_context *i830 )
|
||||
{
|
||||
i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj;
|
||||
i830->intel.vtbl.check_vertex_size = i830_check_vertex_size;
|
||||
i830->intel.vtbl.clear_with_tris = i830ClearWithTris;
|
||||
i830->intel.vtbl.destroy = i830_destroy_context;
|
||||
i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state;
|
||||
i830->intel.vtbl.emit_state = i830_emit_state;
|
||||
i830->intel.vtbl.lost_hardware = i830_lost_hardware;
|
||||
i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state;
|
||||
i830->intel.vtbl.set_draw_offset = i830_set_draw_offset;
|
||||
i830->intel.vtbl.set_draw_region = i830_set_draw_region;
|
||||
i830->intel.vtbl.update_texture_state = i830UpdateTextureState;
|
||||
i830->intel.vtbl.emit_flush = i830_emit_flush;
|
||||
i830->intel.vtbl.flush_cmd = i830_flush_cmd;
|
||||
i830->intel.vtbl.render_start = i830_render_start;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
#include "utils.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
#include "intel_bufmgr.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
|
||||
/***************************************
|
||||
* Mesa's Driver Functions
|
||||
***************************************/
|
||||
@@ -65,7 +69,7 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state )
|
||||
_ac_InvalidateState( ctx, new_state );
|
||||
_tnl_InvalidateState( ctx, new_state );
|
||||
_tnl_invalidate_vertex_state( ctx, new_state );
|
||||
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
|
||||
intel_context(ctx)->NewGLState |= new_state;
|
||||
|
||||
/* Todo: gather state values under which tracked parameters become
|
||||
* invalidated, add callbacks for things like
|
||||
@@ -99,13 +103,16 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
||||
void *sharedContextPrivate)
|
||||
{
|
||||
struct dd_function_table functions;
|
||||
i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context);
|
||||
intelContextPtr intel = &i915->intel;
|
||||
struct i915_context *i915 = (struct i915_context *) CALLOC_STRUCT(i915_context);
|
||||
struct intel_context *intel = &i915->intel;
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
|
||||
if (!i915) return GL_FALSE;
|
||||
|
||||
_mesa_printf( "\ntexmem branch (i915, drop3)\n\n");
|
||||
|
||||
i915InitVtbl( i915 );
|
||||
i915InitMetaFuncs( i915 );
|
||||
|
||||
i915InitDriverFunctions( &functions );
|
||||
|
||||
@@ -119,48 +126,28 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
||||
ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS;
|
||||
ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS;
|
||||
|
||||
intel->nr_heaps = 1;
|
||||
intel->texture_heaps[0] =
|
||||
driCreateTextureHeap( 0, intel,
|
||||
intel->intelScreen->tex.size,
|
||||
12,
|
||||
I830_NR_TEX_REGIONS,
|
||||
intel->sarea->texList,
|
||||
& intel->sarea->texAge,
|
||||
& intel->swapped,
|
||||
sizeof( struct i915_texture_object ),
|
||||
(destroy_texture_object_t *)intelDestroyTexObj );
|
||||
|
||||
/* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are
|
||||
* tightly packed, but they're not in Intel graphics
|
||||
* hardware.
|
||||
/* Advertise the full hardware capabilities. The new memory
|
||||
* manager should cope much better with overload situations:
|
||||
*/
|
||||
ctx->Const.MaxTextureUnits = 1;
|
||||
driCalculateMaxTextureLevels( intel->texture_heaps,
|
||||
intel->nr_heaps,
|
||||
&intel->ctx.Const,
|
||||
4,
|
||||
11, /* max 2D texture size is 2048x2048 */
|
||||
8, /* 3D texture */
|
||||
11, /* cube texture. */
|
||||
11, /* rect texture */
|
||||
12,
|
||||
GL_FALSE );
|
||||
ctx->Const.MaxTextureLevels = 12;
|
||||
ctx->Const.Max3DTextureLevels = 9;
|
||||
ctx->Const.MaxCubeTextureLevels = 12;
|
||||
ctx->Const.MaxTextureRectSize = (1<<11);
|
||||
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
|
||||
|
||||
/* GL_ARB_fragment_program limits - don't think Mesa actually
|
||||
* validates programs against these, and in any case one ARB
|
||||
* instruction can translate to more than one HW instruction, so
|
||||
* we'll still have to check and fallback each time.
|
||||
*/
|
||||
|
||||
*/
|
||||
ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY;
|
||||
ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */
|
||||
ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT;
|
||||
ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN;
|
||||
ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN;
|
||||
ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +
|
||||
I915_MAX_TEX_INSN);
|
||||
I915_MAX_TEX_INSN);
|
||||
ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT;
|
||||
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
#define I915_UPLOAD_PROGRAM 0x8
|
||||
#define I915_UPLOAD_CONSTANTS 0x10
|
||||
#define I915_UPLOAD_FOG 0x20
|
||||
#define I915_UPLOAD_INVARIENT 0x40
|
||||
#define I915_UPLOAD_DEFAULTS 0x80
|
||||
#define I915_UPLOAD_TEX(i) (0x00010000<<(i))
|
||||
#define I915_UPLOAD_TEX_ALL (0x00ff0000)
|
||||
#define I915_UPLOAD_TEX_0_SHIFT 16
|
||||
@@ -52,10 +54,8 @@
|
||||
*/
|
||||
#define I915_DESTREG_CBUFADDR0 0
|
||||
#define I915_DESTREG_CBUFADDR1 1
|
||||
#define I915_DESTREG_CBUFADDR2 2
|
||||
#define I915_DESTREG_DBUFADDR0 3
|
||||
#define I915_DESTREG_DBUFADDR1 4
|
||||
#define I915_DESTREG_DBUFADDR2 5
|
||||
#define I915_DESTREG_DV0 6
|
||||
#define I915_DESTREG_DV1 7
|
||||
#define I915_DESTREG_SENABLE 8
|
||||
@@ -86,7 +86,6 @@
|
||||
#define I915_STPREG_ST1 1
|
||||
#define I915_STP_SETUP_SIZE 2
|
||||
|
||||
#define I915_TEXREG_MS2 0
|
||||
#define I915_TEXREG_MS3 1
|
||||
#define I915_TEXREG_MS4 2
|
||||
#define I915_TEXREG_SS2 3
|
||||
@@ -94,6 +93,15 @@
|
||||
#define I915_TEXREG_SS4 5
|
||||
#define I915_TEX_SETUP_SIZE 6
|
||||
|
||||
#define I915_DEFREG_C0 0
|
||||
#define I915_DEFREG_C1 1
|
||||
#define I915_DEFREG_S0 2
|
||||
#define I915_DEFREG_S1 3
|
||||
#define I915_DEFREG_Z0 4
|
||||
#define I915_DEFREG_Z1 5
|
||||
#define I915_DEF_SETUP_SIZE 6
|
||||
|
||||
|
||||
#define I915_MAX_CONSTANT 32
|
||||
#define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT))
|
||||
|
||||
@@ -163,8 +171,6 @@ struct i915_fragment_program {
|
||||
GLuint nr_params;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Helpers for i915_texprog.c:
|
||||
*/
|
||||
GLuint src_texture; /* Reg containing sampled texture color,
|
||||
@@ -185,13 +191,6 @@ struct i915_fragment_program {
|
||||
|
||||
|
||||
|
||||
struct i915_texture_object
|
||||
{
|
||||
struct intel_texture_object intel;
|
||||
GLenum lastTarget;
|
||||
GLboolean refs_border_color;
|
||||
GLuint Setup[I915_TEX_SETUP_SIZE];
|
||||
};
|
||||
|
||||
#define I915_TEX_UNITS 8
|
||||
|
||||
@@ -201,11 +200,27 @@ struct i915_hw_state {
|
||||
GLuint Buffer[I915_DEST_SETUP_SIZE];
|
||||
GLuint Stipple[I915_STP_SETUP_SIZE];
|
||||
GLuint Fog[I915_FOG_SETUP_SIZE];
|
||||
GLuint Defaults[I915_DEF_SETUP_SIZE];
|
||||
GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE];
|
||||
GLuint Constant[I915_CONSTANT_SIZE];
|
||||
GLuint ConstantSize;
|
||||
GLuint Program[I915_PROGRAM_SIZE];
|
||||
GLuint ProgramSize;
|
||||
|
||||
/* Region pointers for relocation:
|
||||
*/
|
||||
struct intel_region *draw_region;
|
||||
struct intel_region *depth_region;
|
||||
/* struct intel_region *tex_region[I915_TEX_UNITS]; */
|
||||
|
||||
/* Regions aren't actually that appropriate here as the memory may
|
||||
* be from a PBO or FBO. Just use the buffer id. Will have to do
|
||||
* this for draw and depth for FBO's...
|
||||
*/
|
||||
GLuint tex_buffer[I915_TEX_UNITS];
|
||||
GLuint tex_offset[I915_TEX_UNITS];
|
||||
|
||||
|
||||
GLuint active; /* I915_UPLOAD_* */
|
||||
GLuint emitted; /* I915_UPLOAD_* */
|
||||
};
|
||||
@@ -220,6 +235,8 @@ struct i915_context
|
||||
|
||||
GLuint last_ReallyEnabled;
|
||||
GLuint vertex_fog;
|
||||
GLuint lodbias_ss2[MAX_TEXTURE_UNITS];
|
||||
|
||||
|
||||
struct i915_fragment_program tex_program;
|
||||
struct i915_fragment_program *current_program;
|
||||
@@ -228,24 +245,14 @@ struct i915_context
|
||||
};
|
||||
|
||||
|
||||
typedef struct i915_context *i915ContextPtr;
|
||||
typedef struct i915_texture_object *i915TextureObjectPtr;
|
||||
|
||||
#define I915_CONTEXT(ctx) ((i915ContextPtr)(ctx))
|
||||
|
||||
|
||||
|
||||
#define I915_STATECHANGE(i915, flag) \
|
||||
do { \
|
||||
if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__); \
|
||||
INTEL_FIREVERTICES( &(i915)->intel ); \
|
||||
(i915)->state.emitted &= ~(flag); \
|
||||
} while (0)
|
||||
|
||||
#define I915_ACTIVESTATE(i915, flag, mode) \
|
||||
do { \
|
||||
if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n", \
|
||||
flag, mode, __FUNCTION__); \
|
||||
INTEL_FIREVERTICES( &(i915)->intel ); \
|
||||
if (mode) \
|
||||
(i915)->state.active |= (flag); \
|
||||
@@ -257,7 +264,13 @@ do { \
|
||||
/*======================================================================
|
||||
* i915_vtbl.c
|
||||
*/
|
||||
extern void i915InitVtbl( i915ContextPtr i915 );
|
||||
extern void i915InitVtbl( struct i915_context *i915 );
|
||||
|
||||
extern void
|
||||
i915_state_draw_region(struct intel_context *intel,
|
||||
struct i915_hw_state *state,
|
||||
struct intel_region *color_region,
|
||||
struct intel_region *depth_region);
|
||||
|
||||
|
||||
|
||||
@@ -294,7 +307,7 @@ extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
||||
/*======================================================================
|
||||
* i915_texprog.c
|
||||
*/
|
||||
extern void i915ValidateTextureProgram( i915ContextPtr i915 );
|
||||
extern void i915ValidateTextureProgram( struct i915_context *i915 );
|
||||
|
||||
|
||||
/*======================================================================
|
||||
@@ -308,44 +321,43 @@ extern void i915_print_ureg( const char *msg, GLuint ureg );
|
||||
* i915_state.c
|
||||
*/
|
||||
extern void i915InitStateFunctions( struct dd_function_table *functions );
|
||||
extern void i915InitState( i915ContextPtr i915 );
|
||||
extern void i915InitState( struct i915_context *i915 );
|
||||
extern void i915_update_fog( GLcontext *ctx );
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* i915_tex.c
|
||||
*/
|
||||
extern void i915UpdateTextureState( intelContextPtr intel );
|
||||
extern void i915UpdateTextureState( struct intel_context *intel );
|
||||
extern void i915InitTextureFuncs( struct dd_function_table *functions );
|
||||
extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj );
|
||||
|
||||
/*======================================================================
|
||||
* i915_metaops.c
|
||||
*/
|
||||
extern GLboolean
|
||||
i915TryTextureReadPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels );
|
||||
|
||||
extern GLboolean
|
||||
i915TryTextureDrawPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels );
|
||||
|
||||
extern void
|
||||
i915ClearWithTris( intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
|
||||
void i915InitMetaFuncs( struct i915_context *i915 );
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* i915_fragprog.c
|
||||
*/
|
||||
extern void i915ValidateFragmentProgram( i915ContextPtr i915 );
|
||||
extern void i915ValidateFragmentProgram( struct i915_context *i915 );
|
||||
extern void i915InitFragProgFuncs( struct dd_function_table *functions );
|
||||
|
||||
/*======================================================================
|
||||
* Inline conversion functions. These are better-typed than the
|
||||
* macros used previously:
|
||||
*/
|
||||
static INLINE struct i915_context *
|
||||
i915_context( GLcontext *ctx )
|
||||
{
|
||||
return (struct i915_context *)ctx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define I915_CONTEXT(ctx) i915_context(ctx)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -806,7 +806,7 @@ static void check_wpos( struct i915_fragment_program *p )
|
||||
|
||||
static void translate_program( struct i915_fragment_program *p )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(p->ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(p->ctx);
|
||||
|
||||
i915_init_program( i915, p );
|
||||
check_wpos( p );
|
||||
@@ -840,7 +840,7 @@ static void i915BindProgram( GLcontext *ctx,
|
||||
struct program *prog )
|
||||
{
|
||||
if (target == GL_FRAGMENT_PROGRAM_ARB) {
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
struct i915_fragment_program *p = (struct i915_fragment_program *)prog;
|
||||
|
||||
if (i915->current_program == p)
|
||||
@@ -896,7 +896,7 @@ static void i915DeleteProgram( GLcontext *ctx,
|
||||
struct program *prog )
|
||||
{
|
||||
if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
struct i915_fragment_program *p = (struct i915_fragment_program *)prog;
|
||||
|
||||
if (i915->current_program == p)
|
||||
@@ -940,10 +940,10 @@ static void i915ProgramStringNotify( GLcontext *ctx,
|
||||
}
|
||||
|
||||
|
||||
void i915ValidateFragmentProgram( i915ContextPtr i915 )
|
||||
void i915ValidateFragmentProgram( struct i915_context *i915 )
|
||||
{
|
||||
GLcontext *ctx = &i915->intel.ctx;
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
|
||||
@@ -1028,6 +1028,7 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 )
|
||||
|
||||
if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
|
||||
s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
|
||||
int k;
|
||||
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_CTX );
|
||||
|
||||
@@ -1044,7 +1045,8 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 )
|
||||
i915->state.Ctx[I915_CTXREG_LIS2] = s2;
|
||||
i915->state.Ctx[I915_CTXREG_LIS4] = s4;
|
||||
|
||||
assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
|
||||
k = intel->vtbl.check_vertex_size( intel, intel->vertex_size );
|
||||
assert(k);
|
||||
}
|
||||
|
||||
if (!p->params_uptodate)
|
||||
|
||||
@@ -34,44 +34,45 @@
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
#include "i915_context.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
/* A large amount of state doesn't need to be uploaded.
|
||||
/* We touch almost everything:
|
||||
*/
|
||||
#define ACTIVE (I915_UPLOAD_PROGRAM | \
|
||||
I915_UPLOAD_STIPPLE | \
|
||||
#define ACTIVE (I915_UPLOAD_INVARIENT | \
|
||||
I915_UPLOAD_CTX | \
|
||||
I915_UPLOAD_BUFFERS | \
|
||||
I915_UPLOAD_STIPPLE | \
|
||||
I915_UPLOAD_PROGRAM | \
|
||||
I915_UPLOAD_FOG | \
|
||||
I915_UPLOAD_TEX(0))
|
||||
|
||||
#define SET_STATE( i915, STATE ) \
|
||||
#define SET_STATE( i915, STATE ) \
|
||||
do { \
|
||||
i915->current->emitted &= ~ACTIVE; \
|
||||
i915->current = &i915->STATE; \
|
||||
i915->current = &i915->STATE; \
|
||||
i915->current->emitted &= ~ACTIVE; \
|
||||
} while (0)
|
||||
|
||||
/* Operations where the 3D engine is decoupled temporarily from the
|
||||
* current GL state and used for other purposes than simply rendering
|
||||
* incoming triangles.
|
||||
*/
|
||||
static void set_initial_state( i915ContextPtr i915 )
|
||||
{
|
||||
memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
|
||||
i915->meta.active = ACTIVE;
|
||||
i915->meta.emitted = 0;
|
||||
}
|
||||
|
||||
|
||||
static void set_no_depth_stencil_write( i915ContextPtr i915 )
|
||||
static void meta_no_stencil_write( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE )
|
||||
*/
|
||||
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
|
||||
S5_STENCIL_WRITE_ENABLE);
|
||||
|
||||
i915->meta.emitted &= ~I915_UPLOAD_CTX;
|
||||
}
|
||||
|
||||
static void meta_no_depth_write( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
|
||||
*/
|
||||
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
|
||||
@@ -80,12 +81,33 @@ static void set_no_depth_stencil_write( i915ContextPtr i915 )
|
||||
i915->meta.emitted &= ~I915_UPLOAD_CTX;
|
||||
}
|
||||
|
||||
static void meta_depth_replace( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_TRUE )
|
||||
* ctx->Driver.DepthMask( ctx, GL_TRUE )
|
||||
*/
|
||||
i915->meta.Ctx[I915_CTXREG_LIS6] |= (S6_DEPTH_TEST_ENABLE |
|
||||
S6_DEPTH_WRITE_ENABLE);
|
||||
|
||||
/* ctx->Driver.DepthFunc( ctx, GL_REPLACE )
|
||||
*/
|
||||
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK;
|
||||
i915->meta.Ctx[I915_CTXREG_LIS6] |=
|
||||
COMPAREFUNC_ALWAYS << S6_DEPTH_TEST_FUNC_SHIFT;
|
||||
|
||||
i915->meta.emitted &= ~I915_UPLOAD_CTX;
|
||||
}
|
||||
|
||||
|
||||
/* Set stencil unit to replace always with the reference value.
|
||||
*/
|
||||
static void set_stencil_replace( i915ContextPtr i915,
|
||||
static void meta_stencil_replace( struct intel_context *intel,
|
||||
GLuint s_mask,
|
||||
GLuint s_clear)
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
GLuint op = STENCILOP_REPLACE;
|
||||
GLuint func = COMPAREFUNC_ALWAYS;
|
||||
|
||||
@@ -94,13 +116,6 @@ static void set_stencil_replace( i915ContextPtr i915,
|
||||
i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
|
||||
S5_STENCIL_WRITE_ENABLE);
|
||||
|
||||
|
||||
/* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE )
|
||||
*/
|
||||
i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE |
|
||||
S6_DEPTH_WRITE_ENABLE);
|
||||
|
||||
|
||||
/* ctx->Driver.StencilMask( ctx, s_mask )
|
||||
*/
|
||||
i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
|
||||
@@ -108,7 +123,6 @@ static void set_stencil_replace( i915ContextPtr i915,
|
||||
i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
|
||||
STENCIL_WRITE_MASK(s_mask));
|
||||
|
||||
|
||||
/* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE )
|
||||
*/
|
||||
i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
|
||||
@@ -137,8 +151,9 @@ static void set_stencil_replace( i915ContextPtr i915,
|
||||
}
|
||||
|
||||
|
||||
static void set_color_mask( i915ContextPtr i915, GLboolean state )
|
||||
static void meta_color_mask( struct intel_context *intel, GLboolean state )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
const GLuint mask = (S5_WRITEDISABLE_RED |
|
||||
S5_WRITEDISABLE_GREEN |
|
||||
S5_WRITEDISABLE_BLUE |
|
||||
@@ -159,6 +174,28 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state )
|
||||
|
||||
|
||||
|
||||
static void meta_import_pixel_state( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
memcpy(i915->meta.Fog, i915->state.Fog, I915_FOG_SETUP_SIZE * 4);
|
||||
|
||||
i915->meta.Ctx[I915_CTXREG_LIS5] = i915->state.Ctx[I915_CTXREG_LIS5];
|
||||
i915->meta.Ctx[I915_CTXREG_LIS6] = i915->state.Ctx[I915_CTXREG_LIS6];
|
||||
i915->meta.Ctx[I915_CTXREG_STATE4] = i915->state.Ctx[I915_CTXREG_STATE4];
|
||||
i915->meta.Ctx[I915_CTXREG_BLENDCOLOR1] = i915->state.Ctx[I915_CTXREG_BLENDCOLOR1];
|
||||
i915->meta.Ctx[I915_CTXREG_IAB] = i915->state.Ctx[I915_CTXREG_IAB];
|
||||
|
||||
i915->meta.Buffer[I915_DESTREG_SENABLE] = i915->state.Buffer[I915_DESTREG_SENABLE];
|
||||
i915->meta.Buffer[I915_DESTREG_SR1] = i915->state.Buffer[I915_DESTREG_SR1];
|
||||
i915->meta.Buffer[I915_DESTREG_SR2] = i915->state.Buffer[I915_DESTREG_SR2];
|
||||
|
||||
i915->meta.emitted &= ~I915_UPLOAD_FOG;
|
||||
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
|
||||
i915->meta.emitted &= ~I915_UPLOAD_CTX;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define REG( type, nr ) (((type)<<5)|(nr))
|
||||
|
||||
@@ -210,8 +247,10 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state )
|
||||
|
||||
|
||||
|
||||
static void set_no_texture( i915ContextPtr i915 )
|
||||
static void meta_no_texture( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
static const GLuint prog[] = {
|
||||
_3DSTATE_PIXEL_SHADER_PROGRAM,
|
||||
|
||||
@@ -240,9 +279,10 @@ static void set_no_texture( i915ContextPtr i915 )
|
||||
i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void enable_texture_blend_replace( i915ContextPtr i915 )
|
||||
static void meta_texture_blend_replace( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
static const GLuint prog[] = {
|
||||
_3DSTATE_PIXEL_SHADER_PROGRAM,
|
||||
|
||||
@@ -285,78 +325,126 @@ static void enable_texture_blend_replace( i915ContextPtr i915 )
|
||||
/* Set up an arbitary piece of memory as a rectangular texture
|
||||
* (including the front or back buffer).
|
||||
*/
|
||||
static void set_tex_rect_source( i915ContextPtr i915,
|
||||
GLuint offset,
|
||||
GLuint width,
|
||||
GLuint height,
|
||||
GLuint pitch,
|
||||
GLuint textureFormat )
|
||||
static GLboolean meta_tex_rect_source( struct intel_context *intel,
|
||||
GLuint buffer,
|
||||
GLuint offset,
|
||||
GLuint pitch,
|
||||
GLuint height,
|
||||
GLenum format,
|
||||
GLenum type)
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
GLuint unit = 0;
|
||||
GLint numLevels = 1;
|
||||
GLuint *state = i915->meta.Tex[0];
|
||||
GLuint textureFormat;
|
||||
GLuint cpp;
|
||||
|
||||
pitch *= i915->intel.intelScreen->cpp;
|
||||
/* A full implementation of this would do the upload through
|
||||
* glTexImage2d, and get all the conversion operations at that
|
||||
* point. We are restricted, but still at least have access to the
|
||||
* fragment program swizzle.
|
||||
*/
|
||||
switch (format) {
|
||||
case GL_BGRA:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
|
||||
cpp = 4;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case GL_RGBA:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
|
||||
cpp = 4;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case GL_BGR:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_SHORT_5_6_5_REV:
|
||||
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
|
||||
cpp = 2;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case GL_RGB:
|
||||
switch (type) {
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
|
||||
cpp = 2;
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
/* fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
|
||||
/* __FUNCTION__, offset, width, height, pitch, textureFormat ); */
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if ((pitch * cpp) & 3) {
|
||||
_mesa_printf("%s: texture is not dword pitch\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* intel_region_release(intel, &i915->meta.tex_region[0]); */
|
||||
/* intel_region_reference(&i915->meta.tex_region[0], region); */
|
||||
i915->meta.tex_buffer[0] = buffer;
|
||||
i915->meta.tex_offset[0] = offset;
|
||||
|
||||
state[I915_TEXREG_MS2] = offset;
|
||||
state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) |
|
||||
((width - 1) << MS3_WIDTH_SHIFT) |
|
||||
textureFormat |
|
||||
MS3_USE_FENCE_REGS);
|
||||
((pitch - 1) << MS3_WIDTH_SHIFT) |
|
||||
textureFormat |
|
||||
MS3_USE_FENCE_REGS);
|
||||
|
||||
state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
|
||||
MS4_CUBE_FACE_ENA_MASK |
|
||||
((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
|
||||
state[I915_TEXREG_MS4] = (((((pitch * cpp) / 4) - 1) << MS4_PITCH_SHIFT) |
|
||||
MS4_CUBE_FACE_ENA_MASK |
|
||||
((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT));
|
||||
|
||||
state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) |
|
||||
(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
|
||||
(FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
|
||||
(MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) |
|
||||
(FILTER_NEAREST << SS2_MAG_FILTER_SHIFT));
|
||||
|
||||
state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) |
|
||||
(TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
|
||||
(TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
|
||||
(unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
|
||||
(TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) |
|
||||
(TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) |
|
||||
(unit<<SS3_TEXTUREMAP_INDEX_SHIFT));
|
||||
|
||||
state[I915_TEXREG_SS4] = 0;
|
||||
|
||||
i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
|
||||
return GL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Select between front and back draw buffers.
|
||||
|
||||
/**
|
||||
* Set the color and depth drawing region for meta ops.
|
||||
*/
|
||||
static void set_draw_offset( i915ContextPtr i915,
|
||||
GLuint offset )
|
||||
static void meta_draw_region( struct intel_context *intel,
|
||||
struct intel_region *color_region,
|
||||
struct intel_region *depth_region )
|
||||
{
|
||||
i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset;
|
||||
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
i915_state_draw_region(intel, &i915->meta, color_region, depth_region);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Setup an arbitary draw format, useful for targeting texture or agp
|
||||
* memory.
|
||||
*/
|
||||
static void set_draw_format( i915ContextPtr i915,
|
||||
GLuint format,
|
||||
GLuint depth_format)
|
||||
{
|
||||
i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
|
||||
DSTORG_VERT_BIAS(0x8) | /* .5 */
|
||||
format |
|
||||
LOD_PRECLAMP_OGL |
|
||||
TEX_DEFAULT_COLOR_OGL |
|
||||
depth_format);
|
||||
|
||||
i915->meta.emitted &= ~I915_UPLOAD_BUFFERS;
|
||||
/* fprintf(stderr, "%s: DV1: %x\n", */
|
||||
/* __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_vertex_format( i915ContextPtr i915 )
|
||||
static void set_vertex_format( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
i915->meta.Ctx[I915_CTXREG_LIS2] =
|
||||
(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
|
||||
S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
|
||||
@@ -371,146 +459,52 @@ static void set_vertex_format( i915ContextPtr i915 )
|
||||
|
||||
i915->meta.Ctx[I915_CTXREG_LIS4] |=
|
||||
(S4_VFMT_COLOR |
|
||||
S4_VFMT_SPEC_FOG |
|
||||
S4_VFMT_XYZW);
|
||||
S4_VFMT_XYZ);
|
||||
|
||||
i915->meta.emitted &= ~I915_UPLOAD_CTX;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void draw_quad(i915ContextPtr i915,
|
||||
GLfloat x0, GLfloat x1,
|
||||
GLfloat y0, GLfloat y1,
|
||||
GLubyte red, GLubyte green,
|
||||
GLubyte blue, GLubyte alpha,
|
||||
GLfloat s0, GLfloat s1,
|
||||
GLfloat t0, GLfloat t1 )
|
||||
|
||||
/* Operations where the 3D engine is decoupled temporarily from the
|
||||
* current GL state and used for other purposes than simply rendering
|
||||
* incoming triangles.
|
||||
*/
|
||||
static void install_meta_state( struct intel_context *intel )
|
||||
{
|
||||
GLuint vertex_size = 8;
|
||||
GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
|
||||
PRIM3D_TRIFAN,
|
||||
4 * vertex_size,
|
||||
vertex_size );
|
||||
intelVertex tmp;
|
||||
int i;
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) );
|
||||
i915->meta.active = ACTIVE;
|
||||
i915->meta.emitted = 0;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n",
|
||||
__FUNCTION__,
|
||||
x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1);
|
||||
|
||||
|
||||
/* initial vertex, left bottom */
|
||||
tmp.v.x = x0;
|
||||
tmp.v.y = y0;
|
||||
tmp.v.z = 1.0;
|
||||
tmp.v.w = 1.0;
|
||||
tmp.v.color.red = red;
|
||||
tmp.v.color.green = green;
|
||||
tmp.v.color.blue = blue;
|
||||
tmp.v.color.alpha = alpha;
|
||||
tmp.v.specular.red = 0;
|
||||
tmp.v.specular.green = 0;
|
||||
tmp.v.specular.blue = 0;
|
||||
tmp.v.specular.alpha = 0;
|
||||
tmp.v.u0 = s0;
|
||||
tmp.v.v0 = t0;
|
||||
|
||||
for (i = 0 ; i < vertex_size ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
/* right bottom */
|
||||
vb += vertex_size;
|
||||
tmp.v.x = x1;
|
||||
tmp.v.u0 = s1;
|
||||
for (i = 0 ; i < vertex_size ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
/* right top */
|
||||
vb += vertex_size;
|
||||
tmp.v.y = y1;
|
||||
tmp.v.v0 = t1;
|
||||
for (i = 0 ; i < vertex_size ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
/* left top */
|
||||
vb += vertex_size;
|
||||
tmp.v.x = x0;
|
||||
tmp.v.u0 = s0;
|
||||
for (i = 0 ; i < vertex_size ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
SET_STATE(i915, meta);
|
||||
set_vertex_format(intel);
|
||||
meta_no_texture(intel);
|
||||
}
|
||||
|
||||
void
|
||||
i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch)
|
||||
static void leave_meta_state( struct intel_context *intel )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT( intel );
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
int x0, y0, x1, y1;
|
||||
|
||||
SET_STATE( i915, meta );
|
||||
set_initial_state( i915 );
|
||||
set_no_texture( i915 );
|
||||
set_vertex_format( i915 );
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
if(!all) {
|
||||
x0 = cx;
|
||||
y0 = cy;
|
||||
x1 = x0 + cw;
|
||||
y1 = y0 + ch;
|
||||
} else {
|
||||
x0 = 0;
|
||||
y0 = 0;
|
||||
x1 = x0 + dPriv->w;
|
||||
y1 = y0 + dPriv->h;
|
||||
}
|
||||
|
||||
/* Don't do any clipping to screen - these are window coordinates.
|
||||
* The active cliprects will be applied as for any other geometry.
|
||||
*/
|
||||
|
||||
if (mask & BUFFER_BIT_FRONT_LEFT) {
|
||||
set_no_depth_stencil_write( i915 );
|
||||
set_color_mask( i915, GL_TRUE );
|
||||
set_draw_offset( i915, screen->front.offset );
|
||||
|
||||
draw_quad(i915, x0, x1, y0, y1,
|
||||
intel->clear_red, intel->clear_green,
|
||||
intel->clear_blue, intel->clear_alpha,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (mask & BUFFER_BIT_BACK_LEFT) {
|
||||
set_no_depth_stencil_write( i915 );
|
||||
set_color_mask( i915, GL_TRUE );
|
||||
set_draw_offset( i915, screen->back.offset );
|
||||
|
||||
draw_quad(i915, x0, x1, y0, y1,
|
||||
intel->clear_red, intel->clear_green,
|
||||
intel->clear_blue, intel->clear_alpha,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (mask & BUFFER_BIT_STENCIL) {
|
||||
set_stencil_replace( i915,
|
||||
intel->ctx.Stencil.WriteMask[0],
|
||||
intel->ctx.Stencil.Clear);
|
||||
|
||||
set_color_mask( i915, GL_FALSE );
|
||||
set_draw_offset( i915, screen->front.offset ); /* could be either? */
|
||||
|
||||
draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
SET_STATE( i915, state );
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
intel_region_release(intel, &i915->meta.draw_region);
|
||||
intel_region_release(intel, &i915->meta.depth_region);
|
||||
/* intel_region_release(intel, &i915->meta.tex_region[0]); */
|
||||
SET_STATE(i915, state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i915InitMetaFuncs( struct i915_context *i915 )
|
||||
{
|
||||
i915->intel.vtbl.install_meta_state = install_meta_state;
|
||||
i915->intel.vtbl.leave_meta_state = leave_meta_state;
|
||||
i915->intel.vtbl.meta_no_depth_write = meta_no_depth_write;
|
||||
i915->intel.vtbl.meta_no_stencil_write = meta_no_stencil_write;
|
||||
i915->intel.vtbl.meta_stencil_replace = meta_stencil_replace;
|
||||
i915->intel.vtbl.meta_depth_replace = meta_depth_replace;
|
||||
i915->intel.vtbl.meta_color_mask = meta_color_mask;
|
||||
i915->intel.vtbl.meta_no_texture = meta_no_texture;
|
||||
i915->intel.vtbl.meta_texture_blend_replace = meta_texture_blend_replace;
|
||||
i915->intel.vtbl.meta_tex_rect_source = meta_tex_rect_source;
|
||||
i915->intel.vtbl.meta_draw_region = meta_draw_region;
|
||||
i915->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,8 @@ GLuint i915_emit_arith( struct i915_fragment_program *p,
|
||||
GLuint nr_const = 0;
|
||||
|
||||
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
|
||||
assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
|
||||
dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
|
||||
assert(dest);
|
||||
|
||||
if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) c[nr_const++] = 0;
|
||||
if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) c[nr_const++] = 1;
|
||||
@@ -202,7 +203,8 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
|
||||
GLuint op )
|
||||
{
|
||||
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
|
||||
assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
|
||||
dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest));
|
||||
assert(dest);
|
||||
|
||||
if (GET_UREG_TYPE(coord) != REG_TYPE_T) {
|
||||
p->nr_tex_indirect++;
|
||||
@@ -358,7 +360,7 @@ void i915_program_error( struct i915_fragment_program *p, const char *msg )
|
||||
p->error = 1;
|
||||
}
|
||||
|
||||
void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p )
|
||||
void i915_init_program( struct i915_context *i915, struct i915_fragment_program *p )
|
||||
{
|
||||
GLcontext *ctx = &i915->intel.ctx;
|
||||
TNLcontext *tnl = TNL_CONTEXT( ctx );
|
||||
@@ -431,7 +433,7 @@ void i915_fini_program( struct i915_fragment_program *p )
|
||||
p->declarations[0] |= program_size + decl_size - 2;
|
||||
}
|
||||
|
||||
void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p )
|
||||
void i915_upload_program( struct i915_context *i915, struct i915_fragment_program *p )
|
||||
{
|
||||
GLuint program_size = p->csr - p->program;
|
||||
GLuint decl_size = p->decl - p->declarations;
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
/* One neat thing about the UREG representation:
|
||||
*/
|
||||
static __inline int swizzle( int reg, int x, int y, int z, int w )
|
||||
static INLINE int swizzle( int reg, int x, int y, int z, int w )
|
||||
{
|
||||
return ((reg & ~UREG_XYZW_CHANNEL_MASK) |
|
||||
CHANNEL_SRC( GET_CHANNEL_SRC( reg, x ), 0 ) |
|
||||
@@ -95,7 +95,7 @@ static __inline int swizzle( int reg, int x, int y, int z, int w )
|
||||
|
||||
/* Another neat thing about the UREG representation:
|
||||
*/
|
||||
static __inline int negate( int reg, int x, int y, int z, int w )
|
||||
static INLINE int negate( int reg, int x, int y, int z, int w )
|
||||
{
|
||||
return reg ^ (((x&1)<<UREG_CHANNEL_X_NEGATE_SHIFT)|
|
||||
((y&1)<<UREG_CHANNEL_Y_NEGATE_SHIFT)|
|
||||
@@ -149,10 +149,10 @@ extern GLuint i915_emit_param4fv( struct i915_fragment_program *p,
|
||||
extern void i915_program_error( struct i915_fragment_program *p,
|
||||
const char *msg );
|
||||
|
||||
extern void i915_init_program( i915ContextPtr i915,
|
||||
extern void i915_init_program( struct i915_context *i915,
|
||||
struct i915_fragment_program *p );
|
||||
|
||||
extern void i915_upload_program( i915ContextPtr i915,
|
||||
extern void i915_upload_program( struct i915_context *i915,
|
||||
struct i915_fragment_program *p );
|
||||
|
||||
extern void i915_fini_program( struct i915_fragment_program *p );
|
||||
|
||||
@@ -435,10 +435,10 @@
|
||||
#define LOGICOP_MASK (0xf<<18)
|
||||
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00))
|
||||
#define ENABLE_STENCIL_TEST_MASK (1<<17)
|
||||
#define STENCIL_TEST_MASK(x) ((x)<<8)
|
||||
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8)
|
||||
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff))
|
||||
#define ENABLE_STENCIL_WRITE_MASK (1<<16)
|
||||
#define STENCIL_WRITE_MASK(x) (x)
|
||||
#define STENCIL_WRITE_MASK(x) ((x)&0xff)
|
||||
|
||||
/* _3DSTATE_MODES_5, p220 */
|
||||
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24))
|
||||
@@ -824,10 +824,14 @@
|
||||
#define ST1_ENABLE (1<<16)
|
||||
#define ST1_MASK (0xffff)
|
||||
|
||||
#define _3DSTATE_DEFAULT_Z ((0x3<<29)|(0x1d<<24)|(0x98<<16))
|
||||
#define _3DSTATE_DEFAULT_DIFFUSE ((0x3<<29)|(0x1d<<24)|(0x99<<16))
|
||||
#define _3DSTATE_DEFAULT_SPECULAR ((0x3<<29)|(0x1d<<24)|(0x9a<<16))
|
||||
|
||||
#define MI_FLUSH ((0<<29)|(4<<23))
|
||||
#define FLUSH_MAP_CACHE (1<<0)
|
||||
#define FLUSH_RENDER_CACHE (1<<1)
|
||||
|
||||
#define MI_FLUSH ((0<<29)|(4<<23))
|
||||
#define FLUSH_MAP_CACHE (1<<0)
|
||||
#define INHIBIT_FLUSH_RENDER_CACHE (1<<2)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "texmem.h"
|
||||
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
|
||||
@@ -48,7 +49,7 @@ static void
|
||||
i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
GLuint mask)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func( func );
|
||||
|
||||
mask = mask & 0xff;
|
||||
@@ -73,7 +74,7 @@ i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
static void
|
||||
i915StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask);
|
||||
@@ -91,7 +92,7 @@ static void
|
||||
i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
GLenum zpass)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int fop = intel_translate_stencil_op(fail);
|
||||
int dfop = intel_translate_stencil_op(zfail);
|
||||
int dpop = intel_translate_stencil_op(zpass);
|
||||
@@ -116,7 +117,7 @@ i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
|
||||
static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func( func );
|
||||
GLubyte refByte;
|
||||
|
||||
@@ -137,7 +138,7 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
*/
|
||||
static void i915EvalLogicOpBlendState(GLcontext *ctx)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
|
||||
@@ -157,7 +158,7 @@ static void i915EvalLogicOpBlendState(GLcontext *ctx)
|
||||
|
||||
static void i915BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
GLubyte r, g, b, a;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -194,7 +195,7 @@ static GLuint translate_blend_equation( GLenum mode )
|
||||
|
||||
static void i915UpdateBlendState( GLcontext *ctx )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &
|
||||
~(IAB_SRC_FACTOR_MASK |
|
||||
IAB_DST_FACTOR_MASK |
|
||||
@@ -261,7 +262,7 @@ static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB,
|
||||
|
||||
static void i915DepthFunc(GLcontext *ctx, GLenum func)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func( func );
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -274,7 +275,7 @@ static void i915DepthFunc(GLcontext *ctx, GLenum func)
|
||||
|
||||
static void i915DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag);
|
||||
@@ -295,7 +296,7 @@ static void i915DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
*/
|
||||
static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
const GLubyte *m = mask;
|
||||
GLubyte p[4];
|
||||
int i,j,k;
|
||||
@@ -348,15 +349,14 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
GLsizei w, GLsizei h)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
intelScreenPrivate *screen = i915->intel.intelScreen;
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
if (!i915->intel.driDrawable)
|
||||
if (!ctx->DrawBuffer)
|
||||
return;
|
||||
|
||||
x1 = x;
|
||||
y1 = i915->intel.driDrawable->h - (y + h);
|
||||
y1 = ctx->DrawBuffer->Height - (y + h);
|
||||
x2 = x + w - 1;
|
||||
y2 = y1 + h - 1;
|
||||
|
||||
@@ -364,16 +364,10 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
|
||||
x, y, w, h);
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 < 0) x2 = 0;
|
||||
if (y2 < 0) y2 = 0;
|
||||
|
||||
if (x2 >= screen->width) x2 = screen->width-1;
|
||||
if (y2 >= screen->height) y2 = screen->height-1;
|
||||
if (x1 >= screen->width) x1 = screen->width-1;
|
||||
if (y1 >= screen->height) y1 = screen->height-1;
|
||||
|
||||
x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1);
|
||||
y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1);
|
||||
x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1);
|
||||
y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
|
||||
i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
|
||||
@@ -382,7 +376,7 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
|
||||
static void i915LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int tmp = intel_translate_logic_op(opcode);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -397,7 +391,7 @@ static void i915LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
|
||||
static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
GLuint mode;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -425,7 +419,7 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
|
||||
static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT( ctx );
|
||||
struct i915_context *i915 = I915_CONTEXT( ctx );
|
||||
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK;
|
||||
int width;
|
||||
|
||||
@@ -444,7 +438,7 @@ static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
|
||||
static void i915PointSize(GLcontext *ctx, GLfloat size)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK;
|
||||
GLint point_size = (int)size;
|
||||
|
||||
@@ -469,7 +463,7 @@ static void i915ColorMask(GLcontext *ctx,
|
||||
GLboolean r, GLboolean g,
|
||||
GLboolean b, GLboolean a)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT( ctx );
|
||||
struct i915_context *i915 = I915_CONTEXT( ctx );
|
||||
GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
@@ -490,7 +484,7 @@ static void update_specular( GLcontext *ctx )
|
||||
{
|
||||
/* A hack to trigger the rebuild of the fragment program.
|
||||
*/
|
||||
INTEL_CONTEXT(ctx)->NewGLState |= _NEW_TEXTURE;
|
||||
intel_context(ctx)->NewGLState |= _NEW_TEXTURE;
|
||||
I915_CONTEXT(ctx)->tex_program.translated = 0;
|
||||
}
|
||||
|
||||
@@ -507,7 +501,7 @@ static void i915LightModelfv(GLcontext *ctx, GLenum pname,
|
||||
|
||||
static void i915ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
|
||||
if (mode == GL_SMOOTH) {
|
||||
@@ -526,7 +520,7 @@ static void i915ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
*/
|
||||
void i915_update_fog( GLcontext *ctx )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
GLenum mode;
|
||||
GLboolean enabled;
|
||||
GLboolean try_pixel_fog;
|
||||
@@ -619,7 +613,7 @@ void i915_update_fog( GLcontext *ctx )
|
||||
|
||||
static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
|
||||
switch (pname) {
|
||||
case GL_FOG_COORDINATE_SOURCE_EXT:
|
||||
@@ -671,7 +665,7 @@ static void i915Hint(GLcontext *ctx, GLenum target, GLenum state)
|
||||
|
||||
static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
|
||||
switch(cap) {
|
||||
case GL_TEXTURE_2D:
|
||||
@@ -699,7 +693,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
|
||||
/* Logicop doesn't seem to work at 16bpp:
|
||||
*/
|
||||
if (i915->intel.intelScreen->cpp == 2)
|
||||
if (i915->intel.intelScreen->cpp == 2) /* XXX FBO fix */
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_LOGICOP, state );
|
||||
break;
|
||||
|
||||
@@ -750,16 +744,24 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
break;
|
||||
|
||||
case GL_STENCIL_TEST:
|
||||
if (i915->intel.hw_stencil) {
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
if (state)
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
|
||||
S5_STENCIL_WRITE_ENABLE);
|
||||
else
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
|
||||
S5_STENCIL_WRITE_ENABLE);
|
||||
} else {
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state );
|
||||
{
|
||||
GLboolean hw_stencil = GL_FALSE;
|
||||
if (ctx->DrawBuffer) {
|
||||
struct intel_renderbuffer *irbStencil
|
||||
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
|
||||
hw_stencil = (irbStencil && irbStencil->region);
|
||||
}
|
||||
if (hw_stencil) {
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
if (state)
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
|
||||
S5_STENCIL_WRITE_ENABLE);
|
||||
else
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
|
||||
S5_STENCIL_WRITE_ENABLE);
|
||||
} else {
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -785,7 +787,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
}
|
||||
|
||||
|
||||
static void i915_init_packets( i915ContextPtr i915 )
|
||||
static void i915_init_packets( struct i915_context *i915 )
|
||||
{
|
||||
intelScreenPrivate *screen = i915->intel.intelScreen;
|
||||
|
||||
@@ -808,7 +810,7 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
i915->state.Ctx[I915_CTXREG_LIS4] = 0;
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] = 0;
|
||||
|
||||
if (screen->cpp == 2)
|
||||
if (screen->cpp == 2) /* XXX FBO fix */
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE;
|
||||
|
||||
|
||||
@@ -823,7 +825,6 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
ENABLE_STENCIL_WRITE_MASK |
|
||||
STENCIL_WRITE_MASK(0xff));
|
||||
|
||||
|
||||
i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
|
||||
IAB_MODIFY_ENABLE |
|
||||
IAB_MODIFY_FUNC |
|
||||
@@ -857,24 +858,24 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
{
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
/* XXX FBO: remove this? Also get set in i915_set_draw_region() */
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK |
|
||||
BUF_3D_PITCH(screen->front.pitch * screen->cpp) |
|
||||
BUF_3D_PITCH(screen->front.pitch * screen->cpp) | /* XXX FBO fix */
|
||||
BUF_3D_USE_FENCE);
|
||||
|
||||
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
/* XXX FBO: remove this? Also get set in i915_set_draw_region() */
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH |
|
||||
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) |
|
||||
BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | /* XXX FBO fix */
|
||||
BUF_3D_USE_FENCE);
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset;
|
||||
|
||||
|
||||
i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
|
||||
|
||||
/* XXX FBO: remove this? Also get set in i915_set_draw_region() */
|
||||
#if 0 /* seems we don't need this */
|
||||
switch (screen->fbFormat) {
|
||||
case DV_PF_555:
|
||||
case DV_PF_565:
|
||||
i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
|
||||
DSTORG_VERT_BIAS(0x8) | /* .5 */
|
||||
@@ -893,6 +894,8 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
DEPTH_FRMT_24_FIXED_8_OTHER);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
DISABLE_SCISSOR_RECT);
|
||||
i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD;
|
||||
@@ -901,13 +904,27 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_DEFAULTS);
|
||||
i915->state.Default[I915_DEFREG_C0] = _3DSTATE_DEFAULT_DIFFUSE;
|
||||
i915->state.Default[I915_DEFREG_C1] = 0;
|
||||
i915->state.Default[I915_DEFREG_S0] = _3DSTATE_DEFAULT_SPECULAR;
|
||||
i915->state.Default[I915_DEFREG_S1] = 0;
|
||||
i915->state.Default[I915_DEFREG_Z0] = _3DSTATE_DEFAULT_Z;
|
||||
i915->state.Default[I915_DEFREG_Z1] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* These will be emitted every at the head of every buffer, unless
|
||||
* we get hardware contexts working.
|
||||
*/
|
||||
i915->state.active = (I915_UPLOAD_PROGRAM |
|
||||
I915_UPLOAD_STIPPLE |
|
||||
I915_UPLOAD_CTX |
|
||||
I915_UPLOAD_BUFFERS);
|
||||
I915_UPLOAD_STIPPLE |
|
||||
I915_UPLOAD_CTX |
|
||||
I915_UPLOAD_BUFFERS |
|
||||
I915_UPLOAD_INVARIENT);
|
||||
}
|
||||
|
||||
void i915InitStateFunctions( struct dd_function_table *functions )
|
||||
@@ -937,7 +954,7 @@ void i915InitStateFunctions( struct dd_function_table *functions )
|
||||
}
|
||||
|
||||
|
||||
void i915InitState( i915ContextPtr i915 )
|
||||
void i915InitState( struct i915_context *i915 )
|
||||
{
|
||||
GLcontext *ctx = &i915->intel.ctx;
|
||||
|
||||
|
||||
@@ -45,76 +45,10 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allocate space for and load the mesa images into the texture memory block.
|
||||
* This will happen before drawing with a new texture, or drawing with a
|
||||
* texture after it was swapped out or teximaged again.
|
||||
*/
|
||||
|
||||
intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj )
|
||||
{
|
||||
i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object );
|
||||
if ( !t )
|
||||
return NULL;
|
||||
|
||||
texObj->DriverData = t;
|
||||
t->intel.base.tObj = texObj;
|
||||
t->intel.dirty = I915_UPLOAD_TEX_ALL;
|
||||
make_empty_list( &t->intel.base );
|
||||
return &t->intel;
|
||||
}
|
||||
|
||||
|
||||
static void i915TexParameter( GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *tObj,
|
||||
GLenum pname, const GLfloat *params )
|
||||
{
|
||||
i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData;
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_MIN_FILTER:
|
||||
case GL_TEXTURE_MAG_FILTER:
|
||||
case GL_TEXTURE_MAX_ANISOTROPY_EXT:
|
||||
case GL_TEXTURE_WRAP_S:
|
||||
case GL_TEXTURE_WRAP_T:
|
||||
case GL_TEXTURE_WRAP_R:
|
||||
case GL_TEXTURE_BORDER_COLOR:
|
||||
t->intel.dirty = I915_UPLOAD_TEX_ALL;
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_COMPARE_MODE:
|
||||
t->intel.dirty = I915_UPLOAD_TEX_ALL;
|
||||
break;
|
||||
case GL_TEXTURE_COMPARE_FUNC:
|
||||
t->intel.dirty = I915_UPLOAD_TEX_ALL;
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_BASE_LEVEL:
|
||||
case GL_TEXTURE_MAX_LEVEL:
|
||||
case GL_TEXTURE_MIN_LOD:
|
||||
case GL_TEXTURE_MAX_LOD:
|
||||
/* The i915 and its successors can do a lot of this without
|
||||
* reloading the textures. A project for someone?
|
||||
*/
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( (driTextureObject *) t );
|
||||
t->intel.dirty = I915_UPLOAD_TEX_ALL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void i915TexEnv( GLcontext *ctx, GLenum target,
|
||||
GLenum pname, const GLfloat *param )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT( ctx );
|
||||
GLuint unit = ctx->Texture.CurrentUnit;
|
||||
struct i915_context *i915 = I915_CONTEXT( ctx );
|
||||
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_ENV_COLOR: /* Should be a tracked param */
|
||||
@@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_LOD_BIAS: {
|
||||
int b = (int) ((*param) * 16.0);
|
||||
GLuint unit = ctx->Texture.CurrentUnit;
|
||||
GLint b = (int) ((*param) * 16.0);
|
||||
if (b > 255) b = 255;
|
||||
if (b < -256) b = -256;
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
|
||||
i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK;
|
||||
i915->state.Tex[unit][I915_TEXREG_SS2] |=
|
||||
((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
|
||||
i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
|
||||
|
||||
|
||||
static void i915BindTexture( GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj )
|
||||
struct gl_texture_object *texobj )
|
||||
{
|
||||
i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData;
|
||||
|
||||
if (tex->lastTarget != texObj->Target) {
|
||||
tex->intel.dirty = I915_UPLOAD_TEX_ALL;
|
||||
tex->lastTarget = texObj->Target;
|
||||
}
|
||||
|
||||
/* Need this if image format changes between bound textures.
|
||||
* Could try and shortcircuit by checking for differences in
|
||||
* state between incoming and outgoing textures:
|
||||
@@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
functions->BindTexture = i915BindTexture;
|
||||
functions->TexEnv = i915TexEnv;
|
||||
functions->TexParameter = i915TexParameter;
|
||||
}
|
||||
|
||||
338
src/mesa/drivers/dri/i915/i915_tex_layout.c
Normal file
338
src/mesa/drivers/dri/i915/i915_tex_layout.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Code to layout images in a mipmap tree for i915 and i945
|
||||
* respectively.
|
||||
*/
|
||||
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "macros.h"
|
||||
|
||||
static GLint initial_offsets[6][2] = { {0,0},
|
||||
{0,2},
|
||||
{1,0},
|
||||
{1,2},
|
||||
{1,1},
|
||||
{1,3} };
|
||||
|
||||
|
||||
static GLint step_offsets[6][2] = { {0,2},
|
||||
{0,2},
|
||||
{-1,2},
|
||||
{-1,2},
|
||||
{-1,1},
|
||||
{-1,1} };
|
||||
|
||||
static GLuint minify( GLuint d )
|
||||
{
|
||||
return MAX2(1, d>>1);
|
||||
}
|
||||
|
||||
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt )
|
||||
{
|
||||
GLint i;
|
||||
|
||||
switch (mt->target) {
|
||||
case GL_TEXTURE_CUBE_MAP: {
|
||||
const GLuint dim = mt->width0;
|
||||
GLuint face;
|
||||
|
||||
/* double pitch for cube layouts */
|
||||
mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = dim * 4;
|
||||
|
||||
for ( face = 0 ; face < 6 ; face++) {
|
||||
GLuint x = initial_offsets[face][0] * dim;
|
||||
GLuint y = initial_offsets[face][1] * dim;
|
||||
GLuint d = dim;
|
||||
|
||||
for (i = mt->first_level; i <= mt->last_level; i++) {
|
||||
intel_miptree_set_image_offset(mt, face, i,
|
||||
x, y,
|
||||
d, d, 1);
|
||||
|
||||
if (d == 0)
|
||||
_mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
|
||||
face, i, mt->first_level, mt->last_level);
|
||||
|
||||
d >>= 1;
|
||||
x += step_offsets[face][0] * d;
|
||||
y += step_offsets[face][1] * d;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_3D: {
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
GLuint depth = mt->depth0;
|
||||
|
||||
/* Calculate the size of a single slice.
|
||||
*/
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = 0;
|
||||
|
||||
/* XXX: hardware expects/requires 9 levels at minimum.
|
||||
*/
|
||||
for ( i = mt->first_level ; i <= MAX2(8, mt->last_level) ; i++ ) {
|
||||
intel_miptree_set_image_offset(mt, 0, i,
|
||||
0, mt->total_height,
|
||||
width, height, depth);
|
||||
|
||||
mt->total_height += MAX2(2, height);
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
depth = minify(depth);
|
||||
}
|
||||
|
||||
/* Fixup depth_image_stride:
|
||||
*/
|
||||
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
|
||||
mt->offset[0][i].depth_image_stride = mt->total_height * mt->pitch * mt->cpp;
|
||||
}
|
||||
|
||||
|
||||
/* Multiply slice size by texture depth for total size. It's
|
||||
* remarkable how wasteful of memory the i915 texture layouts
|
||||
* are. They are largely fixed in the i945.
|
||||
*/
|
||||
mt->total_height *= mt->depth0;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = 0;
|
||||
|
||||
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
|
||||
intel_miptree_set_image_offset(mt, 0, i,
|
||||
0, mt->total_height,
|
||||
width, height, 1);
|
||||
|
||||
if (mt->compressed)
|
||||
mt->total_height += MAX2(1, height/4);
|
||||
else
|
||||
mt->total_height += MAX2(2, height);
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
|
||||
mt->pitch,
|
||||
mt->total_height,
|
||||
mt->cpp,
|
||||
mt->pitch * mt->total_height * mt->cpp );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt )
|
||||
{
|
||||
GLint i;
|
||||
|
||||
switch (mt->target) {
|
||||
case GL_TEXTURE_CUBE_MAP: {
|
||||
const GLuint dim = mt->width0;
|
||||
GLuint face;
|
||||
|
||||
/* Depending on the size of the largest images, pitch can be
|
||||
* determined either by the old-style packing of cubemap faces,
|
||||
* or the final row of 4x4, 2x2 and 1x1 faces below this.
|
||||
*/
|
||||
if (dim > 32)
|
||||
mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
|
||||
else
|
||||
mt->pitch = 14 * 8;
|
||||
|
||||
mt->total_height = dim * 4 + 4;
|
||||
|
||||
|
||||
for ( face = 0 ; face < 6 ; face++) {
|
||||
GLuint x = initial_offsets[face][0] * dim;
|
||||
GLuint y = initial_offsets[face][1] * dim;
|
||||
GLuint d = dim;
|
||||
|
||||
if (dim == 4 && face >= 4) {
|
||||
y = mt->total_height - 4;
|
||||
x = (face - 4) * 8;
|
||||
}
|
||||
else if (dim < 4) {
|
||||
y = mt->total_height - 4;
|
||||
x = face * 8;
|
||||
}
|
||||
|
||||
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
|
||||
intel_miptree_set_image_offset(mt, face, i,
|
||||
x, y,
|
||||
d, d, 1);
|
||||
|
||||
d >>= 1;
|
||||
|
||||
switch (d) {
|
||||
case 4:
|
||||
switch (face) {
|
||||
case FACE_POS_X:
|
||||
case FACE_NEG_X:
|
||||
x += step_offsets[face][0] * d;
|
||||
y += step_offsets[face][1] * d;
|
||||
break;
|
||||
case FACE_POS_Y:
|
||||
case FACE_NEG_Y:
|
||||
y += 12;
|
||||
x -= 8;
|
||||
break;
|
||||
case FACE_POS_Z:
|
||||
case FACE_NEG_Z:
|
||||
y = mt->total_height - 4;
|
||||
x = (face - 4) * 8;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
y = mt->total_height - 4;
|
||||
x = 16 + face * 8;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
x += 48;
|
||||
break;
|
||||
|
||||
default:
|
||||
x += step_offsets[face][0] * d;
|
||||
y += step_offsets[face][1] * d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_3D: {
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
GLuint depth = mt->depth0;
|
||||
GLuint depth_pack_pitch;
|
||||
GLuint depth_packing = 0;
|
||||
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = 0;
|
||||
|
||||
depth_pack_pitch = mt->pitch * mt->cpp;
|
||||
|
||||
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
|
||||
|
||||
intel_miptree_set_image_offset(mt, 0, i,
|
||||
0, mt->total_height,
|
||||
width, height, depth);
|
||||
|
||||
|
||||
|
||||
mt->total_height += MAX2(2, height) * MAX2((depth >> depth_packing), 1);
|
||||
|
||||
/* When alignment dominates, can't increase depth packing?
|
||||
* Or does pitch grow??? What are the alignment constraints,
|
||||
* anyway?
|
||||
*/
|
||||
if (depth_pack_pitch > 4) {
|
||||
depth_packing++;
|
||||
depth_pack_pitch >>= 2; /* KW: is this right?? */
|
||||
}
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
depth = minify(depth);
|
||||
|
||||
/* XXX: Not sure how 3d textures work on i945 - where did
|
||||
* t->depth_pitch get set in the old code. Did it ever work?
|
||||
* Fix up later.
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_TEXTURE_1D:
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_RECTANGLE_ARB: {
|
||||
GLuint x = 0;
|
||||
GLuint y = 0;
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = 0;
|
||||
|
||||
for ( i = mt->first_level ; i <= mt->last_level ; i++ ) {
|
||||
intel_miptree_set_image_offset(mt, 0, i,
|
||||
x, y,
|
||||
width, height, 1);
|
||||
|
||||
|
||||
/* LPT change: step right after second mipmap.
|
||||
*/
|
||||
if (i == 1)
|
||||
x += mt->pitch / 2;
|
||||
else {
|
||||
GLuint img_height;
|
||||
|
||||
if (mt->compressed)
|
||||
img_height = MAX2(1, height/4);
|
||||
else
|
||||
img_height = MAX2(2, height);
|
||||
|
||||
y += img_height;
|
||||
}
|
||||
|
||||
/* Because the images are packed better, the final offset
|
||||
* might not be the maximal one:
|
||||
*/
|
||||
mt->total_height = MAX2(mt->total_height, y);
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
_mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");
|
||||
}
|
||||
|
||||
DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
|
||||
mt->pitch,
|
||||
mt->total_height,
|
||||
mt->cpp,
|
||||
mt->pitch * mt->total_height * mt->cpp );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ static void emit_program_fini( struct i915_fragment_program *p )
|
||||
}
|
||||
|
||||
|
||||
static void i915EmitTextureProgram( i915ContextPtr i915 )
|
||||
static void i915EmitTextureProgram( struct i915_context *i915 )
|
||||
{
|
||||
GLcontext *ctx = &i915->intel.ctx;
|
||||
struct i915_fragment_program *p = &i915->tex_program;
|
||||
@@ -570,9 +570,9 @@ static void i915EmitTextureProgram( i915ContextPtr i915 )
|
||||
}
|
||||
|
||||
|
||||
void i915ValidateTextureProgram( i915ContextPtr i915 )
|
||||
void i915ValidateTextureProgram( struct i915_context *i915 )
|
||||
{
|
||||
intelContextPtr intel = &i915->intel;
|
||||
struct intel_context *intel = &i915->intel;
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
@@ -639,7 +639,8 @@ void i915ValidateTextureProgram( i915ContextPtr i915 )
|
||||
*/
|
||||
if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
|
||||
s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
|
||||
|
||||
int k;
|
||||
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_CTX );
|
||||
|
||||
i915->tex_program.translated = 0;
|
||||
@@ -657,7 +658,8 @@ void i915ValidateTextureProgram( i915ContextPtr i915 )
|
||||
i915->state.Ctx[I915_CTXREG_LIS2] = s2;
|
||||
i915->state.Ctx[I915_CTXREG_LIS4] = s4;
|
||||
|
||||
assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
|
||||
k = intel->vtbl.check_vertex_size( intel, intel->vertex_size );
|
||||
assert(k);
|
||||
}
|
||||
|
||||
if (!i915->tex_program.translated ||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,14 +37,16 @@
|
||||
#include "tnl/t_vertex.h"
|
||||
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_context.h"
|
||||
|
||||
static void i915_render_start( intelContextPtr intel )
|
||||
static void i915_render_start( struct intel_context *intel )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
if (ctx->FragmentProgram._Active)
|
||||
i915ValidateFragmentProgram( i915 );
|
||||
@@ -53,42 +55,42 @@ static void i915_render_start( intelContextPtr intel )
|
||||
}
|
||||
|
||||
|
||||
static void i915_reduced_primitive_state( intelContextPtr intel,
|
||||
static void i915_reduced_primitive_state( struct intel_context *intel,
|
||||
GLenum rprim )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
|
||||
|
||||
st1 &= ~ST1_ENABLE;
|
||||
st1 &= ~ST1_ENABLE;
|
||||
|
||||
switch (rprim) {
|
||||
case GL_TRIANGLES:
|
||||
if (intel->ctx.Polygon.StippleFlag &&
|
||||
intel->hw_stipple)
|
||||
st1 |= ST1_ENABLE;
|
||||
break;
|
||||
case GL_LINES:
|
||||
case GL_POINTS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (rprim) {
|
||||
case GL_TRIANGLES:
|
||||
if (intel->ctx.Polygon.StippleFlag &&
|
||||
intel->hw_stipple)
|
||||
st1 |= ST1_ENABLE;
|
||||
break;
|
||||
case GL_LINES:
|
||||
case GL_POINTS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i915->intel.reduced_primitive = rprim;
|
||||
i915->intel.reduced_primitive = rprim;
|
||||
|
||||
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
|
||||
i915->state.Stipple[I915_STPREG_ST1] = st1;
|
||||
}
|
||||
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
|
||||
i915->state.Stipple[I915_STPREG_ST1] = st1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Pull apart the vertex format registers and figure out how large a
|
||||
* vertex is supposed to be.
|
||||
*/
|
||||
static GLboolean i915_check_vertex_size( intelContextPtr intel,
|
||||
static GLboolean i915_check_vertex_size( struct intel_context *intel,
|
||||
GLuint expected )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
int lis2 = i915->current->Ctx[I915_CTXREG_LIS2];
|
||||
int lis4 = i915->current->Ctx[I915_CTXREG_LIS4];
|
||||
int i, sz = 0;
|
||||
@@ -132,11 +134,11 @@ static GLboolean i915_check_vertex_size( intelContextPtr intel,
|
||||
}
|
||||
|
||||
|
||||
static void i915_emit_invarient_state( intelContextPtr intel )
|
||||
static void i915_emit_invarient_state( struct intel_context *intel )
|
||||
{
|
||||
BATCH_LOCALS;
|
||||
|
||||
BEGIN_BATCH( 200 );
|
||||
BEGIN_BATCH( 200, 0 );
|
||||
|
||||
OUT_BATCH(_3DSTATE_AA_CMD |
|
||||
AA_LINE_ECAAR_WIDTH_ENABLE |
|
||||
@@ -204,21 +206,15 @@ static void i915_emit_invarient_state( intelContextPtr intel )
|
||||
}
|
||||
|
||||
|
||||
#define emit( intel, state, size ) \
|
||||
do { \
|
||||
int k; \
|
||||
BEGIN_BATCH( (size) / sizeof(GLuint)); \
|
||||
for (k = 0 ; k < (size) / sizeof(GLuint) ; k++) \
|
||||
OUT_BATCH((state)[k]); \
|
||||
ADVANCE_BATCH(); \
|
||||
} while (0);
|
||||
#define emit(intel, state, size ) \
|
||||
intel_batchbuffer_data(intel->batch, state, size, 0 )
|
||||
|
||||
|
||||
/* Push the state into the sarea and/or texture memory.
|
||||
*/
|
||||
static void i915_emit_state( intelContextPtr intel )
|
||||
static void i915_emit_state( struct intel_context *intel )
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
struct i915_hw_state *state = i915->current;
|
||||
int i;
|
||||
GLuint dirty;
|
||||
@@ -233,27 +229,51 @@ static void i915_emit_state( intelContextPtr intel )
|
||||
dirty = state->active & ~state->emitted;
|
||||
|
||||
|
||||
if (VERBOSE)
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty);
|
||||
|
||||
if (dirty & I915_UPLOAD_INVARIENT) {
|
||||
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n");
|
||||
i915_emit_invarient_state( intel );
|
||||
}
|
||||
|
||||
if (dirty & I915_UPLOAD_CTX) {
|
||||
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");
|
||||
emit( i915, state->Ctx, sizeof(state->Ctx) );
|
||||
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n");
|
||||
emit(intel, state->Ctx, sizeof(state->Ctx) );
|
||||
}
|
||||
|
||||
if (dirty & I915_UPLOAD_BUFFERS) {
|
||||
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
|
||||
emit( i915, state->Buffer, sizeof(state->Buffer) );
|
||||
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
|
||||
BEGIN_BATCH(I915_DEST_SETUP_SIZE+2, 0);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]);
|
||||
OUT_RELOC(state->draw_region->buffer, DRM_MM_TT|DRM_MM_WRITE,
|
||||
state->draw_region->draw_offset);
|
||||
|
||||
if (state->depth_region) {
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]);
|
||||
OUT_RELOC(state->depth_region->buffer, DRM_MM_TT|DRM_MM_WRITE,
|
||||
state->depth_region->draw_offset);
|
||||
}
|
||||
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_DV0]);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_DV1]);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_SR0]);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_SR1]);
|
||||
OUT_BATCH(state->Buffer[I915_DESTREG_SR2]);
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
if (dirty & I915_UPLOAD_STIPPLE) {
|
||||
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
|
||||
emit( i915, state->Stipple, sizeof(state->Stipple) );
|
||||
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");
|
||||
emit(intel, state->Stipple, sizeof(state->Stipple) );
|
||||
}
|
||||
|
||||
if (dirty & I915_UPLOAD_FOG) {
|
||||
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n");
|
||||
emit( i915, state->Fog, sizeof(state->Fog) );
|
||||
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_FOG:\n");
|
||||
emit(intel, state->Fog, sizeof(state->Fog) );
|
||||
}
|
||||
|
||||
/* Combine all the dirty texture state into a single command to
|
||||
@@ -266,18 +286,29 @@ static void i915_emit_state( intelContextPtr intel )
|
||||
if (dirty & I915_UPLOAD_TEX(i))
|
||||
nr++;
|
||||
|
||||
BEGIN_BATCH(2+nr*3);
|
||||
BEGIN_BATCH(2+nr*3, 0);
|
||||
OUT_BATCH(_3DSTATE_MAP_STATE | (3*nr));
|
||||
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
|
||||
for (i = 0 ; i < I915_TEX_UNITS ; i++)
|
||||
if (dirty & I915_UPLOAD_TEX(i)) {
|
||||
OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]);
|
||||
|
||||
if (state->tex_buffer[i]) {
|
||||
OUT_RELOC(state->tex_buffer[i],
|
||||
DRM_MM_TT|DRM_MM_READ,
|
||||
state->tex_offset[i]);
|
||||
}
|
||||
else {
|
||||
assert(i == 0);
|
||||
assert(state == &i915->meta);
|
||||
OUT_BATCH(0);
|
||||
}
|
||||
|
||||
OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]);
|
||||
OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]);
|
||||
}
|
||||
ADVANCE_BATCH();
|
||||
|
||||
BEGIN_BATCH(2+nr*3);
|
||||
BEGIN_BATCH(2+nr*3, 0);
|
||||
OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3*nr));
|
||||
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT);
|
||||
for (i = 0 ; i < I915_TEX_UNITS ; i++)
|
||||
@@ -290,64 +321,132 @@ static void i915_emit_state( intelContextPtr intel )
|
||||
}
|
||||
|
||||
if (dirty & I915_UPLOAD_CONSTANTS) {
|
||||
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
|
||||
emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) );
|
||||
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");
|
||||
emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint) );
|
||||
}
|
||||
|
||||
if (dirty & I915_UPLOAD_PROGRAM) {
|
||||
if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
|
||||
if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");
|
||||
|
||||
assert((state->Program[0] & 0x1ff)+2 == state->ProgramSize);
|
||||
|
||||
emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) );
|
||||
if (VERBOSE)
|
||||
emit(intel, state->Program, state->ProgramSize * sizeof(GLuint) );
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
i915_disassemble_program( state->Program, state->ProgramSize );
|
||||
}
|
||||
|
||||
state->emitted |= dirty;
|
||||
}
|
||||
|
||||
static void i915_destroy_context( intelContextPtr intel )
|
||||
static void i915_destroy_context( struct intel_context *intel )
|
||||
{
|
||||
_tnl_free_vertices(&intel->ctx);
|
||||
}
|
||||
|
||||
static void i915_set_draw_offset( intelContextPtr intel, int offset )
|
||||
|
||||
/**
|
||||
* Set the drawing regions for the color and depth/stencil buffers.
|
||||
* This involves setting the pitch, cpp and buffer ID/location.
|
||||
* Also set pixel format for color and Z rendering
|
||||
* Used for setting both regular and meta state.
|
||||
*/
|
||||
void
|
||||
i915_state_draw_region(struct intel_context *intel,
|
||||
struct i915_hw_state *state,
|
||||
struct intel_region *color_region,
|
||||
struct intel_region *depth_region)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
GLuint value;
|
||||
|
||||
ASSERT(state == &i915->state || state == &i915->meta);
|
||||
|
||||
if (state->draw_region != color_region) {
|
||||
intel_region_release(intel, &state->draw_region);
|
||||
intel_region_reference(&state->draw_region, color_region);
|
||||
}
|
||||
if (state->depth_region != depth_region) {
|
||||
intel_region_release(intel, &state->depth_region);
|
||||
intel_region_reference(&state->depth_region, depth_region);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set stride/cpp values
|
||||
*/
|
||||
if (color_region) {
|
||||
state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
state->Buffer[I915_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK |
|
||||
BUF_3D_PITCH(color_region->pitch * color_region->cpp) |
|
||||
BUF_3D_USE_FENCE);
|
||||
}
|
||||
|
||||
if (depth_region) {
|
||||
state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
state->Buffer[I915_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH |
|
||||
BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) |
|
||||
BUF_3D_USE_FENCE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute/set I915_DESTREG_DV1 value
|
||||
*/
|
||||
value = (DSTORG_HORT_BIAS(0x8) | /* .5 */
|
||||
DSTORG_VERT_BIAS(0x8) | /* .5 */
|
||||
LOD_PRECLAMP_OGL |
|
||||
TEX_DEFAULT_COLOR_OGL);
|
||||
if (color_region && color_region->cpp == 4) {
|
||||
value |= DV_PF_8888;
|
||||
}
|
||||
else {
|
||||
value |= (DITHER_FULL_ALWAYS | DV_PF_565);
|
||||
}
|
||||
if (depth_region && depth_region->cpp == 4) {
|
||||
value |= DEPTH_FRMT_24_FIXED_8_OTHER;
|
||||
}
|
||||
else {
|
||||
value |= DEPTH_FRMT_16_FIXED;
|
||||
}
|
||||
state->Buffer[I915_DESTREG_DV1] = value;
|
||||
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS );
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset;
|
||||
}
|
||||
|
||||
static void i915_lost_hardware( intelContextPtr intel )
|
||||
{
|
||||
I915_CONTEXT(intel)->state.emitted = 0;
|
||||
}
|
||||
|
||||
static void i915_emit_flush( intelContextPtr intel )
|
||||
{
|
||||
BATCH_LOCALS;
|
||||
|
||||
BEGIN_BATCH(2);
|
||||
OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE );
|
||||
OUT_BATCH( 0 );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
|
||||
void i915InitVtbl( i915ContextPtr i915 )
|
||||
static void
|
||||
i915_set_draw_region(struct intel_context *intel,
|
||||
struct intel_region *color_region,
|
||||
struct intel_region *depth_region)
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
i915_state_draw_region(intel, &i915->state, color_region, depth_region);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void i915_lost_hardware( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
i915->state.emitted = 0;
|
||||
}
|
||||
|
||||
static GLuint i915_flush_cmd( void )
|
||||
{
|
||||
return MI_FLUSH | FLUSH_MAP_CACHE;
|
||||
}
|
||||
|
||||
|
||||
void i915InitVtbl( struct i915_context *i915 )
|
||||
{
|
||||
i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj;
|
||||
i915->intel.vtbl.check_vertex_size = i915_check_vertex_size;
|
||||
i915->intel.vtbl.clear_with_tris = i915ClearWithTris;
|
||||
i915->intel.vtbl.destroy = i915_destroy_context;
|
||||
i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state;
|
||||
i915->intel.vtbl.emit_state = i915_emit_state;
|
||||
i915->intel.vtbl.lost_hardware = i915_lost_hardware;
|
||||
i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state;
|
||||
i915->intel.vtbl.render_start = i915_render_start;
|
||||
i915->intel.vtbl.set_draw_offset = i915_set_draw_offset;
|
||||
i915->intel.vtbl.set_draw_region = i915_set_draw_region;
|
||||
i915->intel.vtbl.update_texture_state = i915UpdateTextureState;
|
||||
i915->intel.vtbl.emit_flush = i915_emit_flush;
|
||||
i915->intel.vtbl.flush_cmd = i915_flush_cmd;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -25,664 +25,270 @@
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "context.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "intel_reg.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* ================================================================
|
||||
* Performance monitoring functions
|
||||
/* Relocations in kernel space:
|
||||
* - pass dma buffer seperately
|
||||
* - memory manager knows how to patch
|
||||
* - pass list of dependent buffers
|
||||
* - pass relocation list
|
||||
*
|
||||
* Either:
|
||||
* - get back an offset for buffer to fire
|
||||
* - memory manager knows how to fire buffer
|
||||
*
|
||||
* Really want the buffer to be AGP and pinned.
|
||||
*
|
||||
*/
|
||||
|
||||
static void intel_fill_box( intelContextPtr intel,
|
||||
GLshort x, GLshort y,
|
||||
GLshort w, GLshort h,
|
||||
GLubyte r, GLubyte g, GLubyte b )
|
||||
/* Cliprect fence: The highest fence protecting a dma buffer
|
||||
* containing explicit cliprect information. Like the old drawable
|
||||
* lock but irq-driven. X server must wait for this fence to expire
|
||||
* before changing cliprects [and then doing sw rendering?]. For
|
||||
* other dma buffers, the scheduler will grab current cliprect info
|
||||
* and mix into buffer. X server must hold the lock while changing
|
||||
* cliprects??? Make per-drawable. Need cliprects in shared memory
|
||||
* -- beats storing them with every cmd buffer in the queue.
|
||||
*
|
||||
* ==> X server must wait for this fence to expire before touching the
|
||||
* framebuffer with new cliprects.
|
||||
*
|
||||
* ==> Cliprect-dependent buffers associated with a
|
||||
* cliprect-timestamp. All of the buffers associated with a timestamp
|
||||
* must go to hardware before any buffer with a newer timestamp.
|
||||
*
|
||||
* ==> Dma should be queued per-drawable for correct X/GL
|
||||
* synchronization. Or can fences be used for this?
|
||||
*
|
||||
* Applies to: Blit operations, metaops, X server operations -- X
|
||||
* server automatically waits on its own dma to complete before
|
||||
* modifying cliprects ???
|
||||
*/
|
||||
|
||||
static void intel_dump_batchbuffer( GLuint offset,
|
||||
GLuint *ptr,
|
||||
GLuint count )
|
||||
{
|
||||
intelEmitFillBlitLocked( intel,
|
||||
intel->intelScreen->cpp,
|
||||
intel->intelScreen->back.pitch,
|
||||
intel->intelScreen->front.offset,
|
||||
x, y, w, h,
|
||||
INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
|
||||
r,g,b,0xff));
|
||||
}
|
||||
|
||||
static void intel_draw_performance_boxes( intelContextPtr intel )
|
||||
{
|
||||
/* Purple box for page flipping
|
||||
*/
|
||||
if ( intel->perf_boxes & I830_BOX_FLIP )
|
||||
intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
|
||||
|
||||
/* Red box if we have to wait for idle at any point
|
||||
*/
|
||||
if ( intel->perf_boxes & I830_BOX_WAIT )
|
||||
intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
|
||||
|
||||
/* Blue box: lost context?
|
||||
*/
|
||||
if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )
|
||||
intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
|
||||
|
||||
/* Yellow box for texture swaps
|
||||
*/
|
||||
if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )
|
||||
intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
|
||||
|
||||
/* Green box if hardware never idles (as far as we can tell)
|
||||
*/
|
||||
if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )
|
||||
intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
|
||||
|
||||
|
||||
/* Draw bars indicating number of buffers allocated
|
||||
* (not a great measure, easily confused)
|
||||
*/
|
||||
#if 0
|
||||
if (intel->dma_used) {
|
||||
int bar = intel->dma_used / 10240;
|
||||
if (bar > 100) bar = 100;
|
||||
if (bar < 1) bar = 1;
|
||||
intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
|
||||
intel->dma_used = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
intel->perf_boxes = 0;
|
||||
int i;
|
||||
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count/4);
|
||||
for (i = 0; i < count/4; i += 4)
|
||||
fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]);
|
||||
fprintf(stderr, "END BATCH\n\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int bad_prim_vertex_nr( int primitive, int nr )
|
||||
static void intel_batchbuffer_reset( struct intel_batchbuffer *batch )
|
||||
{
|
||||
switch (primitive & PRIM3D_MASK) {
|
||||
case PRIM3D_POINTLIST:
|
||||
return nr < 1;
|
||||
case PRIM3D_LINELIST:
|
||||
return (nr & 1) || nr == 0;
|
||||
case PRIM3D_LINESTRIP:
|
||||
return nr < 2;
|
||||
case PRIM3D_TRILIST:
|
||||
case PRIM3D_RECTLIST:
|
||||
return nr % 3 || nr == 0;
|
||||
case PRIM3D_POLY:
|
||||
case PRIM3D_TRIFAN:
|
||||
case PRIM3D_TRISTRIP:
|
||||
case PRIM3D_TRISTRIP_RVRSE:
|
||||
return nr < 3;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
bmBufferData(batch->bm,
|
||||
batch->buffer,
|
||||
BATCH_SZ,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (!batch->list)
|
||||
batch->list = bmNewBufferList();
|
||||
|
||||
drmMMClearBufList(batch->list);
|
||||
batch->list_count = 0;
|
||||
batch->nr_relocs = 0;
|
||||
batch->flags = 0;
|
||||
|
||||
bmAddBuffer( batch->bm,
|
||||
batch->list,
|
||||
batch->buffer,
|
||||
DRM_MM_TT,
|
||||
NULL,
|
||||
&batch->offset[batch->list_count++]);
|
||||
|
||||
batch->map = bmMapBuffer(batch->bm, batch->buffer, DRM_MM_WRITE);
|
||||
batch->ptr = batch->map;
|
||||
}
|
||||
|
||||
static void intel_flush_inline_primitive( GLcontext *ctx )
|
||||
/*======================================================================
|
||||
* Public functions
|
||||
*/
|
||||
struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
GLuint used = intel->batch.ptr - intel->prim.start_ptr;
|
||||
GLuint vertcount;
|
||||
struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
|
||||
|
||||
assert(intel->prim.primitive != ~0);
|
||||
batch->intel = intel;
|
||||
batch->bm = intel->bm;
|
||||
|
||||
if (1) {
|
||||
/* Check vertex size against the vertex we're specifying to
|
||||
* hardware. If it's wrong, ditch the primitive.
|
||||
*/
|
||||
if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))
|
||||
goto do_discard;
|
||||
bmGenBuffers(intel->bm, 1, &batch->buffer, BM_BATCHBUFFER);
|
||||
batch->last_fence = bmInitFence(batch->bm);
|
||||
intel_batchbuffer_reset( batch );
|
||||
return batch;
|
||||
}
|
||||
|
||||
vertcount = (used - 4)/ (intel->vertex_size * 4);
|
||||
void intel_batchbuffer_free( struct intel_batchbuffer *batch )
|
||||
{
|
||||
if (batch->map)
|
||||
bmUnmapBuffer(batch->bm, batch->buffer);
|
||||
|
||||
free(batch);
|
||||
}
|
||||
|
||||
if (!vertcount)
|
||||
goto do_discard;
|
||||
/* TODO: Push this whole function into bufmgr.
|
||||
*/
|
||||
static void do_flush_locked( struct intel_batchbuffer *batch,
|
||||
GLuint used,
|
||||
GLboolean ignore_cliprects,
|
||||
GLboolean allow_unlock)
|
||||
{
|
||||
GLuint *ptr;
|
||||
GLuint i;
|
||||
|
||||
bmValidateBufferList( batch->bm,
|
||||
batch->list,
|
||||
DRM_MM_TT );
|
||||
|
||||
/* Apply the relocations. This nasty map indicates to me that the
|
||||
* whole task should be done internally by the memory manager, and
|
||||
* that dma buffers probably need to be pinned within agp space.
|
||||
*/
|
||||
ptr = (GLuint *)bmMapBuffer(batch->bm, batch->buffer, DRM_MM_WRITE);
|
||||
|
||||
|
||||
for (i = 0; i < batch->nr_relocs; i++) {
|
||||
struct buffer_reloc *r = &batch->reloc[i];
|
||||
|
||||
if (vertcount * intel->vertex_size * 4 != used - 4) {
|
||||
fprintf(stderr, "vertex size confusion %d %d\n", used,
|
||||
intel->vertex_size * vertcount * 4);
|
||||
goto do_discard;
|
||||
}
|
||||
|
||||
if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
|
||||
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
|
||||
vertcount);
|
||||
goto do_discard;
|
||||
}
|
||||
assert(r->elem < batch->list_count);
|
||||
ptr[r->offset/4] = batch->offset[r->elem] + r->delta;
|
||||
}
|
||||
|
||||
if (used < 8)
|
||||
goto do_discard;
|
||||
if (INTEL_DEBUG & DEBUG_DMA)
|
||||
intel_dump_batchbuffer( 0, ptr, used );
|
||||
|
||||
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
|
||||
intel->prim.primitive |
|
||||
(used/4-2));
|
||||
|
||||
goto finished;
|
||||
bmUnmapBuffer(batch->bm, batch->buffer);
|
||||
|
||||
do_discard:
|
||||
intel->batch.ptr -= used;
|
||||
intel->batch.space += used;
|
||||
assert(intel->batch.space >= 0);
|
||||
|
||||
finished:
|
||||
intel->prim.primitive = ~0;
|
||||
intel->prim.start_ptr = 0;
|
||||
intel->prim.flush = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Emit a primitive referencing vertices in a vertex buffer.
|
||||
*/
|
||||
void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
|
||||
{
|
||||
BATCH_LOCALS;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
|
||||
|
||||
|
||||
/* Finish any in-progress primitive:
|
||||
/* Fire the batch buffer, which was uploaded above:
|
||||
*/
|
||||
INTEL_FIREVERTICES( intel );
|
||||
|
||||
/* Emit outstanding state:
|
||||
*/
|
||||
intel->vtbl.emit_state( intel );
|
||||
|
||||
/* Make sure there is some space in this buffer:
|
||||
*/
|
||||
if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space)
|
||||
intelFlushBatch(intel, GL_TRUE);
|
||||
|
||||
|
||||
#if 1
|
||||
if (((int)intel->batch.ptr) & 0x4) {
|
||||
BEGIN_BATCH(1);
|
||||
OUT_BATCH(0);
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
intel_batch_ioctl(batch->intel,
|
||||
batch->offset[0],
|
||||
used,
|
||||
ignore_cliprects,
|
||||
allow_unlock);
|
||||
#endif
|
||||
|
||||
/* Emit a slot which will be filled with the inline primitive
|
||||
* command later.
|
||||
*/
|
||||
BEGIN_BATCH(2);
|
||||
OUT_BATCH( 0 );
|
||||
|
||||
intel->prim.start_ptr = batch_ptr;
|
||||
intel->prim.primitive = prim;
|
||||
intel->prim.flush = intel_flush_inline_primitive;
|
||||
|
||||
OUT_BATCH( 0 );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
|
||||
void intelRestartInlinePrimitive( intelContextPtr intel )
|
||||
{
|
||||
GLuint prim = intel->prim.primitive;
|
||||
|
||||
intel_flush_inline_primitive( &intel->ctx );
|
||||
if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
|
||||
intelStartInlinePrimitive( intel, prim );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelWrapInlinePrimitive( intelContextPtr intel )
|
||||
{
|
||||
GLuint prim = intel->prim.primitive;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
intel_flush_inline_primitive( &intel->ctx );
|
||||
intelFlushBatch(intel, GL_TRUE);
|
||||
intelStartInlinePrimitive( intel, prim );
|
||||
}
|
||||
|
||||
|
||||
/* Emit a primitive with space for inline vertices.
|
||||
*/
|
||||
GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
|
||||
int primitive,
|
||||
int dwords,
|
||||
int vertex_size )
|
||||
{
|
||||
GLuint *tmp = 0;
|
||||
BATCH_LOCALS;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
|
||||
|
||||
/* Emit outstanding state:
|
||||
*/
|
||||
intel->vtbl.emit_state( intel );
|
||||
|
||||
|
||||
if (1) {
|
||||
int used = dwords * 4;
|
||||
int vertcount;
|
||||
|
||||
/* Check vertex size against the vertex we're specifying to
|
||||
* hardware. If it's wrong, ditch the primitive.
|
||||
*/
|
||||
if (!intel->vtbl.check_vertex_size( intel, vertex_size ))
|
||||
goto do_discard;
|
||||
|
||||
vertcount = dwords / vertex_size;
|
||||
|
||||
if (dwords % vertex_size) {
|
||||
fprintf(stderr, "did not request a whole number of vertices\n");
|
||||
goto do_discard;
|
||||
}
|
||||
|
||||
if (bad_prim_vertex_nr( primitive, vertcount )) {
|
||||
fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
|
||||
goto do_discard;
|
||||
}
|
||||
|
||||
if (used < 8)
|
||||
goto do_discard;
|
||||
}
|
||||
|
||||
/* Emit 3D_PRIMITIVE commands:
|
||||
*/
|
||||
BEGIN_BATCH(1 + dwords);
|
||||
OUT_BATCH( _3DPRIMITIVE |
|
||||
primitive |
|
||||
(dwords-1) );
|
||||
|
||||
tmp = (GLuint *)batch_ptr;
|
||||
batch_ptr += dwords * 4;
|
||||
|
||||
ADVANCE_BATCH();
|
||||
|
||||
do_discard:
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copy the back buffer to the front buffer.
|
||||
*/
|
||||
void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
|
||||
{
|
||||
intelContextPtr intel;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
assert(dPriv);
|
||||
assert(dPriv->driContextPriv);
|
||||
assert(dPriv->driContextPriv->driverPrivate);
|
||||
|
||||
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
{
|
||||
intelScreenPrivate *intelScreen = intel->intelScreen;
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
int nbox = dPriv->numClipRects;
|
||||
drm_clip_rect_t *pbox = dPriv->pClipRects;
|
||||
int pitch = intelScreen->front.pitch;
|
||||
int cpp = intelScreen->cpp;
|
||||
int i;
|
||||
GLuint CMD, BR13;
|
||||
BATCH_LOCALS;
|
||||
|
||||
switch(cpp) {
|
||||
case 2:
|
||||
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
|
||||
CMD = XY_SRC_COPY_BLT_CMD;
|
||||
break;
|
||||
case 4:
|
||||
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
|
||||
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
|
||||
XY_SRC_COPY_BLT_WRITE_RGB);
|
||||
break;
|
||||
default:
|
||||
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
|
||||
CMD = XY_SRC_COPY_BLT_CMD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (0)
|
||||
intel_draw_performance_boxes( intel );
|
||||
|
||||
for (i = 0 ; i < nbox; i++, pbox++)
|
||||
{
|
||||
if (pbox->x1 > pbox->x2 ||
|
||||
pbox->y1 > pbox->y2 ||
|
||||
pbox->x2 > intelScreen->width ||
|
||||
pbox->y2 > intelScreen->height)
|
||||
continue;
|
||||
batch->last_fence = bmFenceBufferList(batch->bm, batch->list);
|
||||
if (!batch->intel->last_swap_fence_retired) {
|
||||
int retired;
|
||||
drmFence dFence = {0,batch->intel->last_swap_fence};
|
||||
|
||||
BEGIN_BATCH( 8);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
|
||||
OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
|
||||
|
||||
if (intel->sarea->pf_current_page == 0)
|
||||
OUT_BATCH( intelScreen->front.offset );
|
||||
else
|
||||
OUT_BATCH( intelScreen->back.offset );
|
||||
|
||||
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
|
||||
OUT_BATCH( BR13 & 0xffff );
|
||||
|
||||
if (intel->sarea->pf_current_page == 0)
|
||||
OUT_BATCH( intelScreen->back.offset );
|
||||
else
|
||||
OUT_BATCH( intelScreen->front.offset );
|
||||
|
||||
ADVANCE_BATCH();
|
||||
/*FIXME: Temporary fix for fence ageing
|
||||
*
|
||||
*/
|
||||
if (!drmTestFence(batch->intel->driFd, dFence, 0, &retired)) {
|
||||
batch->intel->last_swap_fence_retired = retired;
|
||||
}
|
||||
}
|
||||
intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
|
||||
UNLOCK_HARDWARE( intel );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void intelEmitFillBlitLocked( intelContextPtr intel,
|
||||
GLuint cpp,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_offset,
|
||||
GLshort x, GLshort y,
|
||||
GLshort w, GLshort h,
|
||||
GLuint color )
|
||||
GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch )
|
||||
{
|
||||
GLuint BR13, CMD;
|
||||
BATCH_LOCALS;
|
||||
struct intel_context *intel = batch->intel;
|
||||
GLuint used = batch->ptr - batch->map;
|
||||
|
||||
dst_pitch *= cpp;
|
||||
if (used == 0)
|
||||
return batch->last_fence;
|
||||
|
||||
switch(cpp) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
|
||||
CMD = XY_COLOR_BLT_CMD;
|
||||
break;
|
||||
case 4:
|
||||
BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
|
||||
CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
|
||||
XY_COLOR_BLT_WRITE_RGB);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
/* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
|
||||
* performance drain that we would like to avoid.
|
||||
*/
|
||||
if (used & 4) {
|
||||
((int *)batch->ptr)[0] = intel->vtbl.flush_cmd();
|
||||
((int *)batch->ptr)[1] = 0;
|
||||
((int *)batch->ptr)[2] = MI_BATCH_BUFFER_END;
|
||||
used += 12;
|
||||
}
|
||||
else {
|
||||
((int *)batch->ptr)[0] = intel->vtbl.flush_cmd() ;
|
||||
((int *)batch->ptr)[1] = MI_BATCH_BUFFER_END;
|
||||
used += 8;
|
||||
}
|
||||
|
||||
BEGIN_BATCH( 6);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (y << 16) | x );
|
||||
OUT_BATCH( ((y+h) << 16) | (x+w) );
|
||||
OUT_BATCH( dst_offset );
|
||||
OUT_BATCH( color );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
bmUnmapBuffer(batch->bm, batch->buffer);
|
||||
batch->ptr = NULL;
|
||||
batch->map = NULL;
|
||||
|
||||
|
||||
/* Copy BitBlt
|
||||
*/
|
||||
void intelEmitCopyBlitLocked( intelContextPtr intel,
|
||||
GLuint cpp,
|
||||
GLshort src_pitch,
|
||||
GLuint src_offset,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_offset,
|
||||
GLshort src_x, GLshort src_y,
|
||||
GLshort dst_x, GLshort dst_y,
|
||||
GLshort w, GLshort h )
|
||||
{
|
||||
GLuint CMD, BR13;
|
||||
int dst_y2 = dst_y + h;
|
||||
int dst_x2 = dst_x + w;
|
||||
BATCH_LOCALS;
|
||||
|
||||
src_pitch *= cpp;
|
||||
dst_pitch *= cpp;
|
||||
|
||||
switch(cpp) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
BR13 = dst_pitch | (0xCC << 16) | (1<<24);
|
||||
CMD = XY_SRC_COPY_BLT_CMD;
|
||||
break;
|
||||
case 4:
|
||||
BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
|
||||
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
|
||||
XY_SRC_COPY_BLT_WRITE_RGB);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (dst_y2 < dst_y ||
|
||||
dst_x2 < dst_x) {
|
||||
return;
|
||||
}
|
||||
|
||||
BEGIN_BATCH( 12);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (dst_y << 16) | dst_x );
|
||||
OUT_BATCH( (dst_y2 << 16) | dst_x2 );
|
||||
OUT_BATCH( dst_offset );
|
||||
OUT_BATCH( (src_y << 16) | src_x );
|
||||
OUT_BATCH( src_pitch );
|
||||
OUT_BATCH( src_offset );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
|
||||
GLint cx1, GLint cy1, GLint cw, GLint ch)
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
intelScreenPrivate *intelScreen = intel->intelScreen;
|
||||
GLuint clear_depth, clear_color;
|
||||
GLint cx, cy;
|
||||
GLint pitch = intelScreen->front.pitch;
|
||||
GLint cpp = intelScreen->cpp;
|
||||
GLint i;
|
||||
GLuint BR13, CMD, D_CMD;
|
||||
BATCH_LOCALS;
|
||||
|
||||
|
||||
clear_color = intel->ClearColor;
|
||||
clear_depth = 0;
|
||||
|
||||
if (flags & BUFFER_BIT_DEPTH) {
|
||||
clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
|
||||
}
|
||||
|
||||
if (flags & BUFFER_BIT_STENCIL) {
|
||||
clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
|
||||
}
|
||||
|
||||
switch(cpp) {
|
||||
case 2:
|
||||
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
|
||||
D_CMD = CMD = XY_COLOR_BLT_CMD;
|
||||
break;
|
||||
case 4:
|
||||
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
|
||||
CMD = (XY_COLOR_BLT_CMD |
|
||||
XY_COLOR_BLT_WRITE_ALPHA |
|
||||
XY_COLOR_BLT_WRITE_RGB);
|
||||
D_CMD = XY_COLOR_BLT_CMD;
|
||||
if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
|
||||
if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
|
||||
break;
|
||||
default:
|
||||
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
|
||||
D_CMD = CMD = XY_COLOR_BLT_CMD;
|
||||
break;
|
||||
}
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
/* TODO: Just pass the relocation list and dma buffer up to the
|
||||
* kernel.
|
||||
*/
|
||||
if (!intel->locked)
|
||||
{
|
||||
/* flip top to bottom */
|
||||
cy = intel->driDrawable->h-cy1-ch;
|
||||
cx = cx1 + intel->drawX;
|
||||
cy += intel->drawY;
|
||||
assert(!(batch->flags & INTEL_BATCH_NO_CLIPRECTS));
|
||||
|
||||
/* adjust for page flipping */
|
||||
if ( intel->sarea->pf_current_page == 1 ) {
|
||||
GLuint tmp = flags;
|
||||
|
||||
flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
|
||||
if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
|
||||
if ( tmp & BUFFER_BIT_BACK_LEFT ) flags |= BUFFER_BIT_FRONT_LEFT;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < intel->numClipRects ; i++)
|
||||
{
|
||||
drm_clip_rect_t *box = &intel->pClipRects[i];
|
||||
drm_clip_rect_t b;
|
||||
|
||||
if (!all) {
|
||||
GLint x = box[i].x1;
|
||||
GLint y = box[i].y1;
|
||||
GLint w = box[i].x2 - x;
|
||||
GLint h = box[i].y2 - y;
|
||||
|
||||
if (x < cx) w -= cx - x, x = cx;
|
||||
if (y < cy) h -= cy - y, y = cy;
|
||||
if (x + w > cx + cw) w = cx + cw - x;
|
||||
if (y + h > cy + ch) h = cy + ch - y;
|
||||
if (w <= 0) continue;
|
||||
if (h <= 0) continue;
|
||||
|
||||
b.x1 = x;
|
||||
b.y1 = y;
|
||||
b.x2 = x + w;
|
||||
b.y2 = y + h;
|
||||
} else {
|
||||
b = *box;
|
||||
}
|
||||
|
||||
|
||||
if (b.x1 > b.x2 ||
|
||||
b.y1 > b.y2 ||
|
||||
b.x2 > intelScreen->width ||
|
||||
b.y2 > intelScreen->height)
|
||||
continue;
|
||||
|
||||
if ( flags & BUFFER_BIT_FRONT_LEFT ) {
|
||||
BEGIN_BATCH( 6);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (b.y1 << 16) | b.x1 );
|
||||
OUT_BATCH( (b.y2 << 16) | b.x2 );
|
||||
OUT_BATCH( intelScreen->front.offset );
|
||||
OUT_BATCH( clear_color );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
if ( flags & BUFFER_BIT_BACK_LEFT ) {
|
||||
BEGIN_BATCH( 6);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (b.y1 << 16) | b.x1 );
|
||||
OUT_BATCH( (b.y2 << 16) | b.x2 );
|
||||
OUT_BATCH( intelScreen->back.offset );
|
||||
OUT_BATCH( clear_color );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
|
||||
BEGIN_BATCH( 6);
|
||||
OUT_BATCH( D_CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (b.y1 << 16) | b.x1 );
|
||||
OUT_BATCH( (b.y2 << 16) | b.x2 );
|
||||
OUT_BATCH( intelScreen->depth.offset );
|
||||
OUT_BATCH( clear_depth );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
}
|
||||
}
|
||||
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
|
||||
UNLOCK_HARDWARE( intel );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void intelDestroyBatchBuffer( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
|
||||
if (intel->alloc.ptr) {
|
||||
intelFreeAGP( intel, intel->alloc.ptr );
|
||||
intel->alloc.ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void intelInitBatchBuffer( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
|
||||
if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) {
|
||||
intel->alloc.size = 8 * 1024;
|
||||
intel->alloc.ptr = malloc( intel->alloc.size );
|
||||
intel->alloc.offset = 0;
|
||||
LOCK_HARDWARE(intel);
|
||||
do_flush_locked(batch, used, GL_FALSE, GL_TRUE);
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
else {
|
||||
switch (intel->intelScreen->deviceID) {
|
||||
case PCI_CHIP_I865_G:
|
||||
/* HW bug? Seems to crash if batchbuffer crosses 4k boundary.
|
||||
*/
|
||||
intel->alloc.size = 8 * 1024;
|
||||
break;
|
||||
default:
|
||||
/* This is the smallest amount of memory the kernel deals with.
|
||||
* We'd ideally like to make this smaller.
|
||||
*/
|
||||
intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
|
||||
break;
|
||||
}
|
||||
|
||||
intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
|
||||
if (intel->alloc.ptr)
|
||||
intel->alloc.offset =
|
||||
intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
|
||||
GLboolean ignore_cliprects = !(batch->flags & INTEL_BATCH_CLIPRECTS);
|
||||
do_flush_locked(batch, used, ignore_cliprects, GL_FALSE);
|
||||
}
|
||||
|
||||
if (!intel->alloc.ptr) {
|
||||
FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1);
|
||||
}
|
||||
else {
|
||||
intel->prim.flush = 0;
|
||||
intel->vtbl.emit_invarient_state( intel );
|
||||
|
||||
/* Make sure this gets to the hardware, even if we have no cliprects:
|
||||
*/
|
||||
LOCK_HARDWARE( intel );
|
||||
intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
|
||||
UNLOCK_HARDWARE( intel );
|
||||
}
|
||||
/* Reset the buffer:
|
||||
*/
|
||||
intel_batchbuffer_reset( batch );
|
||||
return batch->last_fence;
|
||||
}
|
||||
|
||||
void intel_batchbuffer_finish( struct intel_batchbuffer *batch )
|
||||
{
|
||||
bmFinishFence(batch->bm,
|
||||
intel_batchbuffer_flush(batch));
|
||||
}
|
||||
|
||||
|
||||
/* This is the only way buffers get added to the validate list.
|
||||
*/
|
||||
GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch,
|
||||
GLuint buffer,
|
||||
GLuint flags,
|
||||
GLuint delta )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
assert(batch->nr_relocs <= MAX_RELOCS);
|
||||
|
||||
i = bmScanBufferList(batch->bm, batch->list, buffer);
|
||||
if (i == -1) {
|
||||
i = batch->list_count;
|
||||
bmAddBuffer(batch->bm,
|
||||
batch->list,
|
||||
buffer,
|
||||
flags,
|
||||
NULL,
|
||||
&batch->offset[batch->list_count++]);
|
||||
}
|
||||
|
||||
{
|
||||
struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
|
||||
r->offset = batch->ptr - batch->map;
|
||||
r->delta = delta;
|
||||
r->elem = i;
|
||||
}
|
||||
|
||||
batch->ptr += 4;
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
|
||||
const void *data,
|
||||
GLuint bytes,
|
||||
GLuint flags)
|
||||
{
|
||||
assert((bytes & 3) == 0);
|
||||
intel_batchbuffer_require_space(batch, bytes, flags);
|
||||
__memcpy(batch->ptr, data, bytes);
|
||||
batch->ptr += bytes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,123 +1,124 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_BATCHBUFFER_H
|
||||
#define INTEL_BATCHBUFFER_H
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "mtypes.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
struct intel_context;
|
||||
|
||||
#define BATCH_SZ 4096
|
||||
#define BATCH_RESERVED 16
|
||||
|
||||
#define MAX_RELOCS 100
|
||||
|
||||
#define INTEL_BATCH_NO_CLIPRECTS 0x1
|
||||
#define INTEL_BATCH_CLIPRECTS 0x2
|
||||
|
||||
struct buffer_reloc {
|
||||
GLuint offset;
|
||||
GLuint elem; /* elem in buffer list, not buffer id */
|
||||
GLuint delta; /* not needed? */
|
||||
};
|
||||
|
||||
struct intel_batchbuffer {
|
||||
struct bufmgr *bm;
|
||||
struct intel_context *intel;
|
||||
|
||||
GLuint buffer;
|
||||
GLuint last_fence;
|
||||
GLuint flags;
|
||||
|
||||
/* In progress:
|
||||
*/
|
||||
unsigned long offset[MAX_RELOCS];
|
||||
struct _drmMMBufList *list;
|
||||
GLuint list_count;
|
||||
GLubyte *map;
|
||||
GLubyte *ptr;
|
||||
|
||||
struct buffer_reloc reloc[MAX_RELOCS];
|
||||
GLuint nr_relocs;
|
||||
};
|
||||
|
||||
struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel );
|
||||
|
||||
void intel_batchbuffer_free( struct intel_batchbuffer *batch );
|
||||
|
||||
|
||||
#define BATCH_LOCALS GLubyte *batch_ptr;
|
||||
void intel_batchbuffer_finish( struct intel_batchbuffer *batch );
|
||||
|
||||
/* #define VERBOSE 0 */
|
||||
#ifndef VERBOSE
|
||||
extern int VERBOSE;
|
||||
#endif
|
||||
GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch );
|
||||
|
||||
|
||||
#define BEGIN_BATCH(n) \
|
||||
do { \
|
||||
if (VERBOSE) fprintf(stderr, \
|
||||
"BEGIN_BATCH(%d) in %s, %d dwords free\n", \
|
||||
(n), __FUNCTION__, intel->batch.space/4); \
|
||||
if (intel->batch.space < (n)*4) \
|
||||
intelFlushBatch(intel, GL_TRUE); \
|
||||
batch_ptr = intel->batch.ptr; \
|
||||
} while (0)
|
||||
/* Unlike bmBufferData, this currently requires the buffer be mapped.
|
||||
* Consider it a convenience function wrapping multple
|
||||
* intel_buffer_dword() calls.
|
||||
*/
|
||||
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
|
||||
const void *data,
|
||||
GLuint bytes,
|
||||
GLuint flags);
|
||||
|
||||
#define OUT_BATCH(n) \
|
||||
do { \
|
||||
*(GLuint *)batch_ptr = (n); \
|
||||
if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__); \
|
||||
batch_ptr += 4; \
|
||||
} while (0)
|
||||
void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
|
||||
GLuint bytes);
|
||||
|
||||
#define ADVANCE_BATCH() \
|
||||
do { \
|
||||
if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n"); \
|
||||
intel->batch.space -= (batch_ptr - intel->batch.ptr); \
|
||||
intel->batch.ptr = batch_ptr; \
|
||||
assert(intel->batch.space >= 0); \
|
||||
} while(0)
|
||||
GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch,
|
||||
GLuint buffer,
|
||||
GLuint flags,
|
||||
GLuint offset );
|
||||
|
||||
extern void intelInitBatchBuffer( GLcontext *ctx );
|
||||
extern void intelDestroyBatchBuffer( GLcontext *ctx );
|
||||
|
||||
extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim );
|
||||
extern void intelWrapInlinePrimitive( intelContextPtr intel );
|
||||
extern void intelRestartInlinePrimitive( intelContextPtr intel );
|
||||
extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
|
||||
int primitive, int dwords,
|
||||
int vertex_size);
|
||||
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
|
||||
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
|
||||
GLint cx1, GLint cy1, GLint cw, GLint ch);
|
||||
|
||||
extern void intelEmitCopyBlitLocked( intelContextPtr intel,
|
||||
GLuint cpp,
|
||||
GLshort src_pitch,
|
||||
GLuint src_offset,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_offset,
|
||||
GLshort srcx, GLshort srcy,
|
||||
GLshort dstx, GLshort dsty,
|
||||
GLshort w, GLshort h );
|
||||
|
||||
extern void intelEmitFillBlitLocked( intelContextPtr intel,
|
||||
GLuint cpp,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_offset,
|
||||
GLshort x, GLshort y,
|
||||
GLshort w, GLshort h,
|
||||
GLuint color );
|
||||
|
||||
|
||||
|
||||
|
||||
static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,
|
||||
GLuint dwords )
|
||||
/* Inline functions - might actually be better off with these
|
||||
* non-inlined. Certainly better off switching all command packets to
|
||||
* be passed as structs rather than dwords, but that's a little bit of
|
||||
* work...
|
||||
*/
|
||||
static INLINE GLuint
|
||||
intel_batchbuffer_space( struct intel_batchbuffer *batch )
|
||||
{
|
||||
GLuint sz = dwords * sizeof(GLuint);
|
||||
GLuint *ptr;
|
||||
|
||||
if (intel->batch.space < sz) {
|
||||
intelWrapInlinePrimitive( intel );
|
||||
/* assert(intel->batch.space >= sz); */
|
||||
}
|
||||
|
||||
/* assert(intel->prim.primitive != ~0); */
|
||||
ptr = (GLuint *)intel->batch.ptr;
|
||||
intel->batch.ptr += sz;
|
||||
intel->batch.space -= sz;
|
||||
|
||||
return ptr;
|
||||
return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->map);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch,
|
||||
GLuint dword)
|
||||
{
|
||||
assert(batch->map);
|
||||
assert(intel_batchbuffer_space(batch) >= 4);
|
||||
*(GLuint *)(batch->ptr) = dword;
|
||||
batch->ptr += 4;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
|
||||
GLuint sz,
|
||||
GLuint flags)
|
||||
{
|
||||
assert(sz < BATCH_SZ - 8);
|
||||
if (intel_batchbuffer_space(batch) < sz ||
|
||||
(batch->flags != 0 && flags != 0 && batch->flags != flags))
|
||||
intel_batchbuffer_flush(batch);
|
||||
|
||||
batch->flags |= flags;
|
||||
}
|
||||
|
||||
/* Here are the crusty old macros, to be removed:
|
||||
*/
|
||||
#define BATCH_LOCALS
|
||||
|
||||
#define BEGIN_BATCH(n, flags) do { \
|
||||
assert(!intel->prim.flush); \
|
||||
intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \
|
||||
} while (0)
|
||||
|
||||
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
|
||||
|
||||
#define OUT_RELOC(buf,flags,delta) do { \
|
||||
assert((delta) >= 0); \
|
||||
intel_batchbuffer_emit_reloc(intel->batch, buf, flags, delta); \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_BATCH() do { } while(0)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
444
src/mesa/drivers/dri/i915/intel_blit.c
Normal file
444
src/mesa/drivers/dri/i915/intel_blit.c
Normal file
@@ -0,0 +1,444 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "context.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_reg.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
|
||||
/**
|
||||
* Copy the back color buffer to the front color buffer.
|
||||
* Used for SwapBuffers().
|
||||
*/
|
||||
void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct intel_context *intel;
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
assert(dPriv);
|
||||
|
||||
/* We need a rendering context in order to issue the blit cmd.
|
||||
* Use the current context.
|
||||
* XXX need to fix this someday.
|
||||
*/
|
||||
if (!ctx) {
|
||||
_mesa_problem(NULL, "No current context in intelCopyBuffer()");
|
||||
return;
|
||||
}
|
||||
intel = (struct intel_context *) ctx;
|
||||
|
||||
/* FIXME: Temporary fix for fence ageing.
|
||||
*
|
||||
*/
|
||||
|
||||
if (!intel->last_swap_fence_retired) {
|
||||
bmFinishFence(intel->bm, intel->last_swap_fence);
|
||||
}
|
||||
|
||||
/* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
|
||||
* should work regardless.
|
||||
*/
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable &&
|
||||
intel->driDrawable->numClipRects)
|
||||
{
|
||||
const intelScreenPrivate *intelScreen = intel->intelScreen;
|
||||
struct gl_framebuffer *fb
|
||||
= (struct gl_framebuffer *) dPriv->driverPrivate;
|
||||
const struct intel_region *frontRegion
|
||||
= intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
|
||||
const struct intel_region *backRegion
|
||||
= intel_get_rb_region(fb, BUFFER_BACK_LEFT);
|
||||
const int nbox = dPriv->numClipRects;
|
||||
const drm_clip_rect_t *pbox = dPriv->pClipRects;
|
||||
const int pitch = frontRegion->pitch;
|
||||
const int cpp = frontRegion->cpp;
|
||||
int BR13, CMD;
|
||||
int i;
|
||||
|
||||
ASSERT(fb);
|
||||
ASSERT(fb->Name == 0); /* Not a user-created FBO */
|
||||
ASSERT(frontRegion);
|
||||
ASSERT(backRegion);
|
||||
ASSERT(frontRegion->pitch == backRegion->pitch);
|
||||
ASSERT(frontRegion->cpp == backRegion->cpp);
|
||||
|
||||
if (cpp == 2) {
|
||||
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24);
|
||||
CMD = XY_SRC_COPY_BLT_CMD;
|
||||
}
|
||||
else {
|
||||
BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25);
|
||||
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
|
||||
XY_SRC_COPY_BLT_WRITE_RGB);
|
||||
}
|
||||
|
||||
for (i = 0 ; i < nbox; i++, pbox++)
|
||||
{
|
||||
if (pbox->x1 > pbox->x2 ||
|
||||
pbox->y1 > pbox->y2 ||
|
||||
pbox->x2 > intelScreen->width ||
|
||||
pbox->y2 > intelScreen->height)
|
||||
continue;
|
||||
|
||||
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
|
||||
OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
|
||||
|
||||
if (intel->sarea->pf_current_page == 0)
|
||||
OUT_RELOC( frontRegion->buffer, DRM_MM_TT|DRM_MM_WRITE, 0 );
|
||||
else
|
||||
OUT_RELOC( backRegion->buffer, DRM_MM_TT|DRM_MM_WRITE, 0 );
|
||||
OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
|
||||
OUT_BATCH( BR13 & 0xffff );
|
||||
|
||||
if (intel->sarea->pf_current_page == 0)
|
||||
OUT_RELOC( backRegion->buffer, DRM_MM_TT|DRM_MM_READ, 0 );
|
||||
else
|
||||
OUT_RELOC( frontRegion->buffer, DRM_MM_TT|DRM_MM_READ, 0 );
|
||||
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
intel->last_swap_fence = intel_batchbuffer_flush( intel->batch );
|
||||
intel->last_swap_fence_retired = GL_FALSE;
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void intelEmitFillBlit( struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_buffer,
|
||||
GLuint dst_offset,
|
||||
GLshort x, GLshort y,
|
||||
GLshort w, GLshort h,
|
||||
GLuint color )
|
||||
{
|
||||
GLuint BR13, CMD;
|
||||
BATCH_LOCALS;
|
||||
|
||||
dst_pitch *= cpp;
|
||||
|
||||
switch(cpp) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
|
||||
CMD = XY_COLOR_BLT_CMD;
|
||||
break;
|
||||
case 4:
|
||||
BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
|
||||
CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
|
||||
XY_COLOR_BLT_WRITE_RGB);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (y << 16) | x );
|
||||
OUT_BATCH( ((y+h) << 16) | (x+w) );
|
||||
OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset );
|
||||
OUT_BATCH( color );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
|
||||
/* Copy BitBlt
|
||||
*/
|
||||
void intelEmitCopyBlit( struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLshort src_pitch,
|
||||
GLuint src_buffer,
|
||||
GLuint src_offset,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_buffer,
|
||||
GLuint dst_offset,
|
||||
GLshort src_x, GLshort src_y,
|
||||
GLshort dst_x, GLshort dst_y,
|
||||
GLshort w, GLshort h )
|
||||
{
|
||||
GLuint CMD, BR13;
|
||||
int dst_y2 = dst_y + h;
|
||||
int dst_x2 = dst_x + w;
|
||||
BATCH_LOCALS;
|
||||
|
||||
|
||||
DBG("%s src:buf(%d)/%d+%d %d,%d dst:buf(%d)/%d+%d %d,%d sz:%dx%d\n",
|
||||
__FUNCTION__,
|
||||
src_buffer, src_pitch, src_offset, src_x, src_y,
|
||||
dst_buffer, dst_pitch, dst_offset, dst_x, dst_y,
|
||||
w,h);
|
||||
|
||||
src_pitch *= cpp;
|
||||
dst_pitch *= cpp;
|
||||
|
||||
switch(cpp) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
BR13 = (((GLint)dst_pitch)&0xffff) | (0xCC << 16) | (1<<24);
|
||||
CMD = XY_SRC_COPY_BLT_CMD;
|
||||
break;
|
||||
case 4:
|
||||
BR13 = (((GLint)dst_pitch)&0xffff) | (0xCC << 16) | (1<<24) | (1<<25);
|
||||
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
|
||||
XY_SRC_COPY_BLT_WRITE_RGB);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (dst_y2 < dst_y ||
|
||||
dst_x2 < dst_x) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initial y values don't seem to work with negative pitches. If
|
||||
* we adjust the offsets manually (below), it seems to work fine.
|
||||
*
|
||||
* On the other hand, if we always adjust, the hardware doesn't
|
||||
* know which blit directions to use, so overlapping copypixels get
|
||||
* the wrong result.
|
||||
*/
|
||||
if ( dst_pitch > 0 &&
|
||||
src_pitch > 0) {
|
||||
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (dst_y << 16) | dst_x );
|
||||
OUT_BATCH( (dst_y2 << 16) | dst_x2 );
|
||||
OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset );
|
||||
OUT_BATCH( (src_y << 16) | src_x );
|
||||
OUT_BATCH( ((GLint)src_pitch&0xffff) );
|
||||
OUT_RELOC( src_buffer, DRM_MM_TT|DRM_MM_READ, src_offset );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
else {
|
||||
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (0 << 16) | dst_x );
|
||||
OUT_BATCH( (h << 16) | dst_x2 );
|
||||
OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset + dst_y * dst_pitch );
|
||||
OUT_BATCH( (0 << 16) | src_x );
|
||||
OUT_BATCH( ((GLint)src_pitch&0xffff) );
|
||||
OUT_RELOC( src_buffer, DRM_MM_TT|DRM_MM_READ, src_offset + src_y * src_pitch );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use blitting to clear the renderbuffers named by 'flags'.
|
||||
* Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferMask field
|
||||
* since that might include software renderbuffers or renderbuffers
|
||||
* which we're clearing with triangles.
|
||||
* \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear
|
||||
*/
|
||||
void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch)
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
GLuint clear_depth;
|
||||
GLbitfield skipBuffers = 0;
|
||||
BATCH_LOCALS;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_DRI)
|
||||
_mesa_printf("%s %x\n", __FUNCTION__, mask);
|
||||
|
||||
/*
|
||||
* Compute values for clearing the buffers.
|
||||
*/
|
||||
clear_depth = 0;
|
||||
if (mask & BUFFER_BIT_DEPTH) {
|
||||
clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear);
|
||||
}
|
||||
if (mask & BUFFER_BIT_STENCIL) {
|
||||
clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
|
||||
}
|
||||
|
||||
/* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in
|
||||
* the loop below.
|
||||
*/
|
||||
if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) {
|
||||
skipBuffers = BUFFER_BIT_STENCIL;
|
||||
}
|
||||
|
||||
/* XXX Move this flush/lock into the following conditional? */
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->numClipRects)
|
||||
{
|
||||
drm_clip_rect_t clear;
|
||||
int i;
|
||||
|
||||
if (intel->ctx.DrawBuffer->Name == 0) {
|
||||
/* clearing a window */
|
||||
|
||||
/* flip top to bottom */
|
||||
clear.x1 = cx + intel->drawX;
|
||||
clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
|
||||
clear.x2 = clear.x1 + cw;
|
||||
clear.y2 = clear.y1 + ch;
|
||||
|
||||
/* adjust for page flipping */
|
||||
if ( intel->sarea->pf_current_page == 1 ) {
|
||||
const GLuint tmp = mask;
|
||||
mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
|
||||
if ( tmp & BUFFER_BIT_FRONT_LEFT ) mask |= BUFFER_BIT_BACK_LEFT;
|
||||
if ( tmp & BUFFER_BIT_BACK_LEFT ) mask |= BUFFER_BIT_FRONT_LEFT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* clearing FBO */
|
||||
ASSERT(intel->numClipRects == 1);
|
||||
ASSERT(intel->pClipRects == &intel->fboRect);
|
||||
clear.x1 = cx;
|
||||
clear.y1 = intel->ctx.DrawBuffer->Height - cy - ch;
|
||||
clear.x2 = clear.y1 + cw;
|
||||
clear.y2 = clear.y1 + ch;
|
||||
/* no change to mask */
|
||||
}
|
||||
|
||||
for (i = 0 ; i < intel->numClipRects ; i++)
|
||||
{
|
||||
const drm_clip_rect_t *box = &intel->pClipRects[i];
|
||||
drm_clip_rect_t b;
|
||||
GLuint buf;
|
||||
GLuint clearMask = mask; /* use copy, since we modify it below */
|
||||
|
||||
if (!all) {
|
||||
intel_intersect_cliprects(&b, &clear, box);
|
||||
} else {
|
||||
b = *box;
|
||||
}
|
||||
|
||||
if (0)
|
||||
_mesa_printf("clear %d,%d..%d,%d, mask %x\n",
|
||||
b.x1, b.y1,
|
||||
b.x2, b.y2,
|
||||
mask);
|
||||
|
||||
/* Loop over all renderbuffers */
|
||||
for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) {
|
||||
const GLbitfield bufBit = 1 << buf;
|
||||
if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
|
||||
/* OK, clear this renderbuffer */
|
||||
const struct intel_renderbuffer *irb
|
||||
= intel_renderbuffer(ctx->DrawBuffer->
|
||||
Attachment[buf].Renderbuffer);
|
||||
GLuint clearVal;
|
||||
GLint pitch, cpp;
|
||||
GLuint BR13, CMD;
|
||||
|
||||
ASSERT(irb);
|
||||
ASSERT(irb->region);
|
||||
|
||||
pitch = irb->region->pitch;
|
||||
cpp = irb->region->cpp;
|
||||
|
||||
/* Setup the blit command */
|
||||
if (cpp == 4) {
|
||||
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25);
|
||||
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
|
||||
CMD = XY_COLOR_BLT_CMD;
|
||||
if (clearMask & BUFFER_BIT_DEPTH)
|
||||
CMD |= XY_COLOR_BLT_WRITE_RGB;
|
||||
if (clearMask & BUFFER_BIT_STENCIL)
|
||||
CMD |= XY_COLOR_BLT_WRITE_ALPHA;
|
||||
}
|
||||
else {
|
||||
/* clearing RGBA */
|
||||
CMD = (XY_COLOR_BLT_CMD |
|
||||
XY_COLOR_BLT_WRITE_ALPHA |
|
||||
XY_COLOR_BLT_WRITE_RGB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(cpp == 2 || cpp == 0);
|
||||
BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24);
|
||||
CMD = XY_COLOR_BLT_CMD;
|
||||
}
|
||||
|
||||
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) {
|
||||
clearVal = clear_depth;
|
||||
}
|
||||
else {
|
||||
clearVal = (cpp == 4)
|
||||
? intel->ClearColor8888 : intel->ClearColor565;
|
||||
}
|
||||
/*
|
||||
_mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
|
||||
buf, irb->Base.Name);
|
||||
*/
|
||||
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
|
||||
OUT_BATCH( CMD );
|
||||
OUT_BATCH( BR13 );
|
||||
OUT_BATCH( (b.y1 << 16) | b.x1 );
|
||||
OUT_BATCH( (b.y2 << 16) | b.x2 );
|
||||
OUT_RELOC( irb->region->buffer, DRM_MM_TT|DRM_MM_WRITE,
|
||||
irb->region->draw_offset );
|
||||
OUT_BATCH( clearVal );
|
||||
ADVANCE_BATCH();
|
||||
clearMask &= ~bufBit; /* turn off bit, for faster loop exit */
|
||||
}
|
||||
}
|
||||
}
|
||||
intel_batchbuffer_flush( intel->batch );
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE( intel );
|
||||
}
|
||||
|
||||
|
||||
60
src/mesa/drivers/dri/i915/intel_blit.h
Normal file
60
src/mesa/drivers/dri/i915/intel_blit.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_BLIT_H
|
||||
#define INTEL_BLIT_H
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
|
||||
extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv );
|
||||
extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all,
|
||||
GLint cx1, GLint cy1, GLint cw, GLint ch);
|
||||
|
||||
extern void intelEmitCopyBlit( struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLshort src_pitch,
|
||||
GLuint src_buffer,
|
||||
GLuint src_offset,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_buffer,
|
||||
GLuint dst_offset,
|
||||
GLshort srcx, GLshort srcy,
|
||||
GLshort dstx, GLshort dsty,
|
||||
GLshort w, GLshort h );
|
||||
|
||||
extern void intelEmitFillBlit( struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLshort dst_pitch,
|
||||
GLuint dst_buffer,
|
||||
GLuint dst_offset,
|
||||
GLshort x, GLshort y,
|
||||
GLshort w, GLshort h,
|
||||
GLuint color );
|
||||
|
||||
|
||||
#endif
|
||||
201
src/mesa/drivers/dri/i915/intel_buffer_objects.c
Normal file
201
src/mesa/drivers/dri/i915/intel_buffer_objects.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "imports.h"
|
||||
#include "mtypes.h"
|
||||
#include "bufferobj.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_buffer_objects.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
|
||||
/**
|
||||
* There is some duplication between mesa's bufferobjects and our
|
||||
* bufmgr buffers. Both have an integer handle and a hashtable to
|
||||
* lookup an opaque structure. It would be nice if the handles and
|
||||
* internal structure where somehow shared.
|
||||
*/
|
||||
static struct gl_buffer_object *intel_bufferobj_alloc( GLcontext *ctx,
|
||||
GLuint name,
|
||||
GLenum target )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_buffer_object *obj = MALLOC_STRUCT(intel_buffer_object);
|
||||
|
||||
_mesa_initialize_buffer_object(&obj->Base, name, target);
|
||||
|
||||
/* XXX: We generate our own handle, which is different to 'name' above.
|
||||
*/
|
||||
bmGenBuffers(intel->bm, 1, &obj->buffer, 0);
|
||||
|
||||
return &obj->Base;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deallocate/free a vertex/pixel buffer object.
|
||||
* Called via glDeleteBuffersARB().
|
||||
*/
|
||||
static void intel_bufferobj_free( GLcontext *ctx,
|
||||
struct gl_buffer_object *obj )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
assert(intel_obj);
|
||||
|
||||
if (intel_obj->buffer)
|
||||
bmDeleteBuffers( intel->bm, 1, &intel_obj->buffer );
|
||||
|
||||
_mesa_free(intel_obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allocate space for and store data in a buffer object. Any data that was
|
||||
* previously stored in the buffer object is lost. If data is NULL,
|
||||
* memory will be allocated, but no copy will occur.
|
||||
* Called via glBufferDataARB().
|
||||
*/
|
||||
static void intel_bufferobj_data( GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLsizeiptrARB size,
|
||||
const GLvoid *data,
|
||||
GLenum usage,
|
||||
struct gl_buffer_object *obj )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
/* XXX: do something useful with 'usage' (eg. populate flags
|
||||
* argument below)
|
||||
*/
|
||||
assert(intel_obj);
|
||||
|
||||
obj->Size = size;
|
||||
obj->Usage = usage;
|
||||
|
||||
bmBufferData(intel->bm, intel_obj->buffer, size, data, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace data in a subrange of buffer object. If the data range
|
||||
* specified by size + offset extends beyond the end of the buffer or
|
||||
* if data is NULL, no copy is performed.
|
||||
* Called via glBufferSubDataARB().
|
||||
*/
|
||||
static void intel_bufferobj_subdata( GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLintptrARB offset,
|
||||
GLsizeiptrARB size,
|
||||
const GLvoid * data,
|
||||
struct gl_buffer_object * obj )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
assert(intel_obj);
|
||||
bmBufferSubData(intel->bm, intel_obj->buffer, offset, size, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via glGetBufferSubDataARB().
|
||||
*/
|
||||
static void intel_bufferobj_get_subdata( GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLintptrARB offset,
|
||||
GLsizeiptrARB size,
|
||||
GLvoid * data,
|
||||
struct gl_buffer_object * obj )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
assert(intel_obj);
|
||||
bmBufferGetSubData(intel->bm, intel_obj->buffer, offset, size, data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called via glMapBufferARB().
|
||||
*/
|
||||
static void *intel_bufferobj_map( GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLenum access,
|
||||
struct gl_buffer_object *obj )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
/* XXX: Translate access to flags arg below:
|
||||
*/
|
||||
assert(intel_obj);
|
||||
obj->Pointer = bmMapBuffer(intel->bm, intel_obj->buffer, 0);
|
||||
return obj->Pointer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via glMapBufferARB().
|
||||
*/
|
||||
static GLboolean intel_bufferobj_unmap( GLcontext *ctx,
|
||||
GLenum target,
|
||||
struct gl_buffer_object *obj )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
assert(intel_obj);
|
||||
assert(obj->Pointer);
|
||||
bmUnmapBuffer(intel->bm, intel_obj->buffer);
|
||||
obj->Pointer = NULL;
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
GLuint intel_bufferobj_buffer( const struct intel_buffer_object *intel_obj )
|
||||
{
|
||||
return intel_obj->buffer;
|
||||
}
|
||||
|
||||
void intel_bufferobj_init( struct intel_context *intel )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
|
||||
ctx->Driver.NewBufferObject = intel_bufferobj_alloc;
|
||||
ctx->Driver.DeleteBuffer = intel_bufferobj_free;
|
||||
ctx->Driver.BufferData = intel_bufferobj_data;
|
||||
ctx->Driver.BufferSubData = intel_bufferobj_subdata;
|
||||
ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata;
|
||||
ctx->Driver.MapBuffer = intel_bufferobj_map;
|
||||
ctx->Driver.UnmapBuffer = intel_bufferobj_unmap;
|
||||
}
|
||||
70
src/mesa/drivers/dri/i915/intel_buffer_objects.h
Normal file
70
src/mesa/drivers/dri/i915/intel_buffer_objects.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_BUFFEROBJ_H
|
||||
#define INTEL_BUFFEROBJ_H
|
||||
|
||||
#include "mtypes.h"
|
||||
|
||||
struct intel_context;
|
||||
struct gl_buffer_object;
|
||||
|
||||
|
||||
/**
|
||||
* Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object.
|
||||
*/
|
||||
struct intel_buffer_object {
|
||||
struct gl_buffer_object Base;
|
||||
GLuint buffer; /* the low-level buffer manager's buffer handle */
|
||||
};
|
||||
|
||||
|
||||
/* Get the bm buffer associated with a GL bufferobject:
|
||||
*/
|
||||
GLuint intel_bufferobj_buffer( const struct intel_buffer_object *obj );
|
||||
|
||||
/* Hook the bufferobject implementation into mesa:
|
||||
*/
|
||||
void intel_bufferobj_init( struct intel_context *intel );
|
||||
|
||||
|
||||
|
||||
/* Are the obj->Name tests necessary? Unfortunately yes, mesa
|
||||
* allocates a couple of gl_buffer_object structs statically, and
|
||||
* the Name == 0 test is the only way to identify them and avoid
|
||||
* casting them erroneously to our structs.
|
||||
*/
|
||||
static INLINE struct intel_buffer_object *
|
||||
intel_buffer_object( struct gl_buffer_object *obj )
|
||||
{
|
||||
if (obj->Name)
|
||||
return (struct intel_buffer_object *)obj;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
730
src/mesa/drivers/dri/i915/intel_buffers.c
Normal file
730
src/mesa/drivers/dri/i915/intel_buffers.c
Normal file
@@ -0,0 +1,730 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_depthstencil.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_tris.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "context.h"
|
||||
#include "framebuffer.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
|
||||
/**
|
||||
* XXX move this into a new dri/common/cliprects.c file.
|
||||
*/
|
||||
GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst,
|
||||
const drm_clip_rect_t *a,
|
||||
const drm_clip_rect_t *b )
|
||||
{
|
||||
GLint bx = b->x1;
|
||||
GLint by = b->y1;
|
||||
GLint bw = b->x2 - bx;
|
||||
GLint bh = b->y2 - by;
|
||||
|
||||
if (bx < a->x1) bw -= a->x1 - bx, bx = a->x1;
|
||||
if (by < a->y1) bh -= a->y1 - by, by = a->y1;
|
||||
if (bx + bw > a->x2) bw = a->x2 - bx;
|
||||
if (by + bh > a->y2) bh = a->y2 - by;
|
||||
if (bw <= 0) return GL_FALSE;
|
||||
if (bh <= 0) return GL_FALSE;
|
||||
|
||||
dst->x1 = bx;
|
||||
dst->y1 = by;
|
||||
dst->x2 = bx + bw;
|
||||
dst->y2 = by + bh;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pointer to current color drawing region, or NULL.
|
||||
*/
|
||||
struct intel_region *intel_drawbuf_region( struct intel_context *intel )
|
||||
{
|
||||
struct intel_renderbuffer *irbColor =
|
||||
intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]);
|
||||
if (irbColor)
|
||||
return irbColor->region;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pointer to current color reading region, or NULL.
|
||||
*/
|
||||
struct intel_region *intel_readbuf_region( struct intel_context *intel )
|
||||
{
|
||||
struct intel_renderbuffer *irb
|
||||
= intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
|
||||
if (irb)
|
||||
return irb->region;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void intelBufferSize(GLframebuffer *buffer,
|
||||
GLuint *width,
|
||||
GLuint *height)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
/* Need to lock to make sure the driDrawable is uptodate. This
|
||||
* information is used to resize Mesa's software buffers, so it has
|
||||
* to be correct.
|
||||
*/
|
||||
/* XXX This isn't 100% correct, the given buffer might not be
|
||||
* bound to the current context!
|
||||
*/
|
||||
LOCK_HARDWARE(intel);
|
||||
if (intel->driDrawable) {
|
||||
*width = intel->driDrawable->w;
|
||||
*height = intel->driDrawable->h;
|
||||
}
|
||||
else {
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
}
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Update the following fields for rendering to a user-created FBO:
|
||||
* intel->numClipRects
|
||||
* intel->pClipRects
|
||||
* intel->drawX
|
||||
* intel->drawY
|
||||
*/
|
||||
static void intelSetRenderbufferClipRects( struct intel_context *intel )
|
||||
{
|
||||
assert(intel->ctx.DrawBuffer->Width > 0);
|
||||
assert(intel->ctx.DrawBuffer->Height > 0);
|
||||
intel->fboRect.x1 = 0;
|
||||
intel->fboRect.y1 = 0;
|
||||
intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
|
||||
intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
|
||||
intel->numClipRects = 1;
|
||||
intel->pClipRects = &intel->fboRect;
|
||||
intel->drawX = 0;
|
||||
intel->drawY = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As above, but for rendering to front buffer of a window.
|
||||
* \sa intelSetRenderbufferClipRects
|
||||
*/
|
||||
static void intelSetFrontClipRects( struct intel_context *intel )
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
|
||||
if (!dPriv) return;
|
||||
|
||||
intel->numClipRects = dPriv->numClipRects;
|
||||
intel->pClipRects = dPriv->pClipRects;
|
||||
intel->drawX = dPriv->x;
|
||||
intel->drawY = dPriv->y;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As above, but for rendering to back buffer of a window.
|
||||
*/
|
||||
static void intelSetBackClipRects( struct intel_context *intel )
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
|
||||
if (!dPriv) return;
|
||||
|
||||
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
|
||||
/* use the front clip rects */
|
||||
intel->numClipRects = dPriv->numClipRects;
|
||||
intel->pClipRects = dPriv->pClipRects;
|
||||
intel->drawX = dPriv->x;
|
||||
intel->drawY = dPriv->y;
|
||||
} else {
|
||||
/* use the back clip rects */
|
||||
intel->numClipRects = dPriv->numBackClipRects;
|
||||
intel->pClipRects = dPriv->pBackClipRects;
|
||||
intel->drawX = dPriv->backX;
|
||||
intel->drawY = dPriv->backY;
|
||||
|
||||
if (dPriv->numBackClipRects == 1 &&
|
||||
dPriv->x == dPriv->backX &&
|
||||
dPriv->y == dPriv->backY) {
|
||||
|
||||
/* Repeat the calculation of the back cliprect dimensions here
|
||||
* as early versions of dri.a in the Xserver are incorrect. Try
|
||||
* very hard not to restrict future versions of dri.a which
|
||||
* might eg. allocate truly private back buffers.
|
||||
*/
|
||||
int x1, y1;
|
||||
int x2, y2;
|
||||
|
||||
x1 = dPriv->x;
|
||||
y1 = dPriv->y;
|
||||
x2 = dPriv->x + dPriv->w;
|
||||
y2 = dPriv->y + dPriv->h;
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
|
||||
if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
|
||||
|
||||
if (x1 == dPriv->pBackClipRects[0].x1 &&
|
||||
y1 == dPriv->pBackClipRects[0].y1) {
|
||||
|
||||
dPriv->pBackClipRects[0].x2 = x2;
|
||||
dPriv->pBackClipRects[0].y2 = y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This will be called whenever the currently bound window is moved/resized.
|
||||
* XXX: actually, it seems to NOT be called when the window is only moved (BP).
|
||||
*/
|
||||
void intelWindowMoved( struct intel_context *intel )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
|
||||
if (!intel->ctx.DrawBuffer) {
|
||||
/* when would this happen? -BP */
|
||||
intelSetFrontClipRects( intel );
|
||||
}
|
||||
else if (intel->ctx.DrawBuffer->Name != 0) {
|
||||
/* drawing to user-created FBO - do nothing */
|
||||
/* Cliprects would be set from intelDrawBuffer() */
|
||||
}
|
||||
else {
|
||||
/* drawing to a window */
|
||||
switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
|
||||
case BUFFER_BIT_FRONT_LEFT:
|
||||
intelSetFrontClipRects( intel );
|
||||
break;
|
||||
case BUFFER_BIT_BACK_LEFT:
|
||||
intelSetBackClipRects( intel );
|
||||
break;
|
||||
default:
|
||||
/* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
|
||||
intelSetFrontClipRects( intel );
|
||||
}
|
||||
}
|
||||
|
||||
/* this update Mesa's notion of window size */
|
||||
if (ctx->WinSysDrawBuffer) {
|
||||
_mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer,
|
||||
intel->driDrawable->w, intel->driDrawable->h);
|
||||
}
|
||||
|
||||
/* Update hardware scissor */
|
||||
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
|
||||
ctx->Scissor.Width, ctx->Scissor.Height );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* A true meta version of this would be very simple and additionally
|
||||
* machine independent. Maybe we'll get there one day.
|
||||
*/
|
||||
static void intelClearWithTris(struct intel_context *intel,
|
||||
GLbitfield mask,
|
||||
GLboolean all,
|
||||
GLint cx, GLint cy,
|
||||
GLint cw, GLint ch)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
drm_clip_rect_t clear;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_DRI)
|
||||
_mesa_printf("%s 0x%x\n", __FUNCTION__, mask);
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
/* XXX FBO: was: intel->driDrawable->numClipRects */
|
||||
if (intel->numClipRects) {
|
||||
GLuint buf;
|
||||
|
||||
intel->vtbl.install_meta_state(intel);
|
||||
|
||||
/* note: regardless of 'all', cx, cy, cw, ch are correct */
|
||||
clear.x1 = cx;
|
||||
clear.y1 = cy;
|
||||
clear.x2 = cx + cw;
|
||||
clear.y2 = cy + ch;
|
||||
|
||||
/* Back and stencil cliprects are the same. Try and do both
|
||||
* buffers at once:
|
||||
*/
|
||||
if (mask & (BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH)) {
|
||||
struct intel_region *backRegion
|
||||
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT);
|
||||
struct intel_region *depthRegion
|
||||
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH);
|
||||
const GLuint clearColor = (backRegion && backRegion->cpp == 4)
|
||||
? intel->ClearColor8888 : intel->ClearColor565;
|
||||
|
||||
intel->vtbl.meta_draw_region(intel, backRegion, depthRegion );
|
||||
|
||||
if (mask & BUFFER_BIT_BACK_LEFT)
|
||||
intel->vtbl.meta_color_mask(intel, GL_TRUE );
|
||||
else
|
||||
intel->vtbl.meta_color_mask(intel, GL_FALSE );
|
||||
|
||||
if (mask & BUFFER_BIT_STENCIL)
|
||||
intel->vtbl.meta_stencil_replace( intel,
|
||||
intel->ctx.Stencil.WriteMask[0],
|
||||
intel->ctx.Stencil.Clear);
|
||||
else
|
||||
intel->vtbl.meta_no_stencil_write(intel);
|
||||
|
||||
if (mask & BUFFER_BIT_DEPTH)
|
||||
intel->vtbl.meta_depth_replace( intel );
|
||||
else
|
||||
intel->vtbl.meta_no_depth_write(intel);
|
||||
|
||||
/* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
|
||||
* drawing origin may not be correctly emitted.
|
||||
*/
|
||||
intel_meta_draw_quad(intel,
|
||||
clear.x1, clear.x2,
|
||||
clear.y1, clear.y2,
|
||||
intel->ctx.Depth.Clear,
|
||||
clearColor,
|
||||
0, 0, 0, 0); /* texcoords */
|
||||
|
||||
mask &= ~(BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH);
|
||||
}
|
||||
|
||||
/* clear the remaining (color) renderbuffers */
|
||||
for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
|
||||
const GLuint bufBit = 1 << buf;
|
||||
if (mask & bufBit) {
|
||||
struct intel_renderbuffer *irbColor =
|
||||
intel_renderbuffer(ctx->DrawBuffer->
|
||||
Attachment[buf].Renderbuffer);
|
||||
GLuint color = (irbColor->region->cpp == 4)
|
||||
? intel->ClearColor8888 : intel->ClearColor565;
|
||||
|
||||
ASSERT(irbColor);
|
||||
|
||||
intel->vtbl.meta_no_depth_write(intel);
|
||||
intel->vtbl.meta_no_stencil_write(intel);
|
||||
intel->vtbl.meta_color_mask(intel, GL_TRUE );
|
||||
intel->vtbl.meta_draw_region(intel, irbColor->region, NULL);
|
||||
|
||||
/* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
|
||||
* drawing origin may not be correctly emitted.
|
||||
*/
|
||||
intel_meta_draw_quad(intel,
|
||||
clear.x1, clear.x2,
|
||||
clear.y1, clear.y2,
|
||||
0, /* depth clear val */
|
||||
color,
|
||||
0, 0, 0, 0); /* texcoords */
|
||||
|
||||
mask &= ~bufBit;
|
||||
}
|
||||
}
|
||||
|
||||
intel->vtbl.leave_meta_state( intel );
|
||||
intel_batchbuffer_flush( intel->batch );
|
||||
}
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called by ctx->Driver.Clear.
|
||||
*/
|
||||
static void intelClear(GLcontext *ctx,
|
||||
GLbitfield mask,
|
||||
GLboolean all,
|
||||
GLint cx, GLint cy,
|
||||
GLint cw, GLint ch)
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
|
||||
GLbitfield tri_mask = 0;
|
||||
GLbitfield blit_mask = 0;
|
||||
GLbitfield swrast_mask = 0;
|
||||
GLuint i;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
/* HW color buffers (front, back, aux, generic FBO, etc) */
|
||||
if (colorMask == ~0) {
|
||||
/* clear all R,G,B,A */
|
||||
/* XXX FBO: need to check if colorbuffers are software RBOs! */
|
||||
blit_mask |= (mask & BUFFER_BITS_COLOR);
|
||||
}
|
||||
else {
|
||||
/* glColorMask in effect */
|
||||
tri_mask |= (mask & BUFFER_BITS_COLOR);
|
||||
}
|
||||
|
||||
/* HW stencil */
|
||||
if (mask & BUFFER_BIT_STENCIL) {
|
||||
const struct intel_region *stencilRegion
|
||||
= intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL);
|
||||
if (stencilRegion) {
|
||||
/* have hw stencil */
|
||||
if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
|
||||
/* not clearing all stencil bits, so use triangle clearing */
|
||||
tri_mask |= BUFFER_BIT_STENCIL;
|
||||
}
|
||||
else {
|
||||
/* clearing all stencil bits, use blitting */
|
||||
blit_mask |= BUFFER_BIT_STENCIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* HW depth */
|
||||
if (mask & BUFFER_BIT_DEPTH) {
|
||||
/* clear depth with whatever method is used for stencil (see above) */
|
||||
if (tri_mask & BUFFER_BIT_STENCIL)
|
||||
tri_mask |= BUFFER_BIT_DEPTH;
|
||||
else
|
||||
blit_mask |= BUFFER_BIT_DEPTH;
|
||||
}
|
||||
|
||||
/* SW fallback clearing */
|
||||
swrast_mask = mask & ~tri_mask & ~blit_mask;
|
||||
|
||||
for (i = 0; i < BUFFER_COUNT; i++) {
|
||||
GLuint bufBit = 1 << i;
|
||||
if ((blit_mask | tri_mask) & bufBit) {
|
||||
if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) {
|
||||
blit_mask &= ~bufBit;
|
||||
tri_mask &= ~bufBit;
|
||||
swrast_mask |= bufBit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
intelFlush( ctx ); /* XXX intelClearWithBlit also does this */
|
||||
|
||||
if (blit_mask)
|
||||
intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
|
||||
|
||||
if (tri_mask)
|
||||
intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch);
|
||||
|
||||
if (swrast_mask)
|
||||
_swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Flip the front & back buffers
|
||||
*/
|
||||
static void intelPageFlip( const __DRIdrawablePrivate *dPriv )
|
||||
{
|
||||
#if 0
|
||||
struct intel_context *intel;
|
||||
int tmp, ret;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_IOCTL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
assert(dPriv);
|
||||
assert(dPriv->driContextPriv);
|
||||
assert(dPriv->driContextPriv->driverPrivate);
|
||||
|
||||
intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (dPriv->pClipRects) {
|
||||
*(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
|
||||
intel->sarea->nbox = 1;
|
||||
}
|
||||
|
||||
ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
|
||||
if (ret) {
|
||||
fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
|
||||
UNLOCK_HARDWARE( intel );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tmp = intel->sarea->last_enqueue;
|
||||
intelRefillBatchLocked( intel );
|
||||
UNLOCK_HARDWARE( intel );
|
||||
|
||||
|
||||
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
|
||||
{
|
||||
if (dPriv->driverPrivate) {
|
||||
const struct gl_framebuffer *fb
|
||||
= (struct gl_framebuffer *) dPriv->driverPrivate;
|
||||
if (fb->Visual.doubleBufferMode) {
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
if (ctx && ctx->DrawBuffer == fb) {
|
||||
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering */
|
||||
}
|
||||
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
|
||||
intelPageFlip( dPriv );
|
||||
} else {
|
||||
intelCopyBuffer( dPriv );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
_mesa_problem(NULL,
|
||||
"dPriv has no gl_framebuffer pointer in intelSwapBuffers");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the hardware state for drawing into a window or framebuffer object.
|
||||
*
|
||||
* Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other
|
||||
* places within the driver.
|
||||
*
|
||||
* Basically, this needs to be called any time the current framebuffer
|
||||
* changes, the renderbuffers change, or we need to draw into different
|
||||
* color buffers.
|
||||
*/
|
||||
void
|
||||
intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_region *colorRegion, *depthRegion = NULL;
|
||||
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
|
||||
int front = 0; /* drawing to front color buffer? */
|
||||
|
||||
if (!fb) {
|
||||
/* this can happen during the initial context initialization */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Do this here, note core Mesa, since this function is called from
|
||||
* many places within the driver.
|
||||
*/
|
||||
if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
|
||||
/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */
|
||||
_mesa_update_framebuffer(ctx);
|
||||
/* this updates the DrawBuffer's Width/Height if it's a FBO */
|
||||
_mesa_update_draw_buffer_bounds(ctx);
|
||||
}
|
||||
|
||||
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
/* this may occur when we're called by glBindFrameBuffer() during
|
||||
* the process of someone setting up renderbuffers, etc.
|
||||
*/
|
||||
_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fb->Name)
|
||||
intel_validate_paired_depth_stencil(ctx, fb);
|
||||
|
||||
/*
|
||||
* How many color buffers are we drawing into?
|
||||
*/
|
||||
if (fb->_NumColorDrawBuffers[0] != 1
|
||||
#if 0
|
||||
/* XXX FBO temporary - always use software rendering */
|
||||
|| 1
|
||||
#endif
|
||||
) {
|
||||
/* writing to 0 or 2 or 4 color buffers */
|
||||
/*_mesa_debug(ctx, "Software rendering\n");*/
|
||||
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
|
||||
front = 1; /* might not have back color buffer */
|
||||
}
|
||||
else {
|
||||
/* draw to exactly one color buffer */
|
||||
/*_mesa_debug(ctx, "Hardware rendering\n");*/
|
||||
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
|
||||
if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
|
||||
front = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the intel_renderbuffer for the colorbuffer we're drawing into.
|
||||
* And set up cliprects.
|
||||
*/
|
||||
if (fb->Name == 0) {
|
||||
/* drawing to window system buffer */
|
||||
if (intel->sarea->pf_current_page == 1 ) {
|
||||
/* page flipped back/front */
|
||||
front ^= 1;
|
||||
}
|
||||
if (front) {
|
||||
intelSetFrontClipRects( intel );
|
||||
colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
|
||||
}
|
||||
else {
|
||||
intelSetBackClipRects( intel );
|
||||
colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* drawing to user-created FBO */
|
||||
struct intel_renderbuffer *irb;
|
||||
intelSetRenderbufferClipRects(intel);
|
||||
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
|
||||
colorRegion = (irb && irb->region) ? irb->region : NULL;
|
||||
}
|
||||
|
||||
if (!colorRegion) {
|
||||
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
|
||||
}
|
||||
else {
|
||||
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
|
||||
}
|
||||
|
||||
/***
|
||||
*** Get depth buffer region and check if we need a software fallback.
|
||||
*** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
|
||||
***/
|
||||
if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
|
||||
irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
|
||||
if (irbDepth->region) {
|
||||
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
|
||||
depthRegion = irbDepth->region;
|
||||
}
|
||||
else {
|
||||
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
|
||||
depthRegion = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* not using depth buffer */
|
||||
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
|
||||
depthRegion = NULL;
|
||||
}
|
||||
|
||||
/***
|
||||
*** Stencil buffer
|
||||
*** This can only be hardware accelerated if we're using a
|
||||
*** combined DEPTH_STENCIL buffer (for now anyway).
|
||||
***/
|
||||
if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
|
||||
irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
|
||||
if (irbStencil && irbStencil->region) {
|
||||
ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
|
||||
/* need to re-compute stencil hw state */
|
||||
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
|
||||
if (!depthRegion)
|
||||
depthRegion = irbStencil->region;
|
||||
}
|
||||
else {
|
||||
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
|
||||
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
|
||||
/* need to re-compute stencil hw state */
|
||||
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** Release old regions, reference new regions
|
||||
**/
|
||||
#if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
|
||||
if (intel->draw_region != colorRegion) {
|
||||
intel_region_release(intel, &intel->draw_region);
|
||||
intel_region_reference(&intel->draw_region, colorRegion);
|
||||
}
|
||||
if (intel->depth_region != depthRegion) {
|
||||
intel_region_release(intel, &intel->depth_region);
|
||||
intel_region_reference(&intel->depth_region, depthRegion);
|
||||
}
|
||||
#endif
|
||||
|
||||
intel->vtbl.set_draw_region( intel, colorRegion, depthRegion );
|
||||
|
||||
/* update viewport since it depends on window size */
|
||||
ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
|
||||
ctx->Viewport.Width, ctx->Viewport.Height);
|
||||
|
||||
/* Update hardware scissor */
|
||||
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
|
||||
ctx->Scissor.Width, ctx->Scissor.Height );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intelDrawBuffer(GLcontext *ctx, GLenum mode)
|
||||
{
|
||||
intel_draw_buffer(ctx, ctx->DrawBuffer);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intelReadBuffer( GLcontext *ctx, GLenum mode )
|
||||
{
|
||||
if (ctx->ReadBuffer == ctx->DrawBuffer) {
|
||||
/* This will update FBO completeness status.
|
||||
* A framebuffer will be incomplete if the GL_READ_BUFFER setting
|
||||
* refers to a missing renderbuffer. Calling glReadBuffer can set
|
||||
* that straight and can make the drawing buffer complete.
|
||||
*/
|
||||
intel_draw_buffer(ctx, ctx->DrawBuffer);
|
||||
}
|
||||
/* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
|
||||
* reference ctx->ReadBuffer and do appropriate state checks.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void intelInitBufferFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
functions->Clear = intelClear;
|
||||
functions->GetBufferSize = intelBufferSize;
|
||||
functions->ResizeBuffers = _mesa_resize_framebuffer;
|
||||
functions->DrawBuffer = intelDrawBuffer;
|
||||
functions->ReadBuffer = intelReadBuffer;
|
||||
}
|
||||
58
src/mesa/drivers/dri/i915/intel_buffers.h
Normal file
58
src/mesa/drivers/dri/i915/intel_buffers.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_BUFFERS_H
|
||||
#define INTEL_BUFFERS_H
|
||||
|
||||
|
||||
struct intel_context;
|
||||
|
||||
|
||||
extern GLboolean
|
||||
intel_intersect_cliprects(drm_clip_rect_t *dest,
|
||||
const drm_clip_rect_t *a,
|
||||
const drm_clip_rect_t *b);
|
||||
|
||||
extern struct intel_region *
|
||||
intel_readbuf_region(struct intel_context *intel);
|
||||
|
||||
extern struct intel_region *
|
||||
intel_drawbuf_region(struct intel_context *intel);
|
||||
|
||||
extern void
|
||||
intelSwapBuffers( __DRIdrawablePrivate *dPriv);
|
||||
|
||||
extern void
|
||||
intelWindowMoved(struct intel_context *intel);
|
||||
|
||||
extern void
|
||||
intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb);
|
||||
|
||||
extern void
|
||||
intelInitBufferFuncs(struct dd_function_table *functions);
|
||||
|
||||
#endif /* INTEL_BUFFERS_H */
|
||||
453
src/mesa/drivers/dri/i915/intel_bufmgr.c
Normal file
453
src/mesa/drivers/dri/i915/intel_bufmgr.c
Normal file
@@ -0,0 +1,453 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO.
|
||||
* 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 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
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
|
||||
#include "hash.h"
|
||||
#include "simple_list.h"
|
||||
#include "mm.h"
|
||||
#include "imports.h"
|
||||
#include "glthread.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <drm.h>
|
||||
|
||||
struct _mesa_HashTable;
|
||||
|
||||
/* The buffer manager is really part of the gl_shared_state struct.
|
||||
* TODO: Organize for the bufmgr to be created/deleted with the shared
|
||||
* state and stored within the DriverData of that struct. Currently
|
||||
* there are no mesa callbacks for this.
|
||||
*/
|
||||
|
||||
#define BM_MAX 16
|
||||
static struct bufmgr
|
||||
{
|
||||
_glthread_Mutex mutex; /**< for thread safety */
|
||||
int driFd;
|
||||
int refcount;
|
||||
struct _mesa_HashTable *hash;
|
||||
|
||||
unsigned buf_nr; /* for generating ids */
|
||||
drmMMPool batchPool;
|
||||
drmFence initFence;
|
||||
} bufmgr_pool[BM_MAX];
|
||||
|
||||
static int nr_bms;
|
||||
|
||||
#define LOCK(bm) _glthread_LOCK_MUTEX(bm->mutex)
|
||||
#define UNLOCK(bm) _glthread_UNLOCK_MUTEX(bm->mutex)
|
||||
|
||||
static void
|
||||
bmError(int val, const char *file, const char *function, int line)
|
||||
{
|
||||
_mesa_printf("Fatal video memory manager error \"%s\".\n"
|
||||
"Check kernel logs or set the LIBGL_DEBUG\n"
|
||||
"environment variable to \"verbose\" for more info.\n"
|
||||
"Detected in file %s, line %d, function %s.\n",
|
||||
strerror(-val), file, line, function);
|
||||
#ifndef NDEBUG
|
||||
exit(-1);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define BM_CKFATAL(val) \
|
||||
do{ \
|
||||
int tstVal = (val); \
|
||||
if (tstVal) \
|
||||
bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \
|
||||
} while(0);
|
||||
|
||||
/***********************************************************************
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
/* The initialization functions are skewed in the fake implementation.
|
||||
* This call would be to attach to an existing manager, rather than to
|
||||
* create a local one.
|
||||
*/
|
||||
|
||||
struct bufmgr *
|
||||
bm_intel_Attach(struct intel_context *intel)
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < nr_bms; i++)
|
||||
if (bufmgr_pool[i].driFd == intel->driFd) {
|
||||
bufmgr_pool[i].refcount++;
|
||||
_mesa_printf("retrieive old bufmgr for fd %d\n",
|
||||
bufmgr_pool[i].driFd);
|
||||
return &bufmgr_pool[i];
|
||||
}
|
||||
|
||||
if (nr_bms < BM_MAX) {
|
||||
struct bufmgr *bm = &bufmgr_pool[nr_bms++];
|
||||
|
||||
_mesa_printf("create new bufmgr for fd %d\n", intel->driFd);
|
||||
bm->driFd = intel->driFd;
|
||||
bm->hash = _mesa_NewHashTable();
|
||||
bm->refcount = 1;
|
||||
_glthread_INIT_MUTEX(bm->mutex);
|
||||
|
||||
drmGetLock(bm->driFd, intel->hHWContext, 0);
|
||||
BM_CKFATAL(drmMMAllocBufferPool(bm->driFd, mmPoolRing, 0,
|
||||
DRM_MM_TT | DRM_MM_NO_EVICT |
|
||||
DRM_MM_READ | DRM_MM_EXE |
|
||||
BM_BATCHBUFFER, 1024 * 1024, 4096,
|
||||
&bm->batchPool));
|
||||
|
||||
|
||||
BM_CKFATAL(drmEmitFence(bm->driFd, 0, &bm->initFence));
|
||||
drmUnlock(bm->driFd, intel->hHWContext);
|
||||
return bm;
|
||||
}
|
||||
|
||||
_mesa_printf("failed to create new bufmgr for fd %d\n", intel->driFd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
bmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers, unsigned flags)
|
||||
{
|
||||
LOCK(bm);
|
||||
{
|
||||
unsigned i;
|
||||
unsigned bFlags =
|
||||
(flags) ? flags : DRM_MM_TT | DRM_MM_VRAM | DRM_MM_SYSTEM;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
drmMMBuf *buf = calloc(sizeof(*buf), 1);
|
||||
|
||||
BM_CKFATAL(drmMMInitBuffer(bm->driFd, bFlags, 12, buf));
|
||||
buf->client_priv = ++bm->buf_nr;
|
||||
buffers[i] = buf->client_priv;
|
||||
_mesa_HashInsert(bm->hash, buffers[i], buf);
|
||||
}
|
||||
}
|
||||
UNLOCK(bm);
|
||||
}
|
||||
|
||||
void
|
||||
bmSetShared(struct bufmgr *bm, unsigned buffer, unsigned flags,
|
||||
unsigned long offset, void *virtual)
|
||||
{
|
||||
LOCK(bm);
|
||||
{
|
||||
drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
assert(buf);
|
||||
|
||||
buf->flags = DRM_MM_NO_EVICT | DRM_MM_SHARED
|
||||
| DRM_MM_WRITE | DRM_MM_READ;
|
||||
buf->flags |= flags & DRM_MM_MEMTYPE_MASK;
|
||||
buf->offset = offset;
|
||||
buf->virtual = virtual;
|
||||
BM_CKFATAL(drmMMAllocBuffer(bm->driFd, 0, NULL, 0, buf));
|
||||
}
|
||||
UNLOCK(bm);
|
||||
}
|
||||
|
||||
void
|
||||
bmDeleteBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers)
|
||||
{
|
||||
LOCK(bm);
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffers[i]);
|
||||
|
||||
if (buf) {
|
||||
BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));
|
||||
|
||||
_mesa_HashRemove(bm->hash, buffers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
UNLOCK(bm);
|
||||
}
|
||||
|
||||
/* If buffer size changes, free and reallocate. Otherwise update in
|
||||
* place.
|
||||
*/
|
||||
|
||||
void
|
||||
bmBufferData(struct bufmgr *bm,
|
||||
unsigned buffer, unsigned size, const void *data, unsigned flags)
|
||||
{
|
||||
LOCK(bm);
|
||||
{
|
||||
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
DBG("bmBufferData %d sz 0x%x data: %p\n", buffer, size, data);
|
||||
|
||||
assert(buf);
|
||||
assert(!buf->mapped);
|
||||
|
||||
if (buf->flags & BM_BATCHBUFFER) {
|
||||
BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));
|
||||
BM_CKFATAL(drmMMAllocBuffer
|
||||
(bm->driFd, size, &bm->batchPool, 1, buf));
|
||||
} else if (!(buf->flags & DRM_MM_SHARED)) {
|
||||
|
||||
if (buf->block && (buf->size < size || drmBufIsBusy(bm->driFd, buf))) {
|
||||
BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));
|
||||
}
|
||||
if (!buf->block) {
|
||||
BM_CKFATAL(drmMMAllocBuffer(bm->driFd, size, NULL, 0, buf));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
|
||||
memcpy(drmMMMapBuffer(bm->driFd, buf), data, size);
|
||||
drmMMUnmapBuffer(bm->driFd, buf);
|
||||
|
||||
}
|
||||
}
|
||||
UNLOCK(bm);
|
||||
}
|
||||
|
||||
/* Update the buffer in place, in whatever space it is currently resident:
|
||||
*/
|
||||
void
|
||||
bmBufferSubData(struct bufmgr *bm,
|
||||
unsigned buffer,
|
||||
unsigned offset, unsigned size, const void *data)
|
||||
{
|
||||
LOCK(bm);
|
||||
{
|
||||
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);
|
||||
|
||||
assert(buf);
|
||||
drmBufWaitBusy(bm->driFd, buf);
|
||||
|
||||
if (size) {
|
||||
memcpy((unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset,
|
||||
data, size);
|
||||
drmMMUnmapBuffer(bm->driFd, buf);
|
||||
}
|
||||
}
|
||||
UNLOCK(bm);
|
||||
}
|
||||
|
||||
/* Extract data from the buffer:
|
||||
*/
|
||||
void
|
||||
bmBufferGetSubData(struct bufmgr *bm,
|
||||
unsigned buffer,
|
||||
unsigned offset, unsigned size, void *data)
|
||||
{
|
||||
LOCK(bm);
|
||||
{
|
||||
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);
|
||||
|
||||
assert(buf);
|
||||
drmBufWaitBusy(bm->driFd, buf);
|
||||
|
||||
if (size) {
|
||||
memcpy(data,
|
||||
(unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset,
|
||||
size);
|
||||
drmMMUnmapBuffer(bm->driFd, buf);
|
||||
}
|
||||
}
|
||||
UNLOCK(bm);
|
||||
}
|
||||
|
||||
/* Return a pointer to whatever space the buffer is currently resident in:
|
||||
*/
|
||||
void *
|
||||
bmMapBuffer(struct bufmgr *bm, unsigned buffer, unsigned flags)
|
||||
{
|
||||
void *retval;
|
||||
|
||||
LOCK(bm);
|
||||
{
|
||||
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
DBG("bmMapBuffer %d\n", buffer);
|
||||
DBG("Map: Block is 0x%x\n", &buf->block);
|
||||
|
||||
assert(buf);
|
||||
/* assert(!buf->mapped); */
|
||||
retval = drmMMMapBuffer(bm->driFd, buf);
|
||||
}
|
||||
UNLOCK(bm);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
bmUnmapBuffer(struct bufmgr *bm, unsigned buffer)
|
||||
{
|
||||
LOCK(bm);
|
||||
{
|
||||
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
DBG("bmUnmapBuffer %d\n", buffer);
|
||||
|
||||
drmMMUnmapBuffer(bm->driFd, buf);
|
||||
}
|
||||
out:
|
||||
UNLOCK(bm);
|
||||
}
|
||||
|
||||
/* Build the list of buffers to validate. Note that the buffer list
|
||||
* isn't a shared structure so we don't need mutexes when manipulating
|
||||
* it.
|
||||
*
|
||||
* XXX: need refcounting for drmMMBuf structs so that they can't be
|
||||
* deleted while on these lists.
|
||||
*/
|
||||
struct _drmMMBufList *
|
||||
bmNewBufferList(void)
|
||||
{
|
||||
return drmMMInitListHead();
|
||||
}
|
||||
|
||||
int
|
||||
bmAddBuffer(struct bufmgr *bm,
|
||||
struct _drmMMBufList *list,
|
||||
unsigned buffer,
|
||||
unsigned flags,
|
||||
unsigned *memtype_return, unsigned long *offset_return)
|
||||
{
|
||||
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
assert(buf);
|
||||
return drmMMBufListAdd(list, buf, 0, flags, memtype_return, offset_return);
|
||||
}
|
||||
|
||||
void
|
||||
bmFreeBufferList(struct _drmMMBufList *list)
|
||||
{
|
||||
drmMMFreeBufList(list);
|
||||
}
|
||||
|
||||
int
|
||||
bmScanBufferList(struct bufmgr *bm,
|
||||
struct _drmMMBufList *list, unsigned buffer)
|
||||
{
|
||||
drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);
|
||||
|
||||
assert(buf);
|
||||
return drmMMScanBufList(list, buf);
|
||||
}
|
||||
|
||||
/* To be called prior to emitting commands to hardware which reference
|
||||
* these buffers. The buffer_usage list provides information on where
|
||||
* the buffers should be placed and whether their contents need to be
|
||||
* preserved on copying. The offset and pool data elements are return
|
||||
* values from this function telling the driver exactly where the
|
||||
* buffers are currently located.
|
||||
*/
|
||||
|
||||
int
|
||||
bmValidateBufferList(struct bufmgr *bm,
|
||||
struct _drmMMBufList *list, unsigned flags)
|
||||
{
|
||||
BM_CKFATAL(drmMMValidateBuffers(bm->driFd, list));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* After commands are emitted but before unlocking, this must be
|
||||
* called so that the buffer manager can correctly age the buffers.
|
||||
* The buffer manager keeps track of the list of validated buffers, so
|
||||
* already knows what to apply the fence to.
|
||||
*
|
||||
* The buffer manager knows how to emit and test fences directly
|
||||
* through the drm and without callbacks or whatever into the driver.
|
||||
*/
|
||||
unsigned
|
||||
bmFenceBufferList(struct bufmgr *bm, struct _drmMMBufList *list)
|
||||
{
|
||||
drmFence fence;
|
||||
|
||||
BM_CKFATAL(drmMMFenceBuffers(bm->driFd, list));
|
||||
BM_CKFATAL(drmEmitFence(bm->driFd, 0, &fence));
|
||||
|
||||
return fence.fenceSeq;
|
||||
}
|
||||
|
||||
/* This functionality is used by the buffer manager, not really sure
|
||||
* if we need to be exposing it in this way, probably libdrm will
|
||||
* offer equivalent calls.
|
||||
*
|
||||
* For now they can stay, but will likely change/move before final:
|
||||
*/
|
||||
unsigned
|
||||
bmSetFence(struct bufmgr *bm)
|
||||
{
|
||||
drmFence dFence;
|
||||
|
||||
BM_CKFATAL(drmEmitFence(bm->driFd, 0, &dFence));
|
||||
|
||||
return dFence.fenceSeq;
|
||||
}
|
||||
|
||||
int
|
||||
bmTestFence(struct bufmgr *bm, unsigned fence)
|
||||
{
|
||||
drmFence dFence;
|
||||
int retired;
|
||||
|
||||
dFence.fenceType = 0;
|
||||
dFence.fenceSeq = fence;
|
||||
BM_CKFATAL(drmTestFence(bm->driFd, dFence, 0, &retired));
|
||||
return retired;
|
||||
}
|
||||
|
||||
void
|
||||
bmFinishFence(struct bufmgr *bm, unsigned fence)
|
||||
{
|
||||
drmFence dFence;
|
||||
dFence.fenceType = 0;
|
||||
dFence.fenceSeq = fence;
|
||||
BM_CKFATAL(drmWaitFence(bm->driFd, dFence));
|
||||
bm->initFence = dFence;
|
||||
}
|
||||
|
||||
unsigned
|
||||
bmInitFence(struct bufmgr *bm)
|
||||
{
|
||||
return bm->initFence.fenceSeq;
|
||||
}
|
||||
132
src/mesa/drivers/dri/i915/intel_bufmgr.h
Normal file
132
src/mesa/drivers/dri/i915/intel_bufmgr.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO.
|
||||
* 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 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
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS 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.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BUFMGR_H
|
||||
#define BUFMGR_H
|
||||
|
||||
#include "intel_context.h"
|
||||
|
||||
/* Note that this is destined to be external to Mesa, so don't use GL
|
||||
* types like GLuint, etc.
|
||||
*/
|
||||
|
||||
/* The buffer manager context. Opaque.
|
||||
*/
|
||||
struct bufmgr;
|
||||
|
||||
struct bufmgr *bm_intel_Attach(struct intel_context *intel);
|
||||
|
||||
#define BM_BATCHBUFFER 0x10000000 /* for map - pointer will be accessed
|
||||
* without dri lock */
|
||||
|
||||
/* Stick closely to ARB_vbo semantics - they're well defined and
|
||||
* understood, and drivers can just pass the calls through without too
|
||||
* much thunking.
|
||||
*/
|
||||
void bmGenBuffers(struct bufmgr *, unsigned n, unsigned *buffers,
|
||||
unsigned flags);
|
||||
|
||||
void bmDeleteBuffers(struct bufmgr *, unsigned n, unsigned *buffers);
|
||||
|
||||
/* The driver has more intimate knowledge of the hardare than a GL
|
||||
* client would, so flags here is more proscriptive than the usage
|
||||
* values in the ARB_vbo interface:
|
||||
*/
|
||||
void bmBufferData(struct bufmgr *,
|
||||
unsigned buffer,
|
||||
unsigned size, const void *data, unsigned flags);
|
||||
|
||||
void bmBufferSubData(struct bufmgr *,
|
||||
unsigned buffer,
|
||||
unsigned offset, unsigned size, const void *data);
|
||||
|
||||
void bmBufferGetSubData(struct bufmgr *,
|
||||
unsigned buffer,
|
||||
unsigned offset, unsigned size, void *data);
|
||||
|
||||
void *bmMapBuffer(struct bufmgr *, unsigned buffer, unsigned access);
|
||||
|
||||
void bmUnmapBuffer(struct bufmgr *, unsigned buffer);
|
||||
|
||||
/* To be called prior to emitting commands to hardware which reference
|
||||
* these buffers.
|
||||
*
|
||||
* NewBufferList() and AddBuffer() build up a list of buffers to be
|
||||
* validated. The buffer list provides information on where the
|
||||
* buffers should be placed and whether their contents need to be
|
||||
* preserved on copying. The offset data elements are return values
|
||||
* from this function telling the driver exactly where the buffers are
|
||||
* currently located.
|
||||
*
|
||||
* ValidateBufferList() performs the actual validation and returns the
|
||||
* buffer pools and offsets within the pools.
|
||||
*
|
||||
* FenceBufferList() must be called to set fences and other
|
||||
* housekeeping before unlocking after a successful call to
|
||||
* ValidateBufferList(). The buffer manager knows how to emit and test
|
||||
* fences directly through the drm and without callbacks to the
|
||||
* driver.
|
||||
*/
|
||||
struct _drmMMBufList *bmNewBufferList(void);
|
||||
|
||||
int bmAddBuffer(struct bufmgr *bm,
|
||||
struct _drmMMBufList *list,
|
||||
unsigned buffer,
|
||||
unsigned flags,
|
||||
unsigned *pool_return, unsigned long *offset_return);
|
||||
|
||||
int bmValidateBufferList(struct bufmgr *,
|
||||
struct _drmMMBufList *, unsigned flags);
|
||||
|
||||
unsigned bmFenceBufferList(struct bufmgr *, struct _drmMMBufList *);
|
||||
|
||||
void bmFreeBufferList(struct _drmMMBufList *);
|
||||
|
||||
int bmScanBufferList(struct bufmgr *bm,
|
||||
struct _drmMMBufList *list, unsigned buffer);
|
||||
|
||||
/* This functionality is used by the buffer manager, not really sure
|
||||
* if we need to be exposing it in this way, probably libdrm will
|
||||
* offer equivalent calls.
|
||||
*
|
||||
* For now they can stay, but will likely change/move before final:
|
||||
*/
|
||||
unsigned bmSetFence(struct bufmgr *);
|
||||
int bmTestFence(struct bufmgr *, unsigned fence);
|
||||
void bmFinishFence(struct bufmgr *, unsigned fence);
|
||||
unsigned bmInitFence(struct bufmgr *bm);
|
||||
void bmSetShared(struct bufmgr *bm, unsigned buffer,
|
||||
unsigned flags, unsigned long offset, void *virtual);
|
||||
|
||||
extern int INTEL_DEBUG;
|
||||
|
||||
#define DEBUG_BUFMGR 0x2000
|
||||
|
||||
#define DBG(...) do { if (INTEL_DEBUG & DEBUG_BUFMGR) _mesa_printf(__VA_ARGS__); } while(0)
|
||||
|
||||
#endif
|
||||
@@ -47,13 +47,20 @@
|
||||
#include "intel_screen.h"
|
||||
|
||||
#include "i830_dri.h"
|
||||
#include "i830_common.h"
|
||||
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_span.h"
|
||||
#include "intel_tris.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_pixel.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_buffer_objects.h"
|
||||
#include "intel_fbo.h"
|
||||
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
#include "utils.h"
|
||||
#ifndef INTEL_DEBUG
|
||||
@@ -72,27 +79,20 @@ int INTEL_DEBUG = (0);
|
||||
#define need_GL_EXT_blend_minmax
|
||||
#define need_GL_EXT_cull_vertex
|
||||
#define need_GL_EXT_fog_coord
|
||||
#define need_GL_EXT_framebuffer_object
|
||||
#define need_GL_EXT_multi_draw_arrays
|
||||
#define need_GL_EXT_secondary_color
|
||||
#define need_GL_NV_vertex_program
|
||||
#include "extension_helper.h"
|
||||
|
||||
#ifndef VERBOSE
|
||||
int VERBOSE = 0;
|
||||
#endif
|
||||
|
||||
#if DEBUG_LOCKING
|
||||
char *prevLockFile;
|
||||
int prevLockLine;
|
||||
#endif
|
||||
#define DRIVER_DATE "20060329"
|
||||
|
||||
/***************************************
|
||||
* Mesa's Driver Functions
|
||||
***************************************/
|
||||
_glthread_Mutex lockMutex;
|
||||
static GLboolean lockMutexInit = GL_FALSE;
|
||||
|
||||
#define DRIVER_DATE "20050225"
|
||||
|
||||
const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
|
||||
static const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
|
||||
{
|
||||
const char * chipset;
|
||||
static char buffer[128];
|
||||
@@ -103,7 +103,7 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
|
||||
break;
|
||||
|
||||
case GL_RENDERER:
|
||||
switch (INTEL_CONTEXT(ctx)->intelScreen->deviceID) {
|
||||
switch (intel_context(ctx)->intelScreen->deviceID) {
|
||||
case PCI_CHIP_845_G:
|
||||
chipset = "Intel(R) 845G"; break;
|
||||
case PCI_CHIP_I830_M:
|
||||
@@ -130,27 +130,6 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name )
|
||||
}
|
||||
}
|
||||
|
||||
static void intelBufferSize(GLframebuffer *buffer,
|
||||
GLuint *width, GLuint *height)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
/* Need to lock to make sure the driDrawable is uptodate. This
|
||||
* information is used to resize Mesa's software buffers, so it has
|
||||
* to be correct.
|
||||
*/
|
||||
LOCK_HARDWARE(intel);
|
||||
if (intel->driDrawable) {
|
||||
*width = intel->driDrawable->w;
|
||||
*height = intel->driDrawable->h;
|
||||
}
|
||||
else {
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
}
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extension strings exported by the intel driver.
|
||||
@@ -173,6 +152,7 @@ const struct dri_extension card_extensions[] =
|
||||
{ "GL_ARB_texture_mirrored_repeat", NULL },
|
||||
{ "GL_ARB_texture_rectangle", NULL },
|
||||
{ "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
|
||||
{ "GL_ARB_pixel_buffer_object", NULL },
|
||||
{ "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
|
||||
{ "GL_ARB_window_pos", GL_ARB_window_pos_functions },
|
||||
{ "GL_EXT_blend_color", GL_EXT_blend_color_functions },
|
||||
@@ -182,7 +162,11 @@ const struct dri_extension card_extensions[] =
|
||||
{ "GL_EXT_blend_subtract", NULL },
|
||||
{ "GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions },
|
||||
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
|
||||
{ "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions },
|
||||
{ "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
|
||||
#if 1 /* XXX FBO temporary? */
|
||||
{ "GL_EXT_packed_depth_stencil", NULL },
|
||||
#endif
|
||||
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
|
||||
{ "GL_EXT_stencil_wrap", NULL },
|
||||
{ "GL_EXT_texture_edge_clamp", NULL },
|
||||
@@ -197,7 +181,7 @@ const struct dri_extension card_extensions[] =
|
||||
{ "GL_NV_blend_square", NULL },
|
||||
{ "GL_NV_vertex_program", GL_NV_vertex_program_functions },
|
||||
{ "GL_NV_vertex_program1_1", NULL },
|
||||
{ "GL_SGIS_generate_mipmap", NULL },
|
||||
/* { "GL_SGIS_generate_mipmap", NULL }, */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -237,6 +221,7 @@ static const struct dri_debug_control debug_control[] =
|
||||
{ "sync", DEBUG_SYNC },
|
||||
{ "sleep", DEBUG_SLEEP },
|
||||
{ "pix", DEBUG_PIXEL },
|
||||
{ "buf", DEBUG_BUFMGR },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -248,7 +233,32 @@ static void intelInvalidateState( GLcontext *ctx, GLuint new_state )
|
||||
_ac_InvalidateState( ctx, new_state );
|
||||
_tnl_InvalidateState( ctx, new_state );
|
||||
_tnl_invalidate_vertex_state( ctx, new_state );
|
||||
INTEL_CONTEXT(ctx)->NewGLState |= new_state;
|
||||
intel_context(ctx)->NewGLState |= new_state;
|
||||
}
|
||||
|
||||
|
||||
void intelFlush( GLcontext *ctx )
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
|
||||
if (intel->Fallback)
|
||||
_swrast_flush( ctx );
|
||||
|
||||
INTEL_FIREVERTICES( intel );
|
||||
|
||||
if (intel->batch->map != intel->batch->ptr)
|
||||
intel_batchbuffer_flush( intel->batch );
|
||||
|
||||
/* XXX: Need to do an MI_FLUSH here. Actually, the bufmgr_fake.c
|
||||
* code will have done one already.
|
||||
*/
|
||||
}
|
||||
|
||||
void intelFinish( GLcontext *ctx )
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
intelFlush( ctx );
|
||||
bmFinishFence( intel->bm, intel->batch->last_fence );
|
||||
}
|
||||
|
||||
|
||||
@@ -257,10 +267,7 @@ void intelInitDriverFunctions( struct dd_function_table *functions )
|
||||
_mesa_init_driver_functions( functions );
|
||||
|
||||
functions->Flush = intelFlush;
|
||||
functions->Clear = intelClear;
|
||||
functions->Finish = intelFinish;
|
||||
functions->GetBufferSize = intelBufferSize;
|
||||
functions->ResizeBuffers = _mesa_resize_framebuffer;
|
||||
functions->GetString = intelGetString;
|
||||
functions->UpdateState = intelInvalidateState;
|
||||
functions->CopyColorTable = _swrast_CopyColorTable;
|
||||
@@ -271,11 +278,12 @@ void intelInitDriverFunctions( struct dd_function_table *functions )
|
||||
intelInitTextureFuncs( functions );
|
||||
intelInitPixelFuncs( functions );
|
||||
intelInitStateFuncs( functions );
|
||||
intelInitBufferFuncs( functions );
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLboolean intelInitContext( intelContextPtr intel,
|
||||
GLboolean intelInitContext( struct intel_context *intel,
|
||||
const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
void *sharedContextPrivate,
|
||||
@@ -299,9 +307,10 @@ GLboolean intelInitContext( intelContextPtr intel,
|
||||
intel->driScreen = sPriv;
|
||||
intel->sarea = saPriv;
|
||||
|
||||
|
||||
(void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) );
|
||||
make_empty_list( & intel->swapped );
|
||||
if (!lockMutexInit) {
|
||||
lockMutexInit = GL_TRUE;
|
||||
_glthread_INIT_MUTEX(lockMutex);
|
||||
}
|
||||
|
||||
ctx->Const.MaxTextureMaxAnisotropy = 2.0;
|
||||
|
||||
@@ -317,6 +326,8 @@ GLboolean intelInitContext( intelContextPtr intel,
|
||||
ctx->Const.MaxPointSizeAA = 3.0;
|
||||
ctx->Const.PointSizeGranularity = 1.0;
|
||||
|
||||
ctx->Const.MaxColorAttachments = 4; /* XXX FBO: review this */
|
||||
|
||||
/* Initialize the software rasterizer and helper modules. */
|
||||
_swrast_CreateContext( ctx );
|
||||
_ac_CreateContext( ctx );
|
||||
@@ -336,23 +347,16 @@ GLboolean intelInitContext( intelContextPtr intel,
|
||||
intel->driFd = sPriv->fd;
|
||||
intel->driHwLock = (drmLock *) &sPriv->pSAREA->lock;
|
||||
|
||||
intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
|
||||
intel->hw_stipple = 1;
|
||||
|
||||
/* XXX FBO: this doesn't seem to be used anywhere */
|
||||
switch(mesaVis->depthBits) {
|
||||
case 0: /* what to do in this case? */
|
||||
case 16:
|
||||
intel->depth_scale = 1.0/0xffff;
|
||||
intel->polygon_offset_scale = 1.0/0xffff;
|
||||
intel->depth_clear_mask = ~0;
|
||||
intel->ClearDepth = 0xffff;
|
||||
break;
|
||||
case 24:
|
||||
intel->depth_scale = 1.0/0xffffff;
|
||||
intel->polygon_offset_scale = 2.0/0xffffff; /* req'd to pass glean */
|
||||
intel->depth_clear_mask = 0x00ffffff;
|
||||
intel->stencil_clear_mask = 0xff000000;
|
||||
intel->ClearDepth = 0x00ffffff;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -371,7 +375,65 @@ GLboolean intelInitContext( intelContextPtr intel,
|
||||
|
||||
_math_matrix_ctr (&intel->ViewportMatrix);
|
||||
|
||||
driInitExtensions( ctx, card_extensions, GL_TRUE );
|
||||
/* Disable imaging extension until convolution is working in
|
||||
* teximage paths:
|
||||
*/
|
||||
driInitExtensions( ctx, card_extensions,
|
||||
/* GL_TRUE, */
|
||||
GL_FALSE);
|
||||
|
||||
|
||||
/* Buffer manager:
|
||||
*/
|
||||
intel->bm = bm_intel_Attach( intel );
|
||||
#if 0
|
||||
bmInitPool(intel->bm,
|
||||
intel->intelScreen->tex.offset, /* low offset */
|
||||
intel->intelScreen->tex.map, /* low virtual */
|
||||
intel->intelScreen->tex.size,
|
||||
DRM_MM_TT);
|
||||
#endif
|
||||
|
||||
/* XXX FBO: these have to go away!
|
||||
* FBO regions should be setup when creating the drawable. */
|
||||
|
||||
/* These are still static, but create regions for them.
|
||||
*/
|
||||
intel->front_region =
|
||||
intel_region_create_static(intel,
|
||||
DRM_MM_TT,
|
||||
intelScreen->front.offset,
|
||||
intelScreen->front.map,
|
||||
intelScreen->cpp,
|
||||
intelScreen->front.pitch,
|
||||
intelScreen->height);
|
||||
|
||||
|
||||
intel->back_region =
|
||||
intel_region_create_static(intel,
|
||||
DRM_MM_TT,
|
||||
intelScreen->back.offset,
|
||||
intelScreen->back.map,
|
||||
intelScreen->cpp,
|
||||
intelScreen->back.pitch,
|
||||
intelScreen->height);
|
||||
|
||||
/* Still assuming front.cpp == depth.cpp
|
||||
*/
|
||||
intel->depth_region =
|
||||
intel_region_create_static(intel,
|
||||
DRM_MM_TT,
|
||||
intelScreen->depth.offset,
|
||||
intelScreen->depth.map,
|
||||
intelScreen->cpp,
|
||||
intelScreen->depth.pitch,
|
||||
intelScreen->height);
|
||||
|
||||
intel->batch = intel_batchbuffer_alloc( intel );
|
||||
intel->last_swap_fence_retired = GL_TRUE;
|
||||
intel->last_swap_fence = bmInitFence(intel->bm);
|
||||
intel_bufferobj_init( intel );
|
||||
intel_fbo_init( intel );
|
||||
|
||||
if (intel->ctx.Mesa_DXTn) {
|
||||
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
|
||||
@@ -381,30 +443,15 @@ GLboolean intelInitContext( intelContextPtr intel,
|
||||
_mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" );
|
||||
}
|
||||
|
||||
/* driInitTextureObjects( ctx, & intel->swapped, */
|
||||
/* DRI_TEXMGR_DO_TEXTURE_1D | */
|
||||
/* DRI_TEXMGR_DO_TEXTURE_2D | */
|
||||
/* DRI_TEXMGR_DO_TEXTURE_RECT ); */
|
||||
|
||||
|
||||
intel->prim.flush = intelInitBatchBuffer;
|
||||
intel->prim.primitive = ~0;
|
||||
|
||||
|
||||
#if DO_DEBUG
|
||||
INTEL_DEBUG = driParseDebugString( getenv( "INTEL_DEBUG" ),
|
||||
debug_control );
|
||||
INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ),
|
||||
debug_control );
|
||||
#endif
|
||||
|
||||
#ifndef VERBOSE
|
||||
if (getenv("INTEL_VERBOSE"))
|
||||
VERBOSE=1;
|
||||
#endif
|
||||
|
||||
if (getenv("INTEL_NO_RAST") ||
|
||||
getenv("INTEL_NO_RAST")) {
|
||||
if (getenv("INTEL_NO_RAST")) {
|
||||
fprintf(stderr, "disabling 3D rasterization\n");
|
||||
FALLBACK(intel, INTEL_FALLBACK_USER, 1);
|
||||
}
|
||||
@@ -414,7 +461,7 @@ GLboolean intelInitContext( intelContextPtr intel,
|
||||
|
||||
void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
|
||||
{
|
||||
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
|
||||
struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate;
|
||||
|
||||
assert(intel); /* should never be null */
|
||||
if (intel) {
|
||||
@@ -431,121 +478,19 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv)
|
||||
_swrast_DestroyContext (&intel->ctx);
|
||||
intel->Fallback = 0; /* don't call _swrast_Flush later */
|
||||
|
||||
intelDestroyBatchBuffer(&intel->ctx);
|
||||
intel_batchbuffer_free(intel->batch);
|
||||
|
||||
|
||||
if ( release_texture_heaps ) {
|
||||
/* This share group is about to go away, free our private
|
||||
* texture object data.
|
||||
*/
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
|
||||
driDestroyTextureHeap( intel->texture_heaps[ i ] );
|
||||
intel->texture_heaps[ i ] = NULL;
|
||||
}
|
||||
|
||||
assert( is_empty_list( & intel->swapped ) );
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "do something to free texture heaps\n");
|
||||
}
|
||||
|
||||
/* free the Mesa context */
|
||||
_mesa_destroy_context(&intel->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void intelSetFrontClipRects( intelContextPtr intel )
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
|
||||
if (!dPriv) return;
|
||||
|
||||
intel->numClipRects = dPriv->numClipRects;
|
||||
intel->pClipRects = dPriv->pClipRects;
|
||||
intel->drawX = dPriv->x;
|
||||
intel->drawY = dPriv->y;
|
||||
}
|
||||
|
||||
|
||||
void intelSetBackClipRects( intelContextPtr intel )
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
|
||||
if (!dPriv) return;
|
||||
|
||||
if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) {
|
||||
intel->numClipRects = dPriv->numClipRects;
|
||||
intel->pClipRects = dPriv->pClipRects;
|
||||
intel->drawX = dPriv->x;
|
||||
intel->drawY = dPriv->y;
|
||||
} else {
|
||||
intel->numClipRects = dPriv->numBackClipRects;
|
||||
intel->pClipRects = dPriv->pBackClipRects;
|
||||
intel->drawX = dPriv->backX;
|
||||
intel->drawY = dPriv->backY;
|
||||
|
||||
if (dPriv->numBackClipRects == 1 &&
|
||||
dPriv->x == dPriv->backX &&
|
||||
dPriv->y == dPriv->backY) {
|
||||
|
||||
/* Repeat the calculation of the back cliprect dimensions here
|
||||
* as early versions of dri.a in the Xserver are incorrect. Try
|
||||
* very hard not to restrict future versions of dri.a which
|
||||
* might eg. allocate truly private back buffers.
|
||||
*/
|
||||
int x1, y1;
|
||||
int x2, y2;
|
||||
|
||||
x1 = dPriv->x;
|
||||
y1 = dPriv->y;
|
||||
x2 = dPriv->x + dPriv->w;
|
||||
y2 = dPriv->y + dPriv->h;
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width;
|
||||
if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height;
|
||||
|
||||
if (x1 == dPriv->pBackClipRects[0].x1 &&
|
||||
y1 == dPriv->pBackClipRects[0].y1) {
|
||||
|
||||
dPriv->pBackClipRects[0].x2 = x2;
|
||||
dPriv->pBackClipRects[0].y2 = y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void intelWindowMoved( intelContextPtr intel )
|
||||
{
|
||||
if (!intel->ctx.DrawBuffer) {
|
||||
intelSetFrontClipRects( intel );
|
||||
}
|
||||
else {
|
||||
switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) {
|
||||
case BUFFER_BIT_FRONT_LEFT:
|
||||
intelSetFrontClipRects( intel );
|
||||
break;
|
||||
case BUFFER_BIT_BACK_LEFT:
|
||||
intelSetBackClipRects( intel );
|
||||
break;
|
||||
default:
|
||||
/* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
|
||||
intelSetFrontClipRects( intel );
|
||||
}
|
||||
}
|
||||
|
||||
/* Set state we know depends on drawable parameters:
|
||||
*/
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
|
||||
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
|
||||
ctx->Scissor.Width, ctx->Scissor.Height );
|
||||
|
||||
ctx->Driver.DepthRange( ctx,
|
||||
ctx->Viewport.Near,
|
||||
ctx->Viewport.Far );
|
||||
_mesa_free_context_data(&intel->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,7 +505,9 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
|
||||
{
|
||||
|
||||
if (driContextPriv) {
|
||||
intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate;
|
||||
struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate;
|
||||
GLframebuffer *drawFb = (GLframebuffer *) driDrawPriv->driverPrivate;
|
||||
GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate;
|
||||
|
||||
if ( intel->driDrawable != driDrawPriv ) {
|
||||
/* Shouldn't the readbuffer be stored also? */
|
||||
@@ -568,28 +515,53 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
|
||||
intelWindowMoved( intel );
|
||||
}
|
||||
|
||||
_mesa_make_current(&intel->ctx,
|
||||
(GLframebuffer *) driDrawPriv->driverPrivate,
|
||||
(GLframebuffer *) driReadPriv->driverPrivate);
|
||||
/* XXX FBO temporary fix-ups! */
|
||||
/* if the renderbuffers don't have regions, init them from the context */
|
||||
{
|
||||
struct intel_renderbuffer *irbFront
|
||||
= intel_get_renderbuffer(drawFb, BUFFER_FRONT_LEFT);
|
||||
struct intel_renderbuffer *irbBack
|
||||
= intel_get_renderbuffer(drawFb, BUFFER_BACK_LEFT);
|
||||
struct intel_renderbuffer *irbDepth
|
||||
= intel_get_renderbuffer(drawFb, BUFFER_DEPTH);
|
||||
struct intel_renderbuffer *irbStencil
|
||||
= intel_get_renderbuffer(drawFb, BUFFER_STENCIL);
|
||||
|
||||
intel->ctx.Driver.DrawBuffer( &intel->ctx, intel->ctx.Color.DrawBuffer[0] );
|
||||
} else {
|
||||
if (irbFront && !irbFront->region) {
|
||||
intel_region_reference(&irbFront->region, intel->front_region);
|
||||
}
|
||||
if (irbBack && !irbBack->region) {
|
||||
intel_region_reference(&irbBack->region, intel->back_region);
|
||||
}
|
||||
if (irbDepth && !irbDepth->region) {
|
||||
intel_region_reference(&irbDepth->region, intel->depth_region);
|
||||
}
|
||||
if (irbStencil && !irbStencil->region) {
|
||||
intel_region_reference(&irbStencil->region, intel->depth_region);
|
||||
}
|
||||
}
|
||||
|
||||
_mesa_make_current(&intel->ctx, drawFb, readFb);
|
||||
|
||||
intel_draw_buffer(&intel->ctx, drawFb);
|
||||
}
|
||||
else {
|
||||
_mesa_make_current(NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void intelGetLock( intelContextPtr intel, GLuint flags )
|
||||
void intelGetLock( struct intel_context *intel, GLuint flags )
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
__DRIscreenPrivate *sPriv = intel->driScreen;
|
||||
drmI830Sarea * sarea = intel->sarea;
|
||||
int me = intel->hHWContext;
|
||||
unsigned i;
|
||||
|
||||
drmGetLock(intel->driFd, intel->hHWContext, flags);
|
||||
|
||||
|
||||
/* If the window moved, may need to set a new cliprect now.
|
||||
*
|
||||
* NOTE: This releases and regains the hw lock, so all state
|
||||
@@ -598,143 +570,19 @@ void intelGetLock( intelContextPtr intel, GLuint flags )
|
||||
if (dPriv)
|
||||
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
|
||||
|
||||
/* If we lost context, need to dump all registers to hardware.
|
||||
* Note that we don't care about 2d contexts, even if they perform
|
||||
* accelerated commands, so the DRI locking in the X server is even
|
||||
* more broken than usual.
|
||||
/* Lost context?
|
||||
*/
|
||||
|
||||
if (sarea->ctxOwner != me) {
|
||||
intel->perf_boxes |= I830_BOX_LOST_CONTEXT;
|
||||
sarea->ctxOwner = me;
|
||||
}
|
||||
|
||||
/* Shared texture managment - if another client has played with
|
||||
* texture space, figure out which if any of our textures have been
|
||||
* ejected, and update our global LRU.
|
||||
/* Drawable changed?
|
||||
*/
|
||||
|
||||
for ( i = 0 ; i < intel->nr_heaps ; i++ ) {
|
||||
DRI_AGE_TEXTURES( intel->texture_heaps[ i ] );
|
||||
}
|
||||
|
||||
if (dPriv && intel->lastStamp != dPriv->lastStamp) {
|
||||
intelWindowMoved( intel );
|
||||
intel->lastStamp = dPriv->lastStamp;
|
||||
}
|
||||
}
|
||||
|
||||
void intelSwapBuffers( __DRIdrawablePrivate *dPriv )
|
||||
{
|
||||
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
|
||||
intelContextPtr intel;
|
||||
GLcontext *ctx;
|
||||
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
|
||||
ctx = &intel->ctx;
|
||||
if (ctx->Visual.doubleBufferMode) {
|
||||
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
|
||||
if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */
|
||||
intelPageFlip( dPriv );
|
||||
} else {
|
||||
intelCopyBuffer( dPriv );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* XXX this shouldn't be an error but we can't handle it for now */
|
||||
fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void intelInitState( GLcontext *ctx )
|
||||
{
|
||||
/* Mesa should do this for us:
|
||||
*/
|
||||
ctx->Driver.AlphaFunc( ctx,
|
||||
ctx->Color.AlphaFunc,
|
||||
ctx->Color.AlphaRef);
|
||||
|
||||
ctx->Driver.BlendColor( ctx,
|
||||
ctx->Color.BlendColor );
|
||||
|
||||
ctx->Driver.BlendEquationSeparate( ctx,
|
||||
ctx->Color.BlendEquationRGB,
|
||||
ctx->Color.BlendEquationA);
|
||||
|
||||
ctx->Driver.BlendFuncSeparate( ctx,
|
||||
ctx->Color.BlendSrcRGB,
|
||||
ctx->Color.BlendDstRGB,
|
||||
ctx->Color.BlendSrcA,
|
||||
ctx->Color.BlendDstA);
|
||||
|
||||
ctx->Driver.ColorMask( ctx,
|
||||
ctx->Color.ColorMask[RCOMP],
|
||||
ctx->Color.ColorMask[GCOMP],
|
||||
ctx->Color.ColorMask[BCOMP],
|
||||
ctx->Color.ColorMask[ACOMP]);
|
||||
|
||||
ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
|
||||
ctx->Driver.DepthFunc( ctx, ctx->Depth.Func );
|
||||
ctx->Driver.DepthMask( ctx, ctx->Depth.Mask );
|
||||
|
||||
ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
|
||||
ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
|
||||
ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag );
|
||||
ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
|
||||
ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
|
||||
ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
|
||||
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
|
||||
|
||||
ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
|
||||
|
||||
{
|
||||
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
|
||||
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
|
||||
}
|
||||
|
||||
ctx->Driver.LineWidth( ctx, ctx->Line.Width );
|
||||
ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp );
|
||||
ctx->Driver.PointSize( ctx, ctx->Point.Size );
|
||||
ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple );
|
||||
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
|
||||
ctx->Scissor.Width, ctx->Scissor.Height );
|
||||
ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel );
|
||||
ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT,
|
||||
ctx->Stencil.Function[0],
|
||||
ctx->Stencil.Ref[0],
|
||||
ctx->Stencil.ValueMask[0] );
|
||||
ctx->Driver.StencilFuncSeparate( ctx, GL_BACK,
|
||||
ctx->Stencil.Function[1],
|
||||
ctx->Stencil.Ref[1],
|
||||
ctx->Stencil.ValueMask[1] );
|
||||
ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
|
||||
ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
|
||||
ctx->Driver.StencilOpSeparate( ctx, GL_FRONT,
|
||||
ctx->Stencil.FailFunc[0],
|
||||
ctx->Stencil.ZFailFunc[0],
|
||||
ctx->Stencil.ZPassFunc[0]);
|
||||
ctx->Driver.StencilOpSeparate( ctx, GL_BACK,
|
||||
ctx->Stencil.FailFunc[1],
|
||||
ctx->Stencil.ZFailFunc[1],
|
||||
ctx->Stencil.ZPassFunc[1]);
|
||||
|
||||
|
||||
ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
|
||||
}
|
||||
|
||||
@@ -47,82 +47,122 @@
|
||||
#define DV_PF_565 (2<<8)
|
||||
#define DV_PF_8888 (3<<8)
|
||||
|
||||
#define INTEL_CONTEXT(ctx) ((intelContextPtr)(ctx))
|
||||
struct intel_region;
|
||||
struct intel_context;
|
||||
|
||||
typedef struct intel_context intelContext;
|
||||
typedef struct intel_context *intelContextPtr;
|
||||
typedef struct intel_texture_object *intelTextureObjectPtr;
|
||||
|
||||
typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *,
|
||||
typedef void (*intel_tri_func)(struct intel_context *, intelVertex *, intelVertex *,
|
||||
intelVertex *);
|
||||
typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *);
|
||||
typedef void (*intel_point_func)(intelContextPtr, intelVertex *);
|
||||
typedef void (*intel_line_func)(struct intel_context *, intelVertex *, intelVertex *);
|
||||
typedef void (*intel_point_func)(struct intel_context *, intelVertex *);
|
||||
|
||||
#define INTEL_FALLBACK_DRAW_BUFFER 0x1
|
||||
#define INTEL_FALLBACK_READ_BUFFER 0x2
|
||||
#define INTEL_FALLBACK_USER 0x4
|
||||
#define INTEL_FALLBACK_NO_BATCHBUFFER 0x8
|
||||
#define INTEL_FALLBACK_NO_TEXMEM 0x10
|
||||
#define INTEL_FALLBACK_DEPTH_BUFFER 0x4
|
||||
#define INTEL_FALLBACK_STENCIL_BUFFER 0x8
|
||||
#define INTEL_FALLBACK_USER 0x10
|
||||
#define INTEL_FALLBACK_RENDERMODE 0x20
|
||||
|
||||
extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode );
|
||||
extern void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode );
|
||||
#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode )
|
||||
|
||||
|
||||
#define INTEL_TEX_MAXLEVELS 10
|
||||
|
||||
|
||||
struct intel_texture_object
|
||||
{
|
||||
driTextureObject base; /* the parent class */
|
||||
struct gl_texture_object base; /* The "parent" object */
|
||||
|
||||
GLuint texelBytes;
|
||||
GLuint age;
|
||||
GLuint Pitch;
|
||||
GLuint Height;
|
||||
GLuint TextureOffset;
|
||||
GLubyte *BufAddr;
|
||||
/* The mipmap tree must include at least these levels once
|
||||
* validated:
|
||||
*/
|
||||
GLuint firstLevel;
|
||||
GLuint lastLevel;
|
||||
|
||||
GLuint min_level;
|
||||
GLuint max_level;
|
||||
GLuint depth_pitch;
|
||||
/* Offset for firstLevel image:
|
||||
*/
|
||||
GLuint textureOffset;
|
||||
|
||||
struct {
|
||||
const struct gl_texture_image *image;
|
||||
GLuint offset; /* into BufAddr */
|
||||
GLuint height;
|
||||
GLuint internalFormat;
|
||||
} image[6][INTEL_TEX_MAXLEVELS];
|
||||
|
||||
GLuint dirty;
|
||||
GLuint firstLevel,lastLevel;
|
||||
/* On validation any active images held in main memory or in other
|
||||
* regions will be copied to this region and the old storage freed.
|
||||
*/
|
||||
struct intel_mipmap_tree *mt;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct intel_texture_image
|
||||
{
|
||||
struct gl_texture_image base;
|
||||
|
||||
/* These aren't stored in gl_texture_image
|
||||
*/
|
||||
GLuint level;
|
||||
GLuint face;
|
||||
|
||||
/* If intelImage->mt != NULL, image data is stored here.
|
||||
* Else if intelImage->base.Data != NULL, image is stored there.
|
||||
* Else there is no image data.
|
||||
*/
|
||||
struct intel_mipmap_tree *mt;
|
||||
};
|
||||
|
||||
|
||||
#define INTEL_MAX_FIXUP 64
|
||||
|
||||
struct intel_context
|
||||
{
|
||||
GLcontext ctx; /* the parent class */
|
||||
|
||||
struct {
|
||||
void (*destroy)( intelContextPtr intel );
|
||||
void (*emit_state)( intelContextPtr intel );
|
||||
void (*emit_invarient_state)( intelContextPtr intel );
|
||||
void (*lost_hardware)( intelContextPtr intel );
|
||||
void (*update_texture_state)( intelContextPtr intel );
|
||||
void (*destroy)( struct intel_context *intel );
|
||||
void (*emit_state)( struct intel_context *intel );
|
||||
void (*lost_hardware)( struct intel_context *intel );
|
||||
void (*update_texture_state)( struct intel_context *intel );
|
||||
|
||||
void (*render_start)( intelContextPtr intel );
|
||||
void (*set_draw_offset)( intelContextPtr intel, int offset );
|
||||
void (*emit_flush)( intelContextPtr intel );
|
||||
void (*render_start)( struct intel_context *intel );
|
||||
void (*set_draw_region)( struct intel_context *intel,
|
||||
struct intel_region *draw_region,
|
||||
struct intel_region *depth_region );
|
||||
|
||||
void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim );
|
||||
GLuint (*flush_cmd)( void );
|
||||
|
||||
GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected );
|
||||
void (*reduced_primitive_state)( struct intel_context *intel, GLenum rprim );
|
||||
|
||||
void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch);
|
||||
GLboolean (*check_vertex_size)( struct intel_context *intel, GLuint expected );
|
||||
|
||||
intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj );
|
||||
|
||||
/* Metaops:
|
||||
*/
|
||||
void (*install_meta_state)( struct intel_context *intel );
|
||||
void (*leave_meta_state)( struct intel_context *intel );
|
||||
|
||||
void (*meta_draw_region)( struct intel_context *intel,
|
||||
struct intel_region *draw_region,
|
||||
struct intel_region *depth_region );
|
||||
|
||||
void (*meta_color_mask)( struct intel_context *intel,
|
||||
GLboolean );
|
||||
|
||||
void (*meta_stencil_replace)( struct intel_context *intel,
|
||||
GLuint mask,
|
||||
GLuint clear );
|
||||
|
||||
void (*meta_depth_replace)( struct intel_context *intel );
|
||||
|
||||
void (*meta_texture_blend_replace)( struct intel_context *intel );
|
||||
|
||||
void (*meta_no_stencil_write)( struct intel_context *intel );
|
||||
void (*meta_no_depth_write)( struct intel_context *intel );
|
||||
void (*meta_no_texture)( struct intel_context *intel );
|
||||
|
||||
void (*meta_import_pixel_state)( struct intel_context *intel );
|
||||
|
||||
GLboolean (*meta_tex_rect_source)( struct intel_context *intel,
|
||||
GLuint buffer,
|
||||
GLuint offset,
|
||||
GLuint pitch,
|
||||
GLuint height,
|
||||
GLenum format,
|
||||
GLenum type);
|
||||
|
||||
} vtbl;
|
||||
|
||||
@@ -130,63 +170,44 @@ struct intel_context
|
||||
GLuint Fallback;
|
||||
GLuint NewGLState;
|
||||
|
||||
struct {
|
||||
GLuint start_offset;
|
||||
GLint size;
|
||||
GLint space;
|
||||
GLubyte *ptr;
|
||||
} batch;
|
||||
|
||||
struct {
|
||||
void *ptr;
|
||||
GLint size;
|
||||
GLuint offset;
|
||||
GLuint active_buf;
|
||||
GLuint irq_emitted;
|
||||
} alloc;
|
||||
GLuint last_fence;
|
||||
GLuint last_swap_fence;
|
||||
GLboolean last_swap_fence_retired;
|
||||
|
||||
struct intel_batchbuffer *batch;
|
||||
|
||||
struct {
|
||||
GLuint id;
|
||||
GLuint primitive;
|
||||
GLubyte *start_ptr;
|
||||
void (*flush)( GLcontext * );
|
||||
void (*flush)( struct intel_context * );
|
||||
} prim;
|
||||
|
||||
GLboolean locked;
|
||||
char *prevLockFile;
|
||||
int prevLockLine;
|
||||
|
||||
GLubyte clear_red;
|
||||
GLubyte clear_green;
|
||||
GLubyte clear_blue;
|
||||
GLubyte clear_alpha;
|
||||
GLuint ClearColor;
|
||||
GLuint ClearDepth;
|
||||
GLuint ClearColor565;
|
||||
GLuint ClearColor8888;
|
||||
|
||||
/* Offsets of fields within the current vertex:
|
||||
*/
|
||||
GLuint coloroffset;
|
||||
GLuint specoffset;
|
||||
|
||||
/* Support for duplicating XYZW as WPOS parameter (crutch for I915).
|
||||
*/
|
||||
GLuint wpos_offset;
|
||||
GLuint wpos_size;
|
||||
|
||||
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX];
|
||||
GLuint vertex_attr_count;
|
||||
|
||||
GLfloat depth_scale;
|
||||
GLfloat polygon_offset_scale; /* dependent on depth_scale, bpp */
|
||||
GLuint depth_clear_mask;
|
||||
GLuint stencil_clear_mask;
|
||||
|
||||
GLboolean hw_stencil;
|
||||
GLboolean hw_stipple;
|
||||
|
||||
/* Texture object bookkeeping
|
||||
/* AGP memory buffer manager:
|
||||
*/
|
||||
GLuint nr_heaps;
|
||||
driTexHeap * texture_heaps[1];
|
||||
driTextureObject swapped;
|
||||
GLuint lastStamp;
|
||||
struct bufmgr *bm;
|
||||
|
||||
struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS];
|
||||
|
||||
/* State for intelvb.c and inteltris.c.
|
||||
*/
|
||||
@@ -195,7 +216,13 @@ struct intel_context
|
||||
GLenum render_primitive;
|
||||
GLenum reduced_primitive;
|
||||
GLuint vertex_size;
|
||||
char *verts; /* points to tnl->clipspace.vertex_buf */
|
||||
GLubyte *verts; /* points to tnl->clipspace.vertex_buf */
|
||||
|
||||
|
||||
struct intel_region *front_region; /* XXX FBO: obsolete */
|
||||
struct intel_region *back_region; /* XXX FBO: obsolete */
|
||||
struct intel_region *draw_region; /* XXX FBO: rename to color_region */
|
||||
struct intel_region *depth_region; /**< currently bound depth/Z region */
|
||||
|
||||
|
||||
/* Fallback rasterization functions
|
||||
@@ -204,21 +231,22 @@ struct intel_context
|
||||
intel_line_func draw_line;
|
||||
intel_tri_func draw_tri;
|
||||
|
||||
/* These refer to the current draw (front vs. back) buffer:
|
||||
/* These refer to the current drawing buffer:
|
||||
*/
|
||||
GLuint drawOffset; /* agp offset of drawbuffer */
|
||||
int drawX; /* origin of drawable in draw buffer */
|
||||
int drawY;
|
||||
GLuint numClipRects; /* cliprects for that buffer */
|
||||
int drawX, drawY; /**< origin of drawing area within region */
|
||||
GLuint numClipRects; /**< cliprects for drawing */
|
||||
drm_clip_rect_t *pClipRects;
|
||||
drm_clip_rect_t fboRect; /**< cliprect for FBO rendering */
|
||||
|
||||
int dirtyAge;
|
||||
int perf_boxes;
|
||||
int do_irqs;
|
||||
|
||||
/* XXX these seem to be unused */
|
||||
#if 0
|
||||
GLboolean scissor;
|
||||
drm_clip_rect_t draw_rect;
|
||||
drm_clip_rect_t scissor_rect;
|
||||
#endif
|
||||
|
||||
drm_context_t hHWContext;
|
||||
drmLock *driHwLock;
|
||||
@@ -228,6 +256,8 @@ struct intel_context
|
||||
__DRIscreenPrivate *driScreen;
|
||||
intelScreenPrivate *intelScreen;
|
||||
drmI830Sarea *sarea;
|
||||
|
||||
GLuint lastStamp;
|
||||
|
||||
/**
|
||||
* Configuration cache
|
||||
@@ -236,22 +266,20 @@ struct intel_context
|
||||
};
|
||||
|
||||
|
||||
#define DEBUG_LOCKING 1
|
||||
#define DEBUG_LOCKING 1
|
||||
|
||||
#if DEBUG_LOCKING
|
||||
extern char *prevLockFile;
|
||||
extern int prevLockLine;
|
||||
|
||||
#define DEBUG_LOCK() \
|
||||
do { \
|
||||
prevLockFile = (__FILE__); \
|
||||
prevLockLine = (__LINE__); \
|
||||
intel->prevLockFile = (__FILE__); \
|
||||
intel->prevLockLine = (__LINE__); \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_RESET() \
|
||||
do { \
|
||||
prevLockFile = 0; \
|
||||
prevLockLine = 0; \
|
||||
intel->prevLockFile = 0; \
|
||||
intel->prevLockLine = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Slightly less broken way of detecting recursive locking in a
|
||||
@@ -270,7 +298,8 @@ extern int prevLockLine;
|
||||
(DRM_LOCK_HELD | intel->hHWContext) ) { \
|
||||
fprintf( stderr, \
|
||||
"LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
|
||||
prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
|
||||
intel->prevLockFile, intel->prevLockLine, \
|
||||
__FILE__, __LINE__ ); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -283,7 +312,7 @@ extern int prevLockLine;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
extern _glthread_Mutex lockMutex;
|
||||
|
||||
|
||||
/* Lock the hardware and validate our state.
|
||||
@@ -291,13 +320,14 @@ extern int prevLockLine;
|
||||
#define LOCK_HARDWARE( intel ) \
|
||||
do { \
|
||||
char __ret=0; \
|
||||
_glthread_LOCK_MUTEX(lockMutex); \
|
||||
DEBUG_CHECK_LOCK(); \
|
||||
assert(!(intel)->locked); \
|
||||
DRM_CAS((intel)->driHwLock, (intel)->hHWContext, \
|
||||
(DRM_LOCK_HELD|(intel)->hHWContext), __ret); \
|
||||
if (__ret) \
|
||||
intelGetLock( (intel), 0 ); \
|
||||
DEBUG_LOCK(); \
|
||||
DEBUG_LOCK(); \
|
||||
(intel)->locked = 1; \
|
||||
}while (0)
|
||||
|
||||
@@ -313,6 +343,7 @@ do { \
|
||||
} \
|
||||
DRM_UNLOCK((intel)->driFd, (intel)->driHwLock, (intel)->hHWContext); \
|
||||
DEBUG_RESET(); \
|
||||
_glthread_UNLOCK_MUTEX(lockMutex); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -321,8 +352,7 @@ do { \
|
||||
|
||||
#define INTEL_FIREVERTICES(intel) \
|
||||
do { \
|
||||
if ((intel)->prim.flush) \
|
||||
(intel)->prim.flush(&(intel)->ctx); \
|
||||
assert(!(intel)->prim.flush); \
|
||||
} while (0)
|
||||
|
||||
/* ================================================================
|
||||
@@ -343,20 +373,14 @@ do { \
|
||||
((a<<24) | (r<<16) | (g<<8) | b)
|
||||
|
||||
|
||||
#define INTEL_PACKCOLOR(format, r, g, b, a) \
|
||||
(format == DV_PF_555 ? INTEL_PACKCOLOR1555(r,g,b,a) : \
|
||||
(format == DV_PF_565 ? INTEL_PACKCOLOR565(r,g,b) : \
|
||||
(format == DV_PF_8888 ? INTEL_PACKCOLOR8888(r,g,b,a) : \
|
||||
0)))
|
||||
|
||||
|
||||
|
||||
/* ================================================================
|
||||
* From linux kernel i386 header files, copes with odd sizes better
|
||||
* than COPY_DWORDS would:
|
||||
* XXX Put this in src/mesa/main/imports.h ???
|
||||
*/
|
||||
#if defined(i386) || defined(__i386__)
|
||||
static __inline__ void * __memcpy(void * to, const void * from, size_t n)
|
||||
static INLINE void * __memcpy(void * to, const void * from, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
@@ -417,21 +441,19 @@ extern int INTEL_DEBUG;
|
||||
* intel_context.c:
|
||||
*/
|
||||
|
||||
extern void intelInitDriverFunctions( struct dd_function_table *functions );
|
||||
|
||||
extern GLboolean intelInitContext( intelContextPtr intel,
|
||||
extern GLboolean intelInitContext( struct intel_context *intel,
|
||||
const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
void *sharedContextPrivate,
|
||||
struct dd_function_table *functions );
|
||||
|
||||
extern void intelGetLock(intelContextPtr intel, GLuint flags);
|
||||
extern void intelSetBackClipRects(intelContextPtr intel);
|
||||
extern void intelSetFrontClipRects(intelContextPtr intel);
|
||||
extern void intelWindowMoved( intelContextPtr intel );
|
||||
extern void intelGetLock(struct intel_context *intel, GLuint flags);
|
||||
|
||||
extern void intelInitState( GLcontext *ctx );
|
||||
extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name );
|
||||
extern void intelFinish( GLcontext *ctx );
|
||||
extern void intelFlush( GLcontext *ctx );
|
||||
|
||||
extern void intelInitDriverFunctions( struct dd_function_table *functions );
|
||||
|
||||
|
||||
/* ================================================================
|
||||
@@ -491,6 +513,8 @@ extern void intelInitStateFuncs( struct dd_function_table *functions );
|
||||
#define BLENDFACT_INV_CONST_ALPHA 0x0f
|
||||
#define BLENDFACT_MASK 0x0f
|
||||
|
||||
#define MI_BATCH_BUFFER_END (0xA<<23)
|
||||
|
||||
|
||||
extern int intel_translate_compare_func( GLenum func );
|
||||
extern int intel_translate_stencil_op( GLenum op );
|
||||
@@ -498,19 +522,26 @@ extern int intel_translate_blend_factor( GLenum factor );
|
||||
extern int intel_translate_logic_op( GLenum opcode );
|
||||
|
||||
|
||||
/* ================================================================
|
||||
* intel_ioctl.c:
|
||||
/*======================================================================
|
||||
* Inline conversion functions.
|
||||
* These are better-typed than the macros used previously:
|
||||
*/
|
||||
extern void intel_dump_batchbuffer( long offset,
|
||||
int *ptr,
|
||||
int count );
|
||||
static INLINE struct intel_context *intel_context( GLcontext *ctx )
|
||||
{
|
||||
return (struct intel_context *)ctx;
|
||||
}
|
||||
|
||||
static INLINE struct intel_texture_object *intel_texture_object( struct gl_texture_object *obj )
|
||||
{
|
||||
return (struct intel_texture_object *)obj;
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* intel_pixel.c:
|
||||
*/
|
||||
extern void intelInitPixelFuncs( struct dd_function_table *functions );
|
||||
static INLINE struct intel_texture_image *intel_texture_image( struct gl_texture_image *img )
|
||||
{
|
||||
return (struct intel_texture_image *)img;
|
||||
}
|
||||
|
||||
extern struct intel_renderbuffer *intel_renderbuffer( struct gl_renderbuffer *rb );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
281
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal file
281
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "glheader.h"
|
||||
#include "imports.h"
|
||||
#include "context.h"
|
||||
#include "depthstencil.h"
|
||||
#include "fbobject.h"
|
||||
#include "framebuffer.h"
|
||||
#include "hash.h"
|
||||
#include "mtypes.h"
|
||||
#include "renderbuffer.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_depthstencil.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
|
||||
/**
|
||||
* The GL_EXT_framebuffer_object allows the user to create their own
|
||||
* framebuffer objects consisting of color renderbuffers (0 or more),
|
||||
* depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1).
|
||||
*
|
||||
* The spec considers depth and stencil renderbuffers to be totally independent
|
||||
* buffers. In reality, most graphics hardware today uses a combined
|
||||
* depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil).
|
||||
*
|
||||
* This causes difficulty because the user may create some number of depth
|
||||
* renderbuffers and some number of stencil renderbuffers and bind them
|
||||
* together in framebuffers in any combination.
|
||||
*
|
||||
* This code manages all that.
|
||||
*
|
||||
* 1. Depth renderbuffers are always allocated in hardware as 32bpp
|
||||
* GL_DEPTH24_STENCIL8 buffers.
|
||||
*
|
||||
* 2. Stencil renderbuffers are initially allocated in software as 8bpp
|
||||
* GL_STENCIL_INDEX8 buffers.
|
||||
*
|
||||
* 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth
|
||||
* fields (respectively) to indicate if the buffer's currently paired
|
||||
* with another stencil or depth buffer (respectively).
|
||||
*
|
||||
* 4. When a depth and stencil buffer are initially both attached to the
|
||||
* current framebuffer, we merge the stencil buffer values into the
|
||||
* depth buffer (really a depth+stencil buffer). The then hardware uses
|
||||
* the combined buffer.
|
||||
*
|
||||
* 5. Whenever a depth or stencil buffer is reallocated (with
|
||||
* glRenderbufferStorage) we undo the pairing and copy the stencil values
|
||||
* from the combined depth/stencil buffer back to the stencil-only buffer.
|
||||
*
|
||||
* 6. We also undo the pairing when we find a change in buffer bindings.
|
||||
*
|
||||
* 7. If a framebuffer is only using a depth renderbuffer (no stencil), we
|
||||
* just use the combined depth/stencil buffer and ignore the stencil values.
|
||||
*
|
||||
* 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have
|
||||
* to promote the 8bpp software stencil buffer to a 32bpp hardware
|
||||
* depth+stencil buffer.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static void
|
||||
map_regions(GLcontext *ctx,
|
||||
struct intel_renderbuffer *depthRb,
|
||||
struct intel_renderbuffer *stencilRb)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
if (depthRb && depthRb->region) {
|
||||
intel_region_map(intel, depthRb->region);
|
||||
depthRb->pfMap = depthRb->region->map;
|
||||
depthRb->pfPitch = depthRb->region->pitch;
|
||||
}
|
||||
if (stencilRb && stencilRb->region) {
|
||||
intel_region_map(intel, stencilRb->region);
|
||||
stencilRb->pfMap = stencilRb->region->map;
|
||||
stencilRb->pfPitch = stencilRb->region->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_regions(GLcontext *ctx,
|
||||
struct intel_renderbuffer *depthRb,
|
||||
struct intel_renderbuffer *stencilRb)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
if (depthRb && depthRb->region) {
|
||||
intel_region_unmap(intel, depthRb->region);
|
||||
depthRb->pfMap = NULL;
|
||||
depthRb->pfPitch = 0;
|
||||
}
|
||||
if (stencilRb && stencilRb->region) {
|
||||
intel_region_unmap(intel, stencilRb->region);
|
||||
stencilRb->pfMap = NULL;
|
||||
stencilRb->pfPitch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Undo the pairing/interleaving between depth and stencil buffers.
|
||||
* irb should be a depth/stencil or stencil renderbuffer.
|
||||
*/
|
||||
void
|
||||
intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb)
|
||||
{
|
||||
if (irb->PairedStencil) {
|
||||
/* irb is a depth/stencil buffer */
|
||||
struct gl_renderbuffer *stencilRb;
|
||||
struct intel_renderbuffer *stencilIrb;
|
||||
|
||||
ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
|
||||
stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil);
|
||||
stencilIrb = intel_renderbuffer(stencilRb);
|
||||
if (stencilIrb) {
|
||||
/* need to extract stencil values from the depth buffer */
|
||||
ASSERT(stencilIrb->PairedDepth == irb->Base.Name);
|
||||
map_regions(ctx, irb, stencilIrb);
|
||||
_mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base);
|
||||
unmap_regions(ctx, irb, stencilIrb);
|
||||
stencilIrb->PairedDepth = 0;
|
||||
}
|
||||
irb->PairedStencil = 0;
|
||||
}
|
||||
else if (irb->PairedDepth) {
|
||||
/* irb is a stencil buffer */
|
||||
struct gl_renderbuffer *depthRb;
|
||||
struct intel_renderbuffer *depthIrb;
|
||||
|
||||
ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
|
||||
irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
|
||||
depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth);
|
||||
depthIrb = intel_renderbuffer(depthRb);
|
||||
if (depthIrb) {
|
||||
/* need to extract stencil values from the depth buffer */
|
||||
ASSERT(depthIrb->PairedStencil == irb->Base.Name);
|
||||
map_regions(ctx, depthIrb, irb);
|
||||
_mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base);
|
||||
unmap_regions(ctx, depthIrb, irb);
|
||||
depthIrb->PairedStencil = 0;
|
||||
}
|
||||
irb->PairedDepth = 0;
|
||||
}
|
||||
else {
|
||||
_mesa_problem(ctx, "Problem in undo_depth_stencil_pairing");
|
||||
}
|
||||
|
||||
ASSERT(irb->PairedStencil == 0);
|
||||
ASSERT(irb->PairedDepth == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Examine the depth and stencil renderbuffers which are attached to the
|
||||
* framebuffer. If both depth and stencil are attached, make sure that the
|
||||
* renderbuffers are 'paired' (combined). If only depth or only stencil is
|
||||
* attached, undo any previous pairing.
|
||||
*
|
||||
* Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments
|
||||
* change, for example).
|
||||
*/
|
||||
void
|
||||
intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb)
|
||||
{
|
||||
struct intel_renderbuffer *depthRb, *stencilRb;
|
||||
|
||||
depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
|
||||
if (depthRb && stencilRb) {
|
||||
if (depthRb == stencilRb) {
|
||||
/* Using a user-created combined depth/stencil buffer.
|
||||
* Nothing to do.
|
||||
*/
|
||||
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT);
|
||||
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
}
|
||||
else {
|
||||
/* Separate depth/stencil buffers, need to interleave now */
|
||||
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT);
|
||||
ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX);
|
||||
/* may need to interleave depth/stencil now */
|
||||
if (depthRb->PairedStencil == stencilRb->Base.Name) {
|
||||
/* OK, the depth and stencil buffers are already interleaved */
|
||||
ASSERT(stencilRb->PairedDepth == depthRb->Base.Name);
|
||||
}
|
||||
else {
|
||||
/* need to setup new pairing/interleaving */
|
||||
if (depthRb->PairedStencil) {
|
||||
intel_unpair_depth_stencil(ctx, depthRb);
|
||||
}
|
||||
if (stencilRb->PairedDepth) {
|
||||
intel_unpair_depth_stencil(ctx, stencilRb);
|
||||
}
|
||||
|
||||
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
|
||||
stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
|
||||
/* establish new pairing: interleave stencil into depth buffer */
|
||||
map_regions(ctx, depthRb, stencilRb);
|
||||
_mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base);
|
||||
unmap_regions(ctx, depthRb, stencilRb);
|
||||
depthRb->PairedStencil = stencilRb->Base.Name;
|
||||
stencilRb->PairedDepth = depthRb->Base.Name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (depthRb) {
|
||||
/* Depth buffer but no stencil buffer.
|
||||
* We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
|
||||
*/
|
||||
/* can't assert this until storage is allocated:
|
||||
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
*/
|
||||
/* intel_undo any previous pairing */
|
||||
if (depthRb->PairedStencil) {
|
||||
intel_unpair_depth_stencil(ctx, depthRb);
|
||||
}
|
||||
}
|
||||
else if (stencilRb) {
|
||||
/* Stencil buffer but no depth buffer.
|
||||
* Since h/w doesn't typically support just 8bpp stencil w/out Z,
|
||||
* we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
|
||||
*/
|
||||
/* undo any previous pairing */
|
||||
if (stencilRb->PairedDepth) {
|
||||
intel_unpair_depth_stencil(ctx, stencilRb);
|
||||
}
|
||||
if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
|
||||
/* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */
|
||||
_mesa_promote_stencil(ctx, &stencilRb->Base);
|
||||
ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */
|
||||
_mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
|
||||
if (depthRb && depthRb->PairedStencil)
|
||||
_mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH);
|
||||
else
|
||||
_mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL);
|
||||
|
||||
|
||||
/* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
|
||||
* first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer
|
||||
* if present.
|
||||
*/
|
||||
}
|
||||
13
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal file
13
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
#ifndef INTEL_DEPTH_STENCIL_H
|
||||
#define INTEL_DEPTH_STENCIL_H
|
||||
|
||||
|
||||
extern void
|
||||
intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb);
|
||||
|
||||
extern void
|
||||
intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb);
|
||||
|
||||
|
||||
#endif /* INTEL_DEPTH_STENCIL_H */
|
||||
638
src/mesa/drivers/dri/i915/intel_fbo.c
Normal file
638
src/mesa/drivers/dri/i915/intel_fbo.c
Normal file
@@ -0,0 +1,638 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "imports.h"
|
||||
#include "mtypes.h"
|
||||
#include "fbobject.h"
|
||||
#include "framebuffer.h"
|
||||
#include "renderbuffer.h"
|
||||
#include "context.h"
|
||||
#include "texformat.h"
|
||||
#include "texrender.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_bufmgr.h"
|
||||
#include "intel_depthstencil.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_span.h"
|
||||
|
||||
#define INTEL_RB_CLASS 0x12345678
|
||||
|
||||
|
||||
/* XXX FBO: move this to intel_context.h (inlined) */
|
||||
/**
|
||||
* Return a gl_renderbuffer ptr casted to intel_renderbuffer.
|
||||
* NULL will be returned if the rb isn't really an intel_renderbuffer.
|
||||
* This is determiend by checking the ClassID.
|
||||
*/
|
||||
struct intel_renderbuffer *intel_renderbuffer( struct gl_renderbuffer *rb )
|
||||
{
|
||||
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
|
||||
if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
|
||||
/*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
|
||||
return irb;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct intel_renderbuffer *
|
||||
intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex)
|
||||
{
|
||||
return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
|
||||
}
|
||||
|
||||
|
||||
struct intel_region *
|
||||
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
|
||||
{
|
||||
struct intel_renderbuffer *irb
|
||||
= intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
|
||||
if (irb)
|
||||
return irb->region;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new framebuffer object.
|
||||
*/
|
||||
static struct gl_framebuffer *
|
||||
intel_new_framebuffer(GLcontext *ctx, GLuint name)
|
||||
{
|
||||
/* there's no intel_framebuffer at this time, just use Mesa's class */
|
||||
return _mesa_new_framebuffer(ctx, name);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_delete_renderbuffer(struct gl_renderbuffer *rb)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
||||
|
||||
ASSERT(irb);
|
||||
|
||||
if (irb->PairedStencil || irb->PairedDepth) {
|
||||
intel_unpair_depth_stencil(ctx, irb);
|
||||
}
|
||||
|
||||
if (intel && irb->region) {
|
||||
intel_region_release(intel, &irb->region);
|
||||
}
|
||||
|
||||
_mesa_free(irb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a pointer to a specific pixel in a renderbuffer.
|
||||
*/
|
||||
static void *
|
||||
intel_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
GLint x, GLint y)
|
||||
{
|
||||
/* By returning NULL we force all software rendering to go through
|
||||
* the span routines.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called via glRenderbufferStorageEXT() to set the format and allocate
|
||||
* storage for a user-created renderbuffer.
|
||||
*/
|
||||
static GLboolean
|
||||
intel_alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
GLenum internalFormat,
|
||||
GLuint width, GLuint height)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
||||
GLboolean softwareBuffer = GL_FALSE;
|
||||
int cpp;
|
||||
|
||||
ASSERT(rb->Name != 0);
|
||||
|
||||
switch (internalFormat) {
|
||||
case GL_R3_G3_B2:
|
||||
case GL_RGB4:
|
||||
case GL_RGB5:
|
||||
rb->_ActualFormat = GL_RGB5;
|
||||
rb->DataType = GL_UNSIGNED_BYTE;
|
||||
rb->RedBits = 5;
|
||||
rb->GreenBits = 6;
|
||||
rb->BlueBits = 5;
|
||||
cpp = 2;
|
||||
break;
|
||||
case GL_RGB:
|
||||
case GL_RGB8:
|
||||
case GL_RGB10:
|
||||
case GL_RGB12:
|
||||
case GL_RGB16:
|
||||
case GL_RGBA:
|
||||
case GL_RGBA2:
|
||||
case GL_RGBA4:
|
||||
case GL_RGB5_A1:
|
||||
case GL_RGBA8:
|
||||
case GL_RGB10_A2:
|
||||
case GL_RGBA12:
|
||||
case GL_RGBA16:
|
||||
rb->_ActualFormat = GL_RGBA8;
|
||||
rb->DataType = GL_UNSIGNED_BYTE;
|
||||
rb->RedBits = 8;
|
||||
rb->GreenBits = 8;
|
||||
rb->BlueBits = 8;
|
||||
rb->AlphaBits = 8;
|
||||
cpp = 4;
|
||||
break;
|
||||
case GL_STENCIL_INDEX:
|
||||
case GL_STENCIL_INDEX1_EXT:
|
||||
case GL_STENCIL_INDEX4_EXT:
|
||||
case GL_STENCIL_INDEX8_EXT:
|
||||
case GL_STENCIL_INDEX16_EXT:
|
||||
/* alloc a depth+stencil buffer */
|
||||
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
|
||||
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
|
||||
rb->StencilBits = 8;
|
||||
cpp = 4;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
|
||||
rb->DataType = GL_UNSIGNED_SHORT;
|
||||
rb->DepthBits = 16;
|
||||
cpp = 2;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
|
||||
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
|
||||
rb->DepthBits = 24;
|
||||
cpp = 4;
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
case GL_DEPTH24_STENCIL8_EXT:
|
||||
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
|
||||
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
|
||||
rb->DepthBits = 24;
|
||||
rb->StencilBits = 8;
|
||||
cpp = 4;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "Unexpected format in intel_alloc_renderbuffer_storage");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
intelFlush(ctx);
|
||||
|
||||
/* free old region */
|
||||
if (irb->region) {
|
||||
/*LOCK_HARDWARE(intel);*/
|
||||
intel_region_release(intel, &irb->region);
|
||||
/*UNLOCK_HARDWARE(intel);*/
|
||||
}
|
||||
|
||||
/* allocate new memory region/renderbuffer */
|
||||
if (softwareBuffer) {
|
||||
return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
|
||||
width, height);
|
||||
}
|
||||
else {
|
||||
/* Choose a pitch to match hardware requirements:
|
||||
*/
|
||||
GLuint pitch = ((cpp * width + 63) & ~63) / cpp;
|
||||
|
||||
/* alloc hardware renderbuffer */
|
||||
_mesa_debug(ctx, "Allocating %d x %d Intel RBO (pitch %d)\n", width, height, pitch);
|
||||
|
||||
irb->region = intel_region_alloc(intel, cpp, pitch, height);
|
||||
if (!irb->region)
|
||||
return GL_FALSE; /* out of memory? */
|
||||
|
||||
ASSERT(irb->region->buffer);
|
||||
|
||||
rb->Width = width;
|
||||
rb->Height = height;
|
||||
|
||||
/* This sets the Get/PutRow/Value functions */
|
||||
intel_set_span_functions(&irb->Base);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called for each hardware renderbuffer when a _window_ is resized.
|
||||
* Just update fields.
|
||||
* Not used for user-created renderbuffers!
|
||||
*/
|
||||
static GLboolean
|
||||
intel_alloc_window_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
GLenum internalFormat,
|
||||
GLuint width, GLuint height)
|
||||
{
|
||||
ASSERT(rb->Name == 0);
|
||||
rb->Width = width;
|
||||
rb->Height = height;
|
||||
rb->_ActualFormat = internalFormat;
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
intel_nop_alloc_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
|
||||
GLenum internalFormat,
|
||||
GLuint width, GLuint height)
|
||||
{
|
||||
_mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new intel_renderbuffer which corresponds to an on-screen window,
|
||||
* not a user-created renderbuffer.
|
||||
* \param width the screen width
|
||||
* \param height the screen height
|
||||
*/
|
||||
struct intel_renderbuffer *
|
||||
intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
|
||||
int offset, int pitch, int cpp, void *map)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
struct intel_renderbuffer *irb;
|
||||
const GLuint name = 0;
|
||||
|
||||
irb = CALLOC_STRUCT(intel_renderbuffer);
|
||||
if (!irb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_mesa_init_renderbuffer(&irb->Base, name);
|
||||
irb->Base.ClassID = INTEL_RB_CLASS;
|
||||
|
||||
switch (intFormat) {
|
||||
case GL_RGB5:
|
||||
irb->Base._ActualFormat = GL_RGB5;
|
||||
irb->Base._BaseFormat = GL_RGBA;
|
||||
irb->Base.RedBits = 5;
|
||||
irb->Base.GreenBits = 6;
|
||||
irb->Base.BlueBits = 5;
|
||||
irb->Base.DataType = GL_UNSIGNED_BYTE;
|
||||
cpp = 2;
|
||||
break;
|
||||
case GL_RGBA8:
|
||||
irb->Base._ActualFormat = GL_RGBA8;
|
||||
irb->Base._BaseFormat = GL_RGBA;
|
||||
irb->Base.RedBits = 8;
|
||||
irb->Base.GreenBits = 8;
|
||||
irb->Base.BlueBits = 8;
|
||||
irb->Base.AlphaBits = 8;
|
||||
irb->Base.DataType = GL_UNSIGNED_BYTE;
|
||||
cpp = 4;
|
||||
break;
|
||||
case GL_STENCIL_INDEX8_EXT:
|
||||
irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
|
||||
irb->Base._BaseFormat = GL_STENCIL_INDEX;
|
||||
irb->Base.StencilBits = 8;
|
||||
irb->Base.DataType = GL_UNSIGNED_BYTE;
|
||||
cpp = 1;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
|
||||
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
|
||||
irb->Base.DepthBits = 16;
|
||||
irb->Base.DataType = GL_UNSIGNED_SHORT;
|
||||
cpp = 2;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
|
||||
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
|
||||
irb->Base.DepthBits = 24;
|
||||
irb->Base.DataType = GL_UNSIGNED_INT;
|
||||
cpp = 4;
|
||||
break;
|
||||
case GL_DEPTH24_STENCIL8_EXT:
|
||||
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
|
||||
irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
|
||||
irb->Base.DepthBits = 24;
|
||||
irb->Base.StencilBits = 8;
|
||||
irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
|
||||
cpp = 4;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(NULL, "Unexpected intFormat in intel_create_renderbuffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
irb->Base.InternalFormat = intFormat;
|
||||
|
||||
/* intel-specific methods */
|
||||
irb->Base.Delete = intel_delete_renderbuffer;
|
||||
irb->Base.AllocStorage = intel_alloc_window_storage;
|
||||
irb->Base.GetPointer = intel_get_pointer;
|
||||
/* This sets the Get/PutRow/Value functions */
|
||||
intel_set_span_functions(&irb->Base);
|
||||
|
||||
irb->pfMap = map;
|
||||
irb->pfPitch = pitch;
|
||||
|
||||
#if 00
|
||||
irb->region = intel_region_create_static(intel,
|
||||
DRM_MM_TT,
|
||||
offset,
|
||||
map,
|
||||
cpp,
|
||||
width, height);
|
||||
#endif
|
||||
|
||||
return irb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new renderbuffer object.
|
||||
* Typically called via glBindRenderbufferEXT().
|
||||
*/
|
||||
static struct gl_renderbuffer *
|
||||
intel_new_renderbuffer(GLcontext *ctx, GLuint name)
|
||||
{
|
||||
/*struct intel_context *intel = intel_context(ctx);*/
|
||||
struct intel_renderbuffer *irb;
|
||||
|
||||
irb = CALLOC_STRUCT(intel_renderbuffer);
|
||||
if (!irb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_mesa_init_renderbuffer(&irb->Base, name);
|
||||
irb->Base.ClassID = INTEL_RB_CLASS;
|
||||
|
||||
/* intel-specific methods */
|
||||
irb->Base.Delete = intel_delete_renderbuffer;
|
||||
irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
|
||||
irb->Base.GetPointer = intel_get_pointer;
|
||||
/* span routines set in alloc_storage function */
|
||||
|
||||
return &irb->Base;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via glBindFramebufferEXT().
|
||||
*/
|
||||
static void
|
||||
intel_bind_framebuffer(GLcontext *ctx, GLenum target,
|
||||
struct gl_framebuffer *fb)
|
||||
{
|
||||
/*
|
||||
_mesa_debug(ctx, "%s %d\n", __FUNCTION__, fb->Name);
|
||||
*/
|
||||
/* XXX FBO: putting this flush here fixes a rendering offset bug.
|
||||
* Not sure why this is needed when _mesa_BindFrameBuffer does
|
||||
* a FLUSH_VERTICES().
|
||||
*/
|
||||
intelFlush(ctx);
|
||||
|
||||
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
|
||||
intel_draw_buffer(ctx, fb);
|
||||
/* Integer depth range depends on depth buffer bits */
|
||||
ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
|
||||
}
|
||||
else {
|
||||
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via glFramebufferRenderbufferEXT().
|
||||
*/
|
||||
static void
|
||||
intel_framebuffer_renderbuffer(GLcontext *ctx,
|
||||
struct gl_framebuffer *fb,
|
||||
GLenum attachment,
|
||||
struct gl_renderbuffer *rb)
|
||||
{
|
||||
/*
|
||||
_mesa_debug(ctx, "Intel FramebufferRenderbuffer %u %u\n",
|
||||
fb->Name, rb ? rb->Name : 0);
|
||||
*/
|
||||
|
||||
intelFlush(ctx);
|
||||
|
||||
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
|
||||
intel_draw_buffer(ctx, fb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When glFramebufferTexture[123]D is called this function sets up the
|
||||
* gl_renderbuffer wrapp around the texture image.
|
||||
* This will have the region info needed for hardware rendering.
|
||||
*/
|
||||
static struct intel_renderbuffer *
|
||||
intel_wrap_texture(GLcontext *ctx, struct gl_texture_image *texImage)
|
||||
{
|
||||
const GLuint name = ~0; /* not significant, but distinct for debugging */
|
||||
struct intel_renderbuffer *irb;
|
||||
|
||||
/* make an intel_renderbuffer to wrap the texture image */
|
||||
irb = CALLOC_STRUCT(intel_renderbuffer);
|
||||
if (!irb) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_mesa_init_renderbuffer(&irb->Base, name);
|
||||
irb->Base.ClassID = INTEL_RB_CLASS;
|
||||
|
||||
if (texImage->TexFormat == &_mesa_texformat_argb8888) {
|
||||
irb->Base._ActualFormat = GL_RGBA8;
|
||||
irb->Base._BaseFormat = GL_RGBA;
|
||||
_mesa_debug(ctx, "Render to RGBA8 texture OK\n");
|
||||
}
|
||||
else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
|
||||
irb->Base._ActualFormat = GL_RGB5;
|
||||
irb->Base._BaseFormat = GL_RGB;
|
||||
_mesa_debug(ctx, "Render to RGB5 texture OK\n");
|
||||
}
|
||||
else if (texImage->TexFormat == &_mesa_texformat_depth_component16) {
|
||||
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
|
||||
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
|
||||
_mesa_debug(ctx, "Render to DEPTH16 texture OK\n");
|
||||
}
|
||||
else {
|
||||
_mesa_debug(ctx, "Render to texture BAD FORMAT %d\n", texImage->TexFormat->MesaFormat);
|
||||
_mesa_free(irb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
irb->Base.InternalFormat = irb->Base._ActualFormat;
|
||||
irb->Base.Width = texImage->Width;
|
||||
irb->Base.Height = texImage->Height;
|
||||
irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */
|
||||
irb->Base.RedBits = texImage->TexFormat->RedBits;
|
||||
irb->Base.GreenBits = texImage->TexFormat->GreenBits;
|
||||
irb->Base.BlueBits = texImage->TexFormat->BlueBits;
|
||||
irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
|
||||
irb->Base.DepthBits = texImage->TexFormat->DepthBits;
|
||||
|
||||
irb->Base.Delete = intel_delete_renderbuffer;
|
||||
irb->Base.AllocStorage = intel_nop_alloc_storage;
|
||||
intel_set_span_functions(&irb->Base);
|
||||
|
||||
irb->RenderToTexture = GL_TRUE;
|
||||
|
||||
return irb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by glFramebufferTexture[123]DEXT() (and other places) to
|
||||
* prepare for rendering into texture memory. This might be called
|
||||
* many times to choose different texture levels, cube faces, etc
|
||||
* before intel_finish_render_texture() is ever called.
|
||||
*/
|
||||
static void
|
||||
intel_render_texture(GLcontext *ctx,
|
||||
struct gl_framebuffer *fb,
|
||||
struct gl_renderbuffer_attachment *att)
|
||||
{
|
||||
struct gl_texture_image *newImage
|
||||
= att->Texture->Image[att->CubeMapFace][att->TextureLevel];
|
||||
struct intel_renderbuffer *irb
|
||||
= intel_renderbuffer(att->Renderbuffer);
|
||||
struct intel_texture_image *intel_image;
|
||||
GLuint imageOffset;
|
||||
|
||||
(void) fb;
|
||||
|
||||
ASSERT(newImage);
|
||||
|
||||
if (!irb) {
|
||||
irb = intel_wrap_texture(ctx, newImage);
|
||||
if (irb) {
|
||||
/* bind the wrapper to the attachment point */
|
||||
att->Renderbuffer = &irb->Base;
|
||||
}
|
||||
else {
|
||||
/* fallback to software rendering */
|
||||
_mesa_render_texture(ctx, fb, att);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
_mesa_debug(ctx, "Begin render texture tex=%u w=%d h=%d refcount=%d\n",
|
||||
att->Texture->Name, newImage->Width, newImage->Height,
|
||||
irb->Base.RefCount);
|
||||
*/
|
||||
|
||||
/* point the renderbufer's region to the texture image region */
|
||||
intel_image = intel_texture_image(newImage);
|
||||
if (irb->region != intel_image->mt->region)
|
||||
intel_region_reference(&irb->region, intel_image->mt->region);
|
||||
|
||||
/* compute offset of the particular 2D image within the texture region */
|
||||
imageOffset = intel_miptree_image_offset(intel_image->mt,
|
||||
att->CubeMapFace,
|
||||
att->TextureLevel);
|
||||
if (att->Texture->Target == GL_TEXTURE_3D) {
|
||||
GLuint imgStride = intel_miptree_depth_image_stride(intel_image->mt,
|
||||
att->CubeMapFace,
|
||||
att->TextureLevel);
|
||||
imageOffset += imgStride * att->Zoffset;
|
||||
}
|
||||
/* store that offset in the region */
|
||||
intel_image->mt->region->draw_offset = imageOffset;
|
||||
|
||||
/* update drawing region, etc */
|
||||
intel_draw_buffer(ctx, fb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by Mesa when rendering to a texture is done.
|
||||
*/
|
||||
static void
|
||||
intel_finish_render_texture(GLcontext *ctx,
|
||||
struct gl_renderbuffer_attachment *att)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_renderbuffer *irb
|
||||
= intel_renderbuffer(att->Renderbuffer);
|
||||
|
||||
/*
|
||||
_mesa_debug(ctx, "End render texture (tid %u) tex %u\n",
|
||||
_glthread_GetID(), att->Texture->Name);
|
||||
*/
|
||||
|
||||
if (irb) {
|
||||
/* just release the region */
|
||||
intel_region_release(intel, &irb->region);
|
||||
}
|
||||
else if (att->Renderbuffer) {
|
||||
/* software fallback */
|
||||
_mesa_finish_render_texture(ctx, att);
|
||||
/* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do one-time context initializations related to GL_EXT_framebuffer_object.
|
||||
* Hook in device driver functions.
|
||||
*/
|
||||
void
|
||||
intel_fbo_init( struct intel_context *intel )
|
||||
{
|
||||
intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
|
||||
intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
|
||||
intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
|
||||
intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
|
||||
intel->ctx.Driver.RenderTexture = intel_render_texture;
|
||||
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
|
||||
}
|
||||
75
src/mesa/drivers/dri/i915/intel_fbo.h
Normal file
75
src/mesa/drivers/dri/i915/intel_fbo.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_FBO_H
|
||||
#define INTEL_FBO_H
|
||||
|
||||
|
||||
struct intel_context;
|
||||
struct intel_region;
|
||||
|
||||
|
||||
/**
|
||||
* Intel renderbuffer, derived from gl_renderbuffer.
|
||||
* Note: The PairedDepth and PairedStencil fields use renderbuffer IDs,
|
||||
* not pointers because in some circumstances a deleted renderbuffer could
|
||||
* result in a dangling pointer here.
|
||||
*/
|
||||
struct intel_renderbuffer {
|
||||
struct gl_renderbuffer Base;
|
||||
struct intel_region *region;
|
||||
void *pfMap; /* possibly paged flipped map pointer */
|
||||
GLuint pfPitch; /* possibly paged flipped pitch */
|
||||
GLboolean RenderToTexture; /* RTT? */
|
||||
|
||||
GLuint PairedDepth; /**< only used if this is a depth renderbuffer */
|
||||
GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */
|
||||
};
|
||||
|
||||
|
||||
extern struct intel_renderbuffer *
|
||||
intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
|
||||
int offset, int pitch, int cpp, void *map);
|
||||
|
||||
|
||||
extern void
|
||||
intel_fbo_init( struct intel_context *intel );
|
||||
|
||||
|
||||
/* XXX make inline or macro */
|
||||
extern struct intel_renderbuffer *
|
||||
intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex);
|
||||
|
||||
|
||||
/* XXX make inline or macro */
|
||||
extern struct intel_region *
|
||||
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* INTEL_FBO_H */
|
||||
@@ -38,11 +38,13 @@
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_regions.h"
|
||||
#include "drm.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
|
||||
|
||||
static int intelEmitIrqLocked( intelContextPtr intel )
|
||||
int intelEmitIrqLocked( struct intel_context *intel )
|
||||
{
|
||||
drmI830IrqEmit ie;
|
||||
int ret, seq = 0;
|
||||
@@ -51,21 +53,21 @@ static int intelEmitIrqLocked( intelContextPtr intel )
|
||||
(DRM_LOCK_HELD|intel->hHWContext));
|
||||
|
||||
ie.irq_seq = &seq;
|
||||
|
||||
|
||||
ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT,
|
||||
&ie, sizeof(ie) );
|
||||
if ( ret ) {
|
||||
fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s --> %d\n", __FUNCTION__, seq );
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
static void intelWaitIrq( intelContextPtr intel, int seq )
|
||||
void intelWaitIrq( struct intel_context *intel, int seq )
|
||||
{
|
||||
drmI830IrqWait iw;
|
||||
int ret;
|
||||
@@ -81,527 +83,69 @@ static void intelWaitIrq( intelContextPtr intel, int seq )
|
||||
|
||||
if ( ret ) {
|
||||
fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret );
|
||||
if (0)
|
||||
intel_dump_batchbuffer( intel->alloc.offset,
|
||||
intel->alloc.ptr,
|
||||
intel->alloc.size );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void age_intel( intelContextPtr intel, int age )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
|
||||
if (intel->CurrentTexObj[i])
|
||||
intel->CurrentTexObj[i]->age = age;
|
||||
}
|
||||
|
||||
void intel_dump_batchbuffer( long offset,
|
||||
int *ptr,
|
||||
int count )
|
||||
{
|
||||
int i;
|
||||
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count);
|
||||
for (i = 0; i < count/4; i += 4)
|
||||
fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
|
||||
(unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]);
|
||||
fprintf(stderr, "END BATCH\n\n\n");
|
||||
}
|
||||
|
||||
void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock )
|
||||
{
|
||||
GLuint last_irq = intel->alloc.irq_emitted;
|
||||
GLuint half = intel->alloc.size / 2;
|
||||
GLuint buf = (intel->alloc.active_buf ^= 1);
|
||||
|
||||
intel->alloc.irq_emitted = intelEmitIrqLocked( intel );
|
||||
|
||||
if (last_irq) {
|
||||
if (allow_unlock) UNLOCK_HARDWARE( intel );
|
||||
intelWaitIrq( intel, last_irq );
|
||||
if (allow_unlock) LOCK_HARDWARE( intel );
|
||||
}
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf);
|
||||
|
||||
intel->batch.start_offset = intel->alloc.offset + buf * half;
|
||||
intel->batch.ptr = (GLubyte *)intel->alloc.ptr + buf * half;
|
||||
intel->batch.size = half - 8;
|
||||
intel->batch.space = half - 8;
|
||||
assert(intel->batch.space >= 0);
|
||||
}
|
||||
|
||||
#define MI_BATCH_BUFFER_END (0xA<<23)
|
||||
|
||||
|
||||
void intelFlushBatchLocked( intelContextPtr intel,
|
||||
GLboolean ignore_cliprects,
|
||||
GLboolean refill,
|
||||
GLboolean allow_unlock)
|
||||
void intel_batch_ioctl( struct intel_context *intel,
|
||||
GLuint start_offset,
|
||||
GLuint used,
|
||||
GLboolean ignore_cliprects,
|
||||
GLboolean allow_unlock)
|
||||
{
|
||||
drmI830BatchBuffer batch;
|
||||
|
||||
assert(intel->locked);
|
||||
assert(used);
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n",
|
||||
fprintf(stderr, "%s used %d offset %x..%x ignore_cliprects %d\n",
|
||||
__FUNCTION__,
|
||||
(intel->batch.size - intel->batch.space),
|
||||
intel->batch.size,
|
||||
intel->batch.start_offset,
|
||||
intel->batch.start_offset +
|
||||
(intel->batch.size - intel->batch.space),
|
||||
refill);
|
||||
used,
|
||||
start_offset,
|
||||
start_offset + used,
|
||||
ignore_cliprects);
|
||||
|
||||
/* Throw away non-effective packets. Won't work once we have
|
||||
* hardware contexts which would preserve statechanges beyond a
|
||||
* single buffer.
|
||||
*/
|
||||
if (intel->numClipRects == 0 && !ignore_cliprects) {
|
||||
|
||||
/* Without this yeild, an application with no cliprects can hog
|
||||
* the hardware. Without unlocking, the effect is much worse -
|
||||
* effectively a lock-out of other contexts.
|
||||
*/
|
||||
if (allow_unlock) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
UNLOCK_HARDWARE(intel);
|
||||
sched_yield();
|
||||
LOCK_HARDWARE( intel );
|
||||
LOCK_HARDWARE(intel);
|
||||
}
|
||||
|
||||
/* Note that any state thought to have been emitted actually
|
||||
* hasn't:
|
||||
*/
|
||||
intel->batch.ptr -= (intel->batch.size - intel->batch.space);
|
||||
intel->batch.space = intel->batch.size;
|
||||
intel->vtbl.lost_hardware( intel );
|
||||
}
|
||||
|
||||
if (intel->batch.space != intel->batch.size) {
|
||||
batch.start = intel->batch.start_offset;
|
||||
batch.used = intel->batch.size - intel->batch.space;
|
||||
batch.cliprects = intel->pClipRects;
|
||||
batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
|
||||
batch.DR1 = 0;
|
||||
batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |
|
||||
(((GLuint)intel->drawY) << 16));
|
||||
|
||||
if (intel->alloc.offset) {
|
||||
if ((batch.used & 0x4) == 0) {
|
||||
((int *)intel->batch.ptr)[0] = 0;
|
||||
((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END;
|
||||
batch.used += 0x8;
|
||||
intel->batch.ptr += 0x8;
|
||||
}
|
||||
else {
|
||||
((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END;
|
||||
batch.used += 0x4;
|
||||
intel->batch.ptr += 0x4;
|
||||
}
|
||||
}
|
||||
|
||||
if (0)
|
||||
intel_dump_batchbuffer( batch.start,
|
||||
(int *)(intel->batch.ptr - batch.used),
|
||||
batch.used );
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
|
||||
__FUNCTION__,
|
||||
batch.start,
|
||||
batch.start + batch.used,
|
||||
batch.DR4, batch.num_cliprects);
|
||||
|
||||
intel->batch.start_offset += batch.used;
|
||||
intel->batch.size -= batch.used;
|
||||
|
||||
if (intel->batch.size < 8) {
|
||||
refill = GL_TRUE;
|
||||
intel->batch.space = intel->batch.size = 0;
|
||||
}
|
||||
else {
|
||||
intel->batch.size -= 8;
|
||||
intel->batch.space = intel->batch.size;
|
||||
}
|
||||
|
||||
|
||||
assert(intel->batch.space >= 0);
|
||||
assert(batch.start >= intel->alloc.offset);
|
||||
assert(batch.start < intel->alloc.offset + intel->alloc.size);
|
||||
assert(batch.start + batch.used > intel->alloc.offset);
|
||||
assert(batch.start + batch.used <=
|
||||
intel->alloc.offset + intel->alloc.size);
|
||||
|
||||
|
||||
if (intel->alloc.offset) {
|
||||
if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,
|
||||
sizeof(batch))) {
|
||||
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
|
||||
UNLOCK_HARDWARE(intel);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
drmI830CmdBuffer cmd;
|
||||
cmd.buf = (char *)intel->alloc.ptr + batch.start;
|
||||
cmd.sz = batch.used;
|
||||
cmd.DR1 = batch.DR1;
|
||||
cmd.DR4 = batch.DR4;
|
||||
cmd.num_cliprects = batch.num_cliprects;
|
||||
cmd.cliprects = batch.cliprects;
|
||||
|
||||
if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd,
|
||||
sizeof(cmd))) {
|
||||
fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n", -errno);
|
||||
UNLOCK_HARDWARE(intel);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
age_intel(intel, intel->sarea->last_enqueue);
|
||||
|
||||
/* FIXME: use hardware contexts to avoid 'losing' hardware after
|
||||
* each buffer flush.
|
||||
*/
|
||||
intel->vtbl.lost_hardware( intel );
|
||||
}
|
||||
|
||||
if (refill)
|
||||
intelRefillBatchLocked( intel, allow_unlock );
|
||||
}
|
||||
|
||||
void intelFlushBatch( intelContextPtr intel, GLboolean refill )
|
||||
{
|
||||
if (intel->locked) {
|
||||
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE );
|
||||
}
|
||||
else {
|
||||
LOCK_HARDWARE(intel);
|
||||
intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE );
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void intelWaitForIdle( intelContextPtr intel )
|
||||
{
|
||||
if (0)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
intel->vtbl.emit_flush( intel );
|
||||
intelFlushBatch( intel, GL_TRUE );
|
||||
|
||||
/* Use an irq to wait for dma idle -- Need to track lost contexts
|
||||
* to shortcircuit consecutive calls to this function:
|
||||
*/
|
||||
intelWaitIrq( intel, intel->alloc.irq_emitted );
|
||||
intel->alloc.irq_emitted = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelFlush( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
|
||||
if (intel->Fallback)
|
||||
_swrast_flush( ctx );
|
||||
|
||||
INTEL_FIREVERTICES( intel );
|
||||
|
||||
if (intel->batch.size != intel->batch.space)
|
||||
intelFlushBatch( intel, GL_FALSE );
|
||||
}
|
||||
|
||||
void intelFinish( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
intelFlush( ctx );
|
||||
intelWaitForIdle( intel );
|
||||
}
|
||||
|
||||
|
||||
void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch)
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask);
|
||||
GLbitfield tri_mask = 0;
|
||||
GLbitfield blit_mask = 0;
|
||||
GLbitfield swrast_mask = 0;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
/* Take care of cliprects, which are handled differently for
|
||||
* clears, etc.
|
||||
*/
|
||||
intelFlush( &intel->ctx );
|
||||
|
||||
if (mask & BUFFER_BIT_FRONT_LEFT) {
|
||||
if (colorMask == ~0) {
|
||||
blit_mask |= BUFFER_BIT_FRONT_LEFT;
|
||||
}
|
||||
else {
|
||||
tri_mask |= BUFFER_BIT_FRONT_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & BUFFER_BIT_BACK_LEFT) {
|
||||
if (colorMask == ~0) {
|
||||
blit_mask |= BUFFER_BIT_BACK_LEFT;
|
||||
}
|
||||
else {
|
||||
tri_mask |= BUFFER_BIT_BACK_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask & BUFFER_BIT_DEPTH) {
|
||||
blit_mask |= BUFFER_BIT_DEPTH;
|
||||
}
|
||||
|
||||
if (mask & BUFFER_BIT_STENCIL) {
|
||||
if (!intel->hw_stencil) {
|
||||
swrast_mask |= BUFFER_BIT_STENCIL;
|
||||
}
|
||||
else if (ctx->Stencil.WriteMask[0] != 0xff) {
|
||||
tri_mask |= BUFFER_BIT_STENCIL;
|
||||
}
|
||||
else {
|
||||
blit_mask |= BUFFER_BIT_STENCIL;
|
||||
}
|
||||
}
|
||||
|
||||
swrast_mask |= (mask & BUFFER_BIT_ACCUM);
|
||||
|
||||
if (blit_mask)
|
||||
intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch );
|
||||
|
||||
if (tri_mask)
|
||||
intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch);
|
||||
|
||||
if (swrast_mask)
|
||||
_swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
|
||||
{
|
||||
int region_offset = 0;
|
||||
drmI830MemAlloc alloc;
|
||||
int ret;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size);
|
||||
|
||||
alloc.region = I830_MEM_REGION_AGP;
|
||||
alloc.alignment = 0;
|
||||
alloc.size = size;
|
||||
alloc.region_offset = ®ion_offset;
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
/* Make sure the global heap is initialized
|
||||
*/
|
||||
if (intel->texture_heaps[0])
|
||||
driAgeTextures( intel->texture_heaps[0] );
|
||||
|
||||
|
||||
ret = drmCommandWriteRead( intel->driFd,
|
||||
DRM_I830_ALLOC,
|
||||
&alloc, sizeof(alloc));
|
||||
|
||||
if (ret) {
|
||||
fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret);
|
||||
UNLOCK_HARDWARE(intel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size);
|
||||
|
||||
/* Need to propogate this information (agp memory in use) to our
|
||||
* local texture lru. The kernel has already updated the global
|
||||
* lru. An alternative would have been to allocate memory the
|
||||
* usual way and then notify the kernel to pin the allocation.
|
||||
*/
|
||||
if (intel->texture_heaps[0])
|
||||
driAgeTextures( intel->texture_heaps[0] );
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
return (void *)((char *)intel->intelScreen->tex.map + region_offset);
|
||||
}
|
||||
|
||||
void intelFreeAGP( intelContextPtr intel, void *pointer )
|
||||
{
|
||||
int region_offset;
|
||||
drmI830MemFree memfree;
|
||||
int ret;
|
||||
|
||||
region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
|
||||
|
||||
if (region_offset < 0 ||
|
||||
region_offset > intel->intelScreen->tex.size) {
|
||||
fprintf(stderr, "offset %d outside range 0..%d\n", region_offset,
|
||||
intel->intelScreen->tex.size);
|
||||
return;
|
||||
}
|
||||
|
||||
memfree.region = I830_MEM_REGION_AGP;
|
||||
memfree.region_offset = region_offset;
|
||||
|
||||
ret = drmCommandWrite( intel->driFd,
|
||||
DRM_I830_FREE,
|
||||
&memfree, sizeof(memfree));
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret);
|
||||
}
|
||||
|
||||
/* This version of AllocateMemoryMESA allocates only agp memory, and
|
||||
* only does so after the point at which the driver has been
|
||||
* initialized.
|
||||
*
|
||||
* Theoretically a valid context isn't required. However, in this
|
||||
* implementation, it is, as I'm using the hardware lock to protect
|
||||
* the kernel data structures, and the current context to get the
|
||||
* device fd.
|
||||
*/
|
||||
void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn,
|
||||
GLsizei size, GLfloat readfreq,
|
||||
GLfloat writefreq, GLfloat priority)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_IOCTL)
|
||||
fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,
|
||||
writefreq, priority);
|
||||
|
||||
if (getenv("INTEL_NO_ALLOC"))
|
||||
return NULL;
|
||||
|
||||
if (!ctx || INTEL_CONTEXT(ctx) == 0)
|
||||
return NULL;
|
||||
|
||||
return intelAllocateAGP( INTEL_CONTEXT(ctx), size );
|
||||
}
|
||||
|
||||
|
||||
/* Called via glXFreeMemoryMESA() */
|
||||
void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
if (INTEL_DEBUG & DEBUG_IOCTL)
|
||||
fprintf(stderr, "%s %p\n", __FUNCTION__, pointer);
|
||||
|
||||
if (!ctx || INTEL_CONTEXT(ctx) == 0) {
|
||||
fprintf(stderr, "%s: no context\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
intelFreeAGP( INTEL_CONTEXT(ctx), pointer );
|
||||
}
|
||||
|
||||
/* Called via glXGetMemoryOffsetMESA()
|
||||
*
|
||||
* Returns offset of pointer from the start of agp aperture.
|
||||
*/
|
||||
GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn,
|
||||
const GLvoid *pointer)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
intelContextPtr intel;
|
||||
|
||||
if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) {
|
||||
fprintf(stderr, "%s: no context\n", __FUNCTION__);
|
||||
return ~0;
|
||||
}
|
||||
|
||||
if (!intelIsAgpMemory( intel, pointer, 0 ))
|
||||
return ~0;
|
||||
|
||||
return intelAgpOffsetFromVirtual( intel, pointer );
|
||||
}
|
||||
|
||||
|
||||
GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
|
||||
GLint size )
|
||||
{
|
||||
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
|
||||
int valid = (size >= 0 &&
|
||||
offset >= 0 &&
|
||||
offset + size < intel->intelScreen->tex.size);
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_IOCTL)
|
||||
fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid );
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer )
|
||||
{
|
||||
int offset = (char *)pointer - (char *)intel->intelScreen->tex.map;
|
||||
|
||||
if (offset < 0 || offset > intel->intelScreen->tex.size)
|
||||
return ~0;
|
||||
else
|
||||
return intel->intelScreen->tex.offset + offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Flip the front & back buffes
|
||||
*/
|
||||
void intelPageFlip( const __DRIdrawablePrivate *dPriv )
|
||||
{
|
||||
#if 0
|
||||
intelContextPtr intel;
|
||||
int tmp, ret;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_IOCTL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
assert(dPriv);
|
||||
assert(dPriv->driContextPriv);
|
||||
assert(dPriv->driContextPriv->driverPrivate);
|
||||
|
||||
intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (dPriv->pClipRects) {
|
||||
*(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0];
|
||||
intel->sarea->nbox = 1;
|
||||
}
|
||||
|
||||
ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
|
||||
if (ret) {
|
||||
fprintf(stderr, "%s: %d\n", __FUNCTION__, ret);
|
||||
UNLOCK_HARDWARE( intel );
|
||||
batch.start = start_offset;
|
||||
batch.used = used;
|
||||
batch.cliprects = intel->pClipRects;
|
||||
batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
|
||||
batch.DR1 = 0;
|
||||
batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |
|
||||
(((GLuint)intel->drawY) << 16));
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_DMA)
|
||||
fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
|
||||
__FUNCTION__,
|
||||
batch.start,
|
||||
batch.start + batch.used * 4,
|
||||
batch.DR4, batch.num_cliprects);
|
||||
#if 1
|
||||
if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,
|
||||
sizeof(batch))) {
|
||||
fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno);
|
||||
UNLOCK_HARDWARE(intel);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tmp = intel->sarea->last_enqueue;
|
||||
intelRefillBatchLocked( intel );
|
||||
UNLOCK_HARDWARE( intel );
|
||||
|
||||
|
||||
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
|
||||
#endif
|
||||
|
||||
/* FIXME: use hardware contexts to avoid 'losing' hardware after
|
||||
* each buffer flush.
|
||||
*/
|
||||
intel->vtbl.lost_hardware( intel );
|
||||
}
|
||||
|
||||
@@ -30,37 +30,14 @@
|
||||
|
||||
#include "intel_context.h"
|
||||
|
||||
extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock );
|
||||
void intelWaitIrq( struct intel_context *intel, int seq );
|
||||
int intelEmitIrqLocked( struct intel_context *intel );
|
||||
|
||||
extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch);
|
||||
|
||||
extern void intelPageFlip( const __DRIdrawablePrivate *dpriv );
|
||||
extern void intelWaitForIdle( intelContextPtr intel );
|
||||
extern void intelFlushBatch( intelContextPtr intel, GLboolean refill );
|
||||
extern void intelFlushBatchLocked( intelContextPtr intel,
|
||||
GLboolean ignore_cliprects,
|
||||
GLboolean refill,
|
||||
GLboolean allow_unlock);
|
||||
extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock );
|
||||
extern void intelFinish( GLcontext *ctx );
|
||||
extern void intelFlush( GLcontext *ctx );
|
||||
|
||||
extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size );
|
||||
extern void intelFreeAGP( intelContextPtr intel, void *pointer );
|
||||
|
||||
extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn,
|
||||
GLsizei size, GLfloat readfreq,
|
||||
GLfloat writefreq, GLfloat priority );
|
||||
|
||||
extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn,
|
||||
GLvoid *pointer );
|
||||
|
||||
extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer );
|
||||
extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
|
||||
GLint size );
|
||||
|
||||
extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p );
|
||||
void intel_batch_ioctl( struct intel_context *intel,
|
||||
GLuint start_offset,
|
||||
GLuint used,
|
||||
GLboolean ignore_cliprects,
|
||||
GLboolean allow_unlock);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
300
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal file
300
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "intel_context.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_bufmgr.h"
|
||||
#include "enums.h"
|
||||
|
||||
static GLenum target_to_target( GLenum target )
|
||||
{
|
||||
switch (target) {
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
|
||||
return GL_TEXTURE_CUBE_MAP_ARB;
|
||||
default:
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
|
||||
GLenum target,
|
||||
GLenum internal_format,
|
||||
GLuint first_level,
|
||||
GLuint last_level,
|
||||
GLuint width0,
|
||||
GLuint height0,
|
||||
GLuint depth0,
|
||||
GLuint cpp,
|
||||
GLboolean compressed)
|
||||
{
|
||||
GLboolean ok;
|
||||
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
|
||||
|
||||
DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(target),
|
||||
_mesa_lookup_enum_by_nr(internal_format),
|
||||
first_level,
|
||||
last_level);
|
||||
|
||||
mt->target = target_to_target(target);
|
||||
mt->internal_format = internal_format;
|
||||
mt->first_level = first_level;
|
||||
mt->last_level = last_level;
|
||||
mt->width0 = width0;
|
||||
mt->height0 = height0;
|
||||
mt->depth0 = depth0;
|
||||
mt->cpp = cpp;
|
||||
mt->compressed = compressed;
|
||||
mt->refcount = 1;
|
||||
|
||||
switch (intel->intelScreen->deviceID) {
|
||||
case PCI_CHIP_I945_G:
|
||||
/* case PCI_CHIP_I945_GM: */
|
||||
ok = i945_miptree_layout( mt );
|
||||
break;
|
||||
default:
|
||||
/* All the i830 chips and the i915 use this layout:
|
||||
*/
|
||||
ok = i915_miptree_layout( mt );
|
||||
break;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
mt->region = intel_region_alloc( intel,
|
||||
mt->cpp,
|
||||
mt->pitch,
|
||||
mt->total_height );
|
||||
|
||||
if (!mt->region) {
|
||||
free(mt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mt;
|
||||
}
|
||||
|
||||
|
||||
void intel_miptree_reference( struct intel_mipmap_tree **dst,
|
||||
struct intel_mipmap_tree *src )
|
||||
{
|
||||
src->refcount++;
|
||||
*dst = src;
|
||||
}
|
||||
|
||||
void intel_miptree_release( struct intel_context *intel,
|
||||
struct intel_mipmap_tree **mt )
|
||||
{
|
||||
if (!*mt)
|
||||
return;
|
||||
|
||||
DBG("%s %d\n", __FUNCTION__, (*mt)->refcount-1);
|
||||
if (--(*mt)->refcount == 0) {
|
||||
intel_region_release(intel, &((*mt)->region));
|
||||
free(*mt);
|
||||
}
|
||||
*mt = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Can the image be pulled into a unified mipmap tree. This mirrors
|
||||
* the completeness test in a lot of ways.
|
||||
*
|
||||
* Not sure whether I want to pass gl_texture_image here.
|
||||
*/
|
||||
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
|
||||
struct gl_texture_image *image,
|
||||
GLuint face,
|
||||
GLuint level )
|
||||
{
|
||||
DBG("%s %d %d/%d %d/%d\n", __FUNCTION__,
|
||||
image->Border,
|
||||
image->InternalFormat, mt->internal_format,
|
||||
image->IsCompressed, mt->compressed);
|
||||
|
||||
/* Images with borders are never pulled into mipmap trees.
|
||||
*/
|
||||
if (image->Border)
|
||||
return GL_FALSE;
|
||||
|
||||
if (image->InternalFormat != mt->internal_format ||
|
||||
image->IsCompressed != mt->compressed)
|
||||
return GL_FALSE;
|
||||
|
||||
DBG("%s: %d/%d %d/%d %d/%d\n", __FUNCTION__,
|
||||
image->Width, mt->offset[face][level].width,
|
||||
image->Height, mt->offset[face][level].height,
|
||||
image->Depth, mt->offset[face][level].depth);
|
||||
|
||||
/* Test image dimensions against the base level image adjusted for
|
||||
* minification. This will also catch images not present in the
|
||||
* tree, changed targets, etc.
|
||||
*/
|
||||
if (image->Width != mt->offset[face][level].width ||
|
||||
image->Height != mt->offset[face][level].height ||
|
||||
image->Depth != mt->offset[face][level].depth)
|
||||
return GL_FALSE;
|
||||
|
||||
|
||||
DBG("%s: success\n", __FUNCTION__);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level)
|
||||
{
|
||||
return mt->offset[face][level].offset;
|
||||
}
|
||||
|
||||
GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level)
|
||||
{
|
||||
return mt->offset[face][level].depth_image_stride;
|
||||
}
|
||||
|
||||
|
||||
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level,
|
||||
GLuint x, GLuint y,
|
||||
GLuint w, GLuint h, GLuint d)
|
||||
{
|
||||
mt->offset[face][level].offset = (x + y * mt->pitch) * mt->cpp;
|
||||
mt->offset[face][level].width = w;
|
||||
mt->offset[face][level].height = h;
|
||||
mt->offset[face][level].depth = d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Map a teximage in a mipmap tree.
|
||||
* \param row_stride returns row stride in bytes
|
||||
* \param image_stride returns image stride in bytes (for 3D textures).
|
||||
* \return address of mapping
|
||||
*/
|
||||
GLubyte *intel_miptree_image_map(struct intel_context *intel,
|
||||
struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level,
|
||||
GLuint *row_stride,
|
||||
GLuint *image_stride)
|
||||
{
|
||||
DBG("%s \n", __FUNCTION__);
|
||||
|
||||
if (row_stride)
|
||||
*row_stride = mt->pitch * mt->cpp;
|
||||
|
||||
if (image_stride)
|
||||
*image_stride = mt->offset[face][level].depth_image_stride;
|
||||
|
||||
return (intel_region_map(intel, mt->region) +
|
||||
intel_miptree_image_offset(mt, face, level));
|
||||
}
|
||||
|
||||
void intel_miptree_image_unmap(struct intel_context *intel,
|
||||
struct intel_mipmap_tree *mt)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
intel_region_unmap(intel, mt->region);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Upload data for a particular image.
|
||||
*/
|
||||
void intel_miptree_image_data(struct intel_context *intel,
|
||||
struct intel_mipmap_tree *dst,
|
||||
GLuint face,
|
||||
GLuint level,
|
||||
void *src,
|
||||
GLuint src_row_pitch,
|
||||
GLuint src_image_pitch)
|
||||
{
|
||||
GLuint depth = dst->offset[face][level].depth;
|
||||
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
|
||||
GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level);
|
||||
GLuint i;
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
for (i = 0; i < depth; i++) {
|
||||
intel_region_data(intel,
|
||||
dst->region, dst_offset,
|
||||
0,
|
||||
0,
|
||||
src,
|
||||
src_row_pitch,
|
||||
0, 0, /* source x,y */
|
||||
dst->offset[face][level].width,
|
||||
dst->offset[face][level].height);
|
||||
dst_offset += dst_image_stride;
|
||||
src += src_image_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy mipmap image between trees
|
||||
*/
|
||||
void intel_miptree_image_copy( struct intel_context *intel,
|
||||
struct intel_mipmap_tree *dst,
|
||||
GLuint face, GLuint level,
|
||||
struct intel_mipmap_tree *src )
|
||||
{
|
||||
GLuint width = src->offset[face][level].width;
|
||||
GLuint height = src->offset[face][level].height;
|
||||
GLuint depth = src->offset[face][level].depth;
|
||||
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
|
||||
GLuint src_offset = intel_miptree_image_offset(src, face, level);
|
||||
GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level);
|
||||
GLuint src_image_stride = intel_miptree_depth_image_stride(src, face, level);
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < depth; i++) {
|
||||
intel_region_copy(intel,
|
||||
dst->region, dst_offset,
|
||||
0,
|
||||
0,
|
||||
src->region, src_offset,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height);
|
||||
|
||||
dst_offset += dst_image_stride;
|
||||
src_offset += src_image_stride;
|
||||
}
|
||||
|
||||
}
|
||||
183
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal file
183
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_MIPMAP_TREE_H
|
||||
#define INTEL_MIPMAP_TREE_H
|
||||
|
||||
#include "intel_regions.h"
|
||||
|
||||
/* A layer on top of the intel_regions code which adds:
|
||||
*
|
||||
* - Code to size and layout a region to hold a set of mipmaps.
|
||||
* - Query to determine if a new image fits in an existing tree.
|
||||
* - More refcounting
|
||||
* - maybe able to remove refcounting from intel_region?
|
||||
* - ?
|
||||
*
|
||||
* The fixed mipmap layout of intel hardware where one offset
|
||||
* specifies the position of all images in a mipmap hierachy
|
||||
* complicates the implementation of GL texture image commands,
|
||||
* compared to hardware where each image is specified with an
|
||||
* independent offset.
|
||||
*
|
||||
* In an ideal world, each texture object would be associated with a
|
||||
* single bufmgr buffer or 2d intel_region, and all the images within
|
||||
* the texture object would slot into the tree as they arrive. The
|
||||
* reality can be a little messier, as images can arrive from the user
|
||||
* with sizes that don't fit in the existing tree, or in an order
|
||||
* where the tree layout cannot be guessed immediately.
|
||||
*
|
||||
* This structure encodes an idealized mipmap tree. The GL image
|
||||
* commands build these where possible, otherwise store the images in
|
||||
* temporary system buffers.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Describes the location of each texture image within a texture region.
|
||||
*/
|
||||
struct intel_mipmap_offset {
|
||||
GLuint offset;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
GLuint depth;
|
||||
GLuint depth_image_stride;
|
||||
};
|
||||
|
||||
struct intel_mipmap_tree {
|
||||
/* Effectively the key:
|
||||
*/
|
||||
GLenum target;
|
||||
GLenum internal_format;
|
||||
|
||||
GLuint first_level;
|
||||
GLuint last_level;
|
||||
|
||||
GLuint width0, height0, depth0; /**< Level zero image dimensions */
|
||||
GLuint cpp;
|
||||
GLboolean compressed;
|
||||
|
||||
/* Derived from the above:
|
||||
*/
|
||||
GLuint pitch;
|
||||
GLuint depth_pitch; /* per-image on i945? */
|
||||
GLuint total_height;
|
||||
struct intel_mipmap_offset offset[MAX_FACES][MAX_TEXTURE_LEVELS];
|
||||
|
||||
/* The data is held here:
|
||||
*/
|
||||
struct intel_region *region;
|
||||
|
||||
/* These are also refcounted:
|
||||
*/
|
||||
GLuint refcount;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel,
|
||||
GLenum target,
|
||||
GLenum internal_format,
|
||||
GLuint first_level,
|
||||
GLuint last_level,
|
||||
GLuint width0,
|
||||
GLuint height0,
|
||||
GLuint depth0,
|
||||
GLuint cpp,
|
||||
GLboolean compressed);
|
||||
|
||||
void intel_miptree_reference( struct intel_mipmap_tree **dst,
|
||||
struct intel_mipmap_tree *src );
|
||||
|
||||
void intel_miptree_release( struct intel_context *intel,
|
||||
struct intel_mipmap_tree **mt );
|
||||
|
||||
/* Check if an image fits an existing mipmap tree layout
|
||||
*/
|
||||
GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,
|
||||
struct gl_texture_image *image,
|
||||
GLuint face,
|
||||
GLuint level );
|
||||
|
||||
/* Return a pointer to an image within a tree. Return image stride as
|
||||
* well.
|
||||
*/
|
||||
GLubyte *intel_miptree_image_map( struct intel_context *intel,
|
||||
struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level,
|
||||
GLuint *row_stride,
|
||||
GLuint *image_stride);
|
||||
|
||||
void intel_miptree_image_unmap( struct intel_context *intel,
|
||||
struct intel_mipmap_tree *mt );
|
||||
|
||||
|
||||
/* Return the linear offset of an image relative to the start of the
|
||||
* tree:
|
||||
*/
|
||||
GLuint intel_miptree_image_offset( struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level );
|
||||
|
||||
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level,
|
||||
GLuint x, GLuint y,
|
||||
GLuint w, GLuint h, GLuint d);
|
||||
|
||||
GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt,
|
||||
GLuint face,
|
||||
GLuint level);
|
||||
|
||||
|
||||
|
||||
/* Upload an image into a tree
|
||||
*/
|
||||
void intel_miptree_image_data(struct intel_context *intel,
|
||||
struct intel_mipmap_tree *dst,
|
||||
GLuint face,
|
||||
GLuint level,
|
||||
void *src,
|
||||
GLuint src_row_pitch,
|
||||
GLuint src_image_pitch);
|
||||
|
||||
/* Copy an image between two trees
|
||||
*/
|
||||
void intel_miptree_image_copy( struct intel_context *intel,
|
||||
struct intel_mipmap_tree *dst,
|
||||
GLuint face, GLuint level,
|
||||
struct intel_mipmap_tree *src );
|
||||
|
||||
/* i915_mipmap_tree.c:
|
||||
*/
|
||||
GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt );
|
||||
GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt );
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -12,7 +12,7 @@
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* next paragraph) shall be included in all copies or substantial portionsalloc
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
@@ -25,465 +25,98 @@
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "glheader.h"
|
||||
#include "enums.h"
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
#include "state.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_pixel.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
|
||||
|
||||
static GLboolean
|
||||
check_color( const GLcontext *ctx, GLenum type, GLenum format,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
const void *pixels, GLint sz, GLint pitch )
|
||||
/**
|
||||
* Check if any fragment operations are in effect which might effect
|
||||
* glDraw/CopyPixels.
|
||||
*/
|
||||
GLboolean intel_check_blit_fragment_ops( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
GLuint cpp = intel->intelScreen->cpp;
|
||||
if (ctx->NewState)
|
||||
_mesa_update_state(ctx);
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
/* XXX Note: Scissor could be done with the blitter:
|
||||
*/
|
||||
return !(ctx->_ImageTransferState ||
|
||||
ctx->Color.AlphaEnabled ||
|
||||
ctx->Depth.Test ||
|
||||
ctx->Fog.Enabled ||
|
||||
ctx->Scissor.Enabled ||
|
||||
ctx->Stencil.Enabled ||
|
||||
!ctx->Color.ColorMask[0] ||
|
||||
!ctx->Color.ColorMask[1] ||
|
||||
!ctx->Color.ColorMask[2] ||
|
||||
!ctx->Color.ColorMask[3] ||
|
||||
ctx->Color.ColorLogicOpEnabled ||
|
||||
ctx->Texture._EnabledUnits ||
|
||||
ctx->FragmentProgram._Enabled);
|
||||
}
|
||||
|
||||
if ( (pitch & 63) ||
|
||||
ctx->_ImageTransferState ||
|
||||
packing->SwapBytes ||
|
||||
packing->LsbFirst) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
|
||||
GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx )
|
||||
{
|
||||
if (ctx->NewState)
|
||||
_mesa_update_state(ctx);
|
||||
|
||||
/* Some of _ImageTransferState (scale, bias) could be done with
|
||||
* fragment programs on i915.
|
||||
*/
|
||||
return !(ctx->_ImageTransferState ||
|
||||
ctx->Fog.Enabled || /* not done yet */
|
||||
ctx->Texture._EnabledUnits ||
|
||||
ctx->FragmentProgram._Enabled);
|
||||
}
|
||||
|
||||
/* The intel_region struct doesn't really do enough to capture the
|
||||
* format of the pixels in the region. For now this code assumes that
|
||||
* the region is a display surface and hence is either ARGB8888 or
|
||||
* RGB565.
|
||||
* XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd
|
||||
* know the buffer's pixel format.
|
||||
*
|
||||
* \param format as given to glDraw/ReadPixels
|
||||
* \param type as given to glDraw/ReadPixels
|
||||
*/
|
||||
GLboolean intel_check_blit_format( struct intel_region *region,
|
||||
GLenum format, GLenum type )
|
||||
{
|
||||
if (region->cpp == 4 &&
|
||||
(type == GL_UNSIGNED_INT_8_8_8_8_REV ||
|
||||
type == GL_UNSIGNED_BYTE) &&
|
||||
format == GL_BGRA ) {
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&
|
||||
cpp == 4 &&
|
||||
format == GL_BGRA ) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: passed 2\n", __FUNCTION__);
|
||||
|
||||
if (region->cpp == 2 &&
|
||||
type == GL_UNSIGNED_SHORT_5_6_5_REV &&
|
||||
format == GL_BGR ) {
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: failed\n", __FUNCTION__);
|
||||
fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",
|
||||
__FUNCTION__, region->cpp,
|
||||
_mesa_lookup_enum_by_nr(type),
|
||||
_mesa_lookup_enum_by_nr(format));
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
check_color_per_fragment_ops( const GLcontext *ctx )
|
||||
{
|
||||
int result;
|
||||
result = (!( ctx->Color.AlphaEnabled ||
|
||||
ctx->Depth.Test ||
|
||||
ctx->Fog.Enabled ||
|
||||
ctx->Scissor.Enabled ||
|
||||
ctx->Stencil.Enabled ||
|
||||
!ctx->Color.ColorMask[0] ||
|
||||
!ctx->Color.ColorMask[1] ||
|
||||
!ctx->Color.ColorMask[2] ||
|
||||
!ctx->Color.ColorMask[3] ||
|
||||
ctx->Color.ColorLogicOpEnabled ||
|
||||
ctx->Texture._EnabledUnits
|
||||
) &&
|
||||
ctx->Current.RasterPosValid);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static GLboolean
|
||||
clip_pixelrect( const GLcontext *ctx,
|
||||
const GLframebuffer *buffer,
|
||||
GLint *x, GLint *y,
|
||||
GLsizei *width, GLsizei *height,
|
||||
GLint *size )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
|
||||
/* left clipping */
|
||||
if (*x < buffer->_Xmin) {
|
||||
*width -= (buffer->_Xmin - *x);
|
||||
*x = buffer->_Xmin;
|
||||
}
|
||||
|
||||
/* right clipping */
|
||||
if (*x + *width > buffer->_Xmax)
|
||||
*width -= (*x + *width - buffer->_Xmax - 1);
|
||||
|
||||
if (*width <= 0)
|
||||
return GL_FALSE;
|
||||
|
||||
/* bottom clipping */
|
||||
if (*y < buffer->_Ymin) {
|
||||
*height -= (buffer->_Ymin - *y);
|
||||
*y = buffer->_Ymin;
|
||||
}
|
||||
|
||||
/* top clipping */
|
||||
if (*y + *height > buffer->_Ymax)
|
||||
*height -= (*y + *height - buffer->_Ymax - 1);
|
||||
|
||||
if (*height <= 0)
|
||||
return GL_FALSE;
|
||||
|
||||
*size = ((*y + *height - 1) * intel->intelScreen->front.pitch +
|
||||
(*x + *width - 1) * intel->intelScreen->cpp);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
intelTryReadPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
GLint size = 0;
|
||||
GLint pitch = pack->RowLength ? pack->RowLength : width;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
/* Only accelerate reading to agp buffers.
|
||||
*/
|
||||
if ( !intelIsAgpMemory(intel, pixels,
|
||||
pitch * height * intel->intelScreen->cpp ) ) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: dest not agp\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Need GL_PACK_INVERT_MESA to cope with upsidedown results from
|
||||
* blitter:
|
||||
*/
|
||||
if (!pack->Invert) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!check_color(ctx, type, format, pack, pixels, size, pitch))
|
||||
return GL_FALSE;
|
||||
|
||||
switch ( intel->intelScreen->cpp ) {
|
||||
case 4:
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Although the blits go on the command buffer, need to do this and
|
||||
* fire with lock held to guarentee cliprects and drawOffset are
|
||||
* correct.
|
||||
*
|
||||
* This is an unusual situation however, as the code which flushes
|
||||
* a full command buffer expects to be called unlocked. As a
|
||||
* workaround, immediately flush the buffer on aquiring the lock.
|
||||
*/
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
int nbox = dPriv->numClipRects;
|
||||
int src_offset = intel->drawOffset;
|
||||
int src_pitch = intel->intelScreen->front.pitch;
|
||||
int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
|
||||
drm_clip_rect_t *box = dPriv->pClipRects;
|
||||
int i;
|
||||
|
||||
if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height,
|
||||
&size)) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s totally clipped -- nothing to do\n",
|
||||
__FUNCTION__);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
y = dPriv->h - y - height;
|
||||
x += dPriv->x;
|
||||
y += dPriv->y;
|
||||
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n",
|
||||
src_pitch, pitch);
|
||||
|
||||
for (i = 0 ; i < nbox ; i++)
|
||||
{
|
||||
GLint bx = box[i].x1;
|
||||
GLint by = box[i].y1;
|
||||
GLint bw = box[i].x2 - bx;
|
||||
GLint bh = box[i].y2 - by;
|
||||
|
||||
if (bx < x) bw -= x - bx, bx = x;
|
||||
if (by < y) bh -= y - by, by = y;
|
||||
if (bx + bw > x + width) bw = x + width - bx;
|
||||
if (by + bh > y + height) bh = y + height - by;
|
||||
if (bw <= 0) continue;
|
||||
if (bh <= 0) continue;
|
||||
|
||||
intelEmitCopyBlitLocked( intel,
|
||||
intel->intelScreen->cpp,
|
||||
src_pitch, src_offset,
|
||||
pitch, dst_offset,
|
||||
bx, by,
|
||||
bx - x, by - y,
|
||||
bw, bh );
|
||||
}
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
intelFinish( &intel->ctx );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
intelReadPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels )
|
||||
{
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,
|
||||
pixels))
|
||||
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,
|
||||
pixels);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void do_draw_pix( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint pitch,
|
||||
const void *pixels,
|
||||
GLuint dest )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
drm_clip_rect_t *box = dPriv->pClipRects;
|
||||
int nbox = dPriv->numClipRects;
|
||||
int i;
|
||||
int size;
|
||||
int src_offset = intelAgpOffsetFromVirtual( intel, pixels);
|
||||
int src_pitch = pitch;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
if (ctx->DrawBuffer)
|
||||
{
|
||||
y -= height; /* cope with pixel zoom */
|
||||
|
||||
if (!clip_pixelrect(ctx, ctx->DrawBuffer,
|
||||
&x, &y, &width, &height,
|
||||
&size)) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
return;
|
||||
}
|
||||
|
||||
y = dPriv->h - y - height; /* convert from gl to hardware coords */
|
||||
x += dPriv->x;
|
||||
y += dPriv->y;
|
||||
|
||||
|
||||
for (i = 0 ; i < nbox ; i++ )
|
||||
{
|
||||
GLint bx = box[i].x1;
|
||||
GLint by = box[i].y1;
|
||||
GLint bw = box[i].x2 - bx;
|
||||
GLint bh = box[i].y2 - by;
|
||||
|
||||
if (bx < x) bw -= x - bx, bx = x;
|
||||
if (by < y) bh -= y - by, by = y;
|
||||
if (bx + bw > x + width) bw = x + width - bx;
|
||||
if (by + bh > y + height) bh = y + height - by;
|
||||
if (bw <= 0) continue;
|
||||
if (bh <= 0) continue;
|
||||
|
||||
intelEmitCopyBlitLocked( intel,
|
||||
intel->intelScreen->cpp,
|
||||
src_pitch, src_offset,
|
||||
intel->intelScreen->front.pitch,
|
||||
intel->drawOffset,
|
||||
bx - x, by - y,
|
||||
bx, by,
|
||||
bw, bh );
|
||||
}
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
intelFinish( &intel->ctx );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static GLboolean
|
||||
intelTryDrawPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
GLint pitch = unpack->RowLength ? unpack->RowLength : width;
|
||||
GLuint dest;
|
||||
GLuint cpp = intel->intelScreen->cpp;
|
||||
GLint size = width * pitch * cpp;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
switch (format) {
|
||||
case GL_RGB:
|
||||
case GL_RGBA:
|
||||
case GL_BGRA:
|
||||
dest = intel->drawOffset;
|
||||
|
||||
/* Planemask doesn't have full support in blits.
|
||||
*/
|
||||
if (!ctx->Color.ColorMask[RCOMP] ||
|
||||
!ctx->Color.ColorMask[GCOMP] ||
|
||||
!ctx->Color.ColorMask[BCOMP] ||
|
||||
!ctx->Color.ColorMask[ACOMP]) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: planemask\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Can't do conversions on agp reads/draws.
|
||||
*/
|
||||
if ( !intelIsAgpMemory( intel, pixels, size ) ) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: not agp memory\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
if (!check_color_per_fragment_ops(ctx)) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (ctx->Pixel.ZoomX != 1.0F ||
|
||||
ctx->Pixel.ZoomY != -1.0F)
|
||||
return GL_FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if ( intelIsAgpMemory(intel, pixels, size) )
|
||||
{
|
||||
do_draw_pix( ctx, x, y, width, height, pitch, pixels,
|
||||
dest );
|
||||
return GL_TRUE;
|
||||
}
|
||||
else if (0)
|
||||
{
|
||||
/* Pixels is in regular memory -- get dma buffers and perform
|
||||
* upload through them. No point doing this for regular uploads
|
||||
* but once we remove some of the restrictions above (colormask,
|
||||
* pixelformat conversion, zoom?, etc), this could be a win.
|
||||
*/
|
||||
}
|
||||
else
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
intelDrawPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
{
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!intelTryDrawPixels( ctx, x, y, width, height, format, type,
|
||||
unpack, pixels ))
|
||||
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
|
||||
unpack, pixels );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
|
||||
* for the color buffer. Don't support zooming, pixel transfer, etc.
|
||||
* We do support copying from one window to another, ala glXMakeCurrentRead.
|
||||
*/
|
||||
static void
|
||||
intelCopyPixels( GLcontext *ctx,
|
||||
GLint srcx, GLint srcy, GLsizei width, GLsizei height,
|
||||
GLint destx, GLint desty, GLenum type )
|
||||
{
|
||||
#if 0
|
||||
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
|
||||
const SWcontext *swrast = SWRAST_CONTEXT( ctx );
|
||||
XMesaDisplay *dpy = xmesa->xm_visual->display;
|
||||
const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
|
||||
const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
|
||||
const XMesaGC gc = xmesa->xm_draw_buffer->gc;
|
||||
|
||||
ASSERT(dpy);
|
||||
ASSERT(gc);
|
||||
|
||||
if (drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
|
||||
readBuffer &&
|
||||
type == GL_COLOR &&
|
||||
(swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
|
||||
ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
|
||||
ctx->Pixel.ZoomX == 1.0 && /* no zooming */
|
||||
ctx->Pixel.ZoomY == 1.0) {
|
||||
/* Note: we don't do any special clipping work here. We could,
|
||||
* but X will do it for us.
|
||||
*/
|
||||
srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
|
||||
desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
|
||||
XCopyArea(dpy, readBuffer, drawBuffer, gc,
|
||||
srcx, srcy, width, height, destx, desty);
|
||||
}
|
||||
#else
|
||||
_swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void intelInitPixelFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
/* Pixel path fallbacks.
|
||||
*/
|
||||
functions->Accum = _swrast_Accum;
|
||||
functions->Bitmap = _swrast_Bitmap;
|
||||
functions->CopyPixels = intelCopyPixels;
|
||||
|
||||
if (!getenv("INTEL_NO_BLITS")) {
|
||||
functions->ReadPixels = intelReadPixels;
|
||||
functions->DrawPixels = intelDrawPixels;
|
||||
}
|
||||
else {
|
||||
functions->ReadPixels = _swrast_ReadPixels;
|
||||
functions->DrawPixels = _swrast_DrawPixels;
|
||||
}
|
||||
functions->ReadPixels = intelReadPixels;
|
||||
functions->DrawPixels = intelDrawPixels;
|
||||
}
|
||||
|
||||
|
||||
64
src/mesa/drivers/dri/i915/intel_pixel.h
Normal file
64
src/mesa/drivers/dri/i915/intel_pixel.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_PIXEL_H
|
||||
#define INTEL_PIXEL_H
|
||||
|
||||
#include "mtypes.h"
|
||||
|
||||
void intelInitPixelFuncs( struct dd_function_table *functions );
|
||||
|
||||
GLboolean intel_check_blit_fragment_ops( GLcontext *ctx );
|
||||
|
||||
GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx );
|
||||
|
||||
GLboolean intel_check_blit_format( struct intel_region *region,
|
||||
GLenum format, GLenum type );
|
||||
|
||||
|
||||
void intelReadPixels( GLcontext *ctx,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels );
|
||||
|
||||
void intelDrawPixels( GLcontext *ctx,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels );
|
||||
|
||||
void intelCopyPixels( GLcontext *ctx,
|
||||
GLint srcx, GLint srcy,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint destx, GLint desty,
|
||||
GLenum type );
|
||||
|
||||
#endif
|
||||
349
src/mesa/drivers/dri/i915/intel_pixel_copy.c
Normal file
349
src/mesa/drivers/dri/i915/intel_pixel_copy.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "glheader.h"
|
||||
#include "enums.h"
|
||||
#include "image.h"
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_tris.h"
|
||||
#include "intel_pixel.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
|
||||
static struct intel_region *copypix_src_region( struct intel_context *intel,
|
||||
GLenum type )
|
||||
{
|
||||
switch (type) {
|
||||
case GL_COLOR:
|
||||
return intel_readbuf_region( intel );
|
||||
case GL_DEPTH:
|
||||
/* Don't think this is really possible execpt at 16bpp, when we have no stencil.
|
||||
*/
|
||||
if (intel->depth_region &&
|
||||
intel->depth_region->cpp == 2)
|
||||
return intel->depth_region;
|
||||
case GL_STENCIL:
|
||||
/* Don't think this is really possible.
|
||||
*/
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
/* Does it matter whether it is stencil/depth or depth/stencil?
|
||||
*/
|
||||
return intel->depth_region;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Doesn't work for overlapping regions. Could do a double copy or
|
||||
* just fallback.
|
||||
*/
|
||||
static GLboolean do_texture_copypixels( GLcontext *ctx,
|
||||
GLint srcx, GLint srcy,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint dstx, GLint dsty,
|
||||
GLenum type )
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
struct intel_region *dst = intel_drawbuf_region( intel );
|
||||
struct intel_region *src = copypix_src_region(intel, type);
|
||||
GLenum src_format;
|
||||
GLenum src_type;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!src || !dst || type != GL_COLOR)
|
||||
return GL_FALSE;
|
||||
|
||||
/* Can't handle overlapping regions. Don't have sufficient control
|
||||
* over rasterization to pull it off in-place. Punt on these for
|
||||
* now.
|
||||
*
|
||||
* XXX: do a copy to a temporary.
|
||||
*/
|
||||
{
|
||||
drm_clip_rect_t src;
|
||||
drm_clip_rect_t dst;
|
||||
drm_clip_rect_t tmp;
|
||||
|
||||
src.x1 = srcx;
|
||||
src.y1 = srcy;
|
||||
src.x2 = srcx + width;
|
||||
src.y2 = srcy + height;
|
||||
|
||||
dst.x1 = dstx;
|
||||
dst.y1 = dsty;
|
||||
dst.x1 = dstx + width * ctx->Pixel.ZoomX;
|
||||
dst.y2 = dsty + height * ctx->Pixel.ZoomY;
|
||||
|
||||
|
||||
if (intel_intersect_cliprects(&tmp, &src, &dst)) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s: regions overlap\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
|
||||
intel->vtbl.install_meta_state(intel);
|
||||
|
||||
/* Is this true? Also will need to turn depth testing on according
|
||||
* to state:
|
||||
*/
|
||||
intel->vtbl.meta_no_stencil_write(intel);
|
||||
intel->vtbl.meta_no_depth_write(intel);
|
||||
|
||||
/* Set the 3d engine to draw into the destination region:
|
||||
*/
|
||||
intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
|
||||
|
||||
intel->vtbl.meta_import_pixel_state(intel);
|
||||
|
||||
if (src->cpp == 2) {
|
||||
src_format = GL_RGB;
|
||||
src_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
}
|
||||
else {
|
||||
src_format = GL_BGRA;
|
||||
src_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
/* Set the frontbuffer up as a large rectangular texture.
|
||||
*/
|
||||
if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, 0,
|
||||
src->pitch,
|
||||
src->height,
|
||||
src_format,
|
||||
src_type )) {
|
||||
intel->vtbl.leave_meta_state(intel);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
intel->vtbl.meta_texture_blend_replace( intel );
|
||||
|
||||
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
|
||||
|
||||
srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
|
||||
|
||||
srcx += dPriv->x;
|
||||
srcy += dPriv->y;
|
||||
|
||||
/* Clip against the source region. This is the only source
|
||||
* clipping we do. XXX: Just set the texcord wrap mode to clamp
|
||||
* or similar.
|
||||
*
|
||||
*/
|
||||
if (0) {
|
||||
GLint orig_x = srcx;
|
||||
GLint orig_y = srcy;
|
||||
|
||||
if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
|
||||
&srcx, &srcy, &width, &height))
|
||||
goto out;
|
||||
|
||||
dstx += srcx - orig_x;
|
||||
dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;
|
||||
}
|
||||
|
||||
/* Just use the regular cliprect mechanism... Does this need to
|
||||
* even hold the lock???
|
||||
*/
|
||||
intel_meta_draw_quad(intel,
|
||||
|
||||
dstx,
|
||||
dstx + width * ctx->Pixel.ZoomX,
|
||||
dPriv->h - (dsty + height * ctx->Pixel.ZoomY),
|
||||
dPriv->h - (dsty),
|
||||
|
||||
0, /* XXX: what z value? */
|
||||
0x00ff00ff,
|
||||
srcx, srcx+width,
|
||||
srcy, srcy+height);
|
||||
|
||||
out:
|
||||
intel->vtbl.leave_meta_state(intel);
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc.
|
||||
*/
|
||||
static GLboolean do_blit_copypixels( GLcontext *ctx,
|
||||
GLint srcx, GLint srcy,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint dstx, GLint dsty,
|
||||
GLenum type )
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
struct intel_region *dst = intel_drawbuf_region( intel );
|
||||
struct intel_region *src = copypix_src_region( intel, type );
|
||||
|
||||
/* Copypixels can be more than a straight copy. Ensure all the
|
||||
* extra operations are disabled:
|
||||
*/
|
||||
if (!intel_check_blit_fragment_ops(ctx) ||
|
||||
ctx->Pixel.ZoomX != 1.0F ||
|
||||
ctx->Pixel.ZoomY != 1.0F)
|
||||
return GL_FALSE;
|
||||
|
||||
if (!src || !dst)
|
||||
return GL_FALSE;
|
||||
|
||||
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
intel->vtbl.render_start(intel);
|
||||
intel->vtbl.emit_state(intel);
|
||||
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
drm_clip_rect_t *box = dPriv->pClipRects;
|
||||
drm_clip_rect_t dest_rect;
|
||||
GLint nbox = dPriv->numClipRects;
|
||||
GLint delta_x = 0;
|
||||
GLint delta_y = 0;
|
||||
GLuint i;
|
||||
|
||||
|
||||
dsty = dPriv->h - dsty - height; /* convert from gl to hardware coords */
|
||||
srcy = dPriv->h - srcy - height; /* convert from gl to hardware coords */
|
||||
dstx += dPriv->x;
|
||||
dsty += dPriv->y;
|
||||
srcx += dPriv->x;
|
||||
srcy += dPriv->y;
|
||||
|
||||
/* Clip against the source region. This is the only source
|
||||
* clipping we do. Dst is clipped with cliprects below.
|
||||
*
|
||||
* TODO: Scissor?
|
||||
*/
|
||||
{
|
||||
delta_x = srcx - dstx;
|
||||
delta_y = srcy - dsty;
|
||||
|
||||
if (!_mesa_clip_to_region(0, 0, src->pitch, src->height,
|
||||
&srcx, &srcy, &width, &height))
|
||||
goto out;
|
||||
|
||||
dstx = srcx - delta_x;
|
||||
dsty = srcy - delta_y;
|
||||
}
|
||||
|
||||
dest_rect.x1 = dstx;
|
||||
dest_rect.y1 = dsty;
|
||||
dest_rect.x2 = dstx + width;
|
||||
dest_rect.y2 = dsty + height;
|
||||
|
||||
/* Could do slightly more clipping: Eg, take the intersection of
|
||||
* the existing set of cliprects and those cliprects translated
|
||||
* by delta_x, delta_y:
|
||||
*
|
||||
* This code will not overwrite other windows, but will
|
||||
* introduce garbage when copying from obscured window regions.
|
||||
*/
|
||||
for (i = 0 ; i < nbox ; i++ )
|
||||
{
|
||||
drm_clip_rect_t rect;
|
||||
|
||||
if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
|
||||
continue;
|
||||
|
||||
|
||||
intelEmitCopyBlit( intel,
|
||||
dst->cpp,
|
||||
src->pitch, src->buffer, 0,
|
||||
dst->pitch, dst->buffer, 0,
|
||||
rect.x1 + delta_x,
|
||||
rect.y1 + delta_y, /* srcx, srcy */
|
||||
rect.x1,
|
||||
rect.y1, /* dstx, dsty */
|
||||
rect.x2 - rect.x1,
|
||||
rect.y2 - rect.y1 );
|
||||
}
|
||||
|
||||
out:
|
||||
intel_batchbuffer_flush( intel->batch );
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void intelCopyPixels( GLcontext *ctx,
|
||||
GLint srcx, GLint srcy,
|
||||
GLsizei width, GLsizei height,
|
||||
GLint destx, GLint desty,
|
||||
GLenum type )
|
||||
{
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
if (do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
|
||||
return;
|
||||
|
||||
if (do_texture_copypixels( ctx, srcx, srcy, width, height, destx, desty, type))
|
||||
return;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("fallback to _swrast_CopyPixels\n");
|
||||
|
||||
_swrast_CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type);
|
||||
}
|
||||
|
||||
|
||||
365
src/mesa/drivers/dri/i915/intel_pixel_draw.c
Normal file
365
src/mesa/drivers/dri/i915/intel_pixel_draw.c
Normal file
@@ -0,0 +1,365 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 portionsalloc
|
||||
* 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 "glheader.h"
|
||||
#include "enums.h"
|
||||
#include "image.h"
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
#include "bufferobj.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_pixel.h"
|
||||
#include "intel_buffer_objects.h"
|
||||
#include "intel_tris.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
|
||||
|
||||
static GLboolean do_texture_drawpixels( GLcontext *ctx,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
struct intel_region *dst = intel_drawbuf_region( intel );
|
||||
struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
|
||||
GLuint rowLength = unpack->RowLength ? unpack->RowLength : width;
|
||||
GLuint src_offset;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
intel->vtbl.render_start(intel);
|
||||
intel->vtbl.emit_state(intel);
|
||||
|
||||
if (!dst)
|
||||
return GL_FALSE;
|
||||
|
||||
if (src) {
|
||||
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
|
||||
format, type, pixels)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
|
||||
return GL_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* PBO only for now:
|
||||
*/
|
||||
/* _mesa_printf("%s - not PBO\n", __FUNCTION__); */
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* There are a couple of things we can't do yet, one of which is
|
||||
* set the correct state for pixel operations when GL texturing is
|
||||
* enabled. That's a pretty rare state and probably not worth the
|
||||
* effort. A completely device-independent version of this may do
|
||||
* more.
|
||||
*
|
||||
* Similarly, we make no attempt to merge metaops processing with
|
||||
* an enabled fragment program, though it would certainly be
|
||||
* possible.
|
||||
*/
|
||||
if (!intel_check_meta_tex_fragment_ops(ctx)) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - bad GL fragment state for metaops texture\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
intel->vtbl.install_meta_state(intel);
|
||||
|
||||
|
||||
/* Is this true? Also will need to turn depth testing on according
|
||||
* to state:
|
||||
*/
|
||||
intel->vtbl.meta_no_stencil_write(intel);
|
||||
intel->vtbl.meta_no_depth_write(intel);
|
||||
|
||||
/* Set the 3d engine to draw into the destination region:
|
||||
*/
|
||||
intel->vtbl.meta_draw_region(intel, dst, intel->depth_region);
|
||||
|
||||
intel->vtbl.meta_import_pixel_state(intel);
|
||||
|
||||
src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
|
||||
format, type, 0, 0, 0);
|
||||
|
||||
|
||||
/* Setup the pbo up as a rectangular texture, if possible.
|
||||
*
|
||||
* TODO: This is almost always possible if the i915 fragment
|
||||
* program is adjusted to correctly swizzle the sampled colors.
|
||||
* The major exception is any 24bit texture, like RGB888, for which
|
||||
* there is no hardware support.
|
||||
*/
|
||||
if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, src_offset,
|
||||
rowLength, height,
|
||||
format, type )) {
|
||||
intel->vtbl.leave_meta_state(intel);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
intel->vtbl.meta_texture_blend_replace( intel );
|
||||
|
||||
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
GLint srcx, srcy;
|
||||
GLint dstx, dsty;
|
||||
|
||||
dstx = x;
|
||||
dsty = dPriv->h - (y + height);
|
||||
|
||||
srcx = 0; /* skiprows/pixels already done */
|
||||
srcy = 0;
|
||||
|
||||
if (0) {
|
||||
const GLint orig_x = dstx;
|
||||
const GLint orig_y = dsty;
|
||||
|
||||
if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height,
|
||||
&dstx, &dsty, &width, &height))
|
||||
goto out;
|
||||
|
||||
srcx += dstx - orig_x;
|
||||
srcy += dsty - orig_y;
|
||||
}
|
||||
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("draw %d,%d %dx%d\n", dstx,dsty,width,height);
|
||||
|
||||
/* Must use the regular cliprect mechanism in order to get the
|
||||
* drawing origin set correctly. Otherwise scissor state is in
|
||||
* incorrect coordinate space. Does this even need to hold the
|
||||
* lock???
|
||||
*/
|
||||
intel_meta_draw_quad(intel,
|
||||
dstx, dstx + width * ctx->Pixel.ZoomX,
|
||||
dPriv->h - (y + height * ctx->Pixel.ZoomY),
|
||||
dPriv->h - (y),
|
||||
- ctx->Current.RasterPos[2] * .5,
|
||||
0x00ff00ff,
|
||||
srcx, srcx+width,
|
||||
srcy+height, srcy);
|
||||
out:
|
||||
intel->vtbl.leave_meta_state(intel);
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Pros:
|
||||
* - no waiting for idle before updating framebuffer.
|
||||
*
|
||||
* Cons:
|
||||
* - if upload is by memcpy, this may actually be slower than fallback path.
|
||||
* - uploads the whole image even if destination is clipped
|
||||
*
|
||||
* Need to benchmark.
|
||||
*
|
||||
* Given the questions about performance, implement for pbo's only.
|
||||
* This path is definitely a win if the pbo is already in agp. If it
|
||||
* turns out otherwise, we can add the code necessary to upload client
|
||||
* data to agp space before performing the blit. (Though it may turn
|
||||
* out to be better/simpler just to use the texture engine).
|
||||
*/
|
||||
static GLboolean do_blit_drawpixels( GLcontext *ctx,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_region *dest = intel_drawbuf_region(intel);
|
||||
struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj);
|
||||
GLuint src_offset;
|
||||
GLuint rowLength;
|
||||
GLuint fence = bmInitFence(intel->bm);
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s\n", __FUNCTION__);
|
||||
|
||||
|
||||
if (!dest) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - no dest\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (src) {
|
||||
/* This validation should be done by core mesa:
|
||||
*/
|
||||
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1,
|
||||
format, type, pixels)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
|
||||
return GL_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* PBO only for now:
|
||||
*/
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - not PBO\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!intel_check_blit_format(dest, format, type)) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - bad format for blit\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (!intel_check_meta_tex_fragment_ops(ctx)) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - bad GL fragment state for meta tex\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (ctx->Pixel.ZoomX != 1.0F) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (unpack->RowLength > 0)
|
||||
rowLength = unpack->RowLength;
|
||||
else
|
||||
rowLength = width;
|
||||
|
||||
if (ctx->Pixel.ZoomY == -1.0F) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
|
||||
return GL_FALSE; /* later */
|
||||
y -= height;
|
||||
}
|
||||
else if (ctx->Pixel.ZoomY == 1.0F) {
|
||||
rowLength = -rowLength;
|
||||
}
|
||||
else {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height,
|
||||
format, type, 0, 0, 0);
|
||||
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
int nbox = dPriv->numClipRects;
|
||||
drm_clip_rect_t *box = dPriv->pClipRects;
|
||||
drm_clip_rect_t rect;
|
||||
drm_clip_rect_t dest_rect;
|
||||
int i;
|
||||
|
||||
dest_rect.x1 = dPriv->x + x;
|
||||
dest_rect.y1 = dPriv->y + dPriv->h - (y + height);
|
||||
dest_rect.x2 = dest_rect.x1 + width;
|
||||
dest_rect.y2 = dest_rect.y1 + height;
|
||||
|
||||
for (i = 0 ; i < nbox ; i++ )
|
||||
{
|
||||
if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i]))
|
||||
continue;
|
||||
|
||||
intelEmitCopyBlit( intel,
|
||||
dest->cpp,
|
||||
rowLength,
|
||||
intel_bufferobj_buffer(src), src_offset,
|
||||
dest->pitch,
|
||||
dest->buffer, 0,
|
||||
rect.x1 - dest_rect.x1,
|
||||
rect.y2 - dest_rect.y2,
|
||||
rect.x1,
|
||||
rect.y1,
|
||||
rect.x2 - rect.x1,
|
||||
rect.y2 - rect.y1 );
|
||||
}
|
||||
fence = intel_batchbuffer_flush( intel->batch );
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
bmFinishFence(intel->bm, fence);
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - DONE\n", __FUNCTION__);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelDrawPixels( GLcontext *ctx,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
const GLvoid *pixels )
|
||||
{
|
||||
if (do_blit_drawpixels( ctx, x, y, width, height, format, type,
|
||||
unpack, pixels ))
|
||||
return;
|
||||
|
||||
if (do_texture_drawpixels( ctx, x, y, width, height, format, type,
|
||||
unpack, pixels ))
|
||||
return;
|
||||
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
|
||||
|
||||
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
|
||||
unpack, pixels );
|
||||
}
|
||||
|
||||
321
src/mesa/drivers/dri/i915/intel_pixel_read.c
Normal file
321
src/mesa/drivers/dri/i915/intel_pixel_read.c
Normal file
@@ -0,0 +1,321 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "glheader.h"
|
||||
#include "enums.h"
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
#include "image.h"
|
||||
#include "bufferobj.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_pixel.h"
|
||||
#include "intel_buffer_objects.h"
|
||||
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
/* For many applications, the new ability to pull the source buffers
|
||||
* back out of the GTT and then do the packing/conversion operations
|
||||
* in software will be as much of an improvement as trying to get the
|
||||
* blitter and/or texture engine to do the work.
|
||||
*
|
||||
* This step is gated on private backbuffers.
|
||||
*
|
||||
* Obviously the frontbuffer can't be pulled back, so that is either
|
||||
* an argument for blit/texture readpixels, or for blitting to a
|
||||
* temporary and then pulling that back.
|
||||
*
|
||||
* When the destination is a pbo, however, it's not clear if it is
|
||||
* ever going to be pulled to main memory (though the access param
|
||||
* will be a good hint). So it sounds like we do want to be able to
|
||||
* choose between blit/texture implementation on the gpu and pullback
|
||||
* and cpu-based copying.
|
||||
*
|
||||
* Unless you can magically turn client memory into a PBO for the
|
||||
* duration of this call, there will be a cpu-based copying step in
|
||||
* any case.
|
||||
*/
|
||||
|
||||
|
||||
static GLboolean
|
||||
do_texture_readpixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
struct intel_region *dest_region )
|
||||
{
|
||||
#if 0
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
GLint pitch = pack->RowLength ? pack->RowLength : width;
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
int textureFormat;
|
||||
GLenum glTextureFormat;
|
||||
int destFormat, depthFormat, destPitch;
|
||||
drm_clip_rect_t tmp;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
|
||||
if ( ctx->_ImageTransferState ||
|
||||
pack->SwapBytes ||
|
||||
pack->LsbFirst ||
|
||||
!pack->Invert) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: check_color failed\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel));
|
||||
|
||||
if (!intel->vtbl.meta_render_dest(intel,
|
||||
dest_region,
|
||||
type, format))
|
||||
{
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: couldn't set dest %s/%s\n",
|
||||
__FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(type),
|
||||
_mesa_lookup_enum_by_nr(format));
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects) {
|
||||
intel->vtbl.install_meta_state(intel);
|
||||
intel->vtbl.meta_no_depth_write(intel);
|
||||
intel->vtbl.meta_no_stencil_write(intel);
|
||||
|
||||
if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
SET_STATE(i830, state);
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
y = dPriv->h - y - height;
|
||||
x += dPriv->x;
|
||||
y += dPriv->y;
|
||||
|
||||
|
||||
/* Set the frontbuffer up as a large rectangular texture.
|
||||
*/
|
||||
intel->vtbl.meta_tex_rect_source( intel,
|
||||
src_region,
|
||||
textureFormat );
|
||||
|
||||
|
||||
intel->vtbl.meta_texture_blend_replace( i830, glTextureFormat );
|
||||
|
||||
|
||||
/* Set the 3d engine to draw into the destination region:
|
||||
*/
|
||||
|
||||
intel->vtbl.meta_draw_region(intel, dest_region);
|
||||
intel->vtbl.meta_draw_format(intel, destFormat, depthFormat ); /* ?? */
|
||||
|
||||
|
||||
/* Draw a single quad, no cliprects:
|
||||
*/
|
||||
intel->vtbl.meta_disable_cliprects(intel);
|
||||
|
||||
intel->vtbl.draw_quad(intel,
|
||||
0, width, 0, height,
|
||||
0x00ff00ff,
|
||||
x, x+width,
|
||||
y, y+height );
|
||||
|
||||
intel->vtbl.leave_meta_state(intel);
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
|
||||
intel_region_wait_fence( ctx, dest_region ); /* required by GL */
|
||||
return GL_TRUE;
|
||||
#endif
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static GLboolean do_blit_readpixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_region *src = intel_readbuf_region(intel);
|
||||
struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
|
||||
GLuint dst_offset;
|
||||
GLuint rowLength;
|
||||
GLuint fence = bmInitFence(intel->bm);
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s\n", __FUNCTION__);
|
||||
|
||||
if (!src)
|
||||
return GL_FALSE;
|
||||
|
||||
if (dst) {
|
||||
/* XXX This validation should be done by core mesa:
|
||||
*/
|
||||
if (!_mesa_validate_pbo_access(2, pack, width, height, 1,
|
||||
format, type, pixels)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels");
|
||||
return GL_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* PBO only for now:
|
||||
*/
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - not PBO\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (ctx->_ImageTransferState ||
|
||||
!intel_check_blit_format(src, format, type)) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - bad format for blit\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s: bad packing params\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if (pack->RowLength > 0)
|
||||
rowLength = pack->RowLength;
|
||||
else
|
||||
rowLength = width;
|
||||
|
||||
if (pack->Invert) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
else {
|
||||
rowLength = -rowLength;
|
||||
}
|
||||
|
||||
/* XXX 64-bit cast? */
|
||||
dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height,
|
||||
format, type, 0, 0, 0);
|
||||
|
||||
|
||||
/* Although the blits go on the command buffer, need to do this and
|
||||
* fire with lock held to guarentee cliprects are correct.
|
||||
*/
|
||||
intelFlush( &intel->ctx );
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
{
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
int nbox = dPriv->numClipRects;
|
||||
drm_clip_rect_t *box = dPriv->pClipRects;
|
||||
drm_clip_rect_t rect;
|
||||
drm_clip_rect_t src_rect;
|
||||
int i;
|
||||
|
||||
src_rect.x1 = dPriv->x + x;
|
||||
src_rect.y1 = dPriv->y + dPriv->h - (y + height);
|
||||
src_rect.x2 = src_rect.x1 + width;
|
||||
src_rect.y2 = src_rect.y1 + height;
|
||||
|
||||
|
||||
|
||||
for (i = 0 ; i < nbox ; i++)
|
||||
{
|
||||
if (!intel_intersect_cliprects(&rect, &src_rect, &box[i]))
|
||||
continue;
|
||||
|
||||
intelEmitCopyBlit( intel,
|
||||
src->cpp,
|
||||
src->pitch, src->buffer, 0,
|
||||
rowLength,
|
||||
intel_bufferobj_buffer(dst), dst_offset,
|
||||
rect.x1,
|
||||
rect.y1,
|
||||
rect.x1 - src_rect.x1,
|
||||
rect.y2 - src_rect.y2,
|
||||
rect.x2 - rect.x1,
|
||||
rect.y2 - rect.y1 );
|
||||
}
|
||||
|
||||
fence = intel_batchbuffer_flush(intel->batch);
|
||||
}
|
||||
UNLOCK_HARDWARE( intel );
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
bmFinishFence(intel->bm, fence);
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s - DONE\n", __FUNCTION__);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
intelReadPixels( GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_pixelstore_attrib *pack,
|
||||
GLvoid *pixels )
|
||||
{
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
intelFlush( ctx );
|
||||
|
||||
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
|
||||
return;
|
||||
|
||||
if (do_texture_readpixels(ctx, x, y, width, height, format, type, pack, pixels))
|
||||
return;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
_mesa_printf("%s: fallback to swrast\n", __FUNCTION__);
|
||||
|
||||
_swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels);
|
||||
}
|
||||
|
||||
264
src/mesa/drivers/dri/i915/intel_regions.c
Normal file
264
src/mesa/drivers/dri/i915/intel_regions.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Provide additional functionality on top of bufmgr buffers:
|
||||
* - 2d semantics and blit operations
|
||||
* - refcounting of buffers for multiple images in a buffer.
|
||||
* - refcounting of buffer mappings.
|
||||
* - some logic for moving the buffers to the best memory pools for
|
||||
* given operations.
|
||||
*
|
||||
* Most of this is to make it easier to implement the fixed-layout
|
||||
* mipmap tree required by intel hardware in the face of GL's
|
||||
* programming interface where each image can be specifed in random
|
||||
* order and it isn't clear what layout the tree should have until the
|
||||
* last moment.
|
||||
*/
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
/* XXX: Thread safety?
|
||||
*/
|
||||
GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
if (!region->map_refcount++) {
|
||||
region->map = bmMapBuffer(intel->bm, region->buffer, 0);
|
||||
}
|
||||
|
||||
return region->map;
|
||||
}
|
||||
|
||||
void intel_region_unmap(struct intel_context *intel,
|
||||
struct intel_region *region)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
if (!--region->map_refcount) {
|
||||
bmUnmapBuffer(intel->bm, region->buffer);
|
||||
region->map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_region *intel_region_alloc( struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLuint pitch,
|
||||
GLuint height )
|
||||
{
|
||||
struct intel_region *region = calloc(sizeof(*region), 1);
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
region->cpp = cpp;
|
||||
region->pitch = pitch;
|
||||
region->height = height; /* needed? */
|
||||
region->refcount = 1;
|
||||
|
||||
bmGenBuffers(intel->bm, 1, ®ion->buffer, 0);
|
||||
bmBufferData(intel->bm, region->buffer, pitch * cpp * height, NULL, 0);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
void intel_region_reference( struct intel_region **dst,
|
||||
struct intel_region *src)
|
||||
{
|
||||
assert(*dst == NULL);
|
||||
if (src) {
|
||||
src->refcount++;
|
||||
*dst = src;
|
||||
}
|
||||
}
|
||||
|
||||
void intel_region_release( struct intel_context *intel,
|
||||
struct intel_region **region )
|
||||
{
|
||||
if (!*region)
|
||||
return;
|
||||
|
||||
DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1);
|
||||
|
||||
ASSERT((*region)->refcount > 0);
|
||||
(*region)->refcount--;
|
||||
|
||||
if ((*region)->refcount == 0) {
|
||||
assert((*region)->map_refcount == 0);
|
||||
bmDeleteBuffers(intel->bm, 1, &(*region)->buffer);
|
||||
free(*region);
|
||||
}
|
||||
*region = NULL;
|
||||
}
|
||||
|
||||
|
||||
struct intel_region *intel_region_create_static( struct intel_context *intel,
|
||||
GLuint mem_type,
|
||||
GLuint offset,
|
||||
void *virtual,
|
||||
GLuint cpp,
|
||||
GLuint pitch,
|
||||
GLuint height )
|
||||
{
|
||||
struct intel_region *region = calloc(sizeof(*region), 1);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
region->cpp = cpp;
|
||||
region->pitch = pitch;
|
||||
region->height = height; /* needed? */
|
||||
region->refcount = 1;
|
||||
|
||||
/*
|
||||
* We use a "shared" buffer type to indicate buffers created and
|
||||
* shared by others.
|
||||
*/
|
||||
|
||||
bmGenBuffers(intel->bm, 1, ®ion->buffer, DRM_MM_TT | DRM_MM_SHARED);
|
||||
bmSetShared(intel->bm, region->buffer, DRM_MM_TT, offset, virtual);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* XXX Move this into core Mesa?
|
||||
*/
|
||||
static void _mesa_copy_rect( GLubyte *dst,
|
||||
GLuint cpp,
|
||||
GLuint dst_pitch,
|
||||
GLuint dst_x,
|
||||
GLuint dst_y,
|
||||
GLuint width,
|
||||
GLuint height,
|
||||
GLubyte *src,
|
||||
GLuint src_pitch,
|
||||
GLuint src_x,
|
||||
GLuint src_y )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
dst_pitch *= cpp;
|
||||
src_pitch *= cpp;
|
||||
dst += dst_x * cpp;
|
||||
src += src_x * cpp;
|
||||
dst += dst_y * dst_pitch;
|
||||
src += src_y * dst_pitch;
|
||||
width *= cpp;
|
||||
|
||||
if (width == dst_pitch &&
|
||||
width == src_pitch)
|
||||
memcpy(dst, src, height * width);
|
||||
else {
|
||||
for (i = 0; i < height; i++) {
|
||||
memcpy(dst, src, width);
|
||||
dst += dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Upload data to a rectangular sub-region. Lots of choices how to do this:
|
||||
*
|
||||
* - memcpy by span to current destination
|
||||
* - upload data as new buffer and blit
|
||||
*
|
||||
* Currently always memcpy.
|
||||
*/
|
||||
void intel_region_data(struct intel_context *intel,
|
||||
struct intel_region *dst,
|
||||
GLuint dst_offset,
|
||||
GLuint dstx, GLuint dsty,
|
||||
void *src, GLuint src_pitch,
|
||||
GLuint srcx, GLuint srcy,
|
||||
GLuint width, GLuint height)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
_mesa_copy_rect(intel_region_map(intel, dst) + dst_offset,
|
||||
dst->cpp,
|
||||
dst->pitch,
|
||||
dstx, dsty,
|
||||
width, height,
|
||||
src,
|
||||
src_pitch,
|
||||
srcx, srcy);
|
||||
|
||||
intel_region_unmap(intel, dst);
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
}
|
||||
|
||||
/* Copy rectangular sub-regions. Need better logic about when to
|
||||
* push buffers into AGP - will currently do so whenever possible.
|
||||
*/
|
||||
void intel_region_copy( struct intel_context *intel,
|
||||
struct intel_region *dst,
|
||||
GLuint dst_offset,
|
||||
GLuint dstx, GLuint dsty,
|
||||
struct intel_region *src,
|
||||
GLuint src_offset,
|
||||
GLuint srcx, GLuint srcy,
|
||||
GLuint width, GLuint height )
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
assert(src->cpp == dst->cpp);
|
||||
|
||||
intelEmitCopyBlit(intel,
|
||||
dst->cpp,
|
||||
src->pitch, src->buffer, src_offset,
|
||||
dst->pitch, dst->buffer, dst_offset,
|
||||
srcx, srcy,
|
||||
dstx, dsty,
|
||||
width, height);
|
||||
}
|
||||
|
||||
/* Fill a rectangular sub-region. Need better logic about when to
|
||||
* push buffers into AGP - will currently do so whenever possible.
|
||||
*/
|
||||
void intel_region_fill( struct intel_context *intel,
|
||||
struct intel_region *dst,
|
||||
GLuint dst_offset,
|
||||
GLuint dstx, GLuint dsty,
|
||||
GLuint width, GLuint height,
|
||||
GLuint color )
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
intelEmitFillBlit(intel,
|
||||
dst->cpp,
|
||||
dst->pitch, dst->buffer, dst_offset,
|
||||
dstx, dsty,
|
||||
width, height,
|
||||
color );
|
||||
}
|
||||
|
||||
119
src/mesa/drivers/dri/i915/intel_regions.h
Normal file
119
src/mesa/drivers/dri/i915/intel_regions.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 INTEL_REGIONS_H
|
||||
#define INTEL_REGIONS_H
|
||||
|
||||
#include "mtypes.h"
|
||||
#include "intel_bufmgr.h" /* for DBG! */
|
||||
struct intel_context;
|
||||
|
||||
/**
|
||||
* A layer on top of the bufmgr buffers that adds a few useful things:
|
||||
*
|
||||
* - Refcounting for local buffer references.
|
||||
* - Refcounting for buffer maps
|
||||
* - Buffer dimensions - pitch and height.
|
||||
* - Blitter commands for copying 2D regions between buffers. (really???)
|
||||
*/
|
||||
struct intel_region {
|
||||
GLuint buffer; /**< buffer manager's buffer ID */
|
||||
GLuint refcount; /**< Reference count for region */
|
||||
GLuint cpp; /**< bytes per pixel */
|
||||
GLuint pitch; /**< in pixels */
|
||||
GLuint height; /**< in pixels */
|
||||
GLubyte *map; /**< only non-NULL when region is actually mapped */
|
||||
GLuint map_refcount; /**< Reference count for mapping */
|
||||
|
||||
GLuint draw_offset; /**< Offset of drawing address within the region */
|
||||
};
|
||||
|
||||
|
||||
/* Allocate a refcounted region. Pointers to regions should only be
|
||||
* copied by calling intel_reference_region().
|
||||
*/
|
||||
struct intel_region *intel_region_alloc( struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLuint pitch,
|
||||
GLuint height );
|
||||
|
||||
void intel_region_reference( struct intel_region **dst,
|
||||
struct intel_region *src );
|
||||
|
||||
void intel_region_release(struct intel_context *intel,
|
||||
struct intel_region **ib );
|
||||
|
||||
|
||||
struct intel_region *intel_region_create_static( struct intel_context *intel,
|
||||
GLuint mem_type,
|
||||
GLuint offset,
|
||||
void *virtual,
|
||||
GLuint cpp,
|
||||
GLuint pitch,
|
||||
GLuint height );
|
||||
|
||||
/* Map/unmap regions. This is refcounted also:
|
||||
*/
|
||||
GLubyte *intel_region_map(struct intel_context *intel,
|
||||
struct intel_region *ib);
|
||||
|
||||
void intel_region_unmap(struct intel_context *intel,
|
||||
struct intel_region *ib);
|
||||
|
||||
|
||||
/* Upload data to a rectangular sub-region
|
||||
*/
|
||||
void intel_region_data(struct intel_context *intel,
|
||||
struct intel_region *dest,
|
||||
GLuint dest_offset,
|
||||
GLuint destx, GLuint desty,
|
||||
void *src, GLuint src_stride,
|
||||
GLuint srcx, GLuint srcy,
|
||||
GLuint width, GLuint height);
|
||||
|
||||
/* Copy rectangular sub-regions
|
||||
*/
|
||||
void intel_region_copy( struct intel_context *intel,
|
||||
struct intel_region *dest,
|
||||
GLuint dest_offset,
|
||||
GLuint destx, GLuint desty,
|
||||
struct intel_region *src,
|
||||
GLuint src_offset,
|
||||
GLuint srcx, GLuint srcy,
|
||||
GLuint width, GLuint height );
|
||||
|
||||
/* Fill a rectangular sub-region
|
||||
*/
|
||||
void intel_region_fill( struct intel_context *intel,
|
||||
struct intel_region *dest,
|
||||
GLuint dest_offset,
|
||||
GLuint destx, GLuint desty,
|
||||
GLuint width, GLuint height,
|
||||
GLuint color );
|
||||
|
||||
|
||||
#endif
|
||||
@@ -106,24 +106,29 @@ static const int scale_prim[GL_POLYGON+1] = {
|
||||
};
|
||||
|
||||
|
||||
static void intelDmaPrimitive( intelContextPtr intel, GLenum prim )
|
||||
static void intelDmaPrimitive( struct intel_context *intel, GLenum prim )
|
||||
{
|
||||
if (0) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
|
||||
INTEL_FIREVERTICES(intel);
|
||||
intel->vtbl.reduced_primitive_state( intel, reduced_prim[prim] );
|
||||
intelStartInlinePrimitive( intel, hw_prim[prim] );
|
||||
intelStartInlinePrimitive( intel, hw_prim[prim], INTEL_BATCH_CLIPRECTS );
|
||||
}
|
||||
|
||||
|
||||
#define LOCAL_VARS intelContextPtr intel = INTEL_CONTEXT(ctx)
|
||||
#define LOCAL_VARS struct intel_context *intel = intel_context(ctx)
|
||||
#define INIT( prim ) \
|
||||
do { \
|
||||
intelDmaPrimitive( intel, prim ); \
|
||||
} while (0)
|
||||
#define FLUSH() INTEL_FIREVERTICES( intel )
|
||||
|
||||
#define FLUSH() \
|
||||
do { \
|
||||
if (intel->prim.flush) \
|
||||
intel->prim.flush(intel); \
|
||||
} while (0)
|
||||
|
||||
#define GET_SUBSEQUENT_VB_MAX_VERTS() \
|
||||
(((intel->alloc.size / 2) - 1500) / (intel->vertex_size*4))
|
||||
((BATCH_SZ - 1500) / (intel->vertex_size*4))
|
||||
#define GET_CURRENT_VB_MAX_VERTS() GET_SUBSEQUENT_VB_MAX_VERTS()
|
||||
|
||||
#define ALLOC_VERTS( nr ) \
|
||||
@@ -142,7 +147,7 @@ do { \
|
||||
|
||||
/* Heuristic to choose between the two render paths:
|
||||
*/
|
||||
static GLboolean choose_render( intelContextPtr intel,
|
||||
static GLboolean choose_render( struct intel_context *intel,
|
||||
struct vertex_buffer *VB )
|
||||
{
|
||||
int vertsz = intel->vertex_size;
|
||||
@@ -194,7 +199,7 @@ static GLboolean choose_render( intelContextPtr intel,
|
||||
static GLboolean intel_run_render( GLcontext *ctx,
|
||||
struct tnl_pipeline_stage *stage )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
GLuint i;
|
||||
@@ -225,6 +230,9 @@ static GLboolean intel_run_render( GLcontext *ctx,
|
||||
}
|
||||
|
||||
tnl->Driver.Render.Finish( ctx );
|
||||
|
||||
if (intel->prim.flush)
|
||||
intel->prim.flush(intel);
|
||||
|
||||
return GL_FALSE; /* finished the pipe */
|
||||
}
|
||||
|
||||
@@ -37,15 +37,16 @@
|
||||
|
||||
#include "intel_screen.h"
|
||||
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_span.h"
|
||||
#include "intel_tris.h"
|
||||
#include "intel_ioctl.h"
|
||||
|
||||
|
||||
#include "intel_fbo.h"
|
||||
|
||||
#include "i830_dri.h"
|
||||
|
||||
|
||||
PUBLIC const char __driConfigOptions[] =
|
||||
DRI_CONF_BEGIN
|
||||
DRI_CONF_SECTION_PERFORMANCE
|
||||
@@ -104,14 +105,14 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
intelScreen->cpp = gDRIPriv->cpp;
|
||||
|
||||
switch (gDRIPriv->bitsPerPixel) {
|
||||
case 15: intelScreen->fbFormat = DV_PF_555; break;
|
||||
case 16: intelScreen->fbFormat = DV_PF_565; break;
|
||||
case 32: intelScreen->fbFormat = DV_PF_8888; break;
|
||||
default: exit(1); break;
|
||||
}
|
||||
|
||||
intelScreen->front.pitch = gDRIPriv->fbStride;
|
||||
intelScreen->front.offset = gDRIPriv->fbOffset;
|
||||
intelScreen->front.map = sPriv->pFB;
|
||||
intelScreen->front.map = (char *)sPriv->pFB;
|
||||
|
||||
intelScreen->back.offset = gDRIPriv->backOffset;
|
||||
intelScreen->back.pitch = gDRIPriv->backPitch;
|
||||
@@ -146,6 +147,12 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
* FIXME: Remove this code and its references.
|
||||
*/
|
||||
|
||||
intelScreen->tex.offset = gDRIPriv->textureOffset;
|
||||
intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity;
|
||||
intelScreen->tex.handle = gDRIPriv->textures;
|
||||
@@ -163,10 +170,17 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
sPriv->private = NULL;
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
intelScreen->tex.offset = 0;
|
||||
intelScreen->logTextureGranularity = 0;
|
||||
intelScreen->tex.handle = 0;
|
||||
intelScreen->tex.size = 0;
|
||||
#endif
|
||||
|
||||
intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
|
||||
|
||||
if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
|
||||
if (1) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
|
||||
|
||||
intelScreen->drmMinor = sPriv->drmMinor;
|
||||
|
||||
@@ -202,13 +216,8 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
|
||||
if (glx_enable_extension != NULL) {
|
||||
(*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
|
||||
(*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
|
||||
}
|
||||
|
||||
sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
|
||||
sPriv->psc->freeMemory = (void *) intelFreeMemoryMESA;
|
||||
sPriv->psc->memoryOffset = (void *) intelGetMemoryOffsetMESA;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
@@ -227,6 +236,9 @@ static void intelDestroyScreen(__DRIscreenPrivate *sPriv)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is called when we need to set up GL rendering to a new X window.
|
||||
*/
|
||||
static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
|
||||
__DRIdrawablePrivate *driDrawPriv,
|
||||
const __GLcontextModes *mesaVis,
|
||||
@@ -239,70 +251,71 @@ static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
|
||||
} else {
|
||||
GLboolean swStencil = (mesaVis->stencilBits > 0 &&
|
||||
mesaVis->depthBits != 24);
|
||||
GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8);
|
||||
|
||||
struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
|
||||
|
||||
/* setup the hardware-based renderbuffers */
|
||||
{
|
||||
driRenderbuffer *frontRb
|
||||
= driNewRenderbuffer(GL_RGBA,
|
||||
driScrnPriv->pFB,
|
||||
screen->cpp,
|
||||
screen->front.offset, screen->front.pitch,
|
||||
driDrawPriv);
|
||||
intelSetSpanFunctions(frontRb, mesaVis);
|
||||
struct intel_renderbuffer *frontRb
|
||||
= intel_create_renderbuffer(rgbFormat,
|
||||
screen->width, screen->height,
|
||||
screen->front.offset,
|
||||
screen->front.pitch,
|
||||
screen->cpp,
|
||||
driScrnPriv->pFB);
|
||||
intel_set_span_functions(&frontRb->Base);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
|
||||
}
|
||||
|
||||
if (mesaVis->doubleBufferMode) {
|
||||
driRenderbuffer *backRb
|
||||
= driNewRenderbuffer(GL_RGBA,
|
||||
screen->back.map,
|
||||
screen->cpp,
|
||||
screen->back.offset, screen->back.pitch,
|
||||
driDrawPriv);
|
||||
intelSetSpanFunctions(backRb, mesaVis);
|
||||
struct intel_renderbuffer *backRb
|
||||
= intel_create_renderbuffer(rgbFormat,
|
||||
screen->width, screen->height,
|
||||
screen->back.offset,
|
||||
screen->back.pitch,
|
||||
screen->cpp,
|
||||
screen->back.map);
|
||||
intel_set_span_functions(&backRb->Base);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
|
||||
}
|
||||
|
||||
if (mesaVis->depthBits == 16) {
|
||||
driRenderbuffer *depthRb
|
||||
= driNewRenderbuffer(GL_DEPTH_COMPONENT16,
|
||||
screen->depth.map,
|
||||
screen->cpp,
|
||||
screen->depth.offset, screen->depth.pitch,
|
||||
driDrawPriv);
|
||||
intelSetSpanFunctions(depthRb, mesaVis);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
|
||||
if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
|
||||
/* combined depth/stencil buffer */
|
||||
struct intel_renderbuffer *depthStencilRb
|
||||
= intel_create_renderbuffer(
|
||||
GL_DEPTH24_STENCIL8_EXT,
|
||||
screen->width, screen->height,
|
||||
screen->depth.offset,
|
||||
screen->depth.pitch,
|
||||
screen->cpp, /* 4! */
|
||||
screen->depth.map);
|
||||
intel_set_span_functions(&depthStencilRb->Base);
|
||||
/* note: bind RB to two attachment points */
|
||||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base);
|
||||
}
|
||||
else if (mesaVis->depthBits == 24) {
|
||||
driRenderbuffer *depthRb
|
||||
= driNewRenderbuffer(GL_DEPTH_COMPONENT24,
|
||||
screen->depth.map,
|
||||
screen->cpp,
|
||||
screen->depth.offset, screen->depth.pitch,
|
||||
driDrawPriv);
|
||||
intelSetSpanFunctions(depthRb, mesaVis);
|
||||
else if (mesaVis->depthBits == 16) {
|
||||
/* just 16-bit depth buffer, no hw stencil */
|
||||
struct intel_renderbuffer *depthRb
|
||||
= intel_create_renderbuffer(GL_DEPTH_COMPONENT16,
|
||||
screen->width, screen->height,
|
||||
screen->depth.offset,
|
||||
screen->depth.pitch,
|
||||
screen->cpp, /* 2! */
|
||||
screen->depth.map);
|
||||
intel_set_span_functions(&depthRb->Base);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
|
||||
}
|
||||
|
||||
if (mesaVis->stencilBits > 0 && !swStencil) {
|
||||
driRenderbuffer *stencilRb
|
||||
= driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
|
||||
screen->depth.map,
|
||||
screen->cpp,
|
||||
screen->depth.offset, screen->depth.pitch,
|
||||
driDrawPriv);
|
||||
intelSetSpanFunctions(stencilRb, mesaVis);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
|
||||
}
|
||||
|
||||
/* now add any/all software-based renderbuffers we may need */
|
||||
_mesa_add_soft_renderbuffers(fb,
|
||||
GL_FALSE, /* color */
|
||||
GL_FALSE, /* depth */
|
||||
GL_FALSE, /* never sw color */
|
||||
GL_FALSE, /* never sw depth */
|
||||
swStencil,
|
||||
mesaVis->accumRedBits > 0,
|
||||
GL_FALSE, /* alpha */
|
||||
GL_FALSE /* aux */);
|
||||
GL_FALSE, /* never sw alpha */
|
||||
GL_FALSE /* never sw aux */);
|
||||
driDrawPriv->driverPrivate = (void *) fb;
|
||||
|
||||
return (driDrawPriv->driverPrivate != NULL);
|
||||
@@ -338,6 +351,8 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
|
||||
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
|
||||
|
||||
switch (intelScreen->deviceID) {
|
||||
/* Don't deal with i830 until texture work complete:
|
||||
*/
|
||||
case PCI_CHIP_845_G:
|
||||
case PCI_CHIP_I830_M:
|
||||
case PCI_CHIP_I855_GM:
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
#include "dri_util.h"
|
||||
#include "xmlconfig.h"
|
||||
|
||||
/* XXX: change name or eliminate to avoid conflict with "struct
|
||||
* intel_region"!!!
|
||||
*/
|
||||
typedef struct {
|
||||
drm_handle_t handle;
|
||||
drmSize size; /* region size in bytes */
|
||||
@@ -54,7 +57,7 @@ typedef struct
|
||||
|
||||
int cpp; /* for front and back buffers */
|
||||
int bitsPerPixel; /* unused */
|
||||
int fbFormat;
|
||||
int fbFormat; /* XXX FBO: this is obsolete - remove after i830 updates */
|
||||
|
||||
int logTextureGranularity;
|
||||
|
||||
@@ -84,7 +87,4 @@ intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
|
||||
__DRIdrawablePrivate *driDrawPriv,
|
||||
__DRIdrawablePrivate *driReadPriv);
|
||||
|
||||
extern void
|
||||
intelSwapBuffers( __DRIdrawablePrivate *dPriv);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,194 +30,340 @@
|
||||
#include "mtypes.h"
|
||||
#include "colormac.h"
|
||||
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_screen.h"
|
||||
|
||||
#include "intel_span.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_tex.h"
|
||||
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
/*
|
||||
break intelWriteRGBASpan_ARGB8888
|
||||
*/
|
||||
|
||||
#undef DBG
|
||||
#define DBG 0
|
||||
|
||||
#define LOCAL_VARS \
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx); \
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
|
||||
driRenderbuffer *drb = (driRenderbuffer *) rb; \
|
||||
GLuint pitch = drb->pitch * drb->cpp; \
|
||||
GLuint height = dPriv->h; \
|
||||
char *buf = (char *) drb->Base.Data + \
|
||||
dPriv->x * drb->cpp + \
|
||||
dPriv->y * pitch; \
|
||||
GLushort p; \
|
||||
(void) buf; (void) p
|
||||
#define LOCAL_VARS \
|
||||
struct intel_context *intel = intel_context(ctx); \
|
||||
struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
|
||||
const GLint yScale = irb->RenderToTexture ? 1 : -1; \
|
||||
const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
|
||||
GLubyte *buf = (GLubyte *) irb->pfMap \
|
||||
+ (intel->drawY * irb->pfPitch + intel->drawX) * irb->region->cpp;\
|
||||
GLuint p; \
|
||||
assert(irb->pfMap);\
|
||||
(void) p;
|
||||
|
||||
#define LOCAL_DEPTH_VARS \
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx); \
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
|
||||
driRenderbuffer *drb = (driRenderbuffer *) rb; \
|
||||
GLuint pitch = drb->pitch * drb->cpp; \
|
||||
GLuint height = dPriv->h; \
|
||||
char *buf = (char *) drb->Base.Data + \
|
||||
dPriv->x * drb->cpp + \
|
||||
dPriv->y * pitch
|
||||
/* XXX FBO: this is identical to the macro in spantmp2.h except we get
|
||||
* the cliprect info from the context, not the driDrawable.
|
||||
* Move this into spantmp2.h someday.
|
||||
*/
|
||||
#define HW_CLIPLOOP() \
|
||||
do { \
|
||||
int _nc = intel->numClipRects; \
|
||||
while ( _nc-- ) { \
|
||||
int minx = intel->pClipRects[_nc].x1 - intel->drawX; \
|
||||
int miny = intel->pClipRects[_nc].y1 - intel->drawY; \
|
||||
int maxx = intel->pClipRects[_nc].x2 - intel->drawX; \
|
||||
int maxy = intel->pClipRects[_nc].y2 - intel->drawY;
|
||||
|
||||
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
|
||||
|
||||
#define INIT_MONO_PIXEL(p,color)\
|
||||
p = INTEL_PACKCOLOR565(color[0],color[1],color[2])
|
||||
|
||||
#define Y_FLIP(_y) (height - _y - 1)
|
||||
|
||||
#define Y_FLIP(_y) ((_y) * yScale + yBias)
|
||||
|
||||
#define HW_LOCK()
|
||||
|
||||
#define HW_UNLOCK()
|
||||
|
||||
/* 16 bit, 565 rgb color spanline and pixel functions
|
||||
/* 16 bit, RGB565 color spanline and pixel functions
|
||||
*/
|
||||
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
|
||||
*(GLushort *)(buf + _x*2 + _y*pitch) = ( (((int)r & 0xf8) << 8) | \
|
||||
(((int)g & 0xfc) << 3) | \
|
||||
(((int)b & 0xf8) >> 3))
|
||||
#define WRITE_PIXEL( _x, _y, p ) \
|
||||
*(GLushort *)(buf + _x*2 + _y*pitch) = p
|
||||
#define SPANTMP_PIXEL_FMT GL_RGB
|
||||
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
|
||||
|
||||
#define READ_RGBA( rgba, _x, _y ) \
|
||||
do { \
|
||||
GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \
|
||||
rgba[0] = (((p >> 11) & 0x1f) * 255) / 31; \
|
||||
rgba[1] = (((p >> 5) & 0x3f) * 255) / 63; \
|
||||
rgba[2] = (((p >> 0) & 0x1f) * 255) / 31; \
|
||||
rgba[3] = 255; \
|
||||
} while(0)
|
||||
#define TAG(x) intel##x##_RGB565
|
||||
#define TAG2(x,y) intel##x##_RGB565##y
|
||||
#define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 2)
|
||||
#include "spantmp2.h"
|
||||
|
||||
#define TAG(x) intel##x##_565
|
||||
#include "spantmp.h"
|
||||
|
||||
/* 15 bit, 555 rgb color spanline and pixel functions
|
||||
/* 32 bit, ARGB8888 color spanline and pixel functions
|
||||
*/
|
||||
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
|
||||
*(GLushort *)(buf + _x*2 + _y*pitch) = (((r & 0xf8) << 7) | \
|
||||
((g & 0xf8) << 3) | \
|
||||
((b & 0xf8) >> 3))
|
||||
#define SPANTMP_PIXEL_FMT GL_BGRA
|
||||
#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
|
||||
#define WRITE_PIXEL( _x, _y, p ) \
|
||||
*(GLushort *)(buf + _x*2 + _y*pitch) = p
|
||||
#define TAG(x) intel##x##_ARGB8888
|
||||
#define TAG2(x,y) intel##x##_ARGB8888##y
|
||||
#define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 4)
|
||||
#include "spantmp2.h"
|
||||
|
||||
#define READ_RGBA( rgba, _x, _y ) \
|
||||
do { \
|
||||
GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \
|
||||
rgba[0] = (p >> 7) & 0xf8; \
|
||||
rgba[1] = (p >> 3) & 0xf8; \
|
||||
rgba[2] = (p << 3) & 0xf8; \
|
||||
rgba[3] = 255; \
|
||||
} while(0)
|
||||
|
||||
#define TAG(x) intel##x##_555
|
||||
#include "spantmp.h"
|
||||
#define LOCAL_DEPTH_VARS \
|
||||
struct intel_context *intel = intel_context(ctx); \
|
||||
struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
|
||||
const GLuint pitch = irb->pfPitch/***XXX region->pitch*/; /* in pixels */ \
|
||||
const GLint yScale = irb->RenderToTexture ? 1 : -1; \
|
||||
const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
|
||||
char *buf = (char *) irb->pfMap/*XXX use region->map*/ + \
|
||||
(intel->drawY * pitch + intel->drawX) * irb->region->cpp;
|
||||
|
||||
/* 16 bit depthbuffer functions.
|
||||
*/
|
||||
|
||||
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
|
||||
|
||||
/**
|
||||
** 16-bit depthbuffer functions.
|
||||
**/
|
||||
#define WRITE_DEPTH( _x, _y, d ) \
|
||||
*(GLushort *)(buf + (_x)*2 + (_y)*pitch) = d;
|
||||
((GLushort *)buf)[(_x) + (_y) * pitch] = d;
|
||||
|
||||
#define READ_DEPTH( d, _x, _y ) \
|
||||
d = *(GLushort *)(buf + (_x)*2 + (_y)*pitch);
|
||||
d = ((GLushort *)buf)[(_x) + (_y) * pitch];
|
||||
|
||||
|
||||
#define TAG(x) intel##x##_z16
|
||||
#include "depthtmp.h"
|
||||
|
||||
|
||||
#undef LOCAL_VARS
|
||||
#define LOCAL_VARS \
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx); \
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable; \
|
||||
driRenderbuffer *drb = (driRenderbuffer *) rb; \
|
||||
GLuint pitch = drb->pitch * drb->cpp; \
|
||||
GLuint height = dPriv->h; \
|
||||
char *buf = (char *)drb->Base.Data + \
|
||||
dPriv->x * drb->cpp + \
|
||||
dPriv->y * pitch; \
|
||||
GLuint p; \
|
||||
(void) buf; (void) p
|
||||
|
||||
#undef INIT_MONO_PIXEL
|
||||
#define INIT_MONO_PIXEL(p,color)\
|
||||
p = INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3])
|
||||
|
||||
/* 32 bit, 8888 argb color spanline and pixel functions
|
||||
*/
|
||||
#define WRITE_RGBA(_x, _y, r, g, b, a) \
|
||||
*(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) | \
|
||||
(g << 8) | \
|
||||
(b << 0) | \
|
||||
(a << 24) )
|
||||
|
||||
#define WRITE_PIXEL(_x, _y, p) \
|
||||
*(GLuint *)(buf + _x*4 + _y*pitch) = p
|
||||
|
||||
|
||||
#define READ_RGBA(rgba, _x, _y) \
|
||||
do { \
|
||||
GLuint p = *(GLuint *)(buf + _x*4 + _y*pitch); \
|
||||
rgba[0] = (p >> 16) & 0xff; \
|
||||
rgba[1] = (p >> 8) & 0xff; \
|
||||
rgba[2] = (p >> 0) & 0xff; \
|
||||
rgba[3] = (p >> 24) & 0xff; \
|
||||
} while (0)
|
||||
|
||||
#define TAG(x) intel##x##_8888
|
||||
#include "spantmp.h"
|
||||
|
||||
|
||||
/* 24/8 bit interleaved depth/stencil functions
|
||||
*/
|
||||
#define WRITE_DEPTH( _x, _y, d ) { \
|
||||
GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
|
||||
tmp &= 0xff000000; \
|
||||
tmp |= (d) & 0xffffff; \
|
||||
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
|
||||
/**
|
||||
** 24/8-bit interleaved depth/stencil functions
|
||||
** Note: we're actually reading back combined depth+stencil values.
|
||||
** The wrappers in main/depthstencil.c are used to extract the depth
|
||||
** and stencil values.
|
||||
**/
|
||||
/* Change ZZZS -> SZZZ */
|
||||
#define WRITE_DEPTH( _x, _y, d ) { \
|
||||
GLuint tmp = ((d) >> 8) | ((d) << 24); \
|
||||
((GLuint *)buf)[(_x) + (_y) * pitch] = tmp; \
|
||||
}
|
||||
|
||||
#define READ_DEPTH( d, _x, _y ) \
|
||||
d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) & 0xffffff;
|
||||
|
||||
/* Change SZZZ -> ZZZS */
|
||||
#define READ_DEPTH( d, _x, _y ) { \
|
||||
GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch]; \
|
||||
d = (tmp << 8) | (tmp >> 24); \
|
||||
}
|
||||
|
||||
#define TAG(x) intel##x##_z24_s8
|
||||
#include "depthtmp.h"
|
||||
|
||||
#define WRITE_STENCIL( _x, _y, d ) { \
|
||||
GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
|
||||
tmp &= 0xffffff; \
|
||||
tmp |= ((d)<<24); \
|
||||
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
|
||||
|
||||
/**
|
||||
** 8-bit stencil function (XXX FBO: This is obsolete)
|
||||
**/
|
||||
#define WRITE_STENCIL( _x, _y, d ) { \
|
||||
GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch]; \
|
||||
tmp &= 0xffffff; \
|
||||
tmp |= ((d) << 24); \
|
||||
((GLuint *) buf)[(_x) + (_y) * pitch] = tmp; \
|
||||
}
|
||||
|
||||
#define READ_STENCIL( d, _x, _y ) \
|
||||
d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) >> 24;
|
||||
#define READ_STENCIL( d, _x, _y ) \
|
||||
d = ((GLuint *)buf)[(_x) + (_y) * pitch] >> 24;
|
||||
|
||||
#define TAG(x) intel##x##_z24_s8
|
||||
#include "stenciltmp.h"
|
||||
|
||||
|
||||
/* Move locking out to get reasonable span performance.
|
||||
|
||||
/**
|
||||
* Map or unmap all the renderbuffers which we may need during
|
||||
* software rendering.
|
||||
* XXX in the future, we could probably convey extra information to
|
||||
* reduce the number of mappings needed. I.e. if doing a glReadPixels
|
||||
* from the depth buffer, we really only need one mapping.
|
||||
*
|
||||
* XXX Rewrite this function someday.
|
||||
* We can probably just loop over all the renderbuffer attachments,
|
||||
* map/unmap all of them, and not worry about the _ColorDrawBuffers
|
||||
* _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
|
||||
*/
|
||||
static void
|
||||
intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
GLuint i, j;
|
||||
struct intel_renderbuffer *irb;
|
||||
|
||||
/* color draw buffers */
|
||||
for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
|
||||
for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers[i]; j++) {
|
||||
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i][j];
|
||||
irb = intel_renderbuffer(rb);
|
||||
if (irb) {
|
||||
/* this is a user-created intel_renderbuffer */
|
||||
if (irb->region) {
|
||||
if (map)
|
||||
intel_region_map(intel, irb->region);
|
||||
else
|
||||
intel_region_unmap(intel, irb->region);
|
||||
}
|
||||
irb->pfMap = irb->region->map;
|
||||
irb->pfPitch = irb->region->pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check for render to textures */
|
||||
for (i = 0; i < BUFFER_COUNT; i++) {
|
||||
struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment + i;
|
||||
struct gl_texture_object *tex = att->Texture;
|
||||
if (tex) {
|
||||
/* render to texture */
|
||||
ASSERT(att->Renderbuffer);
|
||||
if (map) {
|
||||
struct gl_texture_image *texImg;
|
||||
texImg = tex->Image[att->CubeMapFace][att->TextureLevel];
|
||||
intel_tex_map_images(intel, intel_texture_object(tex));
|
||||
}
|
||||
else {
|
||||
intel_tex_unmap_images(intel, intel_texture_object(tex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* color read buffers */
|
||||
irb = intel_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
|
||||
if (irb && irb->region) {
|
||||
if (map)
|
||||
intel_region_map(intel, irb->region);
|
||||
else
|
||||
intel_region_unmap(intel, irb->region);
|
||||
irb->pfMap = irb->region->map;
|
||||
irb->pfPitch = irb->region->pitch;
|
||||
}
|
||||
|
||||
/* Account for front/back color page flipping.
|
||||
* The span routines use the pfMap and pfPitch fields which will
|
||||
* swap the front/back region map/pitch if we're page flipped.
|
||||
* Do this after mapping, above, so the map field is valid.
|
||||
*/
|
||||
#if 0
|
||||
if (map && ctx->DrawBuffer->Name == 0) {
|
||||
struct intel_renderbuffer *irbFront
|
||||
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_FRONT_LEFT);
|
||||
struct intel_renderbuffer *irbBack
|
||||
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_BACK_LEFT);
|
||||
if (irbBack) {
|
||||
/* double buffered */
|
||||
if (intel->sarea->pf_current_page == 0) {
|
||||
irbFront->pfMap = irbFront->region->map;
|
||||
irbFront->pfPitch = irbFront->region->pitch;
|
||||
irbBack->pfMap = irbBack->region->map;
|
||||
irbBack->pfPitch = irbBack->region->pitch;
|
||||
}
|
||||
else {
|
||||
irbFront->pfMap = irbBack->region->map;
|
||||
irbFront->pfPitch = irbBack->region->pitch;
|
||||
irbBack->pfMap = irbFront->region->map;
|
||||
irbBack->pfPitch = irbFront->region->pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* depth buffer (Note wrapper!) */
|
||||
if (ctx->DrawBuffer->_DepthBuffer) {
|
||||
irb = intel_renderbuffer(ctx->DrawBuffer->_DepthBuffer->Wrapped);
|
||||
if (irb && irb->region && irb->Base.Name != 0) {
|
||||
if (map) {
|
||||
intel_region_map(intel, irb->region);
|
||||
irb->pfMap = irb->region->map;
|
||||
irb->pfPitch = irb->region->pitch;
|
||||
}
|
||||
else {
|
||||
intel_region_unmap(intel, irb->region);
|
||||
irb->pfMap = NULL;
|
||||
irb->pfPitch = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stencil buffer (Note wrapper!) */
|
||||
if (ctx->DrawBuffer->_StencilBuffer) {
|
||||
irb = intel_renderbuffer(ctx->DrawBuffer->_StencilBuffer->Wrapped);
|
||||
if (irb && irb->region && irb->Base.Name != 0) {
|
||||
if (map) {
|
||||
intel_region_map(intel, irb->region);
|
||||
irb->pfMap = irb->region->map;
|
||||
irb->pfPitch = irb->region->pitch;
|
||||
}
|
||||
else {
|
||||
intel_region_unmap(intel, irb->region);
|
||||
irb->pfMap = NULL;
|
||||
irb->pfPitch = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Prepare for softare rendering. Map current read/draw framebuffers'
|
||||
* renderbuffes and all currently bound texture objects.
|
||||
*
|
||||
* Old note: Moved locking out to get reasonable span performance.
|
||||
*/
|
||||
void intelSpanRenderStart( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
GLuint i;
|
||||
|
||||
intelFlush(&intel->ctx);
|
||||
LOCK_HARDWARE(intel);
|
||||
intelWaitForIdle(intel);
|
||||
|
||||
#if 0
|
||||
/* Just map the framebuffer and all textures. Bufmgr code will
|
||||
* take care of waiting on the necessary fences:
|
||||
*/
|
||||
intel_region_map(intel, intel->front_region);
|
||||
intel_region_map(intel, intel->back_region);
|
||||
intel_region_map(intel, intel->depth_region);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
|
||||
if (ctx->Texture.Unit[i]._ReallyEnabled) {
|
||||
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
|
||||
intel_tex_map_images(intel, intel_texture_object(texObj));
|
||||
}
|
||||
}
|
||||
|
||||
intel_map_unmap_buffers(intel, GL_TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when done softare rendering. Unmap the buffers we mapped in
|
||||
* the above function.
|
||||
*/
|
||||
void intelSpanRenderFinish( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
GLuint i;
|
||||
|
||||
_swrast_flush( ctx );
|
||||
|
||||
/* Now unmap the framebuffer:
|
||||
*/
|
||||
#if 0
|
||||
intel_region_unmap(intel, intel->front_region);
|
||||
intel_region_unmap(intel, intel->back_region);
|
||||
intel_region_unmap(intel, intel->depth_region);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
|
||||
if (ctx->Texture.Unit[i]._ReallyEnabled) {
|
||||
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
|
||||
intel_tex_unmap_images(intel, intel_texture_object(texObj));
|
||||
}
|
||||
}
|
||||
|
||||
intel_map_unmap_buffers(intel, GL_FALSE);
|
||||
|
||||
UNLOCK_HARDWARE( intel );
|
||||
}
|
||||
|
||||
|
||||
void intelInitSpanFuncs( GLcontext *ctx )
|
||||
{
|
||||
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
|
||||
@@ -227,32 +373,31 @@ void intelInitSpanFuncs( GLcontext *ctx )
|
||||
|
||||
|
||||
/**
|
||||
* Plug in the Get/Put routines for the given driRenderbuffer.
|
||||
* Plug in appropriate span read/write functions for the given renderbuffer.
|
||||
* These are used for the software fallbacks.
|
||||
*/
|
||||
void
|
||||
intelSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
|
||||
intel_set_span_functions(struct gl_renderbuffer *rb)
|
||||
{
|
||||
if (drb->Base.InternalFormat == GL_RGBA) {
|
||||
if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) {
|
||||
intelInitPointers_555(&drb->Base);
|
||||
}
|
||||
else if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
|
||||
intelInitPointers_565(&drb->Base);
|
||||
}
|
||||
else {
|
||||
assert(vis->redBits == 8);
|
||||
assert(vis->greenBits == 8);
|
||||
assert(vis->blueBits == 8);
|
||||
intelInitPointers_8888(&drb->Base);
|
||||
}
|
||||
if (rb->_ActualFormat == GL_RGB5) {
|
||||
/* 565 RGB */
|
||||
intelInitPointers_RGB565(rb);
|
||||
}
|
||||
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
|
||||
intelInitDepthPointers_z16(&drb->Base);
|
||||
else if (rb->_ActualFormat == GL_RGBA8) {
|
||||
/* 8888 RGBA */
|
||||
intelInitPointers_ARGB8888(rb);
|
||||
}
|
||||
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
|
||||
intelInitDepthPointers_z24_s8(&drb->Base);
|
||||
else if (rb->_ActualFormat == GL_DEPTH_COMPONENT16) {
|
||||
intelInitDepthPointers_z16(rb);
|
||||
}
|
||||
else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
|
||||
intelInitStencilPointers_z24_s8(&drb->Base);
|
||||
else if (rb->_ActualFormat == GL_DEPTH_COMPONENT24 || /* XXX FBO remove */
|
||||
rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
|
||||
intelInitDepthPointers_z24_s8(rb);
|
||||
}
|
||||
else if (rb->_ActualFormat == GL_STENCIL_INDEX8_EXT) { /* XXX FBO remove */
|
||||
intelInitStencilPointers_z24_s8(rb);
|
||||
}
|
||||
else {
|
||||
_mesa_problem(NULL, "Unexpected _ActualFormat in intelSetSpanFunctions");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,14 +28,12 @@
|
||||
#ifndef _INTEL_SPAN_H
|
||||
#define _INTEL_SPAN_H
|
||||
|
||||
#include "drirenderbuffer.h"
|
||||
|
||||
extern void intelInitSpanFuncs( GLcontext *ctx );
|
||||
|
||||
extern void intelSpanRenderFinish( GLcontext *ctx );
|
||||
extern void intelSpanRenderStart( GLcontext *ctx );
|
||||
|
||||
extern void
|
||||
intelSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis);
|
||||
intel_set_span_functions(struct gl_renderbuffer *rb);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,10 +30,13 @@
|
||||
#include "context.h"
|
||||
#include "macros.h"
|
||||
#include "enums.h"
|
||||
#include "colormac.h"
|
||||
#include "dd.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_regions.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
int intel_translate_compare_func( GLenum func )
|
||||
@@ -164,86 +167,67 @@ int intel_translate_logic_op( GLenum opcode )
|
||||
}
|
||||
}
|
||||
|
||||
static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
int front = 0;
|
||||
|
||||
if (!ctx->DrawBuffer)
|
||||
return;
|
||||
|
||||
switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
|
||||
case BUFFER_BIT_FRONT_LEFT:
|
||||
front = 1;
|
||||
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
|
||||
break;
|
||||
case BUFFER_BIT_BACK_LEFT:
|
||||
front = 0;
|
||||
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
|
||||
break;
|
||||
default:
|
||||
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( intel->sarea->pf_current_page == 1 )
|
||||
front ^= 1;
|
||||
|
||||
intelSetFrontClipRects( intel );
|
||||
|
||||
if (front) {
|
||||
intel->drawOffset = screen->front.offset;
|
||||
} else {
|
||||
intel->drawOffset = screen->back.offset;
|
||||
}
|
||||
|
||||
intel->vtbl.set_draw_offset( intel, intel->drawOffset );
|
||||
}
|
||||
|
||||
static void intelReadBuffer( GLcontext *ctx, GLenum mode )
|
||||
{
|
||||
/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
|
||||
}
|
||||
|
||||
|
||||
static void intelClearColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
GLubyte clear[4];
|
||||
|
||||
CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]);
|
||||
CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]);
|
||||
|
||||
intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat,
|
||||
intel->clear_red,
|
||||
intel->clear_green,
|
||||
intel->clear_blue,
|
||||
intel->clear_alpha);
|
||||
/* compute both 32 and 16-bit clear values */
|
||||
intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1],
|
||||
clear[2], clear[3]);
|
||||
intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the viewport transformation matrix. Depends on:
|
||||
* - viewport pos/size
|
||||
* - depthrange
|
||||
* - window pos/size or FBO size
|
||||
*/
|
||||
static void intelCalcViewport( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
const GLfloat *v = ctx->Viewport._WindowMap.m;
|
||||
const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
|
||||
GLfloat *m = intel->ViewportMatrix.m;
|
||||
GLint h = 0;
|
||||
GLfloat yScale, yBias;
|
||||
|
||||
if (intel->driDrawable)
|
||||
h = intel->driDrawable->h + SUBPIXEL_Y;
|
||||
if (ctx->DrawBuffer->Name) {
|
||||
/* User created FBO */
|
||||
struct intel_renderbuffer *irb
|
||||
= intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]);
|
||||
if (irb && !irb->RenderToTexture) {
|
||||
/* y=0=top */
|
||||
yScale = -1.0;
|
||||
yBias = irb->Base.Height;
|
||||
}
|
||||
else {
|
||||
/* y=0=bottom */
|
||||
yScale = 1.0;
|
||||
yBias = 0.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* window buffer, y=0=top */
|
||||
yScale = -1.0;
|
||||
yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F;
|
||||
}
|
||||
|
||||
/* See also intel_translate_vertex. SUBPIXEL adjustments can be done
|
||||
* via state vars, too.
|
||||
*/
|
||||
m[MAT_SX] = v[MAT_SX];
|
||||
m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
|
||||
m[MAT_SY] = - v[MAT_SY];
|
||||
m[MAT_TY] = - v[MAT_TY] + h;
|
||||
m[MAT_SZ] = v[MAT_SZ] * intel->depth_scale;
|
||||
m[MAT_TZ] = v[MAT_TZ] * intel->depth_scale;
|
||||
m[MAT_SX] = v[MAT_SX];
|
||||
m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
|
||||
|
||||
m[MAT_SY] = v[MAT_SY] * yScale;
|
||||
m[MAT_TY] = v[MAT_TY] * yScale + yBias + SUBPIXEL_Y;
|
||||
|
||||
m[MAT_SZ] = v[MAT_SZ] * depthScale;
|
||||
m[MAT_TZ] = v[MAT_TZ] * depthScale;
|
||||
}
|
||||
|
||||
static void intelViewport( GLcontext *ctx,
|
||||
@@ -263,18 +247,112 @@ static void intelDepthRange( GLcontext *ctx,
|
||||
*/
|
||||
static void intelRenderMode( GLcontext *ctx, GLenum mode )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
|
||||
}
|
||||
|
||||
|
||||
void intelInitStateFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
functions->DrawBuffer = intelDrawBuffer;
|
||||
functions->ReadBuffer = intelReadBuffer;
|
||||
functions->RenderMode = intelRenderMode;
|
||||
functions->Viewport = intelViewport;
|
||||
functions->DepthRange = intelDepthRange;
|
||||
functions->ClearColor = intelClearColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void intelInitState( GLcontext *ctx )
|
||||
{
|
||||
/* Mesa should do this for us:
|
||||
*/
|
||||
ctx->Driver.AlphaFunc( ctx,
|
||||
ctx->Color.AlphaFunc,
|
||||
ctx->Color.AlphaRef);
|
||||
|
||||
ctx->Driver.BlendColor( ctx,
|
||||
ctx->Color.BlendColor );
|
||||
|
||||
ctx->Driver.BlendEquationSeparate( ctx,
|
||||
ctx->Color.BlendEquationRGB,
|
||||
ctx->Color.BlendEquationA);
|
||||
|
||||
ctx->Driver.BlendFuncSeparate( ctx,
|
||||
ctx->Color.BlendSrcRGB,
|
||||
ctx->Color.BlendDstRGB,
|
||||
ctx->Color.BlendSrcA,
|
||||
ctx->Color.BlendDstA);
|
||||
|
||||
ctx->Driver.ColorMask( ctx,
|
||||
ctx->Color.ColorMask[RCOMP],
|
||||
ctx->Color.ColorMask[GCOMP],
|
||||
ctx->Color.ColorMask[BCOMP],
|
||||
ctx->Color.ColorMask[ACOMP]);
|
||||
|
||||
ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
|
||||
ctx->Driver.DepthFunc( ctx, ctx->Depth.Func );
|
||||
ctx->Driver.DepthMask( ctx, ctx->Depth.Mask );
|
||||
|
||||
ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled );
|
||||
ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag );
|
||||
ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test );
|
||||
ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag );
|
||||
ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
|
||||
ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag );
|
||||
ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE );
|
||||
ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE );
|
||||
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
|
||||
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
|
||||
|
||||
ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
|
||||
|
||||
{
|
||||
GLfloat f = (GLfloat)ctx->Light.Model.ColorControl;
|
||||
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f );
|
||||
}
|
||||
|
||||
ctx->Driver.LineWidth( ctx, ctx->Line.Width );
|
||||
ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp );
|
||||
ctx->Driver.PointSize( ctx, ctx->Point.Size );
|
||||
ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple );
|
||||
ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
|
||||
ctx->Scissor.Width, ctx->Scissor.Height );
|
||||
ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel );
|
||||
ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT,
|
||||
ctx->Stencil.Function[0],
|
||||
ctx->Stencil.Ref[0],
|
||||
ctx->Stencil.ValueMask[0] );
|
||||
ctx->Driver.StencilFuncSeparate( ctx, GL_BACK,
|
||||
ctx->Stencil.Function[1],
|
||||
ctx->Stencil.Ref[1],
|
||||
ctx->Stencil.ValueMask[1] );
|
||||
ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] );
|
||||
ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] );
|
||||
ctx->Driver.StencilOpSeparate( ctx, GL_FRONT,
|
||||
ctx->Stencil.FailFunc[0],
|
||||
ctx->Stencil.ZFailFunc[0],
|
||||
ctx->Stencil.ZPassFunc[0]);
|
||||
ctx->Driver.StencilOpSeparate( ctx, GL_BACK,
|
||||
ctx->Stencil.FailFunc[1],
|
||||
ctx->Stencil.ZFailFunc[1],
|
||||
ctx->Stencil.ZPassFunc[1]);
|
||||
|
||||
|
||||
/* XXX this isn't really needed */
|
||||
ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
|
||||
}
|
||||
|
||||
@@ -1,830 +1,163 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "glheader.h"
|
||||
#include "mtypes.h"
|
||||
#include "imports.h"
|
||||
#include "macros.h"
|
||||
#include "simple_list.h"
|
||||
#include "enums.h"
|
||||
#include "image.h"
|
||||
#include "texstore.h"
|
||||
#include "texformat.h"
|
||||
#include "teximage.h"
|
||||
#include "texmem.h"
|
||||
#include "texobj.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#include "mm.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_ioctl.h"
|
||||
|
||||
|
||||
|
||||
static GLboolean
|
||||
intelValidateClientStorage( intelContextPtr intel, GLenum target,
|
||||
GLint internalFormat,
|
||||
GLint srcWidth, GLint srcHeight,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
|
||||
static GLboolean intelIsTextureResident(GLcontext *ctx,
|
||||
struct gl_texture_object *texObj)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
int texelBytes;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "intformat %s format %s type %s\n",
|
||||
_mesa_lookup_enum_by_nr( internalFormat ),
|
||||
_mesa_lookup_enum_by_nr( format ),
|
||||
_mesa_lookup_enum_by_nr( type ));
|
||||
|
||||
if (!ctx->Unpack.ClientStorage)
|
||||
return 0;
|
||||
|
||||
if (ctx->_ImageTransferState ||
|
||||
texImage->IsCompressed ||
|
||||
texObj->GenerateMipmap)
|
||||
return 0;
|
||||
|
||||
|
||||
/* This list is incomplete
|
||||
*/
|
||||
switch ( internalFormat ) {
|
||||
case GL_RGBA:
|
||||
if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
|
||||
texImage->TexFormat = &_mesa_texformat_argb8888;
|
||||
texelBytes = 4;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case GL_RGB:
|
||||
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
|
||||
texImage->TexFormat = &_mesa_texformat_rgb565;
|
||||
texelBytes = 2;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case GL_YCBCR_MESA:
|
||||
if ( format == GL_YCBCR_MESA &&
|
||||
type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) {
|
||||
texImage->TexFormat = &_mesa_texformat_ycbcr_rev;
|
||||
texelBytes = 2;
|
||||
}
|
||||
else if ( format == GL_YCBCR_MESA &&
|
||||
(type == GL_UNSIGNED_SHORT_8_8_APPLE ||
|
||||
type == GL_UNSIGNED_BYTE)) {
|
||||
texImage->TexFormat = &_mesa_texformat_ycbcr;
|
||||
texelBytes = 2;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Could deal with these packing issues, but currently don't:
|
||||
*/
|
||||
if (packing->SkipPixels ||
|
||||
packing->SkipRows ||
|
||||
packing->SwapBytes ||
|
||||
packing->LsbFirst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth,
|
||||
format, type);
|
||||
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s: srcRowStride %d/%x\n",
|
||||
__FUNCTION__, srcRowStride, srcRowStride);
|
||||
|
||||
/* Could check this later in upload, pitch restrictions could be
|
||||
* relaxed, but would need to store the image pitch somewhere,
|
||||
* as packing details might change before image is uploaded:
|
||||
*/
|
||||
if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) ||
|
||||
(srcRowStride & 63))
|
||||
return 0;
|
||||
|
||||
|
||||
/* Have validated that _mesa_transfer_teximage would be a straight
|
||||
* memcpy at this point. NOTE: future calls to TexSubImage will
|
||||
* overwrite the client data. This is explicitly mentioned in the
|
||||
* extension spec.
|
||||
*/
|
||||
texImage->Data = (void *)pixels;
|
||||
texImage->IsClientData = GL_TRUE;
|
||||
texImage->RowStride = srcRowStride / texelBytes;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint border,
|
||||
GLenum format, GLenum type, const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
|
||||
assert(t);
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( t );
|
||||
|
||||
texImage->IsClientData = GL_FALSE;
|
||||
|
||||
_mesa_store_teximage1d( ctx, target, level, internalFormat,
|
||||
width, border, format, type,
|
||||
pixels, packing, texObj, texImage );
|
||||
|
||||
t->dirty_images[0] |= (1 << level);
|
||||
}
|
||||
|
||||
static void intelTexSubImage1D( GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset,
|
||||
GLsizei width,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
|
||||
assert(t);
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( t );
|
||||
|
||||
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
|
||||
format, type, pixels, packing, texObj,
|
||||
texImage);
|
||||
#if 0
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_object *intelObj = intel_texture_object(texObj);
|
||||
|
||||
return
|
||||
intelObj->mt &&
|
||||
intelObj->mt->region &&
|
||||
intel_is_region_resident(intel, intelObj->mt->region);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Handles 2D, CUBE, RECT:
|
||||
|
||||
static struct gl_texture_image *intelNewTextureImage( GLcontext *ctx )
|
||||
{
|
||||
(void) ctx;
|
||||
return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image);
|
||||
}
|
||||
|
||||
|
||||
static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx,
|
||||
GLuint name,
|
||||
GLenum target )
|
||||
{
|
||||
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
|
||||
|
||||
_mesa_initialize_texture_object(&obj->base, name, target);
|
||||
|
||||
return &obj->base;
|
||||
}
|
||||
|
||||
|
||||
static void intelFreeTextureImageData( GLcontext *ctx,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_release(intel, &intelImage->mt);
|
||||
}
|
||||
|
||||
if (texImage->Data) {
|
||||
free(texImage->Data);
|
||||
texImage->Data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef __x86_64__
|
||||
static unsigned
|
||||
fastrdtsc(void)
|
||||
{
|
||||
unsigned eax;
|
||||
__asm__ volatile ("\t"
|
||||
"pushl %%ebx\n\t"
|
||||
"cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax)
|
||||
:"0"(0)
|
||||
:"ecx", "edx", "cc");
|
||||
|
||||
return eax;
|
||||
}
|
||||
#else
|
||||
static unsigned
|
||||
fastrdtsc(void)
|
||||
{
|
||||
unsigned eax;
|
||||
__asm__ volatile ("\t"
|
||||
"cpuid\n\t" ".byte 0x0f, 0x31\n\t" :"=a" (eax)
|
||||
:"0"(0)
|
||||
:"ecx", "edx", "ebx", "cc");
|
||||
|
||||
return eax;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned
|
||||
time_diff(unsigned t, unsigned t2)
|
||||
{
|
||||
return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
|
||||
}
|
||||
|
||||
|
||||
/* The system memcpy (at least on ubuntu 5.10) has problems copying
|
||||
* to agp (writecombined) memory from a source which isn't 64-byte
|
||||
* aligned - there is a 4x performance falloff.
|
||||
*
|
||||
* The x86 __memcpy is immune to this but is slightly slower
|
||||
* (10%-ish) than the system memcpy.
|
||||
*
|
||||
* The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
|
||||
* isn't much faster than x86_memcpy for agp copies.
|
||||
*
|
||||
* TODO: switch dynamically.
|
||||
*/
|
||||
static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLenum format, GLenum type, const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
static void *do_memcpy( void *dest, const void *src, size_t n )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
GLuint face;
|
||||
|
||||
/* which cube face or ordinary 2D image */
|
||||
switch (target) {
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
ASSERT(face < 6);
|
||||
break;
|
||||
default:
|
||||
face = 0;
|
||||
if ( (((unsigned)src) & 63) ||
|
||||
(((unsigned)dest) & 63)) {
|
||||
return __memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
assert(t);
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( t );
|
||||
texImage->IsClientData = GL_FALSE;
|
||||
|
||||
if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,
|
||||
internalFormat,
|
||||
width, height,
|
||||
format, type, pixels,
|
||||
packing, texObj, texImage)) {
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);
|
||||
}
|
||||
else {
|
||||
_mesa_store_teximage2d( ctx, target, level, internalFormat,
|
||||
width, height, border, format, type,
|
||||
pixels, packing, texObj, texImage );
|
||||
|
||||
t->dirty_images[face] |= (1 << level);
|
||||
}
|
||||
}
|
||||
|
||||
static void intelTexSubImage2D( GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
GLuint face;
|
||||
|
||||
/* which cube face or ordinary 2D image */
|
||||
switch (target) {
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
ASSERT(face < 6);
|
||||
break;
|
||||
default:
|
||||
face = 0;
|
||||
}
|
||||
|
||||
if (texImage->IsClientData &&
|
||||
(char *)pixels == (char *)texImage->Data +
|
||||
((xoffset + yoffset * texImage->RowStride) *
|
||||
texImage->TexFormat->TexelBytes)) {
|
||||
|
||||
/* Notification only - no upload required */
|
||||
}
|
||||
else {
|
||||
assert( t ); /* this _should_ be true */
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( t );
|
||||
|
||||
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
|
||||
height, format, type, pixels, packing, texObj,
|
||||
texImage);
|
||||
|
||||
t->dirty_images[face] |= (1 << level);
|
||||
}
|
||||
}
|
||||
|
||||
static void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLsizei imageSize, const GLvoid *data,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
GLuint face;
|
||||
|
||||
/* which cube face or ordinary 2D image */
|
||||
switch (target) {
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
ASSERT(face < 6);
|
||||
break;
|
||||
default:
|
||||
face = 0;
|
||||
}
|
||||
|
||||
assert(t);
|
||||
intelFlush( ctx );
|
||||
|
||||
driSwapOutTextureObject( t );
|
||||
texImage->IsClientData = GL_FALSE;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);
|
||||
|
||||
_mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width,
|
||||
height, border, imageSize, data, texObj, texImage);
|
||||
|
||||
t->dirty_images[face] |= (1 << level);
|
||||
else
|
||||
return memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
|
||||
static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format,
|
||||
GLsizei imageSize, const GLvoid *data,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
static void *timed_memcpy( void *dest, const void *src, size_t n )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
GLuint face;
|
||||
void *ret;
|
||||
unsigned t1, t2;
|
||||
double rate;
|
||||
|
||||
if ( (((unsigned)src) & 63) ||
|
||||
(((unsigned)dest) & 63))
|
||||
_mesa_printf("Warning - non-aligned texture copy!\n");
|
||||
|
||||
/* which cube face or ordinary 2D image */
|
||||
switch (target) {
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
||||
face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
ASSERT(face < 6);
|
||||
break;
|
||||
default:
|
||||
face = 0;
|
||||
}
|
||||
t1 = fastrdtsc();
|
||||
ret = do_memcpy(dest, src, n);
|
||||
t2 = fastrdtsc();
|
||||
|
||||
assert( t ); /* this _should_ be true */
|
||||
intelFlush( ctx );
|
||||
driSwapOutTextureObject( t );
|
||||
|
||||
_mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
|
||||
height, format, imageSize, data, texObj, texImage);
|
||||
|
||||
t->dirty_images[face] |= (1 << level);
|
||||
rate = time_diff(t1, t2);
|
||||
rate /= (double) n;
|
||||
_mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint depth,
|
||||
GLint border,
|
||||
GLenum format, GLenum type, const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
void intelInitTextureFuncs(struct dd_function_table * functions)
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
functions->ChooseTextureFormat = intelChooseTextureFormat;
|
||||
functions->TexImage1D = intelTexImage1D;
|
||||
functions->TexImage2D = intelTexImage2D;
|
||||
functions->TexImage3D = intelTexImage3D;
|
||||
functions->TexSubImage1D = intelTexSubImage1D;
|
||||
functions->TexSubImage2D = intelTexSubImage2D;
|
||||
functions->TexSubImage3D = intelTexSubImage3D;
|
||||
functions->CopyTexImage1D = intelCopyTexImage1D;
|
||||
functions->CopyTexImage2D = intelCopyTexImage2D;
|
||||
functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
|
||||
functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
|
||||
functions->GetTexImage = intelGetTexImage;
|
||||
functions->NewTextureObject = intelNewTextureObject;
|
||||
functions->NewTextureImage = intelNewTextureImage;
|
||||
functions->DeleteTexture = _mesa_delete_texture_object;
|
||||
functions->FreeTexImageData = intelFreeTextureImageData;
|
||||
functions->UpdateTexturePalette = 0;
|
||||
functions->IsTextureResident = intelIsTextureResident;
|
||||
|
||||
assert(t);
|
||||
driSwapOutTextureObject( t );
|
||||
texImage->IsClientData = GL_FALSE;
|
||||
|
||||
_mesa_store_teximage3d(ctx, target, level, internalFormat,
|
||||
width, height, depth, border,
|
||||
format, type, pixels,
|
||||
&ctx->Unpack, texObj, texImage);
|
||||
|
||||
t->dirty_images[0] |= (1 << level);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
|
||||
assert( t ); /* this _should_ be true */
|
||||
driSwapOutTextureObject( t );
|
||||
|
||||
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
|
||||
width, height, depth,
|
||||
format, type, pixels, packing, texObj, texImage);
|
||||
|
||||
t->dirty_images[0] |= (1 << level);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) tObj->DriverData;
|
||||
|
||||
if ( t != NULL ) {
|
||||
intelFlush( ctx );
|
||||
driDestroyTextureObject( t );
|
||||
}
|
||||
|
||||
/* Free mipmap images and the texture object itself */
|
||||
_mesa_delete_texture_object(ctx, tObj);
|
||||
}
|
||||
|
||||
|
||||
static const struct gl_texture_format *
|
||||
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
|
||||
GLenum format, GLenum type )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 &&
|
||||
intel->intelScreen->tex.size > 4*1024*1024);
|
||||
|
||||
switch ( internalFormat ) {
|
||||
case 4:
|
||||
case GL_RGBA:
|
||||
case GL_COMPRESSED_RGBA:
|
||||
if ( format == GL_BGRA ) {
|
||||
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
|
||||
return &_mesa_texformat_argb8888;
|
||||
}
|
||||
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
|
||||
return &_mesa_texformat_argb4444;
|
||||
}
|
||||
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
|
||||
return &_mesa_texformat_argb1555;
|
||||
}
|
||||
}
|
||||
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
|
||||
|
||||
case 3:
|
||||
case GL_RGB:
|
||||
case GL_COMPRESSED_RGB:
|
||||
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
|
||||
return &_mesa_texformat_rgb565;
|
||||
}
|
||||
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
|
||||
|
||||
case GL_RGBA8:
|
||||
case GL_RGB10_A2:
|
||||
case GL_RGBA12:
|
||||
case GL_RGBA16:
|
||||
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
|
||||
|
||||
case GL_RGBA4:
|
||||
case GL_RGBA2:
|
||||
return &_mesa_texformat_argb4444;
|
||||
|
||||
case GL_RGB5_A1:
|
||||
return &_mesa_texformat_argb1555;
|
||||
|
||||
case GL_RGB8:
|
||||
case GL_RGB10:
|
||||
case GL_RGB12:
|
||||
case GL_RGB16:
|
||||
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
|
||||
|
||||
case GL_RGB5:
|
||||
case GL_RGB4:
|
||||
case GL_R3_G3_B2:
|
||||
return &_mesa_texformat_rgb565;
|
||||
|
||||
case GL_ALPHA:
|
||||
case GL_ALPHA4:
|
||||
case GL_ALPHA8:
|
||||
case GL_ALPHA12:
|
||||
case GL_ALPHA16:
|
||||
case GL_COMPRESSED_ALPHA:
|
||||
return &_mesa_texformat_a8;
|
||||
|
||||
case 1:
|
||||
case GL_LUMINANCE:
|
||||
case GL_LUMINANCE4:
|
||||
case GL_LUMINANCE8:
|
||||
case GL_LUMINANCE12:
|
||||
case GL_LUMINANCE16:
|
||||
case GL_COMPRESSED_LUMINANCE:
|
||||
return &_mesa_texformat_l8;
|
||||
|
||||
case 2:
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
case GL_LUMINANCE4_ALPHA4:
|
||||
case GL_LUMINANCE6_ALPHA2:
|
||||
case GL_LUMINANCE8_ALPHA8:
|
||||
case GL_LUMINANCE12_ALPHA4:
|
||||
case GL_LUMINANCE12_ALPHA12:
|
||||
case GL_LUMINANCE16_ALPHA16:
|
||||
case GL_COMPRESSED_LUMINANCE_ALPHA:
|
||||
return &_mesa_texformat_al88;
|
||||
|
||||
case GL_INTENSITY:
|
||||
case GL_INTENSITY4:
|
||||
case GL_INTENSITY8:
|
||||
case GL_INTENSITY12:
|
||||
case GL_INTENSITY16:
|
||||
case GL_COMPRESSED_INTENSITY:
|
||||
return &_mesa_texformat_i8;
|
||||
|
||||
case GL_YCBCR_MESA:
|
||||
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
|
||||
type == GL_UNSIGNED_BYTE)
|
||||
return &_mesa_texformat_ycbcr;
|
||||
else
|
||||
return &_mesa_texformat_ycbcr_rev;
|
||||
|
||||
case GL_COMPRESSED_RGB_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgb_fxt1;
|
||||
case GL_COMPRESSED_RGBA_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgba_fxt1;
|
||||
|
||||
case GL_RGB_S3TC:
|
||||
case GL_RGB4_S3TC:
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgb_dxt1;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgba_dxt1;
|
||||
|
||||
case GL_RGBA_S3TC:
|
||||
case GL_RGBA4_S3TC:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
return &_mesa_texformat_rgba_dxt3;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
return &_mesa_texformat_rgba_dxt5;
|
||||
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
return &_mesa_texformat_depth_component16;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unexpected texture format %s in %s\n",
|
||||
_mesa_lookup_enum_by_nr(internalFormat),
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL; /* never get here */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if ( intel == NULL )
|
||||
return;
|
||||
|
||||
if ( t->age > intel->dirtyAge )
|
||||
intel->dirtyAge = t->age;
|
||||
|
||||
for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
|
||||
if ( t == intel->CurrentTexObj[ i ] )
|
||||
intel->CurrentTexObj[ i ] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Upload an image from mesa's internal copy. Image may be 1D, 2D or
|
||||
* 3D. Cubemaps are expanded elsewhere.
|
||||
*/
|
||||
static void intelUploadTexImage( intelContextPtr intel,
|
||||
intelTextureObjectPtr t,
|
||||
const struct gl_texture_image *image,
|
||||
const GLuint offset )
|
||||
{
|
||||
|
||||
if (!image || !image->Data)
|
||||
return;
|
||||
|
||||
if (image->Depth == 1 && image->IsClientData) {
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "Blit uploading\n");
|
||||
|
||||
/* Do it with a blit.
|
||||
*/
|
||||
intelEmitCopyBlitLocked( intel,
|
||||
image->TexFormat->TexelBytes,
|
||||
image->RowStride, /* ? */
|
||||
intelGetMemoryOffsetMESA( NULL, 0, image->Data ),
|
||||
t->Pitch / image->TexFormat->TexelBytes,
|
||||
intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ),
|
||||
0, 0,
|
||||
0, 0,
|
||||
image->Width,
|
||||
image->Height);
|
||||
}
|
||||
else if (image->IsCompressed) {
|
||||
GLuint row_len = image->Width * 2;
|
||||
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
|
||||
GLubyte *src = (GLubyte *)image->Data;
|
||||
GLuint j;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr,
|
||||
"Upload image %dx%dx%d offset %xm row_len %x "
|
||||
"pitch %x depth_pitch %x\n",
|
||||
image->Width, image->Height, image->Depth, offset,
|
||||
row_len, t->Pitch, t->depth_pitch);
|
||||
|
||||
switch (image->InternalFormat) {
|
||||
case GL_COMPRESSED_RGB_FXT1_3DFX:
|
||||
case GL_COMPRESSED_RGBA_FXT1_3DFX:
|
||||
case GL_RGB_S3TC:
|
||||
case GL_RGB4_S3TC:
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
|
||||
__memcpy(dst, src, row_len );
|
||||
src += row_len;
|
||||
}
|
||||
break;
|
||||
case GL_RGBA_S3TC:
|
||||
case GL_RGBA4_S3TC:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) {
|
||||
__memcpy(dst, src, (image->Width*4) );
|
||||
src += image->Width*4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
GLuint row_len = image->Width * image->TexFormat->TexelBytes;
|
||||
GLubyte *dst = (GLubyte *)(t->BufAddr + offset);
|
||||
GLubyte *src = (GLubyte *)image->Data;
|
||||
GLuint d, j;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr,
|
||||
"Upload image %dx%dx%d offset %xm row_len %x "
|
||||
"pitch %x depth_pitch %x\n",
|
||||
image->Width, image->Height, image->Depth, offset,
|
||||
row_len, t->Pitch, t->depth_pitch);
|
||||
|
||||
if (row_len == t->Pitch) {
|
||||
for (d = 0; d < image->Depth; d++) {
|
||||
memcpy( dst, src, t->Pitch * image->Height );
|
||||
dst += t->depth_pitch;
|
||||
src += row_len * image->Height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (d = 0 ; d < image->Depth ; d++) {
|
||||
for (j = 0 ; j < image->Height ; j++) {
|
||||
__memcpy(dst, src, row_len );
|
||||
src += row_len;
|
||||
dst += t->Pitch;
|
||||
}
|
||||
|
||||
dst += t->depth_pitch - (t->Pitch * image->Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int intelUploadTexImages( intelContextPtr intel,
|
||||
intelTextureObjectPtr t,
|
||||
GLuint face)
|
||||
{
|
||||
const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
|
||||
const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image;
|
||||
int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes;
|
||||
|
||||
/* Can we texture out of the existing client data? */
|
||||
if ( numLevels == 1 &&
|
||||
firstImage->IsClientData &&
|
||||
(pitch & 3) == 0) {
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "AGP texturing from client memory\n");
|
||||
|
||||
t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data );
|
||||
t->BufAddr = 0;
|
||||
t->dirty = ~0;
|
||||
return GL_TRUE;
|
||||
}
|
||||
else {
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "Uploading client data to agp\n");
|
||||
|
||||
INTEL_FIREVERTICES( intel );
|
||||
LOCK_HARDWARE( intel );
|
||||
|
||||
if ( t->base.memBlock == NULL ) {
|
||||
int heap;
|
||||
|
||||
heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps,
|
||||
(driTextureObject *) t );
|
||||
if ( heap == -1 ) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Set the base offset of the texture image */
|
||||
t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
|
||||
t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs;
|
||||
t->dirty = ~0;
|
||||
}
|
||||
|
||||
|
||||
/* Let the world know we've used this memory recently.
|
||||
*/
|
||||
driUpdateTextureLRU( (driTextureObject *) t );
|
||||
|
||||
|
||||
/* Upload any images that are new */
|
||||
if (t->base.dirty_images[face]) {
|
||||
int i;
|
||||
|
||||
intelWaitForIdle( intel );
|
||||
|
||||
for (i = 0 ; i < numLevels ; i++) {
|
||||
int level = i + t->base.firstLevel;
|
||||
|
||||
if (t->base.dirty_images[face] & (1<<level)) {
|
||||
|
||||
const struct gl_texture_image *image = t->image[face][i].image;
|
||||
GLuint offset = t->image[face][i].offset;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "upload level %d, offset %x\n",
|
||||
level, offset);
|
||||
|
||||
intelUploadTexImage( intel, t, image, offset );
|
||||
}
|
||||
}
|
||||
t->base.dirty_images[face] = 0;
|
||||
intel->perf_boxes |= I830_BOX_TEXTURE_LOAD;
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE( intel );
|
||||
return GL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new texture object.
|
||||
* Called via ctx->Driver.NewTextureObject.
|
||||
* Note: this function will be called during context creation to
|
||||
* allocate the default texture objects.
|
||||
* Note: we could use containment here to 'derive' the driver-specific
|
||||
* texture object from the core mesa gl_texture_object. Not done at this time.
|
||||
*/
|
||||
static struct gl_texture_object *
|
||||
intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
|
||||
{
|
||||
struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target);
|
||||
INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj );
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
void intelInitTextureFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
functions->NewTextureObject = intelNewTextureObject;
|
||||
functions->ChooseTextureFormat = intelChooseTextureFormat;
|
||||
functions->TexImage1D = intelTexImage1D;
|
||||
functions->TexImage2D = intelTexImage2D;
|
||||
functions->TexImage3D = intelTexImage3D;
|
||||
functions->TexSubImage1D = intelTexSubImage1D;
|
||||
functions->TexSubImage2D = intelTexSubImage2D;
|
||||
functions->TexSubImage3D = intelTexSubImage3D;
|
||||
functions->CopyTexImage1D = _swrast_copy_teximage1d;
|
||||
functions->CopyTexImage2D = _swrast_copy_teximage2d;
|
||||
functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
|
||||
functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
|
||||
functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
|
||||
functions->DeleteTexture = intelDeleteTexture;
|
||||
functions->UpdateTexturePalette = NULL;
|
||||
functions->IsTextureResident = driIsTextureResident;
|
||||
functions->TestProxyTexImage = _mesa_test_proxy_teximage;
|
||||
functions->DeleteTexture = intelDeleteTexture;
|
||||
functions->CompressedTexImage2D = intelCompressedTexImage2D;
|
||||
functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D;
|
||||
if (INTEL_DEBUG & DEBUG_BUFMGR)
|
||||
functions->TextureMemCpy = timed_memcpy;
|
||||
else
|
||||
functions->TextureMemCpy = do_memcpy;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,102 @@
|
||||
|
||||
void intelInitTextureFuncs( struct dd_function_table *functions );
|
||||
|
||||
void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t );
|
||||
int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t,
|
||||
GLuint face );
|
||||
const struct gl_texture_format *
|
||||
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
|
||||
GLenum format, GLenum type );
|
||||
|
||||
|
||||
void intelTexImage3D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint depth,
|
||||
GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
void intelTexSubImage3D(GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
void intelTexImage2D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
void intelTexSubImage2D(GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
void intelTexImage1D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
void intelTexSubImage1D(GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset,
|
||||
GLsizei width,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage);
|
||||
|
||||
void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width,
|
||||
GLint border );
|
||||
|
||||
void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint border );
|
||||
|
||||
void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint xoffset,
|
||||
GLint x, GLint y, GLsizei width );
|
||||
|
||||
void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height );
|
||||
|
||||
void intelGetTexImage( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLenum format, GLenum type, GLvoid *pixels,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage );
|
||||
|
||||
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit );
|
||||
|
||||
void intel_tex_map_images( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj );
|
||||
|
||||
void intel_tex_unmap_images( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
296
src/mesa/drivers/dri/i915/intel_tex_copy.c
Normal file
296
src/mesa/drivers/dri/i915/intel_tex_copy.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "mtypes.h"
|
||||
#include "enums.h"
|
||||
#include "image.h"
|
||||
#include "teximage.h"
|
||||
#include "swrast/swrast.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_pixel.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
|
||||
/**
|
||||
* Get the intel_region which is the source for any glCopyTex[Sub]Image call.
|
||||
*
|
||||
* Do the best we can using the blitter. A future project is to use
|
||||
* the texture engine and fragment programs for these copies.
|
||||
*/
|
||||
static const struct intel_region *
|
||||
get_teximage_source(struct intel_context *intel, GLenum internalFormat)
|
||||
{
|
||||
struct intel_renderbuffer *irb;
|
||||
|
||||
if (0)
|
||||
_mesa_printf("%s %s\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(internalFormat));
|
||||
|
||||
switch (internalFormat) {
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_DEPTH_COMPONENT16_ARB:
|
||||
irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
|
||||
if (irb && irb->region && irb->region->cpp == 2)
|
||||
return irb->region;
|
||||
return NULL;
|
||||
case GL_DEPTH24_STENCIL8_EXT:
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH);
|
||||
if (irb && irb->region && irb->region->cpp == 4)
|
||||
return irb->region;
|
||||
return NULL;
|
||||
case GL_RGBA:
|
||||
return intel_readbuf_region( intel );
|
||||
case GL_RGB:
|
||||
if (intel->intelScreen->cpp == 2)
|
||||
return intel_readbuf_region( intel );
|
||||
return NULL;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GLboolean do_copy_texsubimage( struct intel_context *intel,
|
||||
struct intel_texture_image *intelImage,
|
||||
GLenum internalFormat,
|
||||
GLint dstx, GLint dsty,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
const struct intel_region *src = get_teximage_source(intel, internalFormat);
|
||||
|
||||
if (!intelImage->mt || !src)
|
||||
return GL_FALSE;
|
||||
|
||||
intelFlush(ctx);
|
||||
LOCK_HARDWARE(intel);
|
||||
{
|
||||
GLuint image_offset = intel_miptree_image_offset(intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level);
|
||||
const GLint orig_x = x;
|
||||
const GLint orig_y = y;
|
||||
const struct gl_framebuffer *fb = ctx->DrawBuffer;
|
||||
|
||||
if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax,
|
||||
&x, &y, &width, &height)) {
|
||||
/* Update dst for clipped src. Need to also clip the source rect.
|
||||
*/
|
||||
dstx += x - orig_x;
|
||||
dsty += y - orig_y;
|
||||
|
||||
if (ctx->ReadBuffer->Name == 0) {
|
||||
/* reading from a window, adjust x, y */
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
GLuint window_y;
|
||||
/* window_y = position of window on screen if y=0=bottom */
|
||||
window_y = intel->intelScreen->height - (dPriv->y + dPriv->h);
|
||||
y = window_y + y;
|
||||
x += dPriv->x;
|
||||
}
|
||||
else {
|
||||
/* reading from a FBO */
|
||||
/* invert Y */
|
||||
y = ctx->ReadBuffer->Height - y - 1;
|
||||
}
|
||||
|
||||
|
||||
/* A bit of fiddling to get the blitter to work with -ve
|
||||
* pitches. But we get a nice inverted blit this way, so it's
|
||||
* worth it:
|
||||
*/
|
||||
intelEmitCopyBlit( intel,
|
||||
intelImage->mt->cpp,
|
||||
|
||||
-src->pitch,
|
||||
src->buffer,
|
||||
src->height * src->pitch * src->cpp,
|
||||
|
||||
intelImage->mt->pitch,
|
||||
intelImage->mt->region->buffer,
|
||||
image_offset,
|
||||
|
||||
x, y + height,
|
||||
dstx, dsty,
|
||||
width, height );
|
||||
|
||||
intel_batchbuffer_flush( intel->batch );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
#if 0
|
||||
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
|
||||
* XXX Add a ctx->Driver.GenerateMipmaps() function?
|
||||
*/
|
||||
if (level == texObj->BaseLevel &&
|
||||
texObj->GenerateMipmap) {
|
||||
intel_generate_mipmap(ctx, target,
|
||||
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
|
||||
texObj);
|
||||
}
|
||||
#endif
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width,
|
||||
GLint border )
|
||||
{
|
||||
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
|
||||
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
|
||||
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
|
||||
|
||||
if (border)
|
||||
goto fail;
|
||||
|
||||
/* Setup or redefine the texture object, mipmap tree and texture
|
||||
* image. Don't populate yet.
|
||||
*/
|
||||
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
|
||||
width, border,
|
||||
GL_RGBA, CHAN_TYPE, NULL,
|
||||
&ctx->DefaultPacking, texObj, texImage);
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx),
|
||||
intel_texture_image(texImage),
|
||||
internalFormat,
|
||||
0, 0,
|
||||
x, y,
|
||||
width, 1))
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
_swrast_copy_teximage1d( ctx, target, level, internalFormat, x, y,
|
||||
width, border );
|
||||
}
|
||||
|
||||
void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLenum internalFormat,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint border )
|
||||
{
|
||||
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
|
||||
struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target);
|
||||
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
|
||||
|
||||
if (border)
|
||||
goto fail;
|
||||
|
||||
/* Setup or redefine the texture object, mipmap tree and texture
|
||||
* image. Don't populate yet.
|
||||
*/
|
||||
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
|
||||
width, height, border,
|
||||
GL_RGBA, CHAN_TYPE, NULL,
|
||||
&ctx->DefaultPacking, texObj, texImage);
|
||||
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx),
|
||||
intel_texture_image(texImage),
|
||||
internalFormat,
|
||||
0, 0,
|
||||
x, y,
|
||||
width, height))
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
_swrast_copy_teximage2d( ctx, target, level, internalFormat, x, y,
|
||||
width, height, border );
|
||||
}
|
||||
|
||||
|
||||
void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint xoffset,
|
||||
GLint x, GLint y, GLsizei width )
|
||||
{
|
||||
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
|
||||
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
|
||||
GLenum internalFormat = texImage->InternalFormat;
|
||||
|
||||
/* XXX need to check <border> as in above function? */
|
||||
|
||||
/* Need to check texture is compatible with source format.
|
||||
*/
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx),
|
||||
intel_texture_image(texImage),
|
||||
internalFormat,
|
||||
xoffset, 0,
|
||||
x, y, width, 1)) {
|
||||
_swrast_copy_texsubimage1d( ctx, target, level,
|
||||
xoffset, x, y, width );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height )
|
||||
{
|
||||
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
|
||||
struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
|
||||
GLenum internalFormat = texImage->InternalFormat;
|
||||
|
||||
|
||||
/* Need to check texture is compatible with source format.
|
||||
*/
|
||||
|
||||
if (!do_copy_texsubimage(intel_context(ctx),
|
||||
intel_texture_image(texImage),
|
||||
internalFormat,
|
||||
xoffset, yoffset,
|
||||
x, y, width, height)) {
|
||||
_swrast_copy_texsubimage2d( ctx, target, level,
|
||||
xoffset, yoffset,
|
||||
x, y, width, height );
|
||||
}
|
||||
}
|
||||
148
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal file
148
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal file
@@ -0,0 +1,148 @@
|
||||
#include "intel_context.h"
|
||||
#include "intel_tex.h"
|
||||
#include "texformat.h"
|
||||
#include "enums.h"
|
||||
|
||||
/* It works out that this function is fine for all the supported
|
||||
* hardware. However, there is still a need to map the formats onto
|
||||
* hardware descriptors.
|
||||
*/
|
||||
/* Note that the i915 can actually support many more formats than
|
||||
* these if we take the step of simply swizzling the colors
|
||||
* immediately after sampling...
|
||||
*/
|
||||
const struct gl_texture_format *
|
||||
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
|
||||
GLenum format, GLenum type )
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
const GLboolean do32bpt = (intel->intelScreen->cpp == 4);
|
||||
|
||||
switch ( internalFormat ) {
|
||||
case 4:
|
||||
case GL_RGBA:
|
||||
case GL_COMPRESSED_RGBA:
|
||||
if ( format == GL_BGRA ) {
|
||||
if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
|
||||
return &_mesa_texformat_argb8888;
|
||||
}
|
||||
else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
|
||||
return &_mesa_texformat_argb4444;
|
||||
}
|
||||
else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
|
||||
return &_mesa_texformat_argb1555;
|
||||
}
|
||||
}
|
||||
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
|
||||
|
||||
case 3:
|
||||
case GL_RGB:
|
||||
case GL_COMPRESSED_RGB:
|
||||
if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
|
||||
return &_mesa_texformat_rgb565;
|
||||
}
|
||||
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
|
||||
|
||||
case GL_RGBA8:
|
||||
case GL_RGB10_A2:
|
||||
case GL_RGBA12:
|
||||
case GL_RGBA16:
|
||||
return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
|
||||
|
||||
case GL_RGBA4:
|
||||
case GL_RGBA2:
|
||||
return &_mesa_texformat_argb4444;
|
||||
|
||||
case GL_RGB5_A1:
|
||||
return &_mesa_texformat_argb1555;
|
||||
|
||||
case GL_RGB8:
|
||||
case GL_RGB10:
|
||||
case GL_RGB12:
|
||||
case GL_RGB16:
|
||||
return &_mesa_texformat_argb8888;
|
||||
|
||||
case GL_RGB5:
|
||||
case GL_RGB4:
|
||||
case GL_R3_G3_B2:
|
||||
return &_mesa_texformat_rgb565;
|
||||
|
||||
case GL_ALPHA:
|
||||
case GL_ALPHA4:
|
||||
case GL_ALPHA8:
|
||||
case GL_ALPHA12:
|
||||
case GL_ALPHA16:
|
||||
case GL_COMPRESSED_ALPHA:
|
||||
return &_mesa_texformat_a8;
|
||||
|
||||
case 1:
|
||||
case GL_LUMINANCE:
|
||||
case GL_LUMINANCE4:
|
||||
case GL_LUMINANCE8:
|
||||
case GL_LUMINANCE12:
|
||||
case GL_LUMINANCE16:
|
||||
case GL_COMPRESSED_LUMINANCE:
|
||||
return &_mesa_texformat_l8;
|
||||
|
||||
case 2:
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
case GL_LUMINANCE4_ALPHA4:
|
||||
case GL_LUMINANCE6_ALPHA2:
|
||||
case GL_LUMINANCE8_ALPHA8:
|
||||
case GL_LUMINANCE12_ALPHA4:
|
||||
case GL_LUMINANCE12_ALPHA12:
|
||||
case GL_LUMINANCE16_ALPHA16:
|
||||
case GL_COMPRESSED_LUMINANCE_ALPHA:
|
||||
return &_mesa_texformat_al88;
|
||||
|
||||
case GL_INTENSITY:
|
||||
case GL_INTENSITY4:
|
||||
case GL_INTENSITY8:
|
||||
case GL_INTENSITY12:
|
||||
case GL_INTENSITY16:
|
||||
case GL_COMPRESSED_INTENSITY:
|
||||
return &_mesa_texformat_i8;
|
||||
|
||||
case GL_YCBCR_MESA:
|
||||
if (type == GL_UNSIGNED_SHORT_8_8_MESA ||
|
||||
type == GL_UNSIGNED_BYTE)
|
||||
return &_mesa_texformat_ycbcr;
|
||||
else
|
||||
return &_mesa_texformat_ycbcr_rev;
|
||||
|
||||
case GL_COMPRESSED_RGB_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgb_fxt1;
|
||||
case GL_COMPRESSED_RGBA_FXT1_3DFX:
|
||||
return &_mesa_texformat_rgba_fxt1;
|
||||
|
||||
case GL_RGB_S3TC:
|
||||
case GL_RGB4_S3TC:
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgb_dxt1;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
return &_mesa_texformat_rgba_dxt1;
|
||||
|
||||
case GL_RGBA_S3TC:
|
||||
case GL_RGBA4_S3TC:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
return &_mesa_texformat_rgba_dxt3;
|
||||
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
return &_mesa_texformat_rgba_dxt5;
|
||||
|
||||
case GL_DEPTH_COMPONENT:
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
case GL_DEPTH_COMPONENT32:
|
||||
return &_mesa_texformat_depth_component16;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unexpected texture format %s in %s\n",
|
||||
_mesa_lookup_enum_by_nr(internalFormat),
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL; /* never get here */
|
||||
}
|
||||
444
src/mesa/drivers/dri/i915/intel_tex_image.c
Normal file
444
src/mesa/drivers/dri/i915/intel_tex_image.c
Normal file
@@ -0,0 +1,444 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
#include "mtypes.h"
|
||||
#include "enums.h"
|
||||
#include "colortab.h"
|
||||
#include "convolve.h"
|
||||
#include "context.h"
|
||||
#include "simple_list.h"
|
||||
#include "texcompress.h"
|
||||
#include "texformat.h"
|
||||
#include "texobj.h"
|
||||
#include "texstore.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_ioctl.h"
|
||||
|
||||
|
||||
/* Functions to store texture images. Where possible, mipmap_tree's
|
||||
* will be created or further instantiated with image data, otherwise
|
||||
* images will be stored in malloc'd memory. A validation step is
|
||||
* required to pull those images into a mipmap tree, or otherwise
|
||||
* decide a fallback is required.
|
||||
*/
|
||||
|
||||
|
||||
static int logbase2(int n)
|
||||
{
|
||||
GLint i = 1;
|
||||
GLint log2 = 0;
|
||||
|
||||
while (n > i) {
|
||||
i *= 2;
|
||||
log2++;
|
||||
}
|
||||
|
||||
return log2;
|
||||
}
|
||||
|
||||
|
||||
/* Otherwise, store it in memory if (Border != 0) or (any dimension ==
|
||||
* 1).
|
||||
*
|
||||
* Otherwise, if max_level >= level >= min_level, create tree with
|
||||
* space for textures from min_level down to max_level.
|
||||
*
|
||||
* Otherwise, create tree with space for textures from (level
|
||||
* 0)..(1x1). Consider pruning this tree at a validation if the
|
||||
* saving is worth it.
|
||||
*/
|
||||
static void guess_and_alloc_mipmap_tree( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj,
|
||||
struct intel_texture_image *intelImage )
|
||||
{
|
||||
GLuint firstLevel;
|
||||
GLuint lastLevel;
|
||||
GLuint width = intelImage->base.Width;
|
||||
GLuint height = intelImage->base.Height;
|
||||
GLuint depth = intelImage->base.Depth;
|
||||
GLuint l2width, l2height, l2depth;
|
||||
GLuint i;
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (intelImage->base.Border)
|
||||
return;
|
||||
|
||||
if (intelImage->level > intelObj->base.BaseLevel &&
|
||||
(intelImage->base.Width == 1 ||
|
||||
(intelObj->base.Target != GL_TEXTURE_1D &&
|
||||
intelImage->base.Height == 1) ||
|
||||
(intelObj->base.Target == GL_TEXTURE_3D &&
|
||||
intelImage->base.Depth == 1)))
|
||||
return;
|
||||
|
||||
/* If this image disrespects BaseLevel, allocate from level zero.
|
||||
* Usually BaseLevel == 0, so it's unlikely to happen.
|
||||
*/
|
||||
if (intelImage->level < intelObj->base.BaseLevel)
|
||||
firstLevel = 0;
|
||||
else
|
||||
firstLevel = intelObj->base.BaseLevel;
|
||||
|
||||
|
||||
/* Figure out image dimensions at start level.
|
||||
*/
|
||||
for (i = intelImage->level; i > firstLevel; i--) {
|
||||
width <<= 1;
|
||||
if (height != 1) height <<= 1;
|
||||
if (depth != 1) depth <<= 1;
|
||||
}
|
||||
|
||||
/* Guess a reasonable value for lastLevel. This is probably going
|
||||
* to be wrong fairly often and might mean that we have to look at
|
||||
* resizable buffers, or require that buffers implement lazy
|
||||
* pagetable arrangements.
|
||||
*/
|
||||
if ((intelObj->base.MinFilter == GL_NEAREST ||
|
||||
intelObj->base.MinFilter == GL_LINEAR) &&
|
||||
intelImage->level == firstLevel) {
|
||||
lastLevel = firstLevel;
|
||||
}
|
||||
else {
|
||||
l2width = logbase2(width);
|
||||
l2height = logbase2(height);
|
||||
l2depth = logbase2(depth);
|
||||
lastLevel = firstLevel + MAX2(MAX2(l2width,l2height),l2depth);
|
||||
}
|
||||
|
||||
assert(!intelObj->mt);
|
||||
intelObj->mt = intel_miptree_create( intel,
|
||||
intelObj->base.Target,
|
||||
intelImage->base.InternalFormat,
|
||||
firstLevel,
|
||||
lastLevel,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
intelImage->base.TexFormat->TexelBytes,
|
||||
intelImage->base.IsCompressed );
|
||||
|
||||
DBG("%s - success\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static GLuint target_to_face( GLenum target )
|
||||
{
|
||||
switch (target) {
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
|
||||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
|
||||
return ((GLuint) target -
|
||||
(GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void intelTexImage(GLcontext *ctx,
|
||||
GLint dims,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint depth,
|
||||
GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_object *intelObj = intel_texture_object(texObj);
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
GLint postConvWidth = width;
|
||||
GLint postConvHeight = height;
|
||||
GLint texelBytes, sizeInBytes;
|
||||
GLuint dstRowStride;
|
||||
GLuint dstImageStride;
|
||||
|
||||
|
||||
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(target),
|
||||
level,
|
||||
width, height, depth, border);
|
||||
|
||||
intelFlush(ctx);
|
||||
|
||||
intelImage->face = target_to_face( target );
|
||||
intelImage->level = level;
|
||||
|
||||
if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
|
||||
_mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
|
||||
&postConvHeight);
|
||||
}
|
||||
|
||||
/* choose the texture format */
|
||||
texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat,
|
||||
format, type);
|
||||
|
||||
assert(texImage->TexFormat);
|
||||
|
||||
switch (dims) {
|
||||
case 1:
|
||||
texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
|
||||
texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
|
||||
break;
|
||||
case 2:
|
||||
texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
|
||||
texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
|
||||
break;
|
||||
case 3:
|
||||
texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
|
||||
texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
texelBytes = texImage->TexFormat->TexelBytes;
|
||||
|
||||
|
||||
/* Minimum pitch of 32 bytes */
|
||||
if (postConvWidth * texelBytes < 32) {
|
||||
postConvWidth = 32 / texelBytes;
|
||||
texImage->RowStride = postConvWidth;
|
||||
}
|
||||
|
||||
assert(texImage->RowStride == postConvWidth);
|
||||
|
||||
/* Release the reference to a potentially orphaned buffer.
|
||||
* Release any old malloced memory.
|
||||
*/
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_release(intel, &intelImage->mt);
|
||||
assert(!texImage->Data);
|
||||
}
|
||||
else if (texImage->Data) {
|
||||
free(texImage->Data);
|
||||
}
|
||||
|
||||
/* If this is the only texture image in the tree, could call
|
||||
* bmBufferData with NULL data to free the old block and avoid
|
||||
* waiting on any outstanding fences.
|
||||
*/
|
||||
if (intelObj->mt &&
|
||||
intelObj->mt->first_level == level &&
|
||||
intelObj->mt->last_level == level &&
|
||||
intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
|
||||
!intel_miptree_match_image(intelObj->mt, &intelImage->base,
|
||||
intelImage->face, intelImage->level)) {
|
||||
|
||||
DBG("release it\n");
|
||||
intel_miptree_release(intel, &intelObj->mt);
|
||||
assert(!intelObj->mt);
|
||||
}
|
||||
|
||||
if (!intelObj->mt) {
|
||||
guess_and_alloc_mipmap_tree(intel, intelObj, intelImage);
|
||||
if (!intelObj->mt) {
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
_mesa_printf("guess_and_alloc_mipmap_tree: failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (intelObj->mt &&
|
||||
intelObj->mt != intelImage->mt &&
|
||||
intel_miptree_match_image(intelObj->mt, &intelImage->base,
|
||||
intelImage->face, intelImage->level)) {
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_release(intel, &intelImage->mt);
|
||||
}
|
||||
|
||||
intel_miptree_reference(&intelImage->mt, intelObj->mt);
|
||||
assert(intelImage->mt);
|
||||
}
|
||||
|
||||
if (!intelImage->mt) {
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
_mesa_printf("XXX: Image did not fit into tree - storing in local memory!\n");
|
||||
}
|
||||
|
||||
/* intelCopyTexImage calls this function with pixels == NULL, with
|
||||
* the expectation that the mipmap tree will be set up but nothing
|
||||
* more will be done. This is where those calls return:
|
||||
*/
|
||||
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
|
||||
format, type,
|
||||
pixels, unpack, "glTexImage");
|
||||
if (!pixels)
|
||||
return;
|
||||
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
if (intelImage->mt) {
|
||||
texImage->Data = intel_miptree_image_map(intel,
|
||||
intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&dstRowStride,
|
||||
&dstImageStride);
|
||||
}
|
||||
else {
|
||||
/* Allocate regular memory and store the image there temporarily. */
|
||||
if (texImage->IsCompressed) {
|
||||
sizeInBytes = texImage->CompressedSize;
|
||||
dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width);
|
||||
dstImageStride = 0; /* ? */
|
||||
assert(dims != 3);
|
||||
}
|
||||
else {
|
||||
dstRowStride = postConvWidth * texelBytes;
|
||||
dstImageStride = dstRowStride * postConvHeight;
|
||||
sizeInBytes = depth * dstImageStride;
|
||||
}
|
||||
texImage->Data = malloc(sizeInBytes);
|
||||
}
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
_mesa_printf("Upload image %dx%dx%d row_len %x "
|
||||
"pitch %x depth_pitch %x\n",
|
||||
width, height, depth,
|
||||
width * texelBytes, dstRowStride, dstImageStride);
|
||||
|
||||
/* Copy data. Would like to know when it's ok for us to eg. use
|
||||
* the blitter to copy. Or, use the hardware to do the format
|
||||
* conversion and copy:
|
||||
*/
|
||||
if (!texImage->TexFormat->StoreImage(ctx, dims,
|
||||
texImage->_BaseFormat,
|
||||
texImage->TexFormat,
|
||||
texImage->Data,
|
||||
0, 0, 0, /* dstX/Y/Zoffset */
|
||||
dstRowStride, dstImageStride,
|
||||
width, height, depth,
|
||||
format, type, pixels, unpack)) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
|
||||
}
|
||||
|
||||
_mesa_unmap_teximage_pbo(ctx, unpack);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_image_unmap(intel, intelImage->mt);
|
||||
texImage->Data = NULL;
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
#if 0
|
||||
/* GL_SGIS_generate_mipmap -- this can be accelerated now.
|
||||
*/
|
||||
if (level == texObj->BaseLevel &&
|
||||
texObj->GenerateMipmap) {
|
||||
intel_generate_mipmap(ctx, target,
|
||||
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
|
||||
texObj);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void intelTexImage3D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint depth,
|
||||
GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
intelTexImage( ctx, 3, target, level,
|
||||
internalFormat, width, height, depth, border,
|
||||
format, type, pixels,
|
||||
unpack, texObj, texImage );
|
||||
}
|
||||
|
||||
|
||||
void intelTexImage2D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
intelTexImage( ctx, 2, target, level,
|
||||
internalFormat, width, height, 1, border,
|
||||
format, type, pixels,
|
||||
unpack, texObj, texImage );
|
||||
}
|
||||
|
||||
void intelTexImage1D(GLcontext *ctx,
|
||||
GLenum target, GLint level,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint border,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
intelTexImage( ctx, 1, target, level,
|
||||
internalFormat, width, 1, 1, border,
|
||||
format, type, pixels,
|
||||
unpack, texObj, texImage );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Need to map texture image into memory before copying image data,
|
||||
* then unmap it.
|
||||
*/
|
||||
void intelGetTexImage( GLcontext *ctx, GLenum target, GLint level,
|
||||
GLenum format, GLenum type, GLvoid *pixels,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage )
|
||||
{
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
|
||||
/* Map */
|
||||
#ifdef ALL_IMAGES /* XXX Remove this, just for debug/test */
|
||||
intel_tex_map_images(intel, intel_texture_object(texObj));
|
||||
#else
|
||||
/* XXX what if intelImage->mt is NULL? */
|
||||
if (intelImage->mt) {
|
||||
intelImage->base.Data =
|
||||
intel_miptree_image_map(intel,
|
||||
intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&intelImage->base.RowStride,
|
||||
&intelImage->base.ImageStride);
|
||||
}
|
||||
#endif
|
||||
|
||||
_mesa_get_teximage(ctx, target, level, format, type, pixels,
|
||||
texObj, texImage);
|
||||
|
||||
/* Unmap */
|
||||
#ifdef ALL_IMAGES
|
||||
intel_tex_unmap_images(intel, intel_texture_object(texObj));
|
||||
#else
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_image_unmap(intel, intelImage->mt);
|
||||
intelImage->base.Data = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
178
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal file
178
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal file
@@ -0,0 +1,178 @@
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 "mtypes.h"
|
||||
#include "texobj.h"
|
||||
#include "texstore.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
|
||||
|
||||
static void intelTexSubimage (GLcontext *ctx,
|
||||
GLint dims,
|
||||
GLenum target, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLint width, GLint height, GLint depth,
|
||||
GLenum format, GLenum type, const void *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
GLuint dstImageStride;
|
||||
GLuint dstRowStride;
|
||||
|
||||
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(target),
|
||||
level,
|
||||
xoffset, yoffset,
|
||||
width, height);
|
||||
|
||||
intelFlush(ctx);
|
||||
|
||||
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type,
|
||||
pixels, packing, "glTexSubImage2D");
|
||||
if (!pixels)
|
||||
return;
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
/* Map buffer if necessary. Need to lock to prevent other contexts
|
||||
* from uploading the buffer under us.
|
||||
*/
|
||||
if (intelImage->mt)
|
||||
texImage->Data = intel_miptree_image_map(intel,
|
||||
intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&dstRowStride,
|
||||
&dstImageStride );
|
||||
|
||||
assert(dstRowStride);
|
||||
|
||||
if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
|
||||
texImage->TexFormat,
|
||||
texImage->Data,
|
||||
xoffset, yoffset, zoffset,
|
||||
dstRowStride, dstImageStride,
|
||||
width, height, depth,
|
||||
format, type, pixels, packing)) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage");
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* GL_SGIS_generate_mipmap */
|
||||
if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
|
||||
_mesa_generate_mipmap(ctx, target,
|
||||
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
|
||||
texObj);
|
||||
}
|
||||
#endif
|
||||
|
||||
_mesa_unmap_teximage_pbo(ctx, packing);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_image_unmap(intel, intelImage->mt);
|
||||
texImage->Data = NULL;
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void intelTexSubImage3D(GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
|
||||
intelTexSubimage(ctx, 3,
|
||||
target, level,
|
||||
xoffset, yoffset, zoffset,
|
||||
width, height, depth,
|
||||
format, type, pixels, packing, texObj,
|
||||
texImage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelTexSubImage2D(GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
|
||||
intelTexSubimage(ctx, 2,
|
||||
target, level,
|
||||
xoffset, yoffset, 0,
|
||||
width, height, 1,
|
||||
format, type, pixels, packing, texObj,
|
||||
texImage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void intelTexSubImage1D(GLcontext *ctx,
|
||||
GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset,
|
||||
GLsizei width,
|
||||
GLenum format, GLenum type,
|
||||
const GLvoid *pixels,
|
||||
const struct gl_pixelstore_attrib *packing,
|
||||
struct gl_texture_object *texObj,
|
||||
struct gl_texture_image *texImage)
|
||||
{
|
||||
intelTexSubimage(ctx, 1,
|
||||
target, level,
|
||||
xoffset, 0, 0,
|
||||
width, 1, 1,
|
||||
format, type, pixels, packing, texObj,
|
||||
texImage);
|
||||
|
||||
}
|
||||
247
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal file
247
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal file
@@ -0,0 +1,247 @@
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_bufmgr.h"
|
||||
|
||||
/**
|
||||
* Compute which mipmap levels that really need to be sent to the hardware.
|
||||
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
|
||||
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
|
||||
*/
|
||||
static void intel_calculate_first_last_level( struct intel_texture_object *intelObj )
|
||||
{
|
||||
struct gl_texture_object *tObj = &intelObj->base;
|
||||
const struct gl_texture_image * const baseImage =
|
||||
tObj->Image[0][tObj->BaseLevel];
|
||||
|
||||
/* These must be signed values. MinLod and MaxLod can be negative numbers,
|
||||
* and having firstLevel and lastLevel as signed prevents the need for
|
||||
* extra sign checks.
|
||||
*/
|
||||
int firstLevel;
|
||||
int lastLevel;
|
||||
|
||||
/* Yes, this looks overly complicated, but it's all needed.
|
||||
*/
|
||||
switch (tObj->Target) {
|
||||
case GL_TEXTURE_1D:
|
||||
case GL_TEXTURE_2D:
|
||||
case GL_TEXTURE_3D:
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
|
||||
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
|
||||
*/
|
||||
firstLevel = lastLevel = tObj->BaseLevel;
|
||||
}
|
||||
else {
|
||||
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
|
||||
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
|
||||
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
|
||||
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
|
||||
lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
|
||||
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
|
||||
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
|
||||
}
|
||||
break;
|
||||
case GL_TEXTURE_RECTANGLE_NV:
|
||||
case GL_TEXTURE_4D_SGIS:
|
||||
firstLevel = lastLevel = 0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* save these values */
|
||||
intelObj->firstLevel = firstLevel;
|
||||
intelObj->lastLevel = lastLevel;
|
||||
}
|
||||
|
||||
static void copy_image_data_to_tree( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj,
|
||||
struct intel_texture_image *intelImage )
|
||||
{
|
||||
if (intelImage->mt) {
|
||||
/* Copy potentially with the blitter:
|
||||
*/
|
||||
intel_miptree_image_copy(intel,
|
||||
intelObj->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
intelImage->mt);
|
||||
|
||||
intel_miptree_release(intel, &intelImage->mt);
|
||||
}
|
||||
else {
|
||||
assert(intelImage->base.Data != NULL);
|
||||
|
||||
/* More straightforward upload.
|
||||
*/
|
||||
intel_miptree_image_data(intel,
|
||||
intelObj->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
intelImage->base.Data,
|
||||
intelImage->base.RowStride,
|
||||
intelImage->base.RowStride * intelImage->base.Height);
|
||||
|
||||
free(intelImage->base.Data);
|
||||
intelImage->base.Data = NULL;
|
||||
}
|
||||
|
||||
intel_miptree_reference(&intelImage->mt, intelObj->mt);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit )
|
||||
{
|
||||
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
|
||||
struct intel_texture_object *intelObj = intel_texture_object(tObj);
|
||||
|
||||
GLuint face, i;
|
||||
GLuint nr_faces = 0;
|
||||
struct intel_texture_image *firstImage;
|
||||
|
||||
/* We know/require this is true by now:
|
||||
*/
|
||||
assert(intelObj->base.Complete);
|
||||
|
||||
/* What levels must the tree include at a minimum?
|
||||
*/
|
||||
intel_calculate_first_last_level( intelObj );
|
||||
firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]);
|
||||
|
||||
/* Fallback case:
|
||||
*/
|
||||
if (firstImage->base.Border) {
|
||||
if (intelObj->mt) {
|
||||
intel_miptree_release(intel, &intelObj->mt);
|
||||
}
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* If both firstImage and intelObj have a tree which can contain
|
||||
* all active images, favour firstImage. Note that because of the
|
||||
* completeness requirement, we know that the image dimensions
|
||||
* will match.
|
||||
*/
|
||||
if (firstImage->mt &&
|
||||
firstImage->mt != intelObj->mt &&
|
||||
firstImage->mt->first_level <= intelObj->firstLevel &&
|
||||
firstImage->mt->last_level >= intelObj->lastLevel) {
|
||||
|
||||
if (intelObj->mt)
|
||||
intel_miptree_release(intel, &intelObj->mt);
|
||||
|
||||
intel_miptree_reference(&intelObj->mt, firstImage->mt);
|
||||
}
|
||||
|
||||
/* Check tree can hold all active levels. Check tree matches
|
||||
* target, imageFormat, etc.
|
||||
*
|
||||
* XXX: For some layouts (eg i945?), the test might have to be
|
||||
* first_level == firstLevel, as the tree isn't valid except at the
|
||||
* original start level. Hope to get around this by
|
||||
* programming minLod, maxLod, baseLevel into the hardware and
|
||||
* leaving the tree alone.
|
||||
*/
|
||||
if (intelObj->mt &&
|
||||
((intelObj->mt->first_level > intelObj->firstLevel) ||
|
||||
(intelObj->mt->last_level < intelObj->lastLevel) ||
|
||||
(intelObj->mt->internal_format != firstImage->base.InternalFormat))) {
|
||||
intel_miptree_release(intel, &intelObj->mt);
|
||||
}
|
||||
|
||||
|
||||
/* May need to create a new tree:
|
||||
*/
|
||||
if (!intelObj->mt) {
|
||||
intelObj->mt = intel_miptree_create(intel,
|
||||
intelObj->base.Target,
|
||||
firstImage->base.InternalFormat,
|
||||
intelObj->firstLevel,
|
||||
intelObj->lastLevel,
|
||||
firstImage->base.Width,
|
||||
firstImage->base.Height,
|
||||
firstImage->base.Depth,
|
||||
firstImage->base.TexFormat->TexelBytes,
|
||||
firstImage->base.IsCompressed);
|
||||
}
|
||||
|
||||
/* Pull in any images not in the object's tree:
|
||||
*/
|
||||
nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
||||
for (face = 0; face < nr_faces; face++) {
|
||||
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
|
||||
struct intel_texture_image *intelImage =
|
||||
intel_texture_image(intelObj->base.Image[face][i]);
|
||||
|
||||
/* Need to import images in main memory or held in other trees.
|
||||
*/
|
||||
if (intelObj->mt != intelImage->mt) {
|
||||
copy_image_data_to_tree(intel,
|
||||
intelObj,
|
||||
intelImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intel_tex_map_images( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj )
|
||||
{
|
||||
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
||||
GLuint face, i;
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
for (face = 0; face < nr_faces; face++) {
|
||||
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
|
||||
struct intel_texture_image *intelImage =
|
||||
intel_texture_image(intelObj->base.Image[face][i]);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intelImage->base.Data =
|
||||
intel_miptree_image_map(intel,
|
||||
intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&intelImage->base.RowStride,
|
||||
&intelImage->base.ImageStride);
|
||||
/* convert stride to texels, not bytes */
|
||||
intelImage->base.RowStride /= intelImage->mt->cpp;
|
||||
intelImage->base.ImageStride /= intelImage->mt->cpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intel_tex_unmap_images( struct intel_context *intel,
|
||||
struct intel_texture_object *intelObj )
|
||||
{
|
||||
GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
||||
GLuint face, i;
|
||||
|
||||
for (face = 0; face < nr_faces; face++) {
|
||||
for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) {
|
||||
struct intel_texture_image *intelImage =
|
||||
intel_texture_image(intelObj->base.Image[face][i]);
|
||||
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_image_unmap(intel, intelImage->mt);
|
||||
intelImage->base.Data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,14 +38,95 @@
|
||||
#include "tnl/t_vertex.h"
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_tris.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_reg.h"
|
||||
#include "intel_span.h"
|
||||
#include "intel_tex.h"
|
||||
|
||||
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
|
||||
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
|
||||
|
||||
/*
|
||||
*/
|
||||
static void intel_flush_inline_primitive( struct intel_context *intel )
|
||||
{
|
||||
GLuint used = intel->batch->ptr - intel->prim.start_ptr;
|
||||
|
||||
assert(intel->prim.primitive != ~0);
|
||||
|
||||
if (used < 8)
|
||||
goto do_discard;
|
||||
|
||||
*(int *)intel->prim.start_ptr = (_3DPRIMITIVE |
|
||||
intel->prim.primitive |
|
||||
(used/4-2));
|
||||
|
||||
goto finished;
|
||||
|
||||
do_discard:
|
||||
intel->batch->ptr -= used;
|
||||
|
||||
finished:
|
||||
intel->prim.primitive = ~0;
|
||||
intel->prim.start_ptr = 0;
|
||||
intel->prim.flush = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Emit a primitive referencing vertices in a vertex buffer.
|
||||
*/
|
||||
void intelStartInlinePrimitive( struct intel_context *intel,
|
||||
GLuint prim,
|
||||
GLuint batch_flags )
|
||||
{
|
||||
BATCH_LOCALS;
|
||||
|
||||
/* Emit a slot which will be filled with the inline primitive
|
||||
* command later.
|
||||
*/
|
||||
BEGIN_BATCH(2, batch_flags);
|
||||
OUT_BATCH( 0 );
|
||||
|
||||
intel->prim.start_ptr = intel->batch->ptr;
|
||||
intel->prim.primitive = prim;
|
||||
intel->prim.flush = intel_flush_inline_primitive;
|
||||
|
||||
OUT_BATCH( 0 );
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
|
||||
void intelWrapInlinePrimitive( struct intel_context *intel )
|
||||
{
|
||||
GLuint prim = intel->prim.primitive;
|
||||
GLuint batchflags = intel->batch->flags;
|
||||
|
||||
intel_flush_inline_primitive(intel);
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
|
||||
intel->vtbl.emit_state( intel );
|
||||
intelStartInlinePrimitive( intel, prim, batchflags ); /* ??? */
|
||||
}
|
||||
|
||||
GLuint *intelExtendInlinePrimitive( struct intel_context *intel,
|
||||
GLuint dwords )
|
||||
{
|
||||
GLuint sz = dwords * sizeof(GLuint);
|
||||
GLuint *ptr;
|
||||
|
||||
if (intel_batchbuffer_space(intel->batch) < sz)
|
||||
intelWrapInlinePrimitive( intel );
|
||||
|
||||
ptr = (GLuint *)intel->batch->ptr;
|
||||
intel->batch->ptr += sz;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Emit primitives as inline vertices *
|
||||
***********************************************************************/
|
||||
@@ -63,22 +144,18 @@ do { \
|
||||
#else
|
||||
#define COPY_DWORDS( j, vb, vertsize, v ) \
|
||||
do { \
|
||||
if (0) fprintf(stderr, "\n"); \
|
||||
for ( j = 0 ; j < vertsize ; j++ ) { \
|
||||
if (0) fprintf(stderr, " -- v(%d): %x/%f\n",j, \
|
||||
((GLuint *)v)[j], \
|
||||
((GLfloat *)v)[j]); \
|
||||
vb[j] = ((GLuint *)v)[j]; \
|
||||
} \
|
||||
vb += vertsize; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
static void __inline__ intel_draw_quad( intelContextPtr intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1,
|
||||
intelVertexPtr v2,
|
||||
intelVertexPtr v3 )
|
||||
static void intel_draw_quad( struct intel_context *intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1,
|
||||
intelVertexPtr v2,
|
||||
intelVertexPtr v3 )
|
||||
{
|
||||
GLuint vertsize = intel->vertex_size;
|
||||
GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize );
|
||||
@@ -92,10 +169,10 @@ static void __inline__ intel_draw_quad( intelContextPtr intel,
|
||||
COPY_DWORDS( j, vb, vertsize, v3 );
|
||||
}
|
||||
|
||||
static void __inline__ intel_draw_triangle( intelContextPtr intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1,
|
||||
intelVertexPtr v2 )
|
||||
static void intel_draw_triangle( struct intel_context *intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1,
|
||||
intelVertexPtr v2 )
|
||||
{
|
||||
GLuint vertsize = intel->vertex_size;
|
||||
GLuint *vb = intelExtendInlinePrimitive( intel, 3 * vertsize );
|
||||
@@ -107,9 +184,9 @@ static void __inline__ intel_draw_triangle( intelContextPtr intel,
|
||||
}
|
||||
|
||||
|
||||
static __inline__ void intel_draw_line( intelContextPtr intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1 )
|
||||
static void intel_draw_line( struct intel_context *intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1 )
|
||||
{
|
||||
GLuint vertsize = intel->vertex_size;
|
||||
GLuint *vb = intelExtendInlinePrimitive( intel, 2 * vertsize );
|
||||
@@ -120,8 +197,8 @@ static __inline__ void intel_draw_line( intelContextPtr intel,
|
||||
}
|
||||
|
||||
|
||||
static __inline__ void intel_draw_point( intelContextPtr intel,
|
||||
intelVertexPtr v0 )
|
||||
static void intel_draw_point( struct intel_context *intel,
|
||||
intelVertexPtr v0 )
|
||||
{
|
||||
GLuint vertsize = intel->vertex_size;
|
||||
GLuint *vb = intelExtendInlinePrimitive( intel, vertsize );
|
||||
@@ -140,7 +217,7 @@ static __inline__ void intel_draw_point( intelContextPtr intel,
|
||||
* Fixup for ARB_point_parameters *
|
||||
***********************************************************************/
|
||||
|
||||
static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
|
||||
static void intel_atten_point( struct intel_context *intel, intelVertexPtr v0 )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
GLfloat psz[4], col[4], restore_psz, restore_alpha;
|
||||
@@ -189,7 +266,7 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
|
||||
|
||||
|
||||
|
||||
static void intel_wpos_triangle( intelContextPtr intel,
|
||||
static void intel_wpos_triangle( struct intel_context *intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1,
|
||||
intelVertexPtr v2 )
|
||||
@@ -205,7 +282,7 @@ static void intel_wpos_triangle( intelContextPtr intel,
|
||||
}
|
||||
|
||||
|
||||
static void intel_wpos_line( intelContextPtr intel,
|
||||
static void intel_wpos_line( struct intel_context *intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1 )
|
||||
{
|
||||
@@ -219,7 +296,7 @@ static void intel_wpos_line( intelContextPtr intel,
|
||||
}
|
||||
|
||||
|
||||
static void intel_wpos_point( intelContextPtr intel,
|
||||
static void intel_wpos_point( struct intel_context *intel,
|
||||
intelVertexPtr v0 )
|
||||
{
|
||||
GLuint offset = intel->wpos_offset;
|
||||
@@ -349,7 +426,7 @@ do { \
|
||||
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
|
||||
|
||||
#define LOCAL_VARS(n) \
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx); \
|
||||
struct intel_context *intel = intel_context(ctx); \
|
||||
GLuint color[n], spec[n]; \
|
||||
GLuint coloroffset = intel->coloroffset; \
|
||||
GLboolean specoffset = intel->specoffset; \
|
||||
@@ -481,7 +558,7 @@ static void init_rast_tab( void )
|
||||
* primitives.
|
||||
*/
|
||||
static void
|
||||
intel_fallback_tri( intelContextPtr intel,
|
||||
intel_fallback_tri( struct intel_context *intel,
|
||||
intelVertex *v0,
|
||||
intelVertex *v1,
|
||||
intelVertex *v2 )
|
||||
@@ -491,6 +568,9 @@ intel_fallback_tri( intelContextPtr intel,
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "\n%s\n", __FUNCTION__);
|
||||
|
||||
if (intel->prim.flush)
|
||||
intel->prim.flush(intel);
|
||||
|
||||
_swsetup_Translate( ctx, v0, &v[0] );
|
||||
_swsetup_Translate( ctx, v1, &v[1] );
|
||||
@@ -502,7 +582,7 @@ intel_fallback_tri( intelContextPtr intel,
|
||||
|
||||
|
||||
static void
|
||||
intel_fallback_line( intelContextPtr intel,
|
||||
intel_fallback_line( struct intel_context *intel,
|
||||
intelVertex *v0,
|
||||
intelVertex *v1 )
|
||||
{
|
||||
@@ -512,6 +592,9 @@ intel_fallback_line( intelContextPtr intel,
|
||||
if (0)
|
||||
fprintf(stderr, "\n%s\n", __FUNCTION__);
|
||||
|
||||
if (intel->prim.flush)
|
||||
intel->prim.flush(intel);
|
||||
|
||||
_swsetup_Translate( ctx, v0, &v[0] );
|
||||
_swsetup_Translate( ctx, v1, &v[1] );
|
||||
intelSpanRenderStart( ctx );
|
||||
@@ -520,24 +603,6 @@ intel_fallback_line( intelContextPtr intel,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_fallback_point( intelContextPtr intel,
|
||||
intelVertex *v0 )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
SWvertex v[1];
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "\n%s\n", __FUNCTION__);
|
||||
|
||||
_swsetup_Translate( ctx, v0, &v[0] );
|
||||
intelSpanRenderStart( ctx );
|
||||
_swrast_Point( ctx, &v[0] );
|
||||
intelSpanRenderFinish( ctx );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* Render unclipped begin/end objects */
|
||||
/**********************************************************************/
|
||||
@@ -552,7 +617,7 @@ intel_fallback_point( intelContextPtr intel,
|
||||
#define INIT(x) intelRenderPrimitive( ctx, x )
|
||||
#undef LOCAL_VARS
|
||||
#define LOCAL_VARS \
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx); \
|
||||
struct intel_context *intel = intel_context(ctx); \
|
||||
GLubyte *vertptr = (GLubyte *)intel->verts; \
|
||||
const GLuint vertsize = intel->vertex_size; \
|
||||
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
|
||||
@@ -578,7 +643,7 @@ intel_fallback_point( intelContextPtr intel,
|
||||
static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
|
||||
GLuint n )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
||||
GLuint prim = intel->render_primitive;
|
||||
@@ -609,7 +674,7 @@ static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
|
||||
static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
|
||||
GLuint n )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
struct intel_context *intel = intel_context( ctx );
|
||||
const GLuint vertsize = intel->vertex_size;
|
||||
GLuint *vb = intelExtendInlinePrimitive( intel, (n-2) * 3 * vertsize );
|
||||
GLubyte *vertptr = (GLubyte *)intel->verts;
|
||||
@@ -630,17 +695,13 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
|
||||
|
||||
|
||||
|
||||
#define POINT_FALLBACK (0)
|
||||
#define LINE_FALLBACK (DD_LINE_STIPPLE)
|
||||
#define TRI_FALLBACK (0)
|
||||
#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
|
||||
DD_TRI_STIPPLE|DD_POINT_ATTEN)
|
||||
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
|
||||
#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN)
|
||||
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
|
||||
|
||||
void intelChooseRenderState(GLcontext *ctx)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
GLuint flags = ctx->_TriangleCaps;
|
||||
struct fragment_program *fprog = ctx->FragmentProgram._Current;
|
||||
GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
|
||||
@@ -676,15 +737,9 @@ void intelChooseRenderState(GLcontext *ctx)
|
||||
*/
|
||||
if (flags & ANY_FALLBACK_FLAGS)
|
||||
{
|
||||
if (flags & POINT_FALLBACK)
|
||||
intel->draw_point = intel_fallback_point;
|
||||
|
||||
if (flags & LINE_FALLBACK)
|
||||
if (flags & DD_LINE_STIPPLE)
|
||||
intel->draw_line = intel_fallback_line;
|
||||
|
||||
if (flags & TRI_FALLBACK)
|
||||
intel->draw_tri = intel_fallback_tri;
|
||||
|
||||
if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
|
||||
intel->draw_tri = intel_fallback_tri;
|
||||
|
||||
@@ -740,7 +795,7 @@ static const GLenum reduced_prim[GL_POLYGON+1] = {
|
||||
|
||||
static void intelRunPipeline( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
|
||||
if (intel->NewGLState) {
|
||||
if (intel->NewGLState & _NEW_TEXTURE) {
|
||||
@@ -760,13 +815,21 @@ static void intelRunPipeline( GLcontext *ctx )
|
||||
|
||||
static void intelRenderStart( GLcontext *ctx )
|
||||
{
|
||||
INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) );
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
|
||||
intel->vtbl.render_start( intel_context(ctx) );
|
||||
intel->vtbl.emit_state( intel );
|
||||
}
|
||||
|
||||
static void intelRenderFinish( GLcontext *ctx )
|
||||
{
|
||||
if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
|
||||
if (intel->RenderIndex & INTEL_FALLBACK_BIT)
|
||||
_swrast_flush( ctx );
|
||||
|
||||
if (intel->prim.flush)
|
||||
intel->prim.flush(intel);
|
||||
}
|
||||
|
||||
|
||||
@@ -777,7 +840,7 @@ static void intelRenderFinish( GLcontext *ctx )
|
||||
*/
|
||||
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s %s %x\n", __FUNCTION__,
|
||||
@@ -787,111 +850,185 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
|
||||
|
||||
/* Start a new primitive. Arrange to have it flushed later on.
|
||||
*/
|
||||
if (hwprim != intel->prim.primitive)
|
||||
intelStartInlinePrimitive( intel, hwprim );
|
||||
if (hwprim != intel->prim.primitive) {
|
||||
if (intel->prim.flush)
|
||||
intel->prim.flush(intel);
|
||||
|
||||
intelStartInlinePrimitive( intel, hwprim, INTEL_BATCH_CLIPRECTS );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim )
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
|
||||
if (0)
|
||||
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
|
||||
|
||||
/* Let some clipping routines know which primitive they're dealing
|
||||
* with.
|
||||
*/
|
||||
intel->render_primitive = prim;
|
||||
/* Let some clipping routines know which primitive they're dealing
|
||||
* with.
|
||||
*/
|
||||
intel->render_primitive = prim;
|
||||
|
||||
/* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
|
||||
* triangles. The rasterized primitive will always be reset by
|
||||
* lower level functions in that case, potentially pingponging the
|
||||
* state:
|
||||
*/
|
||||
if (reduced_prim[prim] == GL_TRIANGLES &&
|
||||
(ctx->_TriangleCaps & DD_TRI_UNFILLED))
|
||||
return;
|
||||
/* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
|
||||
* triangles. The rasterized primitive will always be reset by
|
||||
* lower level functions in that case, potentially pingponging the
|
||||
* state:
|
||||
*/
|
||||
if (reduced_prim[prim] == GL_TRIANGLES &&
|
||||
(ctx->_TriangleCaps & DD_TRI_UNFILLED))
|
||||
return;
|
||||
|
||||
/* Set some primitive-dependent state and Start? a new primitive.
|
||||
*/
|
||||
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
|
||||
}
|
||||
/* Set some primitive-dependent state and Start? a new primitive.
|
||||
*/
|
||||
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* Transition to/from hardware rasterization. */
|
||||
/**********************************************************************/
|
||||
|
||||
static char *fallbackStrings[] = {
|
||||
"Texture",
|
||||
"Draw buffer",
|
||||
"Read buffer",
|
||||
"Color mask",
|
||||
"Render mode",
|
||||
"Stencil",
|
||||
"Stipple",
|
||||
"User disable"
|
||||
};
|
||||
static char *fallbackStrings[] = {
|
||||
"Texture",
|
||||
"Draw buffer",
|
||||
"Read buffer",
|
||||
"Color mask",
|
||||
"Render mode",
|
||||
"Stencil",
|
||||
"Stipple",
|
||||
"User disable"
|
||||
};
|
||||
|
||||
|
||||
static char *getFallbackString(GLuint bit)
|
||||
{
|
||||
int i = 0;
|
||||
while (bit > 1) {
|
||||
i++;
|
||||
bit >>= 1;
|
||||
}
|
||||
return fallbackStrings[i];
|
||||
}
|
||||
static char *getFallbackString(GLuint bit)
|
||||
{
|
||||
int i = 0;
|
||||
while (bit > 1) {
|
||||
i++;
|
||||
bit >>= 1;
|
||||
}
|
||||
return fallbackStrings[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLuint oldfallback = intel->Fallback;
|
||||
void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode )
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLuint oldfallback = intel->Fallback;
|
||||
|
||||
if (mode) {
|
||||
intel->Fallback |= bit;
|
||||
if (oldfallback == 0) {
|
||||
intelFlush(ctx);
|
||||
if (INTEL_DEBUG & DEBUG_FALLBACKS)
|
||||
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
|
||||
bit, getFallbackString( bit ));
|
||||
_swsetup_Wakeup( ctx );
|
||||
intel->RenderIndex = ~0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
intel->Fallback &= ~bit;
|
||||
if (oldfallback == bit) {
|
||||
_swrast_flush( ctx );
|
||||
if (INTEL_DEBUG & DEBUG_FALLBACKS)
|
||||
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
|
||||
tnl->Driver.Render.Start = intelRenderStart;
|
||||
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
|
||||
tnl->Driver.Render.Finish = intelRenderFinish;
|
||||
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
|
||||
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
|
||||
tnl->Driver.Render.Interp = _tnl_interp;
|
||||
if (mode) {
|
||||
intel->Fallback |= bit;
|
||||
if (oldfallback == 0) {
|
||||
intelFlush(ctx);
|
||||
if (INTEL_DEBUG & DEBUG_FALLBACKS)
|
||||
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
|
||||
bit, getFallbackString( bit ));
|
||||
_swsetup_Wakeup( ctx );
|
||||
intel->RenderIndex = ~0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
intel->Fallback &= ~bit;
|
||||
if (oldfallback == bit) {
|
||||
_swrast_flush( ctx );
|
||||
if (INTEL_DEBUG & DEBUG_FALLBACKS)
|
||||
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
|
||||
tnl->Driver.Render.Start = intelRenderStart;
|
||||
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
|
||||
tnl->Driver.Render.Finish = intelRenderFinish;
|
||||
tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
|
||||
tnl->Driver.Render.CopyPV = _tnl_copy_pv;
|
||||
tnl->Driver.Render.Interp = _tnl_interp;
|
||||
|
||||
_tnl_invalidate_vertex_state( ctx, ~0 );
|
||||
_tnl_invalidate_vertices( ctx, ~0 );
|
||||
_tnl_install_attrs( ctx,
|
||||
intel->vertex_attrs,
|
||||
intel->vertex_attr_count,
|
||||
intel->ViewportMatrix.m, 0 );
|
||||
_tnl_invalidate_vertex_state( ctx, ~0 );
|
||||
_tnl_invalidate_vertices( ctx, ~0 );
|
||||
_tnl_install_attrs( ctx,
|
||||
intel->vertex_attrs,
|
||||
intel->vertex_attr_count,
|
||||
intel->ViewportMatrix.m, 0 );
|
||||
|
||||
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
union fi {
|
||||
GLfloat f;
|
||||
GLint i;
|
||||
};
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* Used only with the metaops callbacks. */
|
||||
/**********************************************************************/
|
||||
void intel_meta_draw_quad(struct intel_context *intel,
|
||||
GLfloat x0, GLfloat x1,
|
||||
GLfloat y0, GLfloat y1,
|
||||
GLfloat z,
|
||||
GLuint color,
|
||||
GLfloat s0, GLfloat s1,
|
||||
GLfloat t0, GLfloat t1)
|
||||
{
|
||||
union fi *vb;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_DRI)
|
||||
fprintf(stderr, "%s: %f,%f-%f,%f 0x%x %f,%f-%f,%f depth: %f\n",
|
||||
__FUNCTION__,
|
||||
x0,y0,x1,y1,color,s0,t0,s1,t1, z);
|
||||
|
||||
intel->vtbl.emit_state( intel );
|
||||
|
||||
/* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS,
|
||||
* otherwise the drawing origin (DR4) might not be set correctly.
|
||||
*/
|
||||
intelStartInlinePrimitive( intel, PRIM3D_TRIFAN, INTEL_BATCH_CLIPRECTS );
|
||||
vb = (union fi *)intelExtendInlinePrimitive( intel, 4 * 6 );
|
||||
|
||||
|
||||
/* initial vertex, left bottom */
|
||||
vb[0].f = x0;
|
||||
vb[1].f = y0;
|
||||
vb[2].f = z;
|
||||
vb[3].i = color;
|
||||
vb[4].f = s0;
|
||||
vb[5].f = t0;
|
||||
vb += 6;
|
||||
|
||||
/* right bottom */
|
||||
vb[0].f = x1;
|
||||
vb[1].f = y0;
|
||||
vb[2].f = z;
|
||||
vb[3].i = color;
|
||||
vb[4].f = s1;
|
||||
vb[5].f = t0;
|
||||
vb += 6;
|
||||
|
||||
/* right top */
|
||||
vb[0].f = x1;
|
||||
vb[1].f = y1;
|
||||
vb[2].f = z;
|
||||
vb[3].i = color;
|
||||
vb[4].f = s1;
|
||||
vb[5].f = t1;
|
||||
vb += 6;
|
||||
|
||||
/* left top */
|
||||
vb[0].f = x0;
|
||||
vb[1].f = y1;
|
||||
vb[2].f = z;
|
||||
vb[3].i = color;
|
||||
vb[4].f = s0;
|
||||
vb[5].f = t1;
|
||||
|
||||
if (intel->prim.flush)
|
||||
intel->prim.flush(intel);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include "mtypes.h"
|
||||
|
||||
|
||||
|
||||
#define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
|
||||
_DD_NEW_TRI_UNFILLED | \
|
||||
_DD_NEW_TRI_LIGHT_TWOSIDE | \
|
||||
@@ -40,7 +42,22 @@
|
||||
|
||||
extern void intelInitTriFuncs( GLcontext *ctx );
|
||||
|
||||
extern void intelPrintRenderState( const char *msg, GLuint state );
|
||||
extern void intelChooseRenderState( GLcontext *ctx );
|
||||
|
||||
extern void intelStartInlinePrimitive( struct intel_context *intel, GLuint prim, GLuint flags );
|
||||
extern void intelWrapInlinePrimitive( struct intel_context *intel );
|
||||
|
||||
GLuint *intelExtendInlinePrimitive( struct intel_context *intel,
|
||||
GLuint dwords );
|
||||
|
||||
|
||||
void intel_meta_draw_quad(struct intel_context *intel,
|
||||
GLfloat x0, GLfloat x1,
|
||||
GLfloat y0, GLfloat y1,
|
||||
GLfloat z,
|
||||
GLuint color,
|
||||
GLfloat s0, GLfloat s1,
|
||||
GLfloat t0, GLfloat t1);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,11 +18,21 @@ OUTPUTS = glprocs.h glapitemp.h glapioffsets.h glapitable.h dispatch.h \
|
||||
../../glx/x11/indirect_size.h \
|
||||
../../glx/x11/indirect_size.c
|
||||
|
||||
|
||||
#XORG_BASE = /home/idr/devel/graphics/Xorg/xserver/xorg
|
||||
GLX_DIR = $(XORG_BASE)/GL/glx
|
||||
|
||||
SERVER_OUTPUTS = $(GLX_DIR)/indirect_dispatch.c \
|
||||
$(GLX_DIR)/indirect_dispatch_swap.c \
|
||||
$(GLX_DIR)/indirect_dispatch.h
|
||||
|
||||
COMMON = gl_XML.py license.py gl_API.xml typeexpr.py
|
||||
COMMON_GLX = $(COMMON) glX_XML.py glX_proto_common.py
|
||||
|
||||
all: $(OUTPUTS)
|
||||
|
||||
server: $(SERVER_OUTPUTS)
|
||||
|
||||
glprocs.h: $(COMMON) gl_procs.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) gl_procs.py > glprocs.h
|
||||
|
||||
@@ -65,6 +75,21 @@ dispatch.h: $(COMMON) gl_table.py
|
||||
../../glx/x11/indirect_size.c: $(COMMON_GLX) glX_proto_size.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_c --only-set > ../../glx/x11/indirect_size.c
|
||||
|
||||
$(GLX_DIR)/indirect_dispatch.c: $(COMMON_GLX) glX_proto_recv.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_c > $@
|
||||
|
||||
$(GLX_DIR)/indirect_dispatch_swap.c: $(COMMON_GLX) glX_proto_recv.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_c -s > $@
|
||||
|
||||
$(GLX_DIR)/indirect_dispatch.h: $(COMMON_GLX) glX_proto_recv.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_h -s > $@
|
||||
|
||||
$(GLX_DIR)/indirect_size_get.h: $(COMMON_GLX) glX_proto_size.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_h --only-get -h '_INDIRECT_SIZE_GET_H_' > $@
|
||||
|
||||
$(GLX_DIR)/indirect_size_get.c: $(COMMON_GLX) glX_proto_size.py
|
||||
$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_c > $@
|
||||
|
||||
clean:
|
||||
rm -f *~ *.pyo
|
||||
rm -f $(OUTPUTS)
|
||||
|
||||
@@ -2512,10 +2512,13 @@
|
||||
#define CALL_GetQueryObjectui64vEXT(disp, parameters) (*((disp)->GetQueryObjectui64vEXT)) parameters
|
||||
#define GET_GetQueryObjectui64vEXT(disp) ((disp)->GetQueryObjectui64vEXT)
|
||||
#define SET_GetQueryObjectui64vEXT(disp, fn) ((disp)->GetQueryObjectui64vEXT = fn)
|
||||
#define CALL_BlitFramebufferEXT(disp, parameters) (*((disp)->BlitFramebufferEXT)) parameters
|
||||
#define GET_BlitFramebufferEXT(disp) ((disp)->BlitFramebufferEXT)
|
||||
#define SET_BlitFramebufferEXT(disp, fn) ((disp)->BlitFramebufferEXT = fn)
|
||||
|
||||
#else
|
||||
|
||||
#define driDispatchRemapTable_size 410
|
||||
#define driDispatchRemapTable_size 411
|
||||
extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
|
||||
|
||||
#define LoadTransposeMatrixfARB_remap_index 0
|
||||
@@ -2928,6 +2931,7 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
|
||||
#define StencilMaskSeparate_remap_index 407
|
||||
#define GetQueryObjecti64vEXT_remap_index 408
|
||||
#define GetQueryObjectui64vEXT_remap_index 409
|
||||
#define BlitFramebufferEXT_remap_index 410
|
||||
|
||||
#define CALL_LoadTransposeMatrixfARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index], parameters)
|
||||
#define GET_LoadTransposeMatrixfARB(disp) GET_by_offset(disp, driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index])
|
||||
@@ -4159,6 +4163,9 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ];
|
||||
#define CALL_GetQueryObjectui64vEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLuint64EXT *)), driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], parameters)
|
||||
#define GET_GetQueryObjectui64vEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index])
|
||||
#define SET_GetQueryObjectui64vEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], fn)
|
||||
#define CALL_BlitFramebufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)), driDispatchRemapTable[BlitFramebufferEXT_remap_index], parameters)
|
||||
#define GET_BlitFramebufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index])
|
||||
#define SET_BlitFramebufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index], fn)
|
||||
|
||||
#endif /* !defined(IN_DRI_DRIVER) */
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class glx_proto_type(gl_XML.gl_type):
|
||||
|
||||
|
||||
class glx_print_proto(gl_XML.gl_print_base):
|
||||
def size_call(self, func):
|
||||
def size_call(self, func, outputs_also = 0):
|
||||
"""Create C code to calculate 'compsize'.
|
||||
|
||||
Creates code to calculate 'compsize'. If the function does
|
||||
@@ -58,7 +58,7 @@ class glx_print_proto(gl_XML.gl_print_base):
|
||||
compsize = None
|
||||
|
||||
for param in func.parameterIterator():
|
||||
if not param.is_output:
|
||||
if outputs_also or not param.is_output:
|
||||
if param.is_image():
|
||||
[dim, w, h, d, junk] = param.get_dimensions()
|
||||
|
||||
|
||||
561
src/mesa/glapi/glX_proto_recv.py
Normal file
561
src/mesa/glapi/glX_proto_recv.py
Normal file
@@ -0,0 +1,561 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# (C) Copyright IBM Corporation 2005
|
||||
# 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
|
||||
# on 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
|
||||
# IBM 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.
|
||||
#
|
||||
# Authors:
|
||||
# Ian Romanick <idr@us.ibm.com>
|
||||
|
||||
import gl_XML, glX_XML, glX_proto_common, license
|
||||
import sys, getopt, string
|
||||
|
||||
|
||||
class PrintGlxDispatch_h(gl_XML.gl_print_base):
|
||||
def __init__(self):
|
||||
gl_XML.gl_print_base.__init__(self)
|
||||
|
||||
self.name = "glX_proto_recv.py (from Mesa)"
|
||||
self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
|
||||
|
||||
self.header_tag = "_INDIRECT_DISPATCH_H_"
|
||||
return
|
||||
|
||||
|
||||
def printRealHeader(self):
|
||||
self.printVisibility( "HIDDEN", "hidden" )
|
||||
print 'struct __GLXclientStateRec;'
|
||||
print ''
|
||||
return
|
||||
|
||||
|
||||
def printBody(self, api):
|
||||
for func in api.functionIterateAll():
|
||||
if not func.ignore and not func.vectorequiv:
|
||||
if func.glx_rop != 0:
|
||||
print 'extern HIDDEN void __glXDisp_%s(GLbyte * pc);' % (func.name)
|
||||
print 'extern HIDDEN void __glXDispSwap_%s(GLbyte * pc);' % (func.name)
|
||||
elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
|
||||
print 'extern HIDDEN int __glXDisp_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name)
|
||||
print 'extern HIDDEN int __glXDispSwap_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name)
|
||||
|
||||
return
|
||||
|
||||
|
||||
class PrintGlxDispatchFunctions(glX_proto_common.glx_print_proto):
|
||||
def __init__(self, do_swap):
|
||||
gl_XML.gl_print_base.__init__(self)
|
||||
self.name = "glX_proto_recv.py (from Mesa)"
|
||||
self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
|
||||
|
||||
self.real_types = [ '', '', 'uint16_t', '', 'uint32_t', '', '', '', 'uint64_t' ]
|
||||
self.do_swap = do_swap
|
||||
return
|
||||
|
||||
|
||||
def printRealHeader(self):
|
||||
print '#include <X11/Xmd.h>'
|
||||
print '#include <GL/gl.h>'
|
||||
print '#include <GL/glxproto.h>'
|
||||
|
||||
|
||||
# FIXME: Since this block will require changes as other
|
||||
# FIXME: platforms are added, it should probably be in a
|
||||
# FIXME: header file that is not generated by a script.
|
||||
|
||||
if self.do_swap:
|
||||
print '#ifdef __linux__'
|
||||
print '#include <byteswap.h>'
|
||||
print '#elif defined(__OpenBSD__)'
|
||||
print '#include <sys/endian.h>'
|
||||
print '#define bswap_16 __swap16'
|
||||
print '#define bswap_32 __swap32'
|
||||
print '#define bswap_64 __swap64'
|
||||
print '#else'
|
||||
print '#include <sys/endian.h>'
|
||||
print '#define bswap_16 bswap16'
|
||||
print '#define bswap_32 bswap32'
|
||||
print '#define bswap_64 bswap64'
|
||||
print '#endif'
|
||||
|
||||
print '#include <inttypes.h>'
|
||||
print '#include "indirect_size.h"'
|
||||
print '#include "indirect_size_get.h"'
|
||||
print '#include "indirect_dispatch.h"'
|
||||
print '#include "glxserver.h"'
|
||||
print '#include "indirect_util.h"'
|
||||
print '#include "singlesize.h"'
|
||||
print '#include "glapitable.h"'
|
||||
print '#include "glapi.h"'
|
||||
print '#include "glthread.h"'
|
||||
print '#include "dispatch.h"'
|
||||
print ''
|
||||
print '#define __GLX_PAD(x) (((x) + 3) & ~3)'
|
||||
print ''
|
||||
print 'typedef struct {'
|
||||
print ' __GLX_PIXEL_3D_HDR;'
|
||||
print '} __GLXpixel3DHeader;'
|
||||
print ''
|
||||
print 'extern GLboolean __glXErrorOccured( void );'
|
||||
print 'extern void __glXClearErrorOccured( void );'
|
||||
print ''
|
||||
print 'static const unsigned dummy_answer[2] = {0, 0};'
|
||||
print ''
|
||||
return
|
||||
|
||||
|
||||
def printBody(self, api):
|
||||
if self.do_swap:
|
||||
self.emit_swap_wrappers(api)
|
||||
|
||||
|
||||
for func in api.functionIterateByOffset():
|
||||
if not func.ignore and not func.server_handcode and not func.vectorequiv and (func.glx_rop or func.glx_sop or func.glx_vendorpriv):
|
||||
self.printFunction(func)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def printFunction(self, f):
|
||||
if (f.glx_sop or f.glx_vendorpriv) and (len(f.get_images()) != 0):
|
||||
return
|
||||
|
||||
if not self.do_swap:
|
||||
base = '__glXDisp'
|
||||
else:
|
||||
base = '__glXDispSwap'
|
||||
|
||||
if f.glx_rop:
|
||||
print 'void %s_%s(GLbyte * pc)' % (base, f.name)
|
||||
else:
|
||||
print 'int %s_%s(__GLXclientState *cl, GLbyte *pc)' % (base, f.name)
|
||||
|
||||
print '{'
|
||||
|
||||
if f.glx_rop or f.vectorequiv:
|
||||
self.printRenderFunction(f)
|
||||
elif f.glx_sop or f.glx_vendorpriv:
|
||||
if len(f.get_images()) == 0:
|
||||
self.printSingleFunction(f)
|
||||
else:
|
||||
print "/* Missing GLX protocol for %s. */" % (f.name)
|
||||
|
||||
print '}'
|
||||
print ''
|
||||
return
|
||||
|
||||
|
||||
def swap_name(self, bytes):
|
||||
return 'bswap_%u_array' % (8 * bytes)
|
||||
|
||||
|
||||
def emit_swap_wrappers(self, api):
|
||||
self.type_map = {}
|
||||
already_done = [ ]
|
||||
|
||||
for t in api.typeIterate():
|
||||
te = t.get_type_expression()
|
||||
t_size = te.get_element_size()
|
||||
|
||||
if t_size > 1 and t.glx_name:
|
||||
|
||||
t_name = "GL" + t.name
|
||||
self.type_map[ t_name ] = t.glx_name
|
||||
|
||||
if t.glx_name not in already_done:
|
||||
real_name = self.real_types[t_size]
|
||||
|
||||
print 'static %s' % (t_name)
|
||||
print 'bswap_%s( const void * src )' % (t.glx_name)
|
||||
print '{'
|
||||
print ' union { %s dst; %s ret; } x;' % (real_name, t_name)
|
||||
print ' x.dst = bswap_%u( *(%s *) src );' % (t_size * 8, real_name)
|
||||
print ' return x.ret;'
|
||||
print '}'
|
||||
print ''
|
||||
already_done.append( t.glx_name )
|
||||
|
||||
for bits in [16, 32, 64]:
|
||||
print 'static void *'
|
||||
print 'bswap_%u_array( uint%u_t * src, unsigned count )' % (bits, bits)
|
||||
print '{'
|
||||
print ' unsigned i;'
|
||||
print ''
|
||||
print ' for ( i = 0 ; i < count ; i++ ) {'
|
||||
print ' uint%u_t temp = bswap_%u( src[i] );' % (bits, bits)
|
||||
print ' src[i] = temp;'
|
||||
print ' }'
|
||||
print ''
|
||||
print ' return src;'
|
||||
print '}'
|
||||
print ''
|
||||
|
||||
|
||||
def fetch_param(self, param):
|
||||
t = param.type_string()
|
||||
o = param.offset
|
||||
element_size = param.size() / param.get_element_count()
|
||||
|
||||
if self.do_swap and (element_size != 1):
|
||||
if param.is_array():
|
||||
real_name = self.real_types[ element_size ]
|
||||
|
||||
swap_func = self.swap_name( element_size )
|
||||
return ' (%-8s)%s( (%s *) (pc + %2s), %s )' % (t, swap_func, real_name, o, param.count)
|
||||
else:
|
||||
t_name = param.get_base_type_string()
|
||||
return ' (%-8s)bswap_%-7s( pc + %2s )' % (t, self.type_map[ t_name ], o)
|
||||
else:
|
||||
if param.is_array():
|
||||
return ' (%-8s)(pc + %2u)' % (t, o)
|
||||
else:
|
||||
return '*(%-8s *)(pc + %2u)' % (t, o)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def emit_function_call(self, f, retval_assign, indent):
|
||||
list = []
|
||||
|
||||
for param in f.parameterIterator():
|
||||
|
||||
if param.is_counter or param.is_image() or param.is_output or len(param.count_parameter_list):
|
||||
location = param.name
|
||||
else:
|
||||
location = self.fetch_param(param)
|
||||
|
||||
list.append( '%s %s' % (indent, location) )
|
||||
|
||||
|
||||
if len( list ):
|
||||
print '%s %sCALL_%s( GET_DISPATCH(), (' % (indent, retval_assign, f.name)
|
||||
print string.join( list, ",\n" )
|
||||
print '%s ) );' % (indent)
|
||||
else:
|
||||
print '%s %sCALL_%s( GET_DISPATCH(), () );' % (indent, retval_assign, f.name)
|
||||
return
|
||||
|
||||
|
||||
def common_func_print_just_start(self, f, indent):
|
||||
align64 = 0
|
||||
need_blank = 0
|
||||
|
||||
|
||||
f.calculate_offsets()
|
||||
for param in f.parameterIterateGlxSend():
|
||||
# If any parameter has a 64-bit base type, then we
|
||||
# have to do alignment magic for the while thing.
|
||||
|
||||
if param.is_64_bit():
|
||||
align64 = 1
|
||||
|
||||
|
||||
# FIXME img_null_flag is over-loaded. In addition to
|
||||
# FIXME being used for images, it is used to signify
|
||||
# FIXME NULL data pointers for vertex buffer object
|
||||
# FIXME related functions. Re-name it to null_data
|
||||
# FIXME or something similar.
|
||||
|
||||
if param.img_null_flag:
|
||||
print '%s const CARD32 ptr_is_null = *(CARD32 *)(pc + %s);' % (indent, param.offset - 4)
|
||||
cond = '(ptr_is_null != 0) ? NULL : '
|
||||
else:
|
||||
cond = ""
|
||||
|
||||
|
||||
type_string = param.type_string()
|
||||
|
||||
if param.is_image():
|
||||
offset = f.offset_of( param.name )
|
||||
|
||||
print '%s %s const %s = (%s) %s(pc + %s);' % (indent, type_string, param.name, type_string, cond, offset)
|
||||
|
||||
if param.depth:
|
||||
print '%s __GLXpixel3DHeader * const hdr = (__GLXpixel3DHeader *)(pc);' % (indent)
|
||||
else:
|
||||
print '%s __GLXpixelHeader * const hdr = (__GLXpixelHeader *)(pc);' % (indent)
|
||||
|
||||
need_blank = 1
|
||||
elif param.is_counter or param.name in f.count_parameter_list:
|
||||
location = self.fetch_param(param)
|
||||
print '%s const %s %s = %s;' % (indent, type_string, param.name, location)
|
||||
need_blank = 1
|
||||
elif len(param.count_parameter_list):
|
||||
if param.size() == 1 and not self.do_swap:
|
||||
location = self.fetch_param(param)
|
||||
print '%s %s %s = %s%s;' % (indent, type_string, param.name, cond, location)
|
||||
else:
|
||||
print '%s %s %s;' % (indent, type_string, param.name)
|
||||
need_blank = 1
|
||||
|
||||
|
||||
|
||||
if need_blank:
|
||||
print ''
|
||||
|
||||
if align64:
|
||||
print '#ifdef __GLX_ALIGN64'
|
||||
|
||||
if f.has_variable_size_request():
|
||||
self.emit_packet_size_calculation(f, 4)
|
||||
s = "cmdlen"
|
||||
else:
|
||||
s = str((f.command_fixed_length() + 3) & ~3)
|
||||
|
||||
print ' if ((unsigned long)(pc) & 7) {'
|
||||
print ' (void) memmove(pc-4, pc, %s);' % (s)
|
||||
print ' pc -= 4;'
|
||||
print ' }'
|
||||
print '#endif'
|
||||
print ''
|
||||
|
||||
|
||||
need_blank = 0
|
||||
if self.do_swap:
|
||||
for param in f.parameterIterateGlxSend():
|
||||
if param.count_parameter_list:
|
||||
o = param.offset
|
||||
count = param.get_element_count()
|
||||
type_size = param.size() / count
|
||||
|
||||
if param.counter:
|
||||
count_name = param.counter
|
||||
else:
|
||||
count_name = str(count)
|
||||
|
||||
# This is basically an ugly special-
|
||||
# case for glCallLists.
|
||||
|
||||
if type_size == 1:
|
||||
x = []
|
||||
x.append( [1, ['BYTE', 'UNSIGNED_BYTE', '2_BYTES', '3_BYTES', '4_BYTES']] )
|
||||
x.append( [2, ['SHORT', 'UNSIGNED_SHORT']] )
|
||||
x.append( [4, ['INT', 'UNSIGNED_INT', 'FLOAT']] )
|
||||
|
||||
print ' switch(%s) {' % (param.count_parameter_list[0])
|
||||
for sub in x:
|
||||
for t_name in sub[1]:
|
||||
print ' case GL_%s:' % (t_name)
|
||||
|
||||
if sub[0] == 1:
|
||||
print ' %s = (%s) (pc + %s); break;' % (param.name, param.type_string(), o)
|
||||
else:
|
||||
swap_func = self.swap_name(sub[0])
|
||||
print ' %s = (%s) %s( (%s *) (pc + %s), %s ); break;' % (param.name, param.type_string(), swap_func, self.real_types[sub[0]], o, count_name)
|
||||
print ' }'
|
||||
else:
|
||||
swap_func = self.swap_name(type_size)
|
||||
compsize = self.size_call(f, 1)
|
||||
print ' %s = (%s) %s( (%s *) (pc + %s), %s );' % (param.name, param.type_string(), swap_func, self.real_types[type_size], o, compsize)
|
||||
|
||||
need_blank = 1
|
||||
|
||||
else:
|
||||
for param in f.parameterIterateGlxSend():
|
||||
if param.count_parameter_list:
|
||||
print '%s %s = (%s) (pc + %s);' % (indent, param.name, param.type_string(), param.offset)
|
||||
need_blank = 1
|
||||
|
||||
|
||||
if need_blank:
|
||||
print ''
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
def printSingleFunction(self, f):
|
||||
if f.glx_sop:
|
||||
print ' xGLXSingleReq * const req = (xGLXSingleReq *) pc;'
|
||||
else:
|
||||
print ' xGLXVendorPrivateReq * const req = (xGLXVendorPrivateReq *) pc;'
|
||||
|
||||
print ' int error;'
|
||||
|
||||
if self.do_swap:
|
||||
print ' __GLXcontext * const cx = __glXForceCurrent(cl, bswap_CARD32( &req->contextTag ), &error);'
|
||||
else:
|
||||
print ' __GLXcontext * const cx = __glXForceCurrent(cl, req->contextTag, &error);'
|
||||
|
||||
print ''
|
||||
if f.glx_sop:
|
||||
print ' pc += __GLX_SINGLE_HDR_SIZE;'
|
||||
else:
|
||||
print ' pc += __GLX_VENDPRIV_HDR_SIZE;'
|
||||
|
||||
print ' if ( cx != NULL ) {'
|
||||
self.common_func_print_just_start(f, " ")
|
||||
|
||||
|
||||
if f.return_type != 'void':
|
||||
print ' %s retval;' % (f.return_type)
|
||||
retval_string = "retval"
|
||||
retval_assign = "retval = "
|
||||
else:
|
||||
retval_string = "0"
|
||||
retval_assign = ""
|
||||
|
||||
|
||||
type_size = 0
|
||||
answer_string = "dummy_answer"
|
||||
answer_count = "0"
|
||||
is_array_string = "GL_FALSE"
|
||||
|
||||
for param in f.parameterIterateOutputs():
|
||||
answer_type = param.get_base_type_string()
|
||||
if answer_type == "GLvoid":
|
||||
answer_type = "GLubyte"
|
||||
|
||||
|
||||
c = param.get_element_count()
|
||||
type_size = (param.size() / c)
|
||||
if type_size == 1:
|
||||
size_scale = ""
|
||||
else:
|
||||
size_scale = " * %u" % (type_size)
|
||||
|
||||
|
||||
if param.count_parameter_list:
|
||||
print ' const GLuint compsize = %s;' % (self.size_call(f, 1))
|
||||
print ' %s answerBuffer[200];' % (answer_type)
|
||||
print ' %s %s = __glXGetAnswerBuffer(cl, compsize%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, size_scale, type_size )
|
||||
answer_string = param.name
|
||||
answer_count = "compsize"
|
||||
|
||||
print ''
|
||||
print ' if (%s == NULL) return BadAlloc;' % (param.name)
|
||||
print ' __glXClearErrorOccured();'
|
||||
print ''
|
||||
elif param.counter:
|
||||
print ' %s answerBuffer[200];' % (answer_type)
|
||||
print ' %s %s = __glXGetAnswerBuffer(cl, %s%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, param.counter, size_scale, type_size)
|
||||
answer_string = param.name
|
||||
answer_count = param.counter
|
||||
elif c >= 1:
|
||||
print ' %s %s[%u];' % (answer_type, param.name, c)
|
||||
answer_string = param.name
|
||||
answer_count = "%u" % (c)
|
||||
|
||||
if f.reply_always_array:
|
||||
is_array_string = "GL_TRUE"
|
||||
|
||||
|
||||
self.emit_function_call(f, retval_assign, " ")
|
||||
|
||||
|
||||
if f.needs_reply():
|
||||
if self.do_swap:
|
||||
for param in f.parameterIterateOutputs():
|
||||
c = param.get_element_count()
|
||||
type_size = (param.size() / c)
|
||||
|
||||
if type_size > 1:
|
||||
swap_name = self.swap_name( type_size )
|
||||
print ' (void) %s( (uint%u_t *) %s, %s );' % (swap_name, 8 * type_size, param.name, answer_count)
|
||||
|
||||
|
||||
reply_func = '__glXSendReplySwap'
|
||||
else:
|
||||
reply_func = '__glXSendReply'
|
||||
|
||||
print ' %s(cl->client, %s, %s, %u, %s, %s);' % (reply_func, answer_string, answer_count, type_size, is_array_string, retval_string)
|
||||
#elif f.note_unflushed:
|
||||
# print ' cx->hasUnflushedCommands = GL_TRUE;'
|
||||
|
||||
print ' error = Success;'
|
||||
print ' }'
|
||||
print ''
|
||||
print ' return error;'
|
||||
return
|
||||
|
||||
|
||||
def printRenderFunction(self, f):
|
||||
# There are 4 distinct phases in a rendering dispatch function.
|
||||
# In the first phase we compute the sizes and offsets of each
|
||||
# element in the command. In the second phase we (optionally)
|
||||
# re-align 64-bit data elements. In the third phase we
|
||||
# (optionally) byte-swap array data. Finally, in the fourth
|
||||
# phase we actually dispatch the function.
|
||||
|
||||
self.common_func_print_just_start(f, "")
|
||||
|
||||
images = f.get_images()
|
||||
if len(images):
|
||||
if self.do_swap:
|
||||
pre = "bswap_CARD32( & "
|
||||
post = " )"
|
||||
else:
|
||||
pre = ""
|
||||
post = ""
|
||||
|
||||
img = images[0]
|
||||
|
||||
# swapBytes and lsbFirst are single byte fields, so
|
||||
# the must NEVER be byte-swapped.
|
||||
|
||||
if not (img.img_type == "GL_BITMAP" and img.img_format == "GL_COLOR_INDEX"):
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, hdr->swapBytes) );'
|
||||
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, hdr->lsbFirst) );'
|
||||
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, (GLint) %shdr->rowLength%s) );' % (pre, post)
|
||||
if img.depth:
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_IMAGE_HEIGHT, (GLint) %shdr->imageHeight%s) );' % (pre, post)
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, (GLint) %shdr->skipRows%s) );' % (pre, post)
|
||||
if img.depth:
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_IMAGES, (GLint) %shdr->skipImages%s) );' % (pre, post)
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, (GLint) %shdr->skipPixels%s) );' % (pre, post)
|
||||
print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, (GLint) %shdr->alignment%s) );' % (pre, post)
|
||||
print ''
|
||||
|
||||
|
||||
self.emit_function_call(f, "", "")
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
file_name = "gl_API.xml"
|
||||
|
||||
try:
|
||||
(args, trail) = getopt.getopt(sys.argv[1:], "f:m:s")
|
||||
except Exception,e:
|
||||
show_usage()
|
||||
|
||||
mode = "dispatch_c"
|
||||
do_swap = 0
|
||||
for (arg,val) in args:
|
||||
if arg == "-f":
|
||||
file_name = val
|
||||
elif arg == "-m":
|
||||
mode = val
|
||||
elif arg == "-s":
|
||||
do_swap = 1
|
||||
|
||||
if mode == "dispatch_c":
|
||||
printer = PrintGlxDispatchFunctions(do_swap)
|
||||
elif mode == "dispatch_h":
|
||||
printer = PrintGlxDispatch_h()
|
||||
else:
|
||||
show_usage()
|
||||
|
||||
api = gl_XML.parse_GL_API( file_name, glX_proto_common.glx_proto_item_factory() )
|
||||
|
||||
printer.Print( api )
|
||||
@@ -879,7 +879,7 @@ __GLapi * __glXNewIndirectAPI( void )
|
||||
if first:
|
||||
print ''
|
||||
if show_num:
|
||||
print ' /* % 3u. %s */' % (cat_num, cat_name)
|
||||
print ' /* %3u. %s */' % (cat_num, cat_name)
|
||||
else:
|
||||
print ' /* %s */' % (cat_name)
|
||||
print ''
|
||||
|
||||
@@ -10447,8 +10447,8 @@
|
||||
<function name="GenProgramsNV" offset="582">
|
||||
<param name="n" type="GLsizei" counter="true"/>
|
||||
<param name="programs" type="GLuint *" output="true" count="n"/>
|
||||
<glx vendorpriv="1295"/>
|
||||
</function>
|
||||
<glx vendorpriv="1295" always_array="true"/>
|
||||
</function>
|
||||
|
||||
<!-- This isn't 100% correct. Currently, the only valid value of pname
|
||||
is GL_PROGRAM_PARAMETER_NV, and the count for that pname is always
|
||||
@@ -11498,4 +11498,23 @@
|
||||
</function>
|
||||
</category>
|
||||
|
||||
<category name="GL_EXT_framebuffer_blit" number="316">
|
||||
<enum name="GL_READ_FRAMEBUFFER_EXT" value="0x8CA8"/>
|
||||
<enum name="GL_DRAW_FRAMEBUFFER_EXT" value="0x8CA9"/>
|
||||
<enum name="GL_DRAW_FRAMEBUFFER_BINDING_EXT" value="0x8CA6"/>
|
||||
<enum name="GL_READ_FRAMEBUFFER_BINDING_EXT" value="0x8CAA"/>
|
||||
<function name="BlitFramebufferEXT" offset="818">
|
||||
<param name="srcX0" type="GLint"/>
|
||||
<param name="srcY0" type="GLint"/>
|
||||
<param name="srcX1" type="GLint"/>
|
||||
<param name="srcY1" type="GLint"/>
|
||||
<param name="dstX0" type="GLint"/>
|
||||
<param name="dstY0" type="GLint"/>
|
||||
<param name="dstX1" type="GLint"/>
|
||||
<param name="dstY1" type="GLint"/>
|
||||
<param name="mask" type="GLbitfield"/>
|
||||
<param name="filter" type="GLenum"/>
|
||||
</function>
|
||||
</category>
|
||||
|
||||
</OpenGLAPI>
|
||||
|
||||
@@ -161,7 +161,7 @@ int _mesa_lookup_enum_by_name( const char *symbol )
|
||||
print 'static const enum_elt all_enums[%u] =' % (len(name_table))
|
||||
print '{'
|
||||
for [name, enum] in name_table:
|
||||
print ' { % 5u, 0x%08X }, /* %s */' % (string_offsets[name], enum, name)
|
||||
print ' { %5u, 0x%08X }, /* %s */' % (string_offsets[name], enum, name)
|
||||
print '};'
|
||||
print ''
|
||||
|
||||
@@ -174,7 +174,7 @@ int _mesa_lookup_enum_by_name( const char *symbol )
|
||||
else:
|
||||
i = name_table.index( [name, enum] )
|
||||
|
||||
print ' % 4u, /* %s */' % (i, name)
|
||||
print ' %4u, /* %s */' % (i, name)
|
||||
print '};'
|
||||
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ class PrintGlProcs(gl_XML.gl_print_base):
|
||||
print 'static const glprocs_table_t static_functions[] = {'
|
||||
|
||||
for (offset, disp_name, real_name) in table:
|
||||
print ' NAME_FUNC_OFFSET( % 5u, gl%s, _gloffset_%s ),' % (offset, disp_name, real_name)
|
||||
print ' NAME_FUNC_OFFSET( %5u, gl%s, _gloffset_%s ),' % (offset, disp_name, real_name)
|
||||
|
||||
print ' NAME_FUNC_OFFSET( -1, NULL, 0 )'
|
||||
print '};'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.3
|
||||
* Version: 6.5
|
||||
*
|
||||
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
|
||||
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -54,7 +54,6 @@
|
||||
#include "glapi.h"
|
||||
#include "glapioffsets.h"
|
||||
#include "glapitable.h"
|
||||
#include "glthread.h"
|
||||
|
||||
/***** BEGIN NO-OP DISPATCH *****/
|
||||
|
||||
@@ -287,14 +286,14 @@ _glapi_get_context(void)
|
||||
|
||||
/**
|
||||
* Set the global or per-thread dispatch table pointer.
|
||||
* If the dispatch parameter is NULL we'll plug in the no-op dispatch
|
||||
* table (__glapi_noop_table).
|
||||
*/
|
||||
PUBLIC void
|
||||
_glapi_set_dispatch(struct _glapi_table *dispatch)
|
||||
{
|
||||
#if defined(PTHREADS) || defined(GLX_USE_TLS)
|
||||
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
|
||||
pthread_once( & once_control, init_glapi_relocs );
|
||||
#endif
|
||||
|
||||
@@ -327,7 +326,6 @@ PUBLIC struct _glapi_table *
|
||||
_glapi_get_dispatch(void)
|
||||
{
|
||||
struct _glapi_table * api;
|
||||
|
||||
#if defined(GLX_USE_TLS)
|
||||
api = _glapi_tls_Dispatch;
|
||||
#elif defined(THREADS)
|
||||
@@ -337,13 +335,17 @@ _glapi_get_dispatch(void)
|
||||
#else
|
||||
api = _glapi_Dispatch;
|
||||
#endif
|
||||
|
||||
assert( api != NULL );
|
||||
return api;
|
||||
}
|
||||
|
||||
|
||||
#if !defined( USE_X86_ASM ) && !defined( XFree86Server )
|
||||
|
||||
/***
|
||||
*** The rest of this file is pretty much concerned with GetProcAddress
|
||||
*** functionality.
|
||||
***/
|
||||
|
||||
#if !defined( USE_X86_ASM ) && !defined( XFree86Server ) && !defined ( XGLServer )
|
||||
#define NEED_FUNCTION_POINTER
|
||||
#endif
|
||||
|
||||
@@ -359,13 +361,10 @@ static const glprocs_table_t *
|
||||
find_entry( const char * n )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; static_functions[i].Name_offset >= 0; i++) {
|
||||
const char * test_name;
|
||||
|
||||
test_name = gl_string_table + static_functions[i].Name_offset;
|
||||
if (strcmp(test_name, n) == 0) {
|
||||
return & static_functions[i];
|
||||
const char *testName = gl_string_table + static_functions[i].Name_offset;
|
||||
if (strcmp(testName, n) == 0) {
|
||||
return &static_functions[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -380,15 +379,14 @@ static GLint
|
||||
get_static_proc_offset(const char *funcName)
|
||||
{
|
||||
const glprocs_table_t * const f = find_entry( funcName );
|
||||
|
||||
if ( f != NULL ) {
|
||||
if (f) {
|
||||
return f->Offset;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#if !defined( XFree86Server )
|
||||
#if !defined(XFree86Server) && !defined(XGLServer)
|
||||
#ifdef USE_X86_ASM
|
||||
|
||||
#if defined( GLX_USE_TLS )
|
||||
@@ -404,42 +402,33 @@ extern const GLubyte gl_dispatch_functions_start[];
|
||||
# define X86_DISPATCH_FUNCTION_SIZE 16
|
||||
# endif
|
||||
|
||||
#endif /* USE_X86_ASM */
|
||||
|
||||
|
||||
/**
|
||||
* Return dispatch function address the named static (built-in) function.
|
||||
* Return dispatch function address for the named static (built-in) function.
|
||||
* Return NULL if function not found.
|
||||
*/
|
||||
static const _glapi_proc
|
||||
get_static_proc_address(const char *funcName)
|
||||
{
|
||||
const glprocs_table_t * const f = find_entry( funcName );
|
||||
|
||||
if ( f != NULL ) {
|
||||
if (f) {
|
||||
#ifdef USE_X86_ASM
|
||||
return (_glapi_proc) (gl_dispatch_functions_start
|
||||
+ (X86_DISPATCH_FUNCTION_SIZE * f->Offset));
|
||||
#else
|
||||
return f->Address;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#endif /* !defined(XFree86Server) && !defined(XGLServer) */
|
||||
|
||||
|
||||
/**
|
||||
* Return pointer to the named static (built-in) function.
|
||||
* \return NULL if function not found.
|
||||
*/
|
||||
static const _glapi_proc
|
||||
get_static_proc_address(const char *funcName)
|
||||
{
|
||||
const glprocs_table_t * const f = find_entry( funcName );
|
||||
return ( f != NULL ) ? f->Address : NULL;
|
||||
}
|
||||
|
||||
#endif /* USE_X86_ASM */
|
||||
#endif /* !defined( XFree86Server ) */
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the function at the given offset in the dispatch
|
||||
@@ -449,7 +438,6 @@ static const char *
|
||||
get_static_proc_name( GLuint offset )
|
||||
{
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; static_functions[i].Name_offset >= 0; i++) {
|
||||
if (static_functions[i].Offset == offset) {
|
||||
return gl_string_table + static_functions[i].Name_offset;
|
||||
@@ -579,7 +567,7 @@ generate_entrypoint(GLuint functionOffset)
|
||||
0x81c0c000, /* jmpl %g3, %g0 */
|
||||
0x01000000 /* nop */
|
||||
};
|
||||
#endif
|
||||
#endif /* __arch64__ */
|
||||
unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
|
||||
unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
|
||||
if (code) {
|
||||
@@ -601,7 +589,7 @@ generate_entrypoint(GLuint functionOffset)
|
||||
__glapi_sparc_icache_flush(&code[0]);
|
||||
code[2] |= (functionOffset * 4);
|
||||
__glapi_sparc_icache_flush(&code[2]);
|
||||
#endif
|
||||
#endif /* __arch64__ */
|
||||
}
|
||||
return (_glapi_proc) code;
|
||||
#else
|
||||
@@ -621,7 +609,6 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
|
||||
#if defined(USE_X86_ASM)
|
||||
GLubyte * const code = (GLubyte *) entrypoint;
|
||||
|
||||
|
||||
#if X86_DISPATCH_FUNCTION_SIZE == 32
|
||||
*((unsigned int *)(code + 11)) = 4 * offset;
|
||||
*((unsigned int *)(code + 22)) = 4 * offset;
|
||||
@@ -763,14 +750,8 @@ _glapi_add_dispatch( const char * const * function_names,
|
||||
/* Do some trivial validation on the name of the function.
|
||||
*/
|
||||
|
||||
#ifdef MANGLE
|
||||
if (!function_names[i] || function_names[i][0] != 'm' || function_names[i][1] != 'g' || function_names[i][2] != 'l')
|
||||
return GL_FALSE;
|
||||
#else
|
||||
if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l')
|
||||
return GL_FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine if the named function already exists. If the function does
|
||||
* exist, it must have the same parameter signature as the function
|
||||
@@ -817,13 +798,11 @@ _glapi_add_dispatch( const char * const * function_names,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (offset == ~0) {
|
||||
offset = next_dynamic_offset;
|
||||
next_dynamic_offset++;
|
||||
}
|
||||
|
||||
|
||||
for ( i = 0 ; function_names[i] != NULL ; i++ ) {
|
||||
if (! is_static[i] ) {
|
||||
if (entry[i] == NULL) {
|
||||
@@ -835,7 +814,6 @@ _glapi_add_dispatch( const char * const * function_names,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
entry[i]->parameter_signature = str_dup(real_sig);
|
||||
fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset);
|
||||
entry[i]->dispatch_offset = offset;
|
||||
@@ -859,7 +837,6 @@ _glapi_get_proc_offset(const char *funcName)
|
||||
return ExtEntryTable[i].dispatch_offset;
|
||||
}
|
||||
}
|
||||
|
||||
/* search static functions */
|
||||
return get_static_proc_offset(funcName);
|
||||
}
|
||||
@@ -892,7 +869,7 @@ _glapi_get_proc_address(const char *funcName)
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( XFree86Server )
|
||||
#if !defined( XFree86Server ) && !defined( XGLServer )
|
||||
/* search static functions */
|
||||
{
|
||||
const _glapi_proc func = get_static_proc_address(funcName);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.3
|
||||
* Version: 6.5
|
||||
*
|
||||
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
|
||||
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -47,10 +47,26 @@
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "glapitable.h"
|
||||
#include "glthread.h"
|
||||
|
||||
|
||||
typedef void (*_glapi_warning_func)(void *ctx, const char *str, ...);
|
||||
|
||||
|
||||
#if defined(USE_MGL_NAMESPACE)
|
||||
#define _glapi_set_dispatch _mglapi_set_dispatch
|
||||
#define _glapi_get_dispatch _mglapi_get_dispatch
|
||||
#define _glapi_set_context _mglapi_set_context
|
||||
#define _glapi_get_context _mglapi_get_context
|
||||
#define _glapi_Context _mglapi_Context
|
||||
#define _glapi_Dispatch _mglapi_Dispatch
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
** Define the GET_CURRENT_CONTEXT() macro.
|
||||
** \param C local variable which will hold the current context.
|
||||
**/
|
||||
#if defined (GLX_USE_TLS)
|
||||
|
||||
const extern void *_glapi_Context;
|
||||
@@ -66,19 +82,6 @@ extern __thread void * _glapi_tls_Context
|
||||
extern void *_glapi_Context;
|
||||
extern struct _glapi_table *_glapi_Dispatch;
|
||||
|
||||
/**
|
||||
* Macro for declaration and fetching the current context.
|
||||
*
|
||||
* \param C local variable which will hold the current context.
|
||||
*
|
||||
* It should be used in the variable declaration area of a function:
|
||||
* \code
|
||||
* ...
|
||||
* {
|
||||
* GET_CURRENT_CONTEXT(ctx);
|
||||
* ...
|
||||
* \endcode
|
||||
*/
|
||||
# ifdef THREADS
|
||||
# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context())
|
||||
# else
|
||||
@@ -87,6 +90,11 @@ extern struct _glapi_table *_glapi_Dispatch;
|
||||
|
||||
#endif /* defined (GLX_USE_TLS) */
|
||||
|
||||
|
||||
/**
|
||||
** GL API public functions
|
||||
**/
|
||||
|
||||
extern void
|
||||
_glapi_noop_enable_warnings(GLboolean enable);
|
||||
|
||||
|
||||
@@ -850,7 +850,8 @@
|
||||
#define _gloffset_StencilMaskSeparate 815
|
||||
#define _gloffset_GetQueryObjecti64vEXT 816
|
||||
#define _gloffset_GetQueryObjectui64vEXT 817
|
||||
#define _gloffset_FIRST_DYNAMIC 818
|
||||
#define _gloffset_BlitFramebufferEXT 818
|
||||
#define _gloffset_FIRST_DYNAMIC 819
|
||||
|
||||
#else
|
||||
|
||||
@@ -1264,6 +1265,7 @@
|
||||
#define _gloffset_StencilMaskSeparate driDispatchRemapTable[StencilMaskSeparate_remap_index]
|
||||
#define _gloffset_GetQueryObjecti64vEXT driDispatchRemapTable[GetQueryObjecti64vEXT_remap_index]
|
||||
#define _gloffset_GetQueryObjectui64vEXT driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index]
|
||||
#define _gloffset_BlitFramebufferEXT driDispatchRemapTable[BlitFramebufferEXT_remap_index]
|
||||
|
||||
#endif /* !defined(IN_DRI_DRIVER) */
|
||||
|
||||
|
||||
@@ -855,6 +855,7 @@ struct _glapi_table
|
||||
void (GLAPIENTRYP StencilMaskSeparate)(GLenum face, GLuint mask); /* 815 */
|
||||
void (GLAPIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT * params); /* 816 */
|
||||
void (GLAPIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT * params); /* 817 */
|
||||
void (GLAPIENTRYP BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); /* 818 */
|
||||
};
|
||||
|
||||
#endif /* !defined( _GLAPI_TABLE_H_ ) */
|
||||
|
||||
@@ -5050,6 +5050,11 @@ KEYWORD1 void KEYWORD2 NAME(GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLu
|
||||
DISPATCH(GetQueryObjectui64vEXT, (id, pname, params), (F, "glGetQueryObjectui64vEXT(%d, 0x%x, %p);\n", id, pname, (const void *) params));
|
||||
}
|
||||
|
||||
KEYWORD1 void KEYWORD2 NAME(BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
|
||||
{
|
||||
DISPATCH(BlitFramebufferEXT, (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), (F, "glBlitFramebufferEXT(%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x);\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter));
|
||||
}
|
||||
|
||||
|
||||
#endif /* defined( NAME ) */
|
||||
|
||||
@@ -5882,6 +5887,7 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = {
|
||||
TABLE_ENTRY(StencilMaskSeparate),
|
||||
TABLE_ENTRY(GetQueryObjecti64vEXT),
|
||||
TABLE_ENTRY(GetQueryObjectui64vEXT),
|
||||
TABLE_ENTRY(BlitFramebufferEXT),
|
||||
/* A whole bunch of no-op functions. These might be called
|
||||
* when someone tries to call a dynamically-registered
|
||||
* extension function without a current rendering context.
|
||||
|
||||
@@ -864,6 +864,7 @@ static const char gl_string_table[] =
|
||||
"glStencilMaskSeparate\0"
|
||||
"glGetQueryObjecti64vEXT\0"
|
||||
"glGetQueryObjectui64vEXT\0"
|
||||
"glBlitFramebufferEXT\0"
|
||||
"glArrayElementEXT\0"
|
||||
"glBindTextureEXT\0"
|
||||
"glDrawArraysEXT\0"
|
||||
@@ -1863,184 +1864,185 @@ static const glprocs_table_t static_functions[] = {
|
||||
NAME_FUNC_OFFSET( 14649, glStencilMaskSeparate, _gloffset_StencilMaskSeparate ),
|
||||
NAME_FUNC_OFFSET( 14671, glGetQueryObjecti64vEXT, _gloffset_GetQueryObjecti64vEXT ),
|
||||
NAME_FUNC_OFFSET( 14695, glGetQueryObjectui64vEXT, _gloffset_GetQueryObjectui64vEXT ),
|
||||
NAME_FUNC_OFFSET( 14720, glArrayElementEXT, _gloffset_ArrayElement ),
|
||||
NAME_FUNC_OFFSET( 14738, glBindTextureEXT, _gloffset_BindTexture ),
|
||||
NAME_FUNC_OFFSET( 14755, glDrawArraysEXT, _gloffset_DrawArrays ),
|
||||
NAME_FUNC_OFFSET( 14771, glCopyTexImage1DEXT, _gloffset_CopyTexImage1D ),
|
||||
NAME_FUNC_OFFSET( 14791, glCopyTexImage2DEXT, _gloffset_CopyTexImage2D ),
|
||||
NAME_FUNC_OFFSET( 14811, glCopyTexSubImage1DEXT, _gloffset_CopyTexSubImage1D ),
|
||||
NAME_FUNC_OFFSET( 14834, glCopyTexSubImage2DEXT, _gloffset_CopyTexSubImage2D ),
|
||||
NAME_FUNC_OFFSET( 14857, glDeleteTexturesEXT, _gloffset_DeleteTextures ),
|
||||
NAME_FUNC_OFFSET( 14877, glGetPointervEXT, _gloffset_GetPointerv ),
|
||||
NAME_FUNC_OFFSET( 14894, glPrioritizeTexturesEXT, _gloffset_PrioritizeTextures ),
|
||||
NAME_FUNC_OFFSET( 14918, glTexSubImage1DEXT, _gloffset_TexSubImage1D ),
|
||||
NAME_FUNC_OFFSET( 14937, glTexSubImage2DEXT, _gloffset_TexSubImage2D ),
|
||||
NAME_FUNC_OFFSET( 14956, glBlendColorEXT, _gloffset_BlendColor ),
|
||||
NAME_FUNC_OFFSET( 14972, glBlendEquationEXT, _gloffset_BlendEquation ),
|
||||
NAME_FUNC_OFFSET( 14991, glDrawRangeElementsEXT, _gloffset_DrawRangeElements ),
|
||||
NAME_FUNC_OFFSET( 15014, glColorTableSGI, _gloffset_ColorTable ),
|
||||
NAME_FUNC_OFFSET( 15030, glColorTableEXT, _gloffset_ColorTable ),
|
||||
NAME_FUNC_OFFSET( 15046, glColorTableParameterfvSGI, _gloffset_ColorTableParameterfv ),
|
||||
NAME_FUNC_OFFSET( 15073, glColorTableParameterivSGI, _gloffset_ColorTableParameteriv ),
|
||||
NAME_FUNC_OFFSET( 15100, glCopyColorTableSGI, _gloffset_CopyColorTable ),
|
||||
NAME_FUNC_OFFSET( 15120, glColorSubTableEXT, _gloffset_ColorSubTable ),
|
||||
NAME_FUNC_OFFSET( 15139, glCopyColorSubTableEXT, _gloffset_CopyColorSubTable ),
|
||||
NAME_FUNC_OFFSET( 15162, glConvolutionFilter1DEXT, _gloffset_ConvolutionFilter1D ),
|
||||
NAME_FUNC_OFFSET( 15187, glConvolutionFilter2DEXT, _gloffset_ConvolutionFilter2D ),
|
||||
NAME_FUNC_OFFSET( 15212, glConvolutionParameterfEXT, _gloffset_ConvolutionParameterf ),
|
||||
NAME_FUNC_OFFSET( 15239, glConvolutionParameterfvEXT, _gloffset_ConvolutionParameterfv ),
|
||||
NAME_FUNC_OFFSET( 15267, glConvolutionParameteriEXT, _gloffset_ConvolutionParameteri ),
|
||||
NAME_FUNC_OFFSET( 15294, glConvolutionParameterivEXT, _gloffset_ConvolutionParameteriv ),
|
||||
NAME_FUNC_OFFSET( 15322, glCopyConvolutionFilter1DEXT, _gloffset_CopyConvolutionFilter1D ),
|
||||
NAME_FUNC_OFFSET( 15351, glCopyConvolutionFilter2DEXT, _gloffset_CopyConvolutionFilter2D ),
|
||||
NAME_FUNC_OFFSET( 15380, glSeparableFilter2DEXT, _gloffset_SeparableFilter2D ),
|
||||
NAME_FUNC_OFFSET( 15403, glHistogramEXT, _gloffset_Histogram ),
|
||||
NAME_FUNC_OFFSET( 15418, glMinmaxEXT, _gloffset_Minmax ),
|
||||
NAME_FUNC_OFFSET( 15430, glResetHistogramEXT, _gloffset_ResetHistogram ),
|
||||
NAME_FUNC_OFFSET( 15450, glResetMinmaxEXT, _gloffset_ResetMinmax ),
|
||||
NAME_FUNC_OFFSET( 15467, glTexImage3DEXT, _gloffset_TexImage3D ),
|
||||
NAME_FUNC_OFFSET( 15483, glTexSubImage3DEXT, _gloffset_TexSubImage3D ),
|
||||
NAME_FUNC_OFFSET( 15502, glCopyTexSubImage3DEXT, _gloffset_CopyTexSubImage3D ),
|
||||
NAME_FUNC_OFFSET( 15525, glActiveTexture, _gloffset_ActiveTextureARB ),
|
||||
NAME_FUNC_OFFSET( 15541, glClientActiveTexture, _gloffset_ClientActiveTextureARB ),
|
||||
NAME_FUNC_OFFSET( 15563, glMultiTexCoord1d, _gloffset_MultiTexCoord1dARB ),
|
||||
NAME_FUNC_OFFSET( 15581, glMultiTexCoord1dv, _gloffset_MultiTexCoord1dvARB ),
|
||||
NAME_FUNC_OFFSET( 15600, glMultiTexCoord1f, _gloffset_MultiTexCoord1fARB ),
|
||||
NAME_FUNC_OFFSET( 15618, glMultiTexCoord1fv, _gloffset_MultiTexCoord1fvARB ),
|
||||
NAME_FUNC_OFFSET( 15637, glMultiTexCoord1i, _gloffset_MultiTexCoord1iARB ),
|
||||
NAME_FUNC_OFFSET( 15655, glMultiTexCoord1iv, _gloffset_MultiTexCoord1ivARB ),
|
||||
NAME_FUNC_OFFSET( 15674, glMultiTexCoord1s, _gloffset_MultiTexCoord1sARB ),
|
||||
NAME_FUNC_OFFSET( 15692, glMultiTexCoord1sv, _gloffset_MultiTexCoord1svARB ),
|
||||
NAME_FUNC_OFFSET( 15711, glMultiTexCoord2d, _gloffset_MultiTexCoord2dARB ),
|
||||
NAME_FUNC_OFFSET( 15729, glMultiTexCoord2dv, _gloffset_MultiTexCoord2dvARB ),
|
||||
NAME_FUNC_OFFSET( 15748, glMultiTexCoord2f, _gloffset_MultiTexCoord2fARB ),
|
||||
NAME_FUNC_OFFSET( 15766, glMultiTexCoord2fv, _gloffset_MultiTexCoord2fvARB ),
|
||||
NAME_FUNC_OFFSET( 15785, glMultiTexCoord2i, _gloffset_MultiTexCoord2iARB ),
|
||||
NAME_FUNC_OFFSET( 15803, glMultiTexCoord2iv, _gloffset_MultiTexCoord2ivARB ),
|
||||
NAME_FUNC_OFFSET( 15822, glMultiTexCoord2s, _gloffset_MultiTexCoord2sARB ),
|
||||
NAME_FUNC_OFFSET( 15840, glMultiTexCoord2sv, _gloffset_MultiTexCoord2svARB ),
|
||||
NAME_FUNC_OFFSET( 15859, glMultiTexCoord3d, _gloffset_MultiTexCoord3dARB ),
|
||||
NAME_FUNC_OFFSET( 15877, glMultiTexCoord3dv, _gloffset_MultiTexCoord3dvARB ),
|
||||
NAME_FUNC_OFFSET( 15896, glMultiTexCoord3f, _gloffset_MultiTexCoord3fARB ),
|
||||
NAME_FUNC_OFFSET( 15914, glMultiTexCoord3fv, _gloffset_MultiTexCoord3fvARB ),
|
||||
NAME_FUNC_OFFSET( 15933, glMultiTexCoord3i, _gloffset_MultiTexCoord3iARB ),
|
||||
NAME_FUNC_OFFSET( 15951, glMultiTexCoord3iv, _gloffset_MultiTexCoord3ivARB ),
|
||||
NAME_FUNC_OFFSET( 15970, glMultiTexCoord3s, _gloffset_MultiTexCoord3sARB ),
|
||||
NAME_FUNC_OFFSET( 15988, glMultiTexCoord3sv, _gloffset_MultiTexCoord3svARB ),
|
||||
NAME_FUNC_OFFSET( 16007, glMultiTexCoord4d, _gloffset_MultiTexCoord4dARB ),
|
||||
NAME_FUNC_OFFSET( 16025, glMultiTexCoord4dv, _gloffset_MultiTexCoord4dvARB ),
|
||||
NAME_FUNC_OFFSET( 16044, glMultiTexCoord4f, _gloffset_MultiTexCoord4fARB ),
|
||||
NAME_FUNC_OFFSET( 16062, glMultiTexCoord4fv, _gloffset_MultiTexCoord4fvARB ),
|
||||
NAME_FUNC_OFFSET( 16081, glMultiTexCoord4i, _gloffset_MultiTexCoord4iARB ),
|
||||
NAME_FUNC_OFFSET( 16099, glMultiTexCoord4iv, _gloffset_MultiTexCoord4ivARB ),
|
||||
NAME_FUNC_OFFSET( 16118, glMultiTexCoord4s, _gloffset_MultiTexCoord4sARB ),
|
||||
NAME_FUNC_OFFSET( 16136, glMultiTexCoord4sv, _gloffset_MultiTexCoord4svARB ),
|
||||
NAME_FUNC_OFFSET( 16155, glLoadTransposeMatrixf, _gloffset_LoadTransposeMatrixfARB ),
|
||||
NAME_FUNC_OFFSET( 16178, glLoadTransposeMatrixd, _gloffset_LoadTransposeMatrixdARB ),
|
||||
NAME_FUNC_OFFSET( 16201, glMultTransposeMatrixf, _gloffset_MultTransposeMatrixfARB ),
|
||||
NAME_FUNC_OFFSET( 16224, glMultTransposeMatrixd, _gloffset_MultTransposeMatrixdARB ),
|
||||
NAME_FUNC_OFFSET( 16247, glSampleCoverage, _gloffset_SampleCoverageARB ),
|
||||
NAME_FUNC_OFFSET( 16264, glDrawBuffersATI, _gloffset_DrawBuffersARB ),
|
||||
NAME_FUNC_OFFSET( 16281, glSampleMaskEXT, _gloffset_SampleMaskSGIS ),
|
||||
NAME_FUNC_OFFSET( 16297, glSamplePatternEXT, _gloffset_SamplePatternSGIS ),
|
||||
NAME_FUNC_OFFSET( 16316, glPointParameterf, _gloffset_PointParameterfEXT ),
|
||||
NAME_FUNC_OFFSET( 16334, glPointParameterfARB, _gloffset_PointParameterfEXT ),
|
||||
NAME_FUNC_OFFSET( 16355, glPointParameterfSGIS, _gloffset_PointParameterfEXT ),
|
||||
NAME_FUNC_OFFSET( 16377, glPointParameterfv, _gloffset_PointParameterfvEXT ),
|
||||
NAME_FUNC_OFFSET( 16396, glPointParameterfvARB, _gloffset_PointParameterfvEXT ),
|
||||
NAME_FUNC_OFFSET( 16418, glPointParameterfvSGIS, _gloffset_PointParameterfvEXT ),
|
||||
NAME_FUNC_OFFSET( 16441, glWindowPos2d, _gloffset_WindowPos2dMESA ),
|
||||
NAME_FUNC_OFFSET( 16455, glWindowPos2dARB, _gloffset_WindowPos2dMESA ),
|
||||
NAME_FUNC_OFFSET( 16472, glWindowPos2dv, _gloffset_WindowPos2dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16487, glWindowPos2dvARB, _gloffset_WindowPos2dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16505, glWindowPos2f, _gloffset_WindowPos2fMESA ),
|
||||
NAME_FUNC_OFFSET( 16519, glWindowPos2fARB, _gloffset_WindowPos2fMESA ),
|
||||
NAME_FUNC_OFFSET( 16536, glWindowPos2fv, _gloffset_WindowPos2fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16551, glWindowPos2fvARB, _gloffset_WindowPos2fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16569, glWindowPos2i, _gloffset_WindowPos2iMESA ),
|
||||
NAME_FUNC_OFFSET( 16583, glWindowPos2iARB, _gloffset_WindowPos2iMESA ),
|
||||
NAME_FUNC_OFFSET( 16600, glWindowPos2iv, _gloffset_WindowPos2ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16615, glWindowPos2ivARB, _gloffset_WindowPos2ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16633, glWindowPos2s, _gloffset_WindowPos2sMESA ),
|
||||
NAME_FUNC_OFFSET( 16647, glWindowPos2sARB, _gloffset_WindowPos2sMESA ),
|
||||
NAME_FUNC_OFFSET( 16664, glWindowPos2sv, _gloffset_WindowPos2svMESA ),
|
||||
NAME_FUNC_OFFSET( 16679, glWindowPos2svARB, _gloffset_WindowPos2svMESA ),
|
||||
NAME_FUNC_OFFSET( 16697, glWindowPos3d, _gloffset_WindowPos3dMESA ),
|
||||
NAME_FUNC_OFFSET( 16711, glWindowPos3dARB, _gloffset_WindowPos3dMESA ),
|
||||
NAME_FUNC_OFFSET( 16728, glWindowPos3dv, _gloffset_WindowPos3dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16743, glWindowPos3dvARB, _gloffset_WindowPos3dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16761, glWindowPos3f, _gloffset_WindowPos3fMESA ),
|
||||
NAME_FUNC_OFFSET( 16775, glWindowPos3fARB, _gloffset_WindowPos3fMESA ),
|
||||
NAME_FUNC_OFFSET( 16792, glWindowPos3fv, _gloffset_WindowPos3fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16807, glWindowPos3fvARB, _gloffset_WindowPos3fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16825, glWindowPos3i, _gloffset_WindowPos3iMESA ),
|
||||
NAME_FUNC_OFFSET( 16839, glWindowPos3iARB, _gloffset_WindowPos3iMESA ),
|
||||
NAME_FUNC_OFFSET( 16856, glWindowPos3iv, _gloffset_WindowPos3ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16871, glWindowPos3ivARB, _gloffset_WindowPos3ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16889, glWindowPos3s, _gloffset_WindowPos3sMESA ),
|
||||
NAME_FUNC_OFFSET( 16903, glWindowPos3sARB, _gloffset_WindowPos3sMESA ),
|
||||
NAME_FUNC_OFFSET( 16920, glWindowPos3sv, _gloffset_WindowPos3svMESA ),
|
||||
NAME_FUNC_OFFSET( 16935, glWindowPos3svARB, _gloffset_WindowPos3svMESA ),
|
||||
NAME_FUNC_OFFSET( 16953, glBlendFuncSeparate, _gloffset_BlendFuncSeparateEXT ),
|
||||
NAME_FUNC_OFFSET( 16973, glBlendFuncSeparateINGR, _gloffset_BlendFuncSeparateEXT ),
|
||||
NAME_FUNC_OFFSET( 16997, glFogCoordf, _gloffset_FogCoordfEXT ),
|
||||
NAME_FUNC_OFFSET( 17009, glFogCoordfv, _gloffset_FogCoordfvEXT ),
|
||||
NAME_FUNC_OFFSET( 17022, glFogCoordd, _gloffset_FogCoorddEXT ),
|
||||
NAME_FUNC_OFFSET( 17034, glFogCoorddv, _gloffset_FogCoorddvEXT ),
|
||||
NAME_FUNC_OFFSET( 17047, glFogCoordPointer, _gloffset_FogCoordPointerEXT ),
|
||||
NAME_FUNC_OFFSET( 17065, glCompressedTexImage3D, _gloffset_CompressedTexImage3DARB ),
|
||||
NAME_FUNC_OFFSET( 17088, glCompressedTexImage2D, _gloffset_CompressedTexImage2DARB ),
|
||||
NAME_FUNC_OFFSET( 17111, glCompressedTexImage1D, _gloffset_CompressedTexImage1DARB ),
|
||||
NAME_FUNC_OFFSET( 17134, glCompressedTexSubImage3D, _gloffset_CompressedTexSubImage3DARB ),
|
||||
NAME_FUNC_OFFSET( 17160, glCompressedTexSubImage2D, _gloffset_CompressedTexSubImage2DARB ),
|
||||
NAME_FUNC_OFFSET( 17186, glCompressedTexSubImage1D, _gloffset_CompressedTexSubImage1DARB ),
|
||||
NAME_FUNC_OFFSET( 17212, glGetCompressedTexImage, _gloffset_GetCompressedTexImageARB ),
|
||||
NAME_FUNC_OFFSET( 17236, glSecondaryColor3b, _gloffset_SecondaryColor3bEXT ),
|
||||
NAME_FUNC_OFFSET( 17255, glSecondaryColor3bv, _gloffset_SecondaryColor3bvEXT ),
|
||||
NAME_FUNC_OFFSET( 17275, glSecondaryColor3d, _gloffset_SecondaryColor3dEXT ),
|
||||
NAME_FUNC_OFFSET( 17294, glSecondaryColor3dv, _gloffset_SecondaryColor3dvEXT ),
|
||||
NAME_FUNC_OFFSET( 17314, glSecondaryColor3f, _gloffset_SecondaryColor3fEXT ),
|
||||
NAME_FUNC_OFFSET( 17333, glSecondaryColor3fv, _gloffset_SecondaryColor3fvEXT ),
|
||||
NAME_FUNC_OFFSET( 17353, glSecondaryColor3i, _gloffset_SecondaryColor3iEXT ),
|
||||
NAME_FUNC_OFFSET( 17372, glSecondaryColor3iv, _gloffset_SecondaryColor3ivEXT ),
|
||||
NAME_FUNC_OFFSET( 17392, glSecondaryColor3s, _gloffset_SecondaryColor3sEXT ),
|
||||
NAME_FUNC_OFFSET( 17411, glSecondaryColor3sv, _gloffset_SecondaryColor3svEXT ),
|
||||
NAME_FUNC_OFFSET( 17431, glSecondaryColor3ub, _gloffset_SecondaryColor3ubEXT ),
|
||||
NAME_FUNC_OFFSET( 17451, glSecondaryColor3ubv, _gloffset_SecondaryColor3ubvEXT ),
|
||||
NAME_FUNC_OFFSET( 17472, glSecondaryColor3ui, _gloffset_SecondaryColor3uiEXT ),
|
||||
NAME_FUNC_OFFSET( 17492, glSecondaryColor3uiv, _gloffset_SecondaryColor3uivEXT ),
|
||||
NAME_FUNC_OFFSET( 17513, glSecondaryColor3us, _gloffset_SecondaryColor3usEXT ),
|
||||
NAME_FUNC_OFFSET( 17533, glSecondaryColor3usv, _gloffset_SecondaryColor3usvEXT ),
|
||||
NAME_FUNC_OFFSET( 17554, glSecondaryColorPointer, _gloffset_SecondaryColorPointerEXT ),
|
||||
NAME_FUNC_OFFSET( 17578, glBindProgramARB, _gloffset_BindProgramNV ),
|
||||
NAME_FUNC_OFFSET( 17595, glDeleteProgramsARB, _gloffset_DeleteProgramsNV ),
|
||||
NAME_FUNC_OFFSET( 17615, glGenProgramsARB, _gloffset_GenProgramsNV ),
|
||||
NAME_FUNC_OFFSET( 17632, glGetVertexAttribPointervARB, _gloffset_GetVertexAttribPointervNV ),
|
||||
NAME_FUNC_OFFSET( 17661, glIsProgramARB, _gloffset_IsProgramNV ),
|
||||
NAME_FUNC_OFFSET( 17676, glPointParameteri, _gloffset_PointParameteriNV ),
|
||||
NAME_FUNC_OFFSET( 17694, glPointParameteriv, _gloffset_PointParameterivNV ),
|
||||
NAME_FUNC_OFFSET( 17713, glMultiDrawArrays, _gloffset_MultiDrawArraysEXT ),
|
||||
NAME_FUNC_OFFSET( 17731, glMultiDrawElements, _gloffset_MultiDrawElementsEXT ),
|
||||
NAME_FUNC_OFFSET( 17751, glBindBuffer, _gloffset_BindBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17764, glBufferData, _gloffset_BufferDataARB ),
|
||||
NAME_FUNC_OFFSET( 17777, glBufferSubData, _gloffset_BufferSubDataARB ),
|
||||
NAME_FUNC_OFFSET( 17793, glDeleteBuffers, _gloffset_DeleteBuffersARB ),
|
||||
NAME_FUNC_OFFSET( 17809, glGenBuffers, _gloffset_GenBuffersARB ),
|
||||
NAME_FUNC_OFFSET( 17822, glGetBufferParameteriv, _gloffset_GetBufferParameterivARB ),
|
||||
NAME_FUNC_OFFSET( 17845, glGetBufferPointerv, _gloffset_GetBufferPointervARB ),
|
||||
NAME_FUNC_OFFSET( 17865, glGetBufferSubData, _gloffset_GetBufferSubDataARB ),
|
||||
NAME_FUNC_OFFSET( 17884, glIsBuffer, _gloffset_IsBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17895, glMapBuffer, _gloffset_MapBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17907, glUnmapBuffer, _gloffset_UnmapBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17921, glGenQueries, _gloffset_GenQueriesARB ),
|
||||
NAME_FUNC_OFFSET( 17934, glDeleteQueries, _gloffset_DeleteQueriesARB ),
|
||||
NAME_FUNC_OFFSET( 17950, glIsQuery, _gloffset_IsQueryARB ),
|
||||
NAME_FUNC_OFFSET( 17960, glBeginQuery, _gloffset_BeginQueryARB ),
|
||||
NAME_FUNC_OFFSET( 17973, glEndQuery, _gloffset_EndQueryARB ),
|
||||
NAME_FUNC_OFFSET( 17984, glGetQueryiv, _gloffset_GetQueryivARB ),
|
||||
NAME_FUNC_OFFSET( 17997, glGetQueryObjectiv, _gloffset_GetQueryObjectivARB ),
|
||||
NAME_FUNC_OFFSET( 18016, glGetQueryObjectuiv, _gloffset_GetQueryObjectuivARB ),
|
||||
NAME_FUNC_OFFSET( 18036, glBlendEquationSeparateATI, _gloffset_BlendEquationSeparateEXT ),
|
||||
NAME_FUNC_OFFSET( 14720, glBlitFramebufferEXT, _gloffset_BlitFramebufferEXT ),
|
||||
NAME_FUNC_OFFSET( 14741, glArrayElementEXT, _gloffset_ArrayElement ),
|
||||
NAME_FUNC_OFFSET( 14759, glBindTextureEXT, _gloffset_BindTexture ),
|
||||
NAME_FUNC_OFFSET( 14776, glDrawArraysEXT, _gloffset_DrawArrays ),
|
||||
NAME_FUNC_OFFSET( 14792, glCopyTexImage1DEXT, _gloffset_CopyTexImage1D ),
|
||||
NAME_FUNC_OFFSET( 14812, glCopyTexImage2DEXT, _gloffset_CopyTexImage2D ),
|
||||
NAME_FUNC_OFFSET( 14832, glCopyTexSubImage1DEXT, _gloffset_CopyTexSubImage1D ),
|
||||
NAME_FUNC_OFFSET( 14855, glCopyTexSubImage2DEXT, _gloffset_CopyTexSubImage2D ),
|
||||
NAME_FUNC_OFFSET( 14878, glDeleteTexturesEXT, _gloffset_DeleteTextures ),
|
||||
NAME_FUNC_OFFSET( 14898, glGetPointervEXT, _gloffset_GetPointerv ),
|
||||
NAME_FUNC_OFFSET( 14915, glPrioritizeTexturesEXT, _gloffset_PrioritizeTextures ),
|
||||
NAME_FUNC_OFFSET( 14939, glTexSubImage1DEXT, _gloffset_TexSubImage1D ),
|
||||
NAME_FUNC_OFFSET( 14958, glTexSubImage2DEXT, _gloffset_TexSubImage2D ),
|
||||
NAME_FUNC_OFFSET( 14977, glBlendColorEXT, _gloffset_BlendColor ),
|
||||
NAME_FUNC_OFFSET( 14993, glBlendEquationEXT, _gloffset_BlendEquation ),
|
||||
NAME_FUNC_OFFSET( 15012, glDrawRangeElementsEXT, _gloffset_DrawRangeElements ),
|
||||
NAME_FUNC_OFFSET( 15035, glColorTableSGI, _gloffset_ColorTable ),
|
||||
NAME_FUNC_OFFSET( 15051, glColorTableEXT, _gloffset_ColorTable ),
|
||||
NAME_FUNC_OFFSET( 15067, glColorTableParameterfvSGI, _gloffset_ColorTableParameterfv ),
|
||||
NAME_FUNC_OFFSET( 15094, glColorTableParameterivSGI, _gloffset_ColorTableParameteriv ),
|
||||
NAME_FUNC_OFFSET( 15121, glCopyColorTableSGI, _gloffset_CopyColorTable ),
|
||||
NAME_FUNC_OFFSET( 15141, glColorSubTableEXT, _gloffset_ColorSubTable ),
|
||||
NAME_FUNC_OFFSET( 15160, glCopyColorSubTableEXT, _gloffset_CopyColorSubTable ),
|
||||
NAME_FUNC_OFFSET( 15183, glConvolutionFilter1DEXT, _gloffset_ConvolutionFilter1D ),
|
||||
NAME_FUNC_OFFSET( 15208, glConvolutionFilter2DEXT, _gloffset_ConvolutionFilter2D ),
|
||||
NAME_FUNC_OFFSET( 15233, glConvolutionParameterfEXT, _gloffset_ConvolutionParameterf ),
|
||||
NAME_FUNC_OFFSET( 15260, glConvolutionParameterfvEXT, _gloffset_ConvolutionParameterfv ),
|
||||
NAME_FUNC_OFFSET( 15288, glConvolutionParameteriEXT, _gloffset_ConvolutionParameteri ),
|
||||
NAME_FUNC_OFFSET( 15315, glConvolutionParameterivEXT, _gloffset_ConvolutionParameteriv ),
|
||||
NAME_FUNC_OFFSET( 15343, glCopyConvolutionFilter1DEXT, _gloffset_CopyConvolutionFilter1D ),
|
||||
NAME_FUNC_OFFSET( 15372, glCopyConvolutionFilter2DEXT, _gloffset_CopyConvolutionFilter2D ),
|
||||
NAME_FUNC_OFFSET( 15401, glSeparableFilter2DEXT, _gloffset_SeparableFilter2D ),
|
||||
NAME_FUNC_OFFSET( 15424, glHistogramEXT, _gloffset_Histogram ),
|
||||
NAME_FUNC_OFFSET( 15439, glMinmaxEXT, _gloffset_Minmax ),
|
||||
NAME_FUNC_OFFSET( 15451, glResetHistogramEXT, _gloffset_ResetHistogram ),
|
||||
NAME_FUNC_OFFSET( 15471, glResetMinmaxEXT, _gloffset_ResetMinmax ),
|
||||
NAME_FUNC_OFFSET( 15488, glTexImage3DEXT, _gloffset_TexImage3D ),
|
||||
NAME_FUNC_OFFSET( 15504, glTexSubImage3DEXT, _gloffset_TexSubImage3D ),
|
||||
NAME_FUNC_OFFSET( 15523, glCopyTexSubImage3DEXT, _gloffset_CopyTexSubImage3D ),
|
||||
NAME_FUNC_OFFSET( 15546, glActiveTexture, _gloffset_ActiveTextureARB ),
|
||||
NAME_FUNC_OFFSET( 15562, glClientActiveTexture, _gloffset_ClientActiveTextureARB ),
|
||||
NAME_FUNC_OFFSET( 15584, glMultiTexCoord1d, _gloffset_MultiTexCoord1dARB ),
|
||||
NAME_FUNC_OFFSET( 15602, glMultiTexCoord1dv, _gloffset_MultiTexCoord1dvARB ),
|
||||
NAME_FUNC_OFFSET( 15621, glMultiTexCoord1f, _gloffset_MultiTexCoord1fARB ),
|
||||
NAME_FUNC_OFFSET( 15639, glMultiTexCoord1fv, _gloffset_MultiTexCoord1fvARB ),
|
||||
NAME_FUNC_OFFSET( 15658, glMultiTexCoord1i, _gloffset_MultiTexCoord1iARB ),
|
||||
NAME_FUNC_OFFSET( 15676, glMultiTexCoord1iv, _gloffset_MultiTexCoord1ivARB ),
|
||||
NAME_FUNC_OFFSET( 15695, glMultiTexCoord1s, _gloffset_MultiTexCoord1sARB ),
|
||||
NAME_FUNC_OFFSET( 15713, glMultiTexCoord1sv, _gloffset_MultiTexCoord1svARB ),
|
||||
NAME_FUNC_OFFSET( 15732, glMultiTexCoord2d, _gloffset_MultiTexCoord2dARB ),
|
||||
NAME_FUNC_OFFSET( 15750, glMultiTexCoord2dv, _gloffset_MultiTexCoord2dvARB ),
|
||||
NAME_FUNC_OFFSET( 15769, glMultiTexCoord2f, _gloffset_MultiTexCoord2fARB ),
|
||||
NAME_FUNC_OFFSET( 15787, glMultiTexCoord2fv, _gloffset_MultiTexCoord2fvARB ),
|
||||
NAME_FUNC_OFFSET( 15806, glMultiTexCoord2i, _gloffset_MultiTexCoord2iARB ),
|
||||
NAME_FUNC_OFFSET( 15824, glMultiTexCoord2iv, _gloffset_MultiTexCoord2ivARB ),
|
||||
NAME_FUNC_OFFSET( 15843, glMultiTexCoord2s, _gloffset_MultiTexCoord2sARB ),
|
||||
NAME_FUNC_OFFSET( 15861, glMultiTexCoord2sv, _gloffset_MultiTexCoord2svARB ),
|
||||
NAME_FUNC_OFFSET( 15880, glMultiTexCoord3d, _gloffset_MultiTexCoord3dARB ),
|
||||
NAME_FUNC_OFFSET( 15898, glMultiTexCoord3dv, _gloffset_MultiTexCoord3dvARB ),
|
||||
NAME_FUNC_OFFSET( 15917, glMultiTexCoord3f, _gloffset_MultiTexCoord3fARB ),
|
||||
NAME_FUNC_OFFSET( 15935, glMultiTexCoord3fv, _gloffset_MultiTexCoord3fvARB ),
|
||||
NAME_FUNC_OFFSET( 15954, glMultiTexCoord3i, _gloffset_MultiTexCoord3iARB ),
|
||||
NAME_FUNC_OFFSET( 15972, glMultiTexCoord3iv, _gloffset_MultiTexCoord3ivARB ),
|
||||
NAME_FUNC_OFFSET( 15991, glMultiTexCoord3s, _gloffset_MultiTexCoord3sARB ),
|
||||
NAME_FUNC_OFFSET( 16009, glMultiTexCoord3sv, _gloffset_MultiTexCoord3svARB ),
|
||||
NAME_FUNC_OFFSET( 16028, glMultiTexCoord4d, _gloffset_MultiTexCoord4dARB ),
|
||||
NAME_FUNC_OFFSET( 16046, glMultiTexCoord4dv, _gloffset_MultiTexCoord4dvARB ),
|
||||
NAME_FUNC_OFFSET( 16065, glMultiTexCoord4f, _gloffset_MultiTexCoord4fARB ),
|
||||
NAME_FUNC_OFFSET( 16083, glMultiTexCoord4fv, _gloffset_MultiTexCoord4fvARB ),
|
||||
NAME_FUNC_OFFSET( 16102, glMultiTexCoord4i, _gloffset_MultiTexCoord4iARB ),
|
||||
NAME_FUNC_OFFSET( 16120, glMultiTexCoord4iv, _gloffset_MultiTexCoord4ivARB ),
|
||||
NAME_FUNC_OFFSET( 16139, glMultiTexCoord4s, _gloffset_MultiTexCoord4sARB ),
|
||||
NAME_FUNC_OFFSET( 16157, glMultiTexCoord4sv, _gloffset_MultiTexCoord4svARB ),
|
||||
NAME_FUNC_OFFSET( 16176, glLoadTransposeMatrixf, _gloffset_LoadTransposeMatrixfARB ),
|
||||
NAME_FUNC_OFFSET( 16199, glLoadTransposeMatrixd, _gloffset_LoadTransposeMatrixdARB ),
|
||||
NAME_FUNC_OFFSET( 16222, glMultTransposeMatrixf, _gloffset_MultTransposeMatrixfARB ),
|
||||
NAME_FUNC_OFFSET( 16245, glMultTransposeMatrixd, _gloffset_MultTransposeMatrixdARB ),
|
||||
NAME_FUNC_OFFSET( 16268, glSampleCoverage, _gloffset_SampleCoverageARB ),
|
||||
NAME_FUNC_OFFSET( 16285, glDrawBuffersATI, _gloffset_DrawBuffersARB ),
|
||||
NAME_FUNC_OFFSET( 16302, glSampleMaskEXT, _gloffset_SampleMaskSGIS ),
|
||||
NAME_FUNC_OFFSET( 16318, glSamplePatternEXT, _gloffset_SamplePatternSGIS ),
|
||||
NAME_FUNC_OFFSET( 16337, glPointParameterf, _gloffset_PointParameterfEXT ),
|
||||
NAME_FUNC_OFFSET( 16355, glPointParameterfARB, _gloffset_PointParameterfEXT ),
|
||||
NAME_FUNC_OFFSET( 16376, glPointParameterfSGIS, _gloffset_PointParameterfEXT ),
|
||||
NAME_FUNC_OFFSET( 16398, glPointParameterfv, _gloffset_PointParameterfvEXT ),
|
||||
NAME_FUNC_OFFSET( 16417, glPointParameterfvARB, _gloffset_PointParameterfvEXT ),
|
||||
NAME_FUNC_OFFSET( 16439, glPointParameterfvSGIS, _gloffset_PointParameterfvEXT ),
|
||||
NAME_FUNC_OFFSET( 16462, glWindowPos2d, _gloffset_WindowPos2dMESA ),
|
||||
NAME_FUNC_OFFSET( 16476, glWindowPos2dARB, _gloffset_WindowPos2dMESA ),
|
||||
NAME_FUNC_OFFSET( 16493, glWindowPos2dv, _gloffset_WindowPos2dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16508, glWindowPos2dvARB, _gloffset_WindowPos2dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16526, glWindowPos2f, _gloffset_WindowPos2fMESA ),
|
||||
NAME_FUNC_OFFSET( 16540, glWindowPos2fARB, _gloffset_WindowPos2fMESA ),
|
||||
NAME_FUNC_OFFSET( 16557, glWindowPos2fv, _gloffset_WindowPos2fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16572, glWindowPos2fvARB, _gloffset_WindowPos2fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16590, glWindowPos2i, _gloffset_WindowPos2iMESA ),
|
||||
NAME_FUNC_OFFSET( 16604, glWindowPos2iARB, _gloffset_WindowPos2iMESA ),
|
||||
NAME_FUNC_OFFSET( 16621, glWindowPos2iv, _gloffset_WindowPos2ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16636, glWindowPos2ivARB, _gloffset_WindowPos2ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16654, glWindowPos2s, _gloffset_WindowPos2sMESA ),
|
||||
NAME_FUNC_OFFSET( 16668, glWindowPos2sARB, _gloffset_WindowPos2sMESA ),
|
||||
NAME_FUNC_OFFSET( 16685, glWindowPos2sv, _gloffset_WindowPos2svMESA ),
|
||||
NAME_FUNC_OFFSET( 16700, glWindowPos2svARB, _gloffset_WindowPos2svMESA ),
|
||||
NAME_FUNC_OFFSET( 16718, glWindowPos3d, _gloffset_WindowPos3dMESA ),
|
||||
NAME_FUNC_OFFSET( 16732, glWindowPos3dARB, _gloffset_WindowPos3dMESA ),
|
||||
NAME_FUNC_OFFSET( 16749, glWindowPos3dv, _gloffset_WindowPos3dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16764, glWindowPos3dvARB, _gloffset_WindowPos3dvMESA ),
|
||||
NAME_FUNC_OFFSET( 16782, glWindowPos3f, _gloffset_WindowPos3fMESA ),
|
||||
NAME_FUNC_OFFSET( 16796, glWindowPos3fARB, _gloffset_WindowPos3fMESA ),
|
||||
NAME_FUNC_OFFSET( 16813, glWindowPos3fv, _gloffset_WindowPos3fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16828, glWindowPos3fvARB, _gloffset_WindowPos3fvMESA ),
|
||||
NAME_FUNC_OFFSET( 16846, glWindowPos3i, _gloffset_WindowPos3iMESA ),
|
||||
NAME_FUNC_OFFSET( 16860, glWindowPos3iARB, _gloffset_WindowPos3iMESA ),
|
||||
NAME_FUNC_OFFSET( 16877, glWindowPos3iv, _gloffset_WindowPos3ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16892, glWindowPos3ivARB, _gloffset_WindowPos3ivMESA ),
|
||||
NAME_FUNC_OFFSET( 16910, glWindowPos3s, _gloffset_WindowPos3sMESA ),
|
||||
NAME_FUNC_OFFSET( 16924, glWindowPos3sARB, _gloffset_WindowPos3sMESA ),
|
||||
NAME_FUNC_OFFSET( 16941, glWindowPos3sv, _gloffset_WindowPos3svMESA ),
|
||||
NAME_FUNC_OFFSET( 16956, glWindowPos3svARB, _gloffset_WindowPos3svMESA ),
|
||||
NAME_FUNC_OFFSET( 16974, glBlendFuncSeparate, _gloffset_BlendFuncSeparateEXT ),
|
||||
NAME_FUNC_OFFSET( 16994, glBlendFuncSeparateINGR, _gloffset_BlendFuncSeparateEXT ),
|
||||
NAME_FUNC_OFFSET( 17018, glFogCoordf, _gloffset_FogCoordfEXT ),
|
||||
NAME_FUNC_OFFSET( 17030, glFogCoordfv, _gloffset_FogCoordfvEXT ),
|
||||
NAME_FUNC_OFFSET( 17043, glFogCoordd, _gloffset_FogCoorddEXT ),
|
||||
NAME_FUNC_OFFSET( 17055, glFogCoorddv, _gloffset_FogCoorddvEXT ),
|
||||
NAME_FUNC_OFFSET( 17068, glFogCoordPointer, _gloffset_FogCoordPointerEXT ),
|
||||
NAME_FUNC_OFFSET( 17086, glCompressedTexImage3D, _gloffset_CompressedTexImage3DARB ),
|
||||
NAME_FUNC_OFFSET( 17109, glCompressedTexImage2D, _gloffset_CompressedTexImage2DARB ),
|
||||
NAME_FUNC_OFFSET( 17132, glCompressedTexImage1D, _gloffset_CompressedTexImage1DARB ),
|
||||
NAME_FUNC_OFFSET( 17155, glCompressedTexSubImage3D, _gloffset_CompressedTexSubImage3DARB ),
|
||||
NAME_FUNC_OFFSET( 17181, glCompressedTexSubImage2D, _gloffset_CompressedTexSubImage2DARB ),
|
||||
NAME_FUNC_OFFSET( 17207, glCompressedTexSubImage1D, _gloffset_CompressedTexSubImage1DARB ),
|
||||
NAME_FUNC_OFFSET( 17233, glGetCompressedTexImage, _gloffset_GetCompressedTexImageARB ),
|
||||
NAME_FUNC_OFFSET( 17257, glSecondaryColor3b, _gloffset_SecondaryColor3bEXT ),
|
||||
NAME_FUNC_OFFSET( 17276, glSecondaryColor3bv, _gloffset_SecondaryColor3bvEXT ),
|
||||
NAME_FUNC_OFFSET( 17296, glSecondaryColor3d, _gloffset_SecondaryColor3dEXT ),
|
||||
NAME_FUNC_OFFSET( 17315, glSecondaryColor3dv, _gloffset_SecondaryColor3dvEXT ),
|
||||
NAME_FUNC_OFFSET( 17335, glSecondaryColor3f, _gloffset_SecondaryColor3fEXT ),
|
||||
NAME_FUNC_OFFSET( 17354, glSecondaryColor3fv, _gloffset_SecondaryColor3fvEXT ),
|
||||
NAME_FUNC_OFFSET( 17374, glSecondaryColor3i, _gloffset_SecondaryColor3iEXT ),
|
||||
NAME_FUNC_OFFSET( 17393, glSecondaryColor3iv, _gloffset_SecondaryColor3ivEXT ),
|
||||
NAME_FUNC_OFFSET( 17413, glSecondaryColor3s, _gloffset_SecondaryColor3sEXT ),
|
||||
NAME_FUNC_OFFSET( 17432, glSecondaryColor3sv, _gloffset_SecondaryColor3svEXT ),
|
||||
NAME_FUNC_OFFSET( 17452, glSecondaryColor3ub, _gloffset_SecondaryColor3ubEXT ),
|
||||
NAME_FUNC_OFFSET( 17472, glSecondaryColor3ubv, _gloffset_SecondaryColor3ubvEXT ),
|
||||
NAME_FUNC_OFFSET( 17493, glSecondaryColor3ui, _gloffset_SecondaryColor3uiEXT ),
|
||||
NAME_FUNC_OFFSET( 17513, glSecondaryColor3uiv, _gloffset_SecondaryColor3uivEXT ),
|
||||
NAME_FUNC_OFFSET( 17534, glSecondaryColor3us, _gloffset_SecondaryColor3usEXT ),
|
||||
NAME_FUNC_OFFSET( 17554, glSecondaryColor3usv, _gloffset_SecondaryColor3usvEXT ),
|
||||
NAME_FUNC_OFFSET( 17575, glSecondaryColorPointer, _gloffset_SecondaryColorPointerEXT ),
|
||||
NAME_FUNC_OFFSET( 17599, glBindProgramARB, _gloffset_BindProgramNV ),
|
||||
NAME_FUNC_OFFSET( 17616, glDeleteProgramsARB, _gloffset_DeleteProgramsNV ),
|
||||
NAME_FUNC_OFFSET( 17636, glGenProgramsARB, _gloffset_GenProgramsNV ),
|
||||
NAME_FUNC_OFFSET( 17653, glGetVertexAttribPointervARB, _gloffset_GetVertexAttribPointervNV ),
|
||||
NAME_FUNC_OFFSET( 17682, glIsProgramARB, _gloffset_IsProgramNV ),
|
||||
NAME_FUNC_OFFSET( 17697, glPointParameteri, _gloffset_PointParameteriNV ),
|
||||
NAME_FUNC_OFFSET( 17715, glPointParameteriv, _gloffset_PointParameterivNV ),
|
||||
NAME_FUNC_OFFSET( 17734, glMultiDrawArrays, _gloffset_MultiDrawArraysEXT ),
|
||||
NAME_FUNC_OFFSET( 17752, glMultiDrawElements, _gloffset_MultiDrawElementsEXT ),
|
||||
NAME_FUNC_OFFSET( 17772, glBindBuffer, _gloffset_BindBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17785, glBufferData, _gloffset_BufferDataARB ),
|
||||
NAME_FUNC_OFFSET( 17798, glBufferSubData, _gloffset_BufferSubDataARB ),
|
||||
NAME_FUNC_OFFSET( 17814, glDeleteBuffers, _gloffset_DeleteBuffersARB ),
|
||||
NAME_FUNC_OFFSET( 17830, glGenBuffers, _gloffset_GenBuffersARB ),
|
||||
NAME_FUNC_OFFSET( 17843, glGetBufferParameteriv, _gloffset_GetBufferParameterivARB ),
|
||||
NAME_FUNC_OFFSET( 17866, glGetBufferPointerv, _gloffset_GetBufferPointervARB ),
|
||||
NAME_FUNC_OFFSET( 17886, glGetBufferSubData, _gloffset_GetBufferSubDataARB ),
|
||||
NAME_FUNC_OFFSET( 17905, glIsBuffer, _gloffset_IsBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17916, glMapBuffer, _gloffset_MapBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17928, glUnmapBuffer, _gloffset_UnmapBufferARB ),
|
||||
NAME_FUNC_OFFSET( 17942, glGenQueries, _gloffset_GenQueriesARB ),
|
||||
NAME_FUNC_OFFSET( 17955, glDeleteQueries, _gloffset_DeleteQueriesARB ),
|
||||
NAME_FUNC_OFFSET( 17971, glIsQuery, _gloffset_IsQueryARB ),
|
||||
NAME_FUNC_OFFSET( 17981, glBeginQuery, _gloffset_BeginQueryARB ),
|
||||
NAME_FUNC_OFFSET( 17994, glEndQuery, _gloffset_EndQueryARB ),
|
||||
NAME_FUNC_OFFSET( 18005, glGetQueryiv, _gloffset_GetQueryivARB ),
|
||||
NAME_FUNC_OFFSET( 18018, glGetQueryObjectiv, _gloffset_GetQueryObjectivARB ),
|
||||
NAME_FUNC_OFFSET( 18037, glGetQueryObjectuiv, _gloffset_GetQueryObjectuivARB ),
|
||||
NAME_FUNC_OFFSET( 18057, glBlendEquationSeparateATI, _gloffset_BlendEquationSeparateEXT ),
|
||||
NAME_FUNC_OFFSET( -1, NULL, 0 )
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# $Id: mesadef.py,v 1.3 2005/09/05 14:09:25 kschultz Exp $
|
||||
# $Id: mesadef.py,v 1.3.2.1 2006/03/25 23:48:21 brianp Exp $
|
||||
|
||||
# Mesa 3-D graphics library
|
||||
# Version: 4.1
|
||||
@@ -89,6 +89,7 @@ def PrintTail():
|
||||
print '\twglDescribePixelFormat'
|
||||
print '\twglGetCurrentContext'
|
||||
print '\twglGetCurrentDC'
|
||||
print '\twglGetExtensionsStringARB'
|
||||
print '\twglGetLayerPaletteEntries'
|
||||
print '\twglGetPixelFormat'
|
||||
print '\twglGetProcAddress'
|
||||
|
||||
@@ -29,20 +29,21 @@ import string, copy
|
||||
|
||||
class type_node:
|
||||
def __init__(self):
|
||||
self.pointer = 0
|
||||
self.const = 0
|
||||
self.signed = 1
|
||||
self.integer = 1
|
||||
self.pointer = 0 # bool
|
||||
self.const = 0 # bool
|
||||
self.signed = 1 # bool
|
||||
self.integer = 1 # bool
|
||||
|
||||
# If elements is set to non-zero, then field is an array.
|
||||
self.elements = 0
|
||||
|
||||
self.name = None
|
||||
self.size = 0
|
||||
self.size = 0 # type's size in bytes
|
||||
return
|
||||
|
||||
|
||||
def string(self):
|
||||
"""Return string representation of this type_node."""
|
||||
s = ""
|
||||
|
||||
if self.pointer:
|
||||
@@ -85,16 +86,17 @@ class type_table:
|
||||
def create_initial_types():
|
||||
tt = type_table()
|
||||
|
||||
basic_types = [ ["char", 1, 1], \
|
||||
["short", 2, 1], \
|
||||
["int", 4, 1], \
|
||||
["long", 4, 1], \
|
||||
["float", 4, 0], \
|
||||
["double", 8, 0], \
|
||||
["enum", 4, 1] ]
|
||||
basic_types = [
|
||||
("char", 1, 1),
|
||||
("short", 2, 1),
|
||||
("int", 4, 1),
|
||||
("long", 4, 1),
|
||||
("float", 4, 0),
|
||||
("double", 8, 0),
|
||||
("enum", 4, 1)
|
||||
]
|
||||
|
||||
|
||||
for [type_name, type_size, integer] in basic_types:
|
||||
for (type_name, type_size, integer) in basic_types:
|
||||
te = type_expression(None)
|
||||
tn = type_node()
|
||||
tn.name = type_name
|
||||
@@ -113,22 +115,24 @@ class type_expression:
|
||||
def __init__(self, type_string, extra_types = None):
|
||||
self.expr = []
|
||||
|
||||
if not type_string: return
|
||||
if not type_string:
|
||||
return
|
||||
|
||||
self.original_string = type_string
|
||||
|
||||
if not type_expression.built_in_types:
|
||||
raise RuntimeError("create_initial_types must be called before creating type_expression objects.")
|
||||
|
||||
|
||||
elements = string.split( string.replace( type_string, "*", " * " ) )
|
||||
# Replace '*' with ' * ' in type_string. Then, split the string
|
||||
# into tokens, separated by spaces.
|
||||
tokens = string.split( string.replace( type_string, "*", " * " ) )
|
||||
|
||||
const = 0
|
||||
t = None
|
||||
signed = 0
|
||||
unsigned = 0
|
||||
|
||||
for i in elements:
|
||||
for i in tokens:
|
||||
if i == "const":
|
||||
if t and t.pointer:
|
||||
t.const = 1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user