Compare commits
70 Commits
mesa-22.3.
...
texmem_0_3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
814cae6a45 | ||
|
|
410673f64c | ||
|
|
a83a3cfa1c | ||
|
|
da89238b13 | ||
|
|
984387b89c | ||
|
|
93bc5e8402 | ||
|
|
43722cae42 | ||
|
|
f397a2a1e5 | ||
|
|
87a0312068 | ||
|
|
ee525436cc | ||
|
|
520ba25dc3 | ||
|
|
6f9dc91045 | ||
|
|
d17637d47f | ||
|
|
980a25cd92 | ||
|
|
607c474f2d | ||
|
|
2f54146c1f | ||
|
|
72aeeef7c3 | ||
|
|
dadc8e2a50 | ||
|
|
02d401b475 | ||
|
|
9d695abcac | ||
|
|
e070007d16 | ||
|
|
39c4c8d54b | ||
|
|
4fa3cf225f | ||
|
|
1c2c1c4560 | ||
|
|
e3904516bb | ||
|
|
ceb222798b | ||
|
|
6abcf6a3d3 | ||
|
|
db0ed8942f | ||
|
|
bd9f38ccaa | ||
|
|
b15421c22b | ||
|
|
5db0e131ef | ||
|
|
b249ff8a86 | ||
|
|
9d6e0f5d64 | ||
|
|
4f8549634e | ||
|
|
3345ab8ccf | ||
|
|
cd3c9febda | ||
|
|
8c58a32360 | ||
|
|
0d646ea3a8 | ||
|
|
6a33e6d221 | ||
|
|
fc4bc6fc97 | ||
|
|
4239cfd534 | ||
|
|
b0902a4158 | ||
|
|
269219dc05 | ||
|
|
5dbadd418c | ||
|
|
71bce51324 | ||
|
|
308d377ca8 | ||
|
|
4f39d22c29 | ||
|
|
8dab7963b7 | ||
|
|
ec30116c9f | ||
|
|
5ac3ad7722 | ||
|
|
fe239744aa | ||
|
|
137dcd4a46 | ||
|
|
0d7755fc73 | ||
|
|
c863e63549 | ||
|
|
62920e2ab2 | ||
|
|
ce3885fc5f | ||
|
|
bf0c1ca618 | ||
|
|
64bc9caa1c | ||
|
|
89a2ea6fd3 | ||
|
|
41123a85ec | ||
|
|
f10469abe8 | ||
|
|
4a74de797c | ||
|
|
c745394242 | ||
|
|
f9f3de8c31 | ||
|
|
3d0a073a71 | ||
|
|
219ee91fa8 | ||
|
|
632eae3fec | ||
|
|
f378bcd8bf | ||
|
|
ded29089f3 | ||
|
|
527c05eb2a |
@@ -47,6 +47,7 @@ PROGS = \
|
||||
renormal \
|
||||
shadowtex \
|
||||
singlebuffer \
|
||||
streaming_rect \
|
||||
spectex \
|
||||
spriteblast \
|
||||
stex3d \
|
||||
|
||||
407
progs/demos/streaming_rect.c
Normal file
407
progs/demos/streaming_rect.c
Normal file
@@ -0,0 +1,407 @@
|
||||
|
||||
/*
|
||||
* GL_ARB_multitexture demo
|
||||
*
|
||||
* Command line options:
|
||||
* -info print GL implementation information
|
||||
*
|
||||
*
|
||||
* Brian Paul November 1998 This program is in the public domain.
|
||||
* Modified on 12 Feb 2002 for > 2 texture units.
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
#include "readtex.h"
|
||||
|
||||
enum {
|
||||
WHOLERECT,
|
||||
RENDER,
|
||||
SWAPBUF,
|
||||
|
||||
UPLOAD_CONVENTIONAL,
|
||||
UPLOAD_PBO_NAIVE,
|
||||
UPLOAD_PBO_PINGPONG,
|
||||
UPLOAD_PBO_WITH_RESET,
|
||||
UPLOAD_NOOP,
|
||||
|
||||
QUIT
|
||||
};
|
||||
|
||||
static GLint upload_style = UPLOAD_CONVENTIONAL;
|
||||
static GLboolean whole_rect = 1;
|
||||
static GLboolean do_render = 1;
|
||||
static GLboolean do_swapbuffers = 1;
|
||||
|
||||
|
||||
static GLuint col = 0x0;
|
||||
static GLfloat Xrot = 20.0, Yrot = 30.0;
|
||||
|
||||
static GLuint Width = 1024;
|
||||
static GLuint Height = 512;
|
||||
|
||||
#define NR_PBO 2
|
||||
static GLuint texObj, DrawPBO[NR_PBO];
|
||||
|
||||
|
||||
static void Idle( void )
|
||||
{
|
||||
col++;
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
static int min( int a, int b ) { return a < b ? a : b; }
|
||||
|
||||
static void DrawObject()
|
||||
{
|
||||
GLint size = Width * Height * 4;
|
||||
static char *static_image = NULL;
|
||||
static int current = 0;
|
||||
|
||||
switch (upload_style) {
|
||||
case UPLOAD_PBO_NAIVE:
|
||||
/* Continually upload from the one pbo without any attempt to
|
||||
* decouple from hardware trying to access the same data:
|
||||
*/
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[0]);
|
||||
|
||||
{
|
||||
char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB);
|
||||
memset(image, col&0xff, size);
|
||||
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||
break;
|
||||
|
||||
case UPLOAD_PBO_PINGPONG:
|
||||
/* Cycle through the available upload buffers to avoid waiting
|
||||
* on buffers currently enqueued on the hardware. Avoids
|
||||
* waiting on buffer contents that may still be referenced by
|
||||
* hardware.
|
||||
*/
|
||||
current = (current + 1) % NR_PBO;
|
||||
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[current]);
|
||||
|
||||
{
|
||||
char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB);
|
||||
memset(image, col&0xff, size);
|
||||
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||
break;
|
||||
|
||||
|
||||
case UPLOAD_PBO_WITH_RESET:
|
||||
/* Alternate approach, uses BufferDataARB(NULL) to explicitly
|
||||
* release the old image contents from the pbo prior to upload.
|
||||
* Similar effect to double buffering pbos as above, but a
|
||||
* little more subtle as the implications of the NULL data are
|
||||
* not entirely clear. I don't know if all drivers will take
|
||||
* full advantage of the optimization or not.
|
||||
*/
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[0]);
|
||||
|
||||
/* XXX: This is extremely important - semantically makes the buffer
|
||||
* contents undefined, but in practice means that the driver can
|
||||
* release the old copy of the texture and allocate a new one
|
||||
* without waiting for outstanding rendering to complete.
|
||||
*/
|
||||
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, size, NULL, GL_STREAM_DRAW_ARB);
|
||||
|
||||
{
|
||||
char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB);
|
||||
memset(image, col&0xff, size);
|
||||
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||
break;
|
||||
|
||||
|
||||
case UPLOAD_CONVENTIONAL:
|
||||
if (static_image == NULL)
|
||||
static_image = malloc(size);
|
||||
|
||||
memset(static_image, col&0xff, size);
|
||||
|
||||
/* BGRA should be the fast path for regular uploads as well.
|
||||
*/
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, static_image);
|
||||
break;
|
||||
|
||||
case UPLOAD_NOOP:
|
||||
break;
|
||||
}
|
||||
|
||||
if (do_render)
|
||||
{
|
||||
int x,y,w,h;
|
||||
|
||||
if (whole_rect) {
|
||||
x = y = 0;
|
||||
w = Width;
|
||||
h = Height;
|
||||
}
|
||||
else {
|
||||
x = y = 0;
|
||||
w = min(10, Width);
|
||||
h = min(10, Height);
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f( x, y);
|
||||
glVertex2f( x, y );
|
||||
|
||||
glTexCoord2f( x, y + h);
|
||||
glVertex2f( x, y + h);
|
||||
|
||||
glTexCoord2f( x + w, y + h);
|
||||
glVertex2f( x + w, y + h );
|
||||
|
||||
glTexCoord2f( x + w, y);
|
||||
glVertex2f( x + w, y );
|
||||
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void Display( void )
|
||||
{
|
||||
static GLint T0 = 0;
|
||||
static GLint Frames = 0;
|
||||
GLint t;
|
||||
|
||||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
|
||||
glPushMatrix();
|
||||
DrawObject();
|
||||
glPopMatrix();
|
||||
|
||||
if (do_swapbuffers)
|
||||
glutSwapBuffers();
|
||||
else
|
||||
glFlush();
|
||||
|
||||
Frames++;
|
||||
|
||||
t = glutGet(GLUT_ELAPSED_TIME);
|
||||
if (t - T0 >= 1000) {
|
||||
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 Reshape( int width, int height )
|
||||
{
|
||||
glViewport( 0, 0, width, height );
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
/* glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); */
|
||||
gluOrtho2D( 0, width, height, 0 );
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
/* glTranslatef(0.375, 0.375, 0); */
|
||||
}
|
||||
|
||||
|
||||
static void ModeMenu(int entry)
|
||||
{
|
||||
switch (entry) {
|
||||
case WHOLERECT:
|
||||
whole_rect = !whole_rect;
|
||||
break;
|
||||
case RENDER:
|
||||
do_render = !do_render;
|
||||
break;
|
||||
case SWAPBUF:
|
||||
do_swapbuffers = !do_swapbuffers;
|
||||
break;
|
||||
|
||||
case UPLOAD_CONVENTIONAL:
|
||||
case UPLOAD_PBO_NAIVE:
|
||||
case UPLOAD_PBO_PINGPONG:
|
||||
case UPLOAD_PBO_WITH_RESET:
|
||||
case UPLOAD_NOOP:
|
||||
upload_style = entry;
|
||||
break;
|
||||
|
||||
case QUIT:
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
float step = 3.0;
|
||||
(void) x;
|
||||
(void) y;
|
||||
|
||||
switch (key) {
|
||||
case GLUT_KEY_UP:
|
||||
Xrot += step;
|
||||
break;
|
||||
case GLUT_KEY_DOWN:
|
||||
Xrot -= step;
|
||||
break;
|
||||
case GLUT_KEY_LEFT:
|
||||
Yrot += step;
|
||||
break;
|
||||
case GLUT_KEY_RIGHT:
|
||||
Yrot -= step;
|
||||
break;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
static void Init( int argc, char *argv[] )
|
||||
{
|
||||
const char *exten = (const char *) glGetString(GL_EXTENSIONS);
|
||||
GLint size;
|
||||
|
||||
|
||||
if (!strstr(exten, "GL_ARB_multitexture")) {
|
||||
printf("Sorry, GL_ARB_multitexture not supported by this renderer.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
|
||||
printf("%d x %d max texture size\n", size, size);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
/* allocate two texture objects */
|
||||
glGenTextures(1, &texObj);
|
||||
|
||||
/* setup the texture objects */
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texObj);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glGenBuffersARB(NR_PBO, DrawPBO);
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < NR_PBO; i++) {
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[i]);
|
||||
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, Width * Height * 4, NULL, GL_STREAM_DRAW_ARB);
|
||||
}
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glClearColor(0.3, 0.3, 0.4, 1.0);
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "-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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
GLint i;
|
||||
|
||||
glutInit( &argc, argv );
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-w") == 0) {
|
||||
Width = atoi(argv[i+1]);
|
||||
if (Width <= 0) {
|
||||
printf("Error, bad width\n");
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "-h") == 0) {
|
||||
Height = atoi(argv[i+1]);
|
||||
if (Height <= 0) {
|
||||
printf("Error, bad height\n");
|
||||
exit(1);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
glutInitWindowSize( Width, Height );
|
||||
glutInitWindowPosition( 0, 0 );
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
|
||||
glutCreateWindow(argv[0] );
|
||||
|
||||
Init( argc, argv );
|
||||
|
||||
glutReshapeFunc( Reshape );
|
||||
glutKeyboardFunc( Key );
|
||||
glutSpecialFunc( SpecialKey );
|
||||
glutDisplayFunc( Display );
|
||||
glutIdleFunc( Idle );
|
||||
|
||||
glutCreateMenu(ModeMenu);
|
||||
glutAddMenuEntry("Wholerect", WHOLERECT);
|
||||
glutAddMenuEntry("Render", RENDER);
|
||||
glutAddMenuEntry("Swapbuf", SWAPBUF);
|
||||
|
||||
glutAddMenuEntry("Upload style CONVENTIONAL", UPLOAD_CONVENTIONAL);
|
||||
glutAddMenuEntry("Upload style PBO_NAIVE", UPLOAD_PBO_NAIVE);
|
||||
glutAddMenuEntry("Upload style PBO_PINGPONG", UPLOAD_PBO_PINGPONG);
|
||||
glutAddMenuEntry("Upload style PBO_WITH_RESET", UPLOAD_PBO_WITH_RESET);
|
||||
glutAddMenuEntry("Upload style NOOP", UPLOAD_NOOP);
|
||||
|
||||
glutAddMenuEntry("Quit", QUIT);
|
||||
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
@@ -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,16 +224,50 @@ 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;
|
||||
}
|
||||
|
||||
/* draw a tiny polygon to force texture into texram */
|
||||
@@ -192,25 +284,12 @@ MeasureDownloadRate(void)
|
||||
|
||||
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();
|
||||
|
||||
184
progs/tests/arbnpot-mipmap.c
Normal file
184
progs/tests/arbnpot-mipmap.c
Normal file
@@ -0,0 +1,184 @@
|
||||
|
||||
/* Copyright (c) Mark J. Kilgard, 1994. */
|
||||
|
||||
/*
|
||||
* (c) Copyright 1993, Silicon Graphics, Inc.
|
||||
* ALL RIGHTS RESERVED
|
||||
* Permission to use, copy, modify, and distribute this software for
|
||||
* any purpose and without fee is hereby granted, provided that the above
|
||||
* copyright notice appear in all copies and that both the copyright notice
|
||||
* and this permission notice appear in supporting documentation, and that
|
||||
* the name of Silicon Graphics, Inc. not be used in advertising
|
||||
* or publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission.
|
||||
*
|
||||
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
||||
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
||||
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
|
||||
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
|
||||
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
|
||||
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
|
||||
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
||||
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* US Government Users Restricted Rights
|
||||
* Use, duplication, or disclosure by the Government is subject to
|
||||
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
||||
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
|
||||
* clause at DFARS 252.227-7013 and/or in similar or successor
|
||||
* clauses in the FAR or the DOD or NASA FAR Supplement.
|
||||
* Unpublished-- rights reserved under the copyright laws of the
|
||||
* United States. Contractor/manufacturer is Silicon Graphics,
|
||||
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
|
||||
*
|
||||
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
||||
*/
|
||||
/* mipmap.c
|
||||
* This program demonstrates using mipmaps for texture maps.
|
||||
* To overtly show the effect of mipmaps, each mipmap reduction
|
||||
* level has a solidly colored, contrasting texture image.
|
||||
* Thus, the quadrilateral which is drawn is drawn with several
|
||||
* different colors.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
GLubyte mipmapImage32[40][46][3];
|
||||
GLubyte mipmapImage16[20][23][3];
|
||||
GLubyte mipmapImage8[10][11][3];
|
||||
GLubyte mipmapImage4[5][5][3];
|
||||
GLubyte mipmapImage2[2][2][3];
|
||||
GLubyte mipmapImage1[1][1][3];
|
||||
|
||||
static void makeImages(void)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 40; i++) {
|
||||
for (j = 0; j < 46; j++) {
|
||||
mipmapImage32[i][j][0] = 255;
|
||||
mipmapImage32[i][j][1] = 255;
|
||||
mipmapImage32[i][j][2] = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 20; i++) {
|
||||
for (j = 0; j < 23; j++) {
|
||||
mipmapImage16[i][j][0] = 255;
|
||||
mipmapImage16[i][j][1] = 0;
|
||||
mipmapImage16[i][j][2] = 255;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (j = 0; j < 11; j++) {
|
||||
mipmapImage8[i][j][0] = 255;
|
||||
mipmapImage8[i][j][1] = 0;
|
||||
mipmapImage8[i][j][2] = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 5; i++) {
|
||||
for (j = 0; j < 5; j++) {
|
||||
mipmapImage4[i][j][0] = 0;
|
||||
mipmapImage4[i][j][1] = 255;
|
||||
mipmapImage4[i][j][2] = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
mipmapImage2[i][j][0] = 0;
|
||||
mipmapImage2[i][j][1] = 0;
|
||||
mipmapImage2[i][j][2] = 255;
|
||||
}
|
||||
}
|
||||
mipmapImage1[0][0][0] = 255;
|
||||
mipmapImage1[0][0][1] = 255;
|
||||
mipmapImage1[0][0][2] = 255;
|
||||
}
|
||||
|
||||
static void myinit(void)
|
||||
{
|
||||
if (!glutExtensionSupported("GL_ARB_texture_non_power_of_two")) {
|
||||
printf("Sorry, this program requires GL_ARB_texture_non_power_of_two\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
glTranslatef(0.0, 0.0, -3.6);
|
||||
makeImages();
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, 40, 46, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage32[0][0][0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 1, 3, 20, 23, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage16[0][0][0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 2, 3, 10, 11, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage8[0][0][0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 3, 3, 5, 5, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage4[0][0][0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 4, 3, 2, 2, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage2[0][0][0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 5, 3, 1, 1, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage1[0][0][0]);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_NEAREST_MIPMAP_NEAREST);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
static void display(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0);
|
||||
glTexCoord2f(0.0, 8.0); glVertex3f(-2.0, 1.0, 0.0);
|
||||
glTexCoord2f(8.0, 8.0); glVertex3f(2000.0, 1.0, -6000.0);
|
||||
glTexCoord2f(8.0, 0.0); glVertex3f(2000.0, -1.0, -6000.0);
|
||||
glEnd();
|
||||
glFlush();
|
||||
}
|
||||
|
||||
static void myReshape(int w, int h)
|
||||
{
|
||||
glViewport(0, 0, w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(60.0, 1.0*(GLfloat)w/(GLfloat)h, 1.0, 30000.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
static void
|
||||
key(unsigned char k, int x, int y)
|
||||
{
|
||||
switch (k) {
|
||||
case 27: /* Escape */
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
|
||||
glutInitWindowSize (500, 500);
|
||||
glutCreateWindow (argv[0]);
|
||||
myinit();
|
||||
glutReshapeFunc (myReshape);
|
||||
glutDisplayFunc(display);
|
||||
glutKeyboardFunc(key);
|
||||
glutMainLoop();
|
||||
return 0; /* ANSI C requires main to return int. */
|
||||
}
|
||||
@@ -38,7 +38,9 @@ SOURCES = \
|
||||
quad-offset-unfilled.c \
|
||||
quad-unfilled.c \
|
||||
quad-tex-2d.c \
|
||||
quad-tex-pbo.c \
|
||||
quad-tex-3d.c \
|
||||
quad-tex-dep.c \
|
||||
quad.c \
|
||||
quads.c \
|
||||
quadstrip.c \
|
||||
|
||||
245
progs/trivial/quad-tex-dep.c
Normal file
245
progs/trivial/quad-tex-dep.c
Normal file
@@ -0,0 +1,245 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/glut.h>
|
||||
|
||||
|
||||
|
||||
GLenum doubleBuffer;
|
||||
|
||||
/* Demonstrate an equivalent to paletted texturing using fragment
|
||||
* programs and dependent texturing. This requires at least one
|
||||
* texture unit to be reserved for the palette lookup.
|
||||
*/
|
||||
|
||||
static void Init( void )
|
||||
{
|
||||
static const char *modulate2D =
|
||||
"!!ARBfp1.0\n"
|
||||
"TEMP index; \n"
|
||||
"TEX index, fragment.texcoord[0], texture[0], 2D; \n"
|
||||
"TEX result.color, index, texture[1], 1D; \n"
|
||||
"END"
|
||||
;
|
||||
GLuint modulateProg;
|
||||
GLuint Texture;
|
||||
|
||||
if (!glutExtensionSupported("GL_ARB_fragment_program")) {
|
||||
printf("Error: GL_ARB_fragment_program not supported!\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
|
||||
/* Setup the fragment program */
|
||||
glGenProgramsARB(1, &modulateProg);
|
||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, modulateProg);
|
||||
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
strlen(modulate2D), (const GLubyte *)modulate2D);
|
||||
|
||||
printf("glGetError = 0x%x\n", (int) glGetError());
|
||||
printf("glError(GL_PROGRAM_ERROR_STRING_ARB) = %s\n",
|
||||
(char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
||||
assert(glIsProgramARB(modulateProg));
|
||||
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
|
||||
|
||||
{
|
||||
#define HEIGHT 8
|
||||
#define WIDTH 32
|
||||
|
||||
#define B 0
|
||||
#define G 1
|
||||
#define R 2
|
||||
#define A 3
|
||||
|
||||
static char texture[HEIGHT * WIDTH + 1] =
|
||||
" "
|
||||
" MMM EEEE SSS AAA "
|
||||
" M M M E S S A A "
|
||||
" M M M EEEE SS A A "
|
||||
" M M M E SS AAAAA "
|
||||
" M M E S S A A "
|
||||
" M M EEEE SSS A A ";
|
||||
|
||||
GLubyte table[256][4];
|
||||
|
||||
|
||||
|
||||
/* load the color table for each texel-index */
|
||||
memset(table, 0xff, 256*4);
|
||||
table[' '][B] = 255;
|
||||
table[' '][G] = 255;
|
||||
table[' '][R] = 255;
|
||||
table[' '][A] = 64;
|
||||
table['M'][B] = 0;
|
||||
table['M'][G] = 0;
|
||||
table['M'][R] = 255;
|
||||
table['M'][A] = 255;
|
||||
table['E'][B] = 0;
|
||||
table['E'][G] = 255;
|
||||
table['E'][R] = 0;
|
||||
table['E'][A] = 255;
|
||||
table['S'][B] = 255;
|
||||
table['S'][G] = 0;
|
||||
table['S'][R] = 0;
|
||||
table['S'][A] = 255;
|
||||
table['A'][B] = 0;
|
||||
table['A'][G] = 255;
|
||||
table['A'][R] = 255;
|
||||
table['A'][A] = 255;
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
|
||||
/* Load indexed texture as a 2D I8 texture */
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glGenTextures(1, &Texture);
|
||||
glBindTexture(GL_TEXTURE_2D, Texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, /* target */
|
||||
0, /* level */
|
||||
GL_INTENSITY, /* internal format */
|
||||
WIDTH, HEIGHT, /* width, height */
|
||||
0, /* border */
|
||||
GL_LUMINANCE, /* texture format */
|
||||
GL_UNSIGNED_BYTE, /* texture type */
|
||||
texture); /* the texture */
|
||||
|
||||
|
||||
printf("glGetError = 0x%x\n", (int) glGetError());
|
||||
printf("glError(GL_PROGRAM_ERROR_STRING_ARB) = %s\n",
|
||||
(char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
/* Load "pallete" as a 1D BGRA8888 texture */
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glGenTextures(1, &Texture);
|
||||
glBindTexture(GL_TEXTURE_1D, Texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glTexImage1D(GL_TEXTURE_1D, /* target */
|
||||
0, /* level */
|
||||
GL_RGBA, /* internal format */
|
||||
256, /* width */
|
||||
0, /* border */
|
||||
GL_BGRA, /* texture format */
|
||||
GL_UNSIGNED_BYTE, /* texture type */
|
||||
table); /* the texture */
|
||||
|
||||
glEnable(GL_TEXTURE_1D);
|
||||
|
||||
/* glEnable(GL_BLEND); */
|
||||
/* glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); */
|
||||
#undef HEIGHT
|
||||
#undef WIDTH
|
||||
}
|
||||
|
||||
|
||||
glClearColor(.3, .3, .3, 0);
|
||||
}
|
||||
|
||||
static void Reshape(int width, int height)
|
||||
{
|
||||
|
||||
glViewport(0, 0, (GLint)width, (GLint)height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
static void Key(unsigned char key, int x, int y)
|
||||
{
|
||||
|
||||
switch (key) {
|
||||
case 27:
|
||||
exit(1);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
static void Draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(1,1);
|
||||
glVertex3f( 0.9, -0.9, -30.0);
|
||||
glTexCoord2f(1,0);
|
||||
glVertex3f( 0.9, 0.9, -30.0);
|
||||
glTexCoord2f(0,0);
|
||||
glVertex3f(-0.9, 0.9, -30.0);
|
||||
glTexCoord2f(0,1);
|
||||
glVertex3f(-0.9, -0.9, -30.0);
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
|
||||
if (doubleBuffer) {
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static GLenum Args(int argc, char **argv)
|
||||
{
|
||||
GLint i;
|
||||
|
||||
doubleBuffer = GL_FALSE;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-sb") == 0) {
|
||||
doubleBuffer = GL_FALSE;
|
||||
} else if (strcmp(argv[i], "-db") == 0) {
|
||||
doubleBuffer = GL_TRUE;
|
||||
} else {
|
||||
fprintf(stderr, "%s (Bad option).\n", argv[i]);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GLenum type;
|
||||
|
||||
glutInit(&argc, argv);
|
||||
|
||||
if (Args(argc, argv) == GL_FALSE) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
|
||||
|
||||
type = GLUT_RGB;
|
||||
type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
|
||||
glutInitDisplayMode(type);
|
||||
|
||||
if (glutCreateWindow("First Tri") == GL_FALSE) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Init();
|
||||
|
||||
glutReshapeFunc(Reshape);
|
||||
glutKeyboardFunc(Key);
|
||||
glutDisplayFunc(Draw);
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
181
progs/trivial/quad-tex-pbo.c
Normal file
181
progs/trivial/quad-tex-pbo.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the name of
|
||||
* Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
|
||||
* ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <GL/glut.h>
|
||||
|
||||
|
||||
#define CI_OFFSET_1 16
|
||||
#define CI_OFFSET_2 32
|
||||
|
||||
GLenum doubleBuffer;
|
||||
|
||||
static GLuint DrawPBO;
|
||||
|
||||
static void Init(void)
|
||||
{
|
||||
fprintf(stderr, "GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
|
||||
fprintf(stderr, "GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
|
||||
fprintf(stderr, "GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
|
||||
|
||||
glClearColor(0.0, 0.0, 1.0, 0.0);
|
||||
|
||||
#define SIZE 16
|
||||
{
|
||||
GLubyte tex2d[SIZE][SIZE][4];
|
||||
GLint s, t;
|
||||
|
||||
for (s = 0; s < SIZE; s++) {
|
||||
for (t = 0; t < SIZE; t++) {
|
||||
/* bgra:
|
||||
*/
|
||||
tex2d[t][s][0] = 0x30;
|
||||
tex2d[t][s][1] = t*255/(SIZE-1);
|
||||
tex2d[t][s][2] = s*255/(SIZE-1);
|
||||
tex2d[t][s][3] = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* put image into DrawPBO */
|
||||
glGenBuffersARB(1, &DrawPBO);
|
||||
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, DrawPBO);
|
||||
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
|
||||
SIZE * SIZE * 4, tex2d, GL_STATIC_DRAW);
|
||||
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
|
||||
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE, SIZE, 0,
|
||||
GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void Reshape(int width, int height)
|
||||
{
|
||||
|
||||
glViewport(0, 0, (GLint)width, (GLint)height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
static void Key(unsigned char key, int x, int y)
|
||||
{
|
||||
|
||||
switch (key) {
|
||||
case 27:
|
||||
exit(1);
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
static void Draw(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(1,0);
|
||||
glVertex3f( 0.9, -0.9, -30.0);
|
||||
glTexCoord2f(1,1);
|
||||
glVertex3f( 0.9, 0.9, -30.0);
|
||||
glTexCoord2f(0,1);
|
||||
glVertex3f(-0.9, 0.9, -30.0);
|
||||
glTexCoord2f(0,0);
|
||||
glVertex3f(-0.9, -0.9, -30.0);
|
||||
glEnd();
|
||||
|
||||
glFlush();
|
||||
|
||||
if (doubleBuffer) {
|
||||
glutSwapBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum Args(int argc, char **argv)
|
||||
{
|
||||
GLint i;
|
||||
|
||||
doubleBuffer = GL_FALSE;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-sb") == 0) {
|
||||
doubleBuffer = GL_FALSE;
|
||||
} else if (strcmp(argv[i], "-db") == 0) {
|
||||
doubleBuffer = GL_TRUE;
|
||||
} else {
|
||||
fprintf(stderr, "%s (Bad option).\n", argv[i]);
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GLenum type;
|
||||
|
||||
glutInit(&argc, argv);
|
||||
|
||||
if (Args(argc, argv) == GL_FALSE) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250);
|
||||
|
||||
type = GLUT_RGB;
|
||||
type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
|
||||
glutInitDisplayMode(type);
|
||||
|
||||
if (glutCreateWindow("First Tri") == GL_FALSE) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Init();
|
||||
|
||||
glutReshapeFunc(Reshape);
|
||||
glutKeyboardFunc(Key);
|
||||
glutDisplayFunc(Draw);
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
@@ -722,6 +722,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
|
||||
@@ -773,7 +835,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";
|
||||
@@ -800,7 +863,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
|
||||
}
|
||||
|
||||
err_msg = "XF86DRIAuthConnection";
|
||||
if (XF86DRIAuthConnection(dpy, scrn, magic)) {
|
||||
if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) {
|
||||
char *driverName;
|
||||
|
||||
/*
|
||||
@@ -904,7 +967,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
|
||||
}
|
||||
|
||||
if ( fd >= 0 ) {
|
||||
(void)drmClose(fd);
|
||||
(void)drmCloseOnce(fd);
|
||||
}
|
||||
|
||||
(void)XF86DRICloseConnection(dpy, scrn);
|
||||
|
||||
@@ -9,7 +9,10 @@ COMMON_SOURCES = \
|
||||
../common/vblank.c \
|
||||
../common/dri_util.c \
|
||||
../common/xmlconfig.c \
|
||||
../common/drirenderbuffer.c
|
||||
../common/drirenderbuffer.c \
|
||||
../common/dri_bufmgr.c \
|
||||
../common/dri_drmpool.c
|
||||
|
||||
|
||||
ifeq ($(WINDOW_SYSTEM),dri)
|
||||
WINOBJ=
|
||||
|
||||
493
src/mesa/drivers/dri/common/dri_bufmgr.c
Normal file
493
src/mesa/drivers/dri/common/dri_bufmgr.c
Normal file
@@ -0,0 +1,493 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com>
|
||||
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <stdlib.h>
|
||||
#include "glthread.h"
|
||||
#include "errno.h"
|
||||
#include "dri_bufmgr.h"
|
||||
#include "string.h"
|
||||
#include "imports.h"
|
||||
#include "dri_bufpool.h"
|
||||
|
||||
_glthread_DECLARE_STATIC_MUTEX(bmMutex);
|
||||
|
||||
/*
|
||||
* TODO: Introduce fence pools in the same way as
|
||||
* buffer object pools.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef struct _DriFenceObject
|
||||
{
|
||||
int fd;
|
||||
_glthread_Mutex mutex;
|
||||
int refCount;
|
||||
const char *name;
|
||||
drmFence fence;
|
||||
} DriFenceObject;
|
||||
|
||||
typedef struct _DriBufferObject
|
||||
{
|
||||
DriBufferPool *pool;
|
||||
_glthread_Mutex mutex;
|
||||
int refCount;
|
||||
const char *name;
|
||||
unsigned flags;
|
||||
unsigned hint;
|
||||
unsigned alignment;
|
||||
void *private;
|
||||
} DriBufferObject;
|
||||
|
||||
|
||||
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
|
||||
abort();
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
DriFenceObject *
|
||||
driFenceBuffers(int fd, char *name, unsigned flags)
|
||||
{
|
||||
DriFenceObject *fence = (DriFenceObject *) malloc(sizeof(*fence));
|
||||
int ret;
|
||||
|
||||
if (!fence)
|
||||
BM_CKFATAL(-EINVAL);
|
||||
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
fence->refCount = 1;
|
||||
fence->name = name;
|
||||
fence->fd = fd;
|
||||
_glthread_INIT_MUTEX(fence->mutex);
|
||||
ret = drmFenceBuffers(fd, flags, &fence->fence);
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
if (ret) {
|
||||
free(fence);
|
||||
BM_CKFATAL(ret);
|
||||
}
|
||||
return fence;
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
driFenceType(DriFenceObject * fence)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
ret = fence->fence.flags;
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
DriFenceObject *
|
||||
driFenceReference(DriFenceObject * fence)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
++fence->refCount;
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
return fence;
|
||||
}
|
||||
|
||||
void
|
||||
driFenceUnReference(DriFenceObject * fence)
|
||||
{
|
||||
if (!fence)
|
||||
return;
|
||||
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
if (--fence->refCount == 0) {
|
||||
drmFenceDestroy(fence->fd, &fence->fence);
|
||||
free(fence);
|
||||
}
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
}
|
||||
|
||||
void
|
||||
driFenceFinish(DriFenceObject * fence, unsigned type, int lazy)
|
||||
{
|
||||
int ret;
|
||||
unsigned flags = (lazy) ? DRM_FENCE_FLAG_WAIT_LAZY : 0;
|
||||
|
||||
_glthread_LOCK_MUTEX(fence->mutex);
|
||||
ret = drmFenceWait(fence->fd, flags, &fence->fence, type);
|
||||
_glthread_UNLOCK_MUTEX(fence->mutex);
|
||||
BM_CKFATAL(ret);
|
||||
}
|
||||
|
||||
int
|
||||
driFenceSignaled(DriFenceObject * fence, unsigned type)
|
||||
{
|
||||
int signaled;
|
||||
int ret;
|
||||
|
||||
if (fence == NULL)
|
||||
return GL_TRUE;
|
||||
|
||||
_glthread_LOCK_MUTEX(fence->mutex);
|
||||
ret = drmFenceSignaled(fence->fd, &fence->fence, type, &signaled);
|
||||
_glthread_UNLOCK_MUTEX(fence->mutex);
|
||||
BM_CKFATAL(ret);
|
||||
return signaled;
|
||||
}
|
||||
|
||||
|
||||
extern drmBO *
|
||||
driBOKernel(struct _DriBufferObject *buf)
|
||||
{
|
||||
drmBO *ret;
|
||||
|
||||
assert(buf->private != NULL);
|
||||
ret = buf->pool->kernel(buf->pool, buf->private);
|
||||
if (!ret)
|
||||
BM_CKFATAL(-EINVAL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
|
||||
{
|
||||
assert(buf->private != NULL);
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, lazy));
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
}
|
||||
|
||||
void *
|
||||
driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
|
||||
{
|
||||
void *virtual;
|
||||
|
||||
assert(buf->private != NULL);
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
BM_CKFATAL(buf->pool->map(buf->pool, buf->private, flags, hint, &virtual));
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
return virtual;
|
||||
}
|
||||
|
||||
void
|
||||
driBOUnmap(struct _DriBufferObject *buf)
|
||||
{
|
||||
assert(buf->private != NULL);
|
||||
|
||||
buf->pool->unmap(buf->pool, buf->private);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
driBOOffset(struct _DriBufferObject *buf)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
assert(buf->private != NULL);
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
ret = buf->pool->offset(buf->pool, buf->private);
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned
|
||||
driBOFlags(struct _DriBufferObject *buf)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
assert(buf->private != NULL);
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
ret = buf->pool->flags(buf->pool, buf->private);
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct _DriBufferObject *
|
||||
driBOReference(struct _DriBufferObject *buf)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
if (++buf->refCount == 1) {
|
||||
BM_CKFATAL(-EINVAL);
|
||||
}
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
driBOUnReference(struct _DriBufferObject *buf)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
tmp = --buf->refCount;
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
if (!tmp) {
|
||||
buf->pool->destroy(buf->pool, buf->private);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
driBOData(struct _DriBufferObject *buf,
|
||||
unsigned size, const void *data, unsigned flags)
|
||||
{
|
||||
void *virtual;
|
||||
int newBuffer;
|
||||
struct _DriBufferPool *pool;
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
pool = buf->pool;
|
||||
if (!pool->create) {
|
||||
_mesa_error(NULL, GL_INVALID_OPERATION,
|
||||
"driBOData called on invalid buffer\n");
|
||||
BM_CKFATAL(-EINVAL);
|
||||
}
|
||||
newBuffer = !buf->private || (pool->size(pool, buf->private) < size) ||
|
||||
pool->map(pool, buf->private, DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_HINT_DONT_BLOCK, &virtual);
|
||||
|
||||
if (newBuffer) {
|
||||
if (buf->private)
|
||||
pool->destroy(pool, buf->private);
|
||||
if (!flags)
|
||||
flags = buf->flags;
|
||||
buf->private = pool->create(pool, size, flags, 0, buf->alignment);
|
||||
if (!buf->private)
|
||||
BM_CKFATAL(-ENOMEM);
|
||||
BM_CKFATAL(pool->map(pool, buf->private,
|
||||
DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_HINT_DONT_BLOCK, &virtual));
|
||||
}
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(virtual, data, size);
|
||||
|
||||
BM_CKFATAL(pool->unmap(pool, buf->private));
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
driBOSubData(struct _DriBufferObject *buf,
|
||||
unsigned long offset, unsigned long size, const void *data)
|
||||
{
|
||||
void *virtual;
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
if (size && data) {
|
||||
BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
|
||||
DRM_BO_FLAG_WRITE, 0, &virtual));
|
||||
memcpy((unsigned char *) virtual + offset, data, size);
|
||||
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
|
||||
}
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
driBOGetSubData(struct _DriBufferObject *buf,
|
||||
unsigned long offset, unsigned long size, void *data)
|
||||
{
|
||||
void *virtual;
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
if (size && data) {
|
||||
BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
|
||||
DRM_BO_FLAG_READ, 0, &virtual));
|
||||
memcpy(data, (unsigned char *) virtual + offset, size);
|
||||
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
|
||||
}
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
driBOSetStatic(struct _DriBufferObject *buf,
|
||||
unsigned long offset,
|
||||
unsigned long size, void *virtual, unsigned flags)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
if (buf->private != NULL) {
|
||||
_mesa_error(NULL, GL_INVALID_OPERATION,
|
||||
"Invalid buffer for setStatic\n");
|
||||
BM_CKFATAL(-EINVAL);
|
||||
}
|
||||
if (buf->pool->setstatic == NULL) {
|
||||
_mesa_error(NULL, GL_INVALID_OPERATION,
|
||||
"Invalid buffer pool for setStatic\n");
|
||||
BM_CKFATAL(-EINVAL);
|
||||
}
|
||||
|
||||
if (!flags)
|
||||
flags = buf->flags;
|
||||
|
||||
buf->private = buf->pool->setstatic(buf->pool, offset, size,
|
||||
virtual, flags);
|
||||
if (!buf->private) {
|
||||
_mesa_error(NULL, GL_OUT_OF_MEMORY,
|
||||
"Invalid buffer pool for setStatic\n");
|
||||
BM_CKFATAL(-ENOMEM);
|
||||
}
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
driGenBuffers(struct _DriBufferPool *pool,
|
||||
const char *name,
|
||||
unsigned n,
|
||||
struct _DriBufferObject *buffers[],
|
||||
unsigned alignment, unsigned flags, unsigned hint)
|
||||
{
|
||||
struct _DriBufferObject *buf;
|
||||
int i;
|
||||
|
||||
flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM |
|
||||
DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
|
||||
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
|
||||
if (!buf)
|
||||
BM_CKFATAL(-ENOMEM);
|
||||
|
||||
_glthread_INIT_MUTEX(buf->mutex);
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
buf->refCount = 1;
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
buf->flags = flags;
|
||||
buf->hint = hint;
|
||||
buf->name = name;
|
||||
buf->alignment = alignment;
|
||||
buf->pool = pool;
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
buffers[i] = buf;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
driBOUnReference(buffers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
driInitBufMgr(int fd)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
driBOCreateList(int target, drmBOList * list)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
BM_CKFATAL(drmBOCreateList(20, list));
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
}
|
||||
|
||||
void
|
||||
driBOResetList(drmBOList * list)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
BM_CKFATAL(drmBOResetList(list));
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
}
|
||||
|
||||
void
|
||||
driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
|
||||
unsigned flags, unsigned mask)
|
||||
{
|
||||
int newItem;
|
||||
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
BM_CKFATAL(drmAddValidateItem(list, driBOKernel(buf),
|
||||
flags, mask, &newItem));
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
|
||||
/*
|
||||
* Tell userspace pools to validate the buffer. This should be a
|
||||
* noop if the pool is already validated.
|
||||
* FIXME: We should have a list for this as well.
|
||||
*/
|
||||
|
||||
if (buf->pool->validate) {
|
||||
BM_CKFATAL(buf->pool->validate(buf->pool, buf->private));
|
||||
}
|
||||
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
}
|
||||
|
||||
void
|
||||
driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(buf->mutex);
|
||||
BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
|
||||
_glthread_UNLOCK_MUTEX(buf->mutex);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
driBOValidateList(int fd, drmBOList * list)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(bmMutex);
|
||||
BM_CKFATAL(drmBOValidateList(fd, list));
|
||||
_glthread_UNLOCK_MUTEX(bmMutex);
|
||||
}
|
||||
|
||||
void
|
||||
driPoolTakeDown(struct _DriBufferPool *pool)
|
||||
{
|
||||
pool->takeDown(pool);
|
||||
|
||||
}
|
||||
99
src/mesa/drivers/dri/common/dri_bufmgr.h
Normal file
99
src/mesa/drivers/dri/common/dri_bufmgr.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com>
|
||||
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#ifndef _DRI_BUFMGR_H_
|
||||
#define _DRI_BUFMGR_H_
|
||||
#include <xf86drm.h>
|
||||
|
||||
|
||||
struct _DriFenceObject;
|
||||
struct _DriBufferObject;
|
||||
struct _DriBufferPool;
|
||||
|
||||
extern struct _DriFenceObject *driFenceBuffers(int fd, char *name,
|
||||
unsigned flags);
|
||||
|
||||
extern struct _DriFenceObject *driFenceReference(struct _DriFenceObject *fence);
|
||||
|
||||
extern void driFenceUnReference(struct _DriFenceObject *fence);
|
||||
|
||||
extern void
|
||||
driFenceFinish(struct _DriFenceObject *fence, unsigned type, int lazy);
|
||||
|
||||
extern int driFenceSignaled(struct _DriFenceObject *fence, unsigned type);
|
||||
extern unsigned driFenceType(struct _DriFenceObject *fence);
|
||||
|
||||
/*
|
||||
* Return a pointer to the libdrm buffer object this DriBufferObject
|
||||
* uses.
|
||||
*/
|
||||
|
||||
extern drmBO *driBOKernel(struct _DriBufferObject *buf);
|
||||
extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags,
|
||||
unsigned hint);
|
||||
extern void driBOUnmap(struct _DriBufferObject *buf);
|
||||
extern unsigned long driBOOffset(struct _DriBufferObject *buf);
|
||||
extern unsigned driBOFlags(struct _DriBufferObject *buf);
|
||||
extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf);
|
||||
extern void driBOUnReference(struct _DriBufferObject *buf);
|
||||
extern void driBOData(struct _DriBufferObject *r_buf,
|
||||
unsigned size, const void *data, unsigned flags);
|
||||
extern void driBOSubData(struct _DriBufferObject *buf,
|
||||
unsigned long offset, unsigned long size,
|
||||
const void *data);
|
||||
extern void driBOGetSubData(struct _DriBufferObject *buf,
|
||||
unsigned long offset, unsigned long size,
|
||||
void *data);
|
||||
extern void driGenBuffers(struct _DriBufferPool *pool,
|
||||
const char *name,
|
||||
unsigned n,
|
||||
struct _DriBufferObject *buffers[],
|
||||
unsigned alignment, unsigned flags, unsigned hint);
|
||||
extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]);
|
||||
extern void driInitBufMgr(int fd);
|
||||
extern void driBOCreateList(int target, drmBOList * list);
|
||||
extern void driBOResetList(drmBOList * list);
|
||||
extern void driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf,
|
||||
unsigned flags, unsigned mask);
|
||||
extern void driBOValidateList(int fd, drmBOList * list);
|
||||
|
||||
extern void driBOFence(struct _DriBufferObject *buf,
|
||||
struct _DriFenceObject *fence);
|
||||
|
||||
extern void driPoolTakeDown(struct _DriBufferPool *pool);
|
||||
extern void driBOSetStatic(struct _DriBufferObject *buf,
|
||||
unsigned long offset,
|
||||
unsigned long size, void *virtual, unsigned flags);
|
||||
extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy);
|
||||
extern void driPoolTakeDown(struct _DriBufferPool *pool);
|
||||
|
||||
#endif
|
||||
86
src/mesa/drivers/dri/common/dri_bufpool.h
Normal file
86
src/mesa/drivers/dri/common/dri_bufpool.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#ifndef _DRI_BUFPOOL_H_
|
||||
#define _DRI_BUFPOOL_H_
|
||||
|
||||
#include <xf86drm.h>
|
||||
struct _DriFenceObject;
|
||||
|
||||
typedef struct _DriBufferPool
|
||||
{
|
||||
int fd;
|
||||
int (*map) (struct _DriBufferPool * pool, void *private,
|
||||
unsigned flags, int hint, void **virtual);
|
||||
int (*unmap) (struct _DriBufferPool * pool, void *private);
|
||||
int (*destroy) (struct _DriBufferPool * pool, void *private);
|
||||
unsigned long (*offset) (struct _DriBufferPool * pool, void *private);
|
||||
unsigned (*flags) (struct _DriBufferPool * pool, void *private);
|
||||
unsigned long (*size) (struct _DriBufferPool * pool, void *private);
|
||||
void *(*create) (struct _DriBufferPool * pool, unsigned long size,
|
||||
unsigned flags, unsigned hint, unsigned alignment);
|
||||
int (*fence) (struct _DriBufferPool * pool, void *private,
|
||||
struct _DriFenceObject * fence);
|
||||
drmBO *(*kernel) (struct _DriBufferPool * pool, void *private);
|
||||
int (*validate) (struct _DriBufferPool * pool, void *private);
|
||||
void *(*setstatic) (struct _DriBufferPool * pool, unsigned long offset,
|
||||
unsigned long size, void *virtual, unsigned flags);
|
||||
int (*waitIdle) (struct _DriBufferPool *pool, void *private,
|
||||
int lazy);
|
||||
void (*takeDown) (struct _DriBufferPool * pool);
|
||||
void *data;
|
||||
} DriBufferPool;
|
||||
|
||||
extern void bmError(int val, const char *file, const char *function,
|
||||
int line);
|
||||
#define BM_CKFATAL(val) \
|
||||
do{ \
|
||||
int tstVal = (val); \
|
||||
if (tstVal) \
|
||||
bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \
|
||||
} while(0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Builtin pools.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Kernel buffer objects. Size in multiples of page size. Page size aligned.
|
||||
*/
|
||||
|
||||
extern struct _DriBufferPool *driDRMPoolInit(int fd);
|
||||
extern struct _DriBufferPool *driDRMStaticPoolInit(int fd);
|
||||
|
||||
#endif
|
||||
221
src/mesa/drivers/dri/common/dri_drmpool.c
Normal file
221
src/mesa/drivers/dri/common/dri_drmpool.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <stdlib.h>
|
||||
#include "dri_bufpool.h"
|
||||
|
||||
/*
|
||||
* Buffer pool implementation using DRM buffer objects as DRI buffer objects.
|
||||
*/
|
||||
|
||||
static void *
|
||||
pool_create(struct _DriBufferPool *pool,
|
||||
unsigned long size, unsigned flags, unsigned hint,
|
||||
unsigned alignment)
|
||||
{
|
||||
drmBO *buf = (drmBO *) malloc(sizeof(*buf));
|
||||
int ret;
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
if (alignment && ((4096 % alignment) != 0))
|
||||
return NULL;
|
||||
|
||||
ret = drmBOCreate(pool->fd, NULL, 0, size, NULL, drm_bo_type_dc,
|
||||
flags, hint, buf);
|
||||
|
||||
if (ret) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *) buf;
|
||||
}
|
||||
|
||||
static int
|
||||
pool_destroy(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
drmBO *buf = (drmBO *) private;
|
||||
return drmBODestroy(pool->fd, buf);
|
||||
}
|
||||
|
||||
static int
|
||||
pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
|
||||
int hint, void **virtual)
|
||||
{
|
||||
drmBO *buf = (drmBO *) private;
|
||||
|
||||
return drmBOMap(pool->fd, buf, flags, hint, virtual);
|
||||
}
|
||||
|
||||
static int
|
||||
pool_unmap(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
drmBO *buf = (drmBO *) private;
|
||||
return drmBOUnmap(pool->fd, buf);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
pool_offset(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
drmBO *buf = (drmBO *) private;
|
||||
return buf->offset;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
pool_flags(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
drmBO *buf = (drmBO *) private;
|
||||
return buf->flags;
|
||||
}
|
||||
|
||||
|
||||
static unsigned long
|
||||
pool_size(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
drmBO *buf = (drmBO *) private;
|
||||
return buf->size;
|
||||
}
|
||||
|
||||
static int
|
||||
pool_fence(struct _DriBufferPool *pool, void *private,
|
||||
struct _DriFenceObject *fence)
|
||||
{
|
||||
/*
|
||||
* Noop. The kernel handles all fencing.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static drmBO *
|
||||
pool_kernel(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
return (drmBO *) private;
|
||||
}
|
||||
|
||||
static int
|
||||
pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
|
||||
{
|
||||
drmBO *buf = (drmBO *) private;
|
||||
return drmBOWaitIdle(pool->fd, buf, (lazy) ? DRM_BO_HINT_WAIT_LAZY:0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pool_takedown(struct _DriBufferPool *pool)
|
||||
{
|
||||
free(pool);
|
||||
}
|
||||
|
||||
|
||||
struct _DriBufferPool *
|
||||
driDRMPoolInit(int fd)
|
||||
{
|
||||
struct _DriBufferPool *pool;
|
||||
|
||||
pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
|
||||
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
pool->fd = fd;
|
||||
pool->map = &pool_map;
|
||||
pool->unmap = &pool_unmap;
|
||||
pool->destroy = &pool_destroy;
|
||||
pool->offset = &pool_offset;
|
||||
pool->flags = &pool_flags;
|
||||
pool->size = &pool_size;
|
||||
pool->create = &pool_create;
|
||||
pool->fence = &pool_fence;
|
||||
pool->kernel = &pool_kernel;
|
||||
pool->validate = NULL;
|
||||
pool->setstatic = NULL;
|
||||
pool->waitIdle = &pool_waitIdle;
|
||||
pool->takeDown = &pool_takedown;
|
||||
pool->data = NULL;
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
pool_setstatic(struct _DriBufferPool *pool, unsigned long offset,
|
||||
unsigned long size, void *virtual, unsigned flags)
|
||||
{
|
||||
drmBO *buf = (drmBO *) malloc(sizeof(*buf));
|
||||
int ret;
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
|
||||
ret = drmBOCreate(pool->fd, NULL, offset, size, NULL, drm_bo_type_fake,
|
||||
flags, 0, buf);
|
||||
|
||||
if (ret) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf->virtual = virtual;
|
||||
|
||||
return (void *) buf;
|
||||
}
|
||||
|
||||
|
||||
struct _DriBufferPool *
|
||||
driDRMStaticPoolInit(int fd)
|
||||
{
|
||||
struct _DriBufferPool *pool;
|
||||
|
||||
pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
|
||||
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
pool->fd = fd;
|
||||
pool->map = &pool_map;
|
||||
pool->unmap = &pool_unmap;
|
||||
pool->destroy = &pool_destroy;
|
||||
pool->offset = &pool_offset;
|
||||
pool->flags = &pool_flags;
|
||||
pool->size = &pool_size;
|
||||
pool->create = NULL;
|
||||
pool->fence = &pool_fence;
|
||||
pool->kernel = &pool_kernel;
|
||||
pool->validate = NULL;
|
||||
pool->setstatic = &pool_setstatic;
|
||||
pool->waitIdle = &pool_waitIdle;
|
||||
pool->takeDown = &pool_takedown;
|
||||
pool->data = NULL;
|
||||
return pool;
|
||||
}
|
||||
@@ -403,8 +403,9 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
|
||||
__DRIcontextPrivate *pcp = pdp->driContextPriv;
|
||||
|
||||
if (!pcp || (pdp != pcp->driDrawablePriv)) {
|
||||
/* ERROR!!! */
|
||||
return;
|
||||
/* ERROR!!!
|
||||
* ..but we must ignore it. There can be many contexts bound to a drawable.
|
||||
*/
|
||||
}
|
||||
|
||||
psp = pdp->driScreenPriv;
|
||||
@@ -435,6 +436,7 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
|
||||
/* Error -- eg the window may have been destroyed. Keep going
|
||||
* with no cliprects.
|
||||
*/
|
||||
fprintf(stderr, "Drawable destroyed");
|
||||
pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
|
||||
pdp->numClipRects = 0;
|
||||
pdp->pClipRects = NULL;
|
||||
@@ -841,7 +843,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 );
|
||||
}
|
||||
|
||||
@@ -87,15 +87,15 @@ typedef struct __DRIutilversionRec2 __DRIutilversion2;
|
||||
#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \
|
||||
do { \
|
||||
while (*(pdp->pStamp) != pdp->lastStamp) { \
|
||||
DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, \
|
||||
pdp->driContextPriv->hHWContext); \
|
||||
register unsigned int hwContext = psp->pSAREA->lock.lock & \
|
||||
~(DRM_LOCK_HELD | DRM_LOCK_CONT); \
|
||||
DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
|
||||
\
|
||||
DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
|
||||
DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
|
||||
DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
|
||||
\
|
||||
DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, \
|
||||
pdp->driContextPriv->hHWContext); \
|
||||
DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -7,16 +7,6 @@ LIBNAME = i915_dri.so
|
||||
MINIGLX_SOURCES = server/intel_dri.c
|
||||
|
||||
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 \
|
||||
@@ -24,19 +14,43 @@ 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_vtbl.c \
|
||||
intel_context.c \
|
||||
intel_ioctl.c \
|
||||
intel_pixel.c \
|
||||
intel_render.c \
|
||||
intel_rotate.c \
|
||||
intel_screen.c \
|
||||
intel_span.c \
|
||||
intel_state.c \
|
||||
intel_tex.c \
|
||||
intel_texmem.c \
|
||||
intel_tris.c
|
||||
|
||||
intel_tris.c \
|
||||
intel_fbo.c \
|
||||
intel_depthstencil.c \
|
||||
intel_batchpool.c
|
||||
C_SOURCES = \
|
||||
$(COMMON_SOURCES) \
|
||||
$(DRIVER_SOURCES)
|
||||
|
||||
@@ -38,37 +38,38 @@
|
||||
* Mesa's Driver Functions
|
||||
***************************************/
|
||||
|
||||
static const struct dri_extension i830_extensions[] =
|
||||
{
|
||||
{ "GL_ARB_texture_env_crossbar", NULL },
|
||||
{ NULL, NULL }
|
||||
static const struct dri_extension i830_extensions[] = {
|
||||
{"GL_ARB_texture_env_crossbar", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
static void i830InitDriverFunctions( struct dd_function_table *functions )
|
||||
static void
|
||||
i830InitDriverFunctions(struct dd_function_table *functions)
|
||||
{
|
||||
intelInitDriverFunctions( functions );
|
||||
i830InitStateFuncs( functions );
|
||||
i830InitTextureFuncs( functions );
|
||||
intelInitDriverFunctions(functions);
|
||||
i830InitStateFuncs(functions);
|
||||
i830InitTextureFuncs(functions);
|
||||
}
|
||||
|
||||
|
||||
GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
GLboolean
|
||||
i830CreateContext(const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
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;
|
||||
GLuint i;
|
||||
if (!i830) return GL_FALSE;
|
||||
if (!i830)
|
||||
return GL_FALSE;
|
||||
|
||||
i830InitVtbl( i830 );
|
||||
i830InitDriverFunctions( &functions );
|
||||
i830InitVtbl(i830);
|
||||
i830InitDriverFunctions(&functions);
|
||||
|
||||
if (!intelInitContext( intel, mesaVis, driContextPriv,
|
||||
sharedContextPrivate, &functions )) {
|
||||
if (!intelInitContext(intel, mesaVis, driContextPriv,
|
||||
sharedContextPrivate, &functions)) {
|
||||
FREE(i830);
|
||||
return GL_FALSE;
|
||||
}
|
||||
@@ -77,48 +78,27 @@ 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,
|
||||
(unsigned *) & 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 = I830_TEX_UNITS;
|
||||
i = driQueryOptioni( &intel->intelScreen->optionCache, "allow_large_textures");
|
||||
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,
|
||||
i );
|
||||
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) );
|
||||
_tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
|
||||
18 * sizeof(GLfloat));
|
||||
|
||||
intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf;
|
||||
|
||||
driInitExtensions( ctx, i830_extensions, GL_FALSE );
|
||||
driInitExtensions(ctx, i830_extensions, GL_FALSE);
|
||||
|
||||
i830InitState( i830 );
|
||||
i830InitState(i830);
|
||||
i830InitMetaFuncs(i830);
|
||||
|
||||
|
||||
_tnl_allow_vertex_fog( ctx, 1 );
|
||||
_tnl_allow_pixel_fog( ctx, 0 );
|
||||
_tnl_allow_vertex_fog(ctx, 1);
|
||||
_tnl_allow_pixel_fog(ctx, 0);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -103,13 +101,25 @@ struct i830_texture_object
|
||||
|
||||
#define I830_TEX_UNITS 4
|
||||
|
||||
struct i830_hw_state {
|
||||
struct i830_hw_state
|
||||
{
|
||||
GLuint Ctx[I830_CTX_SETUP_SIZE];
|
||||
GLuint Buffer[I830_DEST_SETUP_SIZE];
|
||||
GLuint Stipple[I830_STP_SETUP_SIZE];
|
||||
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...
|
||||
*/
|
||||
struct _DriBufferObject *tex_buffer[I830_TEX_UNITS];
|
||||
GLuint tex_offset[I830_TEX_UNITS];
|
||||
|
||||
GLuint emitted; /* I810_UPLOAD_* */
|
||||
GLuint active;
|
||||
};
|
||||
@@ -118,15 +128,12 @@ struct i830_context
|
||||
{
|
||||
struct intel_context intel;
|
||||
|
||||
GLuint lodbias_tm0s3[MAX_TEXTURE_UNITS];
|
||||
DECLARE_RENDERINPUTS(last_index_bitset);
|
||||
|
||||
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))
|
||||
|
||||
|
||||
|
||||
@@ -147,71 +154,55 @@ do { \
|
||||
|
||||
/* i830_vtbl.c
|
||||
*/
|
||||
extern void
|
||||
i830InitVtbl( i830ContextPtr i830 );
|
||||
extern void i830InitVtbl(struct i830_context *i830);
|
||||
|
||||
/* i830_context.c
|
||||
*/
|
||||
extern GLboolean
|
||||
i830CreateContext( const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
i830CreateContext(const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
void *sharedContextPrivate);
|
||||
|
||||
/* i830_tex.c, i830_texstate.c
|
||||
*/
|
||||
extern void
|
||||
i830UpdateTextureState( intelContextPtr intel );
|
||||
extern void i830UpdateTextureState(struct intel_context *intel);
|
||||
|
||||
extern void
|
||||
i830InitTextureFuncs( struct dd_function_table *functions );
|
||||
|
||||
extern intelTextureObjectPtr
|
||||
i830AllocTexObj( struct gl_texture_object *tObj );
|
||||
extern void i830InitTextureFuncs(struct dd_function_table *functions);
|
||||
|
||||
/* i830_texblend.c
|
||||
*/
|
||||
extern GLuint i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
const struct gl_tex_env_combine_state * combine, GLint blendUnit,
|
||||
GLuint texel_op, GLuint *state, const GLfloat *factor );
|
||||
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 );
|
||||
extern void i830EmitTextureBlend(struct i830_context *i830);
|
||||
|
||||
|
||||
/* i830_state.c
|
||||
*/
|
||||
extern void
|
||||
i830InitStateFuncs( struct dd_function_table *functions );
|
||||
extern void i830InitStateFuncs(struct dd_function_table *functions);
|
||||
|
||||
extern void
|
||||
i830EmitState( i830ContextPtr i830 );
|
||||
extern void i830EmitState(struct i830_context *i830);
|
||||
|
||||
extern void
|
||||
i830InitState( i830ContextPtr i830 );
|
||||
extern void 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 i830InitMetaFuncs(struct i830_context *i830);
|
||||
|
||||
extern void
|
||||
i830ClearWithTris( intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch);
|
||||
|
||||
extern void
|
||||
i830RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
|
||||
i830RotateWindow(struct intel_context *intel, __DRIdrawablePrivate * dPriv,
|
||||
GLuint srcBuf);
|
||||
|
||||
#endif
|
||||
/*======================================================================
|
||||
* 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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -407,7 +407,7 @@
|
||||
#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)&0xff)
|
||||
|
||||
@@ -36,21 +36,23 @@
|
||||
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_fbo.h"
|
||||
|
||||
#include "i830_context.h"
|
||||
#include "i830_reg.h"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_STATE
|
||||
|
||||
static void
|
||||
i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
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;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
|
||||
DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(func), ref, mask);
|
||||
|
||||
|
||||
@@ -67,12 +69,11 @@ i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
}
|
||||
|
||||
static void
|
||||
i830StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
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);
|
||||
DBG("%s : mask 0x%x\n", __FUNCTION__, mask);
|
||||
|
||||
mask = mask & 0xff;
|
||||
|
||||
@@ -83,21 +84,22 @@ i830StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
}
|
||||
|
||||
static void
|
||||
i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
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)
|
||||
fprintf(stderr, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
|
||||
DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(fail),
|
||||
_mesa_lookup_enum_by_nr(zfail),
|
||||
_mesa_lookup_enum_by_nr(zpass));
|
||||
|
||||
fop = 0; dfop = 0; dpop = 0;
|
||||
fop = 0;
|
||||
dfop = 0;
|
||||
dpop = 0;
|
||||
|
||||
switch(fail) {
|
||||
switch (fail) {
|
||||
case GL_KEEP:
|
||||
fop = STENCILOP_KEEP;
|
||||
break;
|
||||
@@ -125,7 +127,7 @@ i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(zfail) {
|
||||
switch (zfail) {
|
||||
case GL_KEEP:
|
||||
dfop = STENCILOP_KEEP;
|
||||
break;
|
||||
@@ -153,7 +155,7 @@ i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(zpass) {
|
||||
switch (zpass) {
|
||||
case GL_KEEP:
|
||||
dpop = STENCILOP_KEEP;
|
||||
break;
|
||||
@@ -187,19 +189,22 @@ i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
|
||||
i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_PARMS |
|
||||
STENCIL_FAIL_OP(fop) |
|
||||
STENCIL_PASS_DEPTH_FAIL_OP(dfop) |
|
||||
STENCIL_PASS_DEPTH_PASS_OP(dpop));
|
||||
STENCIL_PASS_DEPTH_FAIL_OP
|
||||
(dfop) |
|
||||
STENCIL_PASS_DEPTH_PASS_OP
|
||||
(dpop));
|
||||
}
|
||||
|
||||
static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
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;
|
||||
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref);
|
||||
refInt = (GLuint)refByte;
|
||||
refInt = (GLuint) refByte;
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
i830->state.Ctx[I830_CTXREG_STATE2] &= ~ALPHA_TEST_REF_MASK;
|
||||
@@ -219,9 +224,10 @@ static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
* This function is substantially different from the old i830-specific driver.
|
||||
* I'm not sure which is correct.
|
||||
*/
|
||||
static void i830EvalLogicOpBlendState(GLcontext *ctx)
|
||||
static void
|
||||
i830EvalLogicOpBlendState(GLcontext * ctx)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
|
||||
@@ -230,12 +236,14 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx)
|
||||
ENABLE_LOGIC_OP_MASK);
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND |
|
||||
ENABLE_LOGIC_OP);
|
||||
} else if (ctx->Color.BlendEnabled) {
|
||||
}
|
||||
else if (ctx->Color.BlendEnabled) {
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND |
|
||||
ENABLE_LOGIC_OP_MASK);
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND |
|
||||
DISABLE_LOGIC_OP);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND |
|
||||
ENABLE_LOGIC_OP_MASK);
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND |
|
||||
@@ -243,13 +251,13 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
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)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]);
|
||||
@@ -257,7 +265,8 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] = (a<<24) | (r<<16) | (g<<8) | b;
|
||||
i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] =
|
||||
(a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,9 +275,10 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
* function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
|
||||
* change the interpretation of the blend function.
|
||||
*/
|
||||
static void i830_set_blend_state( GLcontext * ctx )
|
||||
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;
|
||||
@@ -277,10 +287,11 @@ static void i830_set_blend_state( GLcontext * ctx )
|
||||
int s1;
|
||||
|
||||
|
||||
funcRGB = SRC_BLND_FACT( intel_translate_blend_factor( ctx->Color.BlendSrcRGB ) )
|
||||
| DST_BLND_FACT( intel_translate_blend_factor( ctx->Color.BlendDstRGB ) );
|
||||
funcRGB =
|
||||
SRC_BLND_FACT(intel_translate_blend_factor(ctx->Color.BlendSrcRGB))
|
||||
| DST_BLND_FACT(intel_translate_blend_factor(ctx->Color.BlendDstRGB));
|
||||
|
||||
switch(ctx->Color.BlendEquationRGB) {
|
||||
switch (ctx->Color.BlendEquationRGB) {
|
||||
case GL_FUNC_ADD:
|
||||
eqnRGB = BLENDFUNC_ADD;
|
||||
break;
|
||||
@@ -299,16 +310,16 @@ static void i830_set_blend_state( GLcontext * ctx )
|
||||
eqnRGB = BLENDFUNC_RVRSE_SUB;
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
|
||||
__FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB );
|
||||
fprintf(stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
|
||||
__FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
funcA = SRC_ABLEND_FACT( intel_translate_blend_factor( ctx->Color.BlendSrcA ) )
|
||||
| DST_ABLEND_FACT( intel_translate_blend_factor( ctx->Color.BlendDstA ) );
|
||||
funcA = SRC_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.BlendSrcA))
|
||||
| DST_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.BlendDstA));
|
||||
|
||||
switch(ctx->Color.BlendEquationA) {
|
||||
switch (ctx->Color.BlendEquationA) {
|
||||
case GL_FUNC_ADD:
|
||||
eqnA = BLENDFUNC_ADD;
|
||||
break;
|
||||
@@ -327,8 +338,8 @@ static void i830_set_blend_state( GLcontext * ctx )
|
||||
eqnA = BLENDFUNC_RVRSE_SUB;
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "[%s:%u] Invalid alpha blend equation (0x%04x).\n",
|
||||
__FUNCTION__, __LINE__, ctx->Color.BlendEquationA );
|
||||
fprintf(stderr, "[%s:%u] Invalid alpha blend equation (0x%04x).\n",
|
||||
__FUNCTION__, __LINE__, ctx->Color.BlendEquationA);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -341,7 +352,7 @@ static void i830_set_blend_state( GLcontext * ctx )
|
||||
| ENABLE_SRC_BLND_FACTOR | ENABLE_DST_BLND_FACTOR
|
||||
| ENABLE_COLR_BLND_FUNC;
|
||||
|
||||
if ( (eqnA | funcA) != (eqnRGB | funcRGB) )
|
||||
if ((eqnA | funcA) != (eqnRGB | funcRGB))
|
||||
iab |= ENABLE_INDPT_ALPHA_BLEND;
|
||||
else
|
||||
iab |= DISABLE_INDPT_ALPHA_BLEND;
|
||||
@@ -361,35 +372,33 @@ static void i830_set_blend_state( GLcontext * ctx )
|
||||
i830EvalLogicOpBlendState(ctx);
|
||||
|
||||
if (0) {
|
||||
fprintf(stderr, "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n",
|
||||
__FUNCTION__, __LINE__,
|
||||
i830->state.Ctx[I830_CTXREG_STATE1],
|
||||
fprintf(stderr,
|
||||
"[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n",
|
||||
__FUNCTION__, __LINE__, i830->state.Ctx[I830_CTXREG_STATE1],
|
||||
i830->state.Ctx[I830_CTXREG_IALPHAB],
|
||||
(ctx->Color.BlendEnabled) ? "en" : "dis");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void i830BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB,
|
||||
GLenum modeA)
|
||||
static void
|
||||
i830BlendEquationSeparate(GLcontext * ctx, GLenum modeRGB, GLenum modeA)
|
||||
{
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s -> %s, %s\n", __FUNCTION__,
|
||||
DBG("%s -> %s, %s\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(modeRGB),
|
||||
_mesa_lookup_enum_by_nr(modeA));
|
||||
|
||||
(void) modeRGB;
|
||||
(void) modeA;
|
||||
i830_set_blend_state( ctx );
|
||||
i830_set_blend_state(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
|
||||
GLenum dfactorRGB, GLenum sfactorA,
|
||||
GLenum dfactorA )
|
||||
static void
|
||||
i830BlendFuncSeparate(GLcontext * ctx, GLenum sfactorRGB,
|
||||
GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA)
|
||||
{
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__,
|
||||
DBG("%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(sfactorRGB),
|
||||
_mesa_lookup_enum_by_nr(dfactorRGB),
|
||||
_mesa_lookup_enum_by_nr(sfactorA),
|
||||
@@ -399,18 +408,18 @@ static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
|
||||
(void) dfactorRGB;
|
||||
(void) sfactorA;
|
||||
(void) dfactorA;
|
||||
i830_set_blend_state( ctx );
|
||||
i830_set_blend_state(ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void i830DepthFunc(GLcontext *ctx, GLenum func)
|
||||
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)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK;
|
||||
@@ -418,12 +427,12 @@ static void i830DepthFunc(GLcontext *ctx, GLenum func)
|
||||
DEPTH_TEST_FUNC(test));
|
||||
}
|
||||
|
||||
static void i830DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
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);
|
||||
DBG("%s flag (%d)\n", __FUNCTION__, flag);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
|
||||
@@ -441,12 +450,13 @@ static void i830DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
* The i830 supports a 4x4 stipple natively, GL wants 32x32.
|
||||
* Fortunately stipple is usually a repeating pattern.
|
||||
*/
|
||||
static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
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;
|
||||
int i, j, k;
|
||||
int active = (ctx->Polygon.StippleFlag &&
|
||||
i830->intel.reduced_primitive == GL_TRIANGLES);
|
||||
GLuint newMask;
|
||||
@@ -456,14 +466,18 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
|
||||
}
|
||||
|
||||
p[0] = mask[12] & 0xf; p[0] |= p[0] << 4;
|
||||
p[1] = mask[8] & 0xf; p[1] |= p[1] << 4;
|
||||
p[2] = mask[4] & 0xf; p[2] |= p[2] << 4;
|
||||
p[3] = mask[0] & 0xf; p[3] |= p[3] << 4;
|
||||
p[0] = mask[12] & 0xf;
|
||||
p[0] |= p[0] << 4;
|
||||
p[1] = mask[8] & 0xf;
|
||||
p[1] |= p[1] << 4;
|
||||
p[2] = mask[4] & 0xf;
|
||||
p[2] |= p[2] << 4;
|
||||
p[3] = mask[0] & 0xf;
|
||||
p[3] |= p[3] << 4;
|
||||
|
||||
for (k = 0 ; k < 8 ; k++)
|
||||
for (j = 3 ; j >= 0; j--)
|
||||
for (i = 0 ; i < 4 ; i++, m++)
|
||||
for (k = 0; k < 8; k++)
|
||||
for (j = 3; j >= 0; j--)
|
||||
for (i = 0; i < 4; i++, m++)
|
||||
if (*m != p[j]) {
|
||||
i830->intel.hw_stipple = 0;
|
||||
return;
|
||||
@@ -471,8 +485,7 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
|
||||
newMask = (((p[0] & 0xf) << 0) |
|
||||
((p[1] & 0xf) << 4) |
|
||||
((p[2] & 0xf) << 8) |
|
||||
((p[3] & 0xf) << 12));
|
||||
((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12));
|
||||
|
||||
|
||||
if (newMask == 0xffff || newMask == 0x0) {
|
||||
@@ -493,48 +506,40 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
/* =============================================================
|
||||
* Hardware clipping
|
||||
*/
|
||||
static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
GLsizei w, GLsizei h)
|
||||
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;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
|
||||
DBG("[%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);
|
||||
i830->state.Buffer[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
|
||||
}
|
||||
|
||||
static void i830LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
static void
|
||||
i830LogicOp(GLcontext * ctx, GLenum opcode)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
int tmp = intel_translate_logic_op( opcode );
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int tmp = intel_translate_logic_op(opcode);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
i830->state.Ctx[I830_CTXREG_STATE4] &= ~LOGICOP_MASK;
|
||||
@@ -543,13 +548,13 @@ static void i830LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
|
||||
|
||||
|
||||
static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
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)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (!ctx->Polygon.CullFlag) {
|
||||
mode = CULLMODE_NONE;
|
||||
@@ -571,16 +576,16 @@ static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] |= ENABLE_CULL_MODE | mode;
|
||||
}
|
||||
|
||||
static void i830LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
static void
|
||||
i830LineWidth(GLcontext * ctx, GLfloat widthf)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT( ctx );
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
int width;
|
||||
int state5;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
width = (int)(widthf * 2);
|
||||
width = (int) (widthf * 2);
|
||||
CLAMP_SELF(width, 1, 15);
|
||||
|
||||
state5 = i830->state.Ctx[I830_CTXREG_STATE5] & ~FIXED_LINE_WIDTH_MASK;
|
||||
@@ -592,13 +597,13 @@ static void i830LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
}
|
||||
}
|
||||
|
||||
static void i830PointSize(GLcontext *ctx, GLfloat size)
|
||||
static void
|
||||
i830PointSize(GLcontext * ctx, GLfloat size)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
GLint point_size = (int)size;
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
GLint point_size = (int) size;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
CLAMP_SELF(point_size, 1, 256);
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
@@ -612,23 +617,21 @@ static void i830PointSize(GLcontext *ctx, GLfloat size)
|
||||
* Color masks
|
||||
*/
|
||||
|
||||
static void i830ColorMask(GLcontext *ctx,
|
||||
GLboolean r, GLboolean g,
|
||||
GLboolean b, GLboolean a)
|
||||
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)
|
||||
fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a);
|
||||
DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a);
|
||||
|
||||
tmp = ((i830->state.Ctx[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) |
|
||||
ENABLE_COLOR_MASK |
|
||||
ENABLE_COLOR_WRITE |
|
||||
((!r) << WRITEMASK_RED_SHIFT) |
|
||||
((!g) << WRITEMASK_GREEN_SHIFT) |
|
||||
((!b) << WRITEMASK_BLUE_SHIFT) |
|
||||
((!a) << WRITEMASK_ALPHA_SHIFT));
|
||||
((!b) << WRITEMASK_BLUE_SHIFT) | ((!a) << WRITEMASK_ALPHA_SHIFT));
|
||||
|
||||
if (tmp != i830->state.Ctx[I830_CTXREG_ENABLES_2]) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
@@ -636,9 +639,10 @@ static void i830ColorMask(GLcontext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void update_specular( 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;
|
||||
@@ -649,22 +653,22 @@ static void update_specular( GLcontext *ctx )
|
||||
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_SPEC_ADD;
|
||||
}
|
||||
|
||||
static void i830LightModelfv(GLcontext *ctx, GLenum pname,
|
||||
const GLfloat *param)
|
||||
static void
|
||||
i830LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
|
||||
{
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
|
||||
update_specular( ctx );
|
||||
update_specular(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* In Mesa 3.5 we can reliably do native flatshading.
|
||||
*/
|
||||
static void i830ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
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);
|
||||
|
||||
|
||||
@@ -673,12 +677,14 @@ static void i830ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] &= ~SHADE_MODE_MASK;
|
||||
|
||||
if (mode == GL_FLAT) {
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_FLAT) |
|
||||
FOG_SHADE_MODE(SHADE_MODE_FLAT) |
|
||||
SPEC_SHADE_MODE(SHADE_MODE_FLAT) |
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] |=
|
||||
(ALPHA_SHADE_MODE(SHADE_MODE_FLAT) | FOG_SHADE_MODE(SHADE_MODE_FLAT)
|
||||
| SPEC_SHADE_MODE(SHADE_MODE_FLAT) |
|
||||
COLOR_SHADE_MODE(SHADE_MODE_FLAT));
|
||||
} else {
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
}
|
||||
else {
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] |=
|
||||
(ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
COLOR_SHADE_MODE(SHADE_MODE_LINEAR));
|
||||
@@ -688,34 +694,36 @@ static void i830ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
/* =============================================================
|
||||
* Fog
|
||||
*/
|
||||
static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
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__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (pname == GL_FOG_COLOR) {
|
||||
GLuint color = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) |
|
||||
((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) |
|
||||
((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0));
|
||||
GLuint color = (((GLubyte) (ctx->Fog.Color[0] * 255.0F) << 16) |
|
||||
((GLubyte) (ctx->Fog.Color[1] * 255.0F) << 8) |
|
||||
((GLubyte) (ctx->Fog.Color[2] * 255.0F) << 0));
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
i830->state.Ctx[I830_CTXREG_FOGCOLOR] = (_3DSTATE_FOG_COLOR_CMD | color);
|
||||
i830->state.Ctx[I830_CTXREG_FOGCOLOR] =
|
||||
(_3DSTATE_FOG_COLOR_CMD | color);
|
||||
}
|
||||
}
|
||||
|
||||
/* =============================================================
|
||||
*/
|
||||
|
||||
static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
static void
|
||||
i830Enable(GLcontext * ctx, GLenum cap, GLboolean state)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(ctx);
|
||||
|
||||
switch(cap) {
|
||||
switch (cap) {
|
||||
case GL_LIGHTING:
|
||||
case GL_COLOR_SUM:
|
||||
update_specular( ctx );
|
||||
update_specular(ctx);
|
||||
break;
|
||||
|
||||
case GL_ALPHA_TEST:
|
||||
@@ -738,7 +746,7 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
/* Logicop doesn't seem to work at 16bpp:
|
||||
*/
|
||||
if (i830->intel.intelScreen->cpp == 2)
|
||||
FALLBACK( &i830->intel, I830_FALLBACK_LOGICOP, state );
|
||||
FALLBACK(&i830->intel, I830_FALLBACK_LOGICOP, state);
|
||||
break;
|
||||
|
||||
case GL_DITHER:
|
||||
@@ -762,7 +770,7 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
|
||||
/* Also turn off depth writes when GL_DEPTH_TEST is disabled:
|
||||
*/
|
||||
i830DepthMask( ctx, ctx->Depth.Mask );
|
||||
i830DepthMask(ctx, ctx->Depth.Mask);
|
||||
break;
|
||||
|
||||
case GL_SCISSOR_TEST:
|
||||
@@ -770,12 +778,10 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
|
||||
if (state)
|
||||
i830->state.Buffer[I830_DESTREG_SENABLE] =
|
||||
(_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
ENABLE_SCISSOR_RECT);
|
||||
(_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT);
|
||||
else
|
||||
i830->state.Buffer[I830_DESTREG_SENABLE] =
|
||||
(_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
DISABLE_SCISSOR_RECT);
|
||||
(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
|
||||
|
||||
break;
|
||||
|
||||
@@ -806,20 +812,32 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
break;
|
||||
|
||||
case GL_STENCIL_TEST:
|
||||
if (i830->intel.hw_stencil) {
|
||||
{
|
||||
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 );
|
||||
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;
|
||||
|
||||
@@ -829,8 +847,7 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
* supports it. Disabled for now.
|
||||
*/
|
||||
if (i830->intel.hw_stipple &&
|
||||
i830->intel.reduced_primitive == GL_TRIANGLES)
|
||||
{
|
||||
i830->intel.reduced_primitive == GL_TRIANGLES) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
|
||||
i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE;
|
||||
if (state)
|
||||
@@ -844,7 +861,8 @@ 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;
|
||||
|
||||
@@ -859,15 +877,13 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
DISABLE_TEX_CNTRL_STAGE |
|
||||
TEXOP_SCALE_1X |
|
||||
TEXOP_MODIFY_PARMS |
|
||||
TEXOP_LAST_STAGE |
|
||||
TEXBLENDOP_ARG1);
|
||||
TEXOP_LAST_STAGE | TEXBLENDOP_ARG1);
|
||||
i830->state.TexBlend[0][1] = (_3DSTATE_MAP_BLEND_OP_CMD(0) |
|
||||
TEXPIPE_ALPHA |
|
||||
ENABLE_TEXOUTPUT_WRT_SEL |
|
||||
TEXOP_OUTPUT_CURRENT |
|
||||
TEXOP_SCALE_1X |
|
||||
TEXOP_MODIFY_PARMS |
|
||||
TEXBLENDOP_ARG1);
|
||||
TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
|
||||
i830->state.TexBlend[0][2] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) |
|
||||
TEXPIPE_COLOR |
|
||||
TEXBLEND_ARG1 |
|
||||
@@ -902,6 +918,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 +928,10 @@ 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 |
|
||||
@@ -928,28 +948,27 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
ENABLE_SRC_BLND_FACTOR |
|
||||
SRC_BLND_FACT(BLENDFACT_ONE) |
|
||||
ENABLE_DST_BLND_FACTOR |
|
||||
DST_BLND_FACT(BLENDFACT_ZERO) );
|
||||
DST_BLND_FACT(BLENDFACT_ZERO));
|
||||
|
||||
i830->state.Ctx[I830_CTXREG_STATE2] = (_3DSTATE_MODES_2_CMD |
|
||||
ENABLE_GLOBAL_DEPTH_BIAS |
|
||||
GLOBAL_DEPTH_BIAS(0) |
|
||||
ENABLE_ALPHA_TEST_FUNC |
|
||||
ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) |
|
||||
ALPHA_REF_VALUE(0) );
|
||||
ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS)
|
||||
| ALPHA_REF_VALUE(0));
|
||||
|
||||
i830->state.Ctx[I830_CTXREG_STATE3] = (_3DSTATE_MODES_3_CMD |
|
||||
ENABLE_DEPTH_TEST_FUNC |
|
||||
DEPTH_TEST_FUNC(COMPAREFUNC_LESS) |
|
||||
ENABLE_ALPHA_SHADE_MODE |
|
||||
ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
ENABLE_FOG_SHADE_MODE |
|
||||
ALPHA_SHADE_MODE(SHADE_MODE_LINEAR)
|
||||
| ENABLE_FOG_SHADE_MODE |
|
||||
FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
ENABLE_SPEC_SHADE_MODE |
|
||||
SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
ENABLE_COLOR_SHADE_MODE |
|
||||
COLOR_SHADE_MODE(SHADE_MODE_LINEAR) |
|
||||
ENABLE_CULL_MODE |
|
||||
CULLMODE_NONE);
|
||||
COLOR_SHADE_MODE(SHADE_MODE_LINEAR)
|
||||
| ENABLE_CULL_MODE | CULLMODE_NONE);
|
||||
|
||||
i830->state.Ctx[I830_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD |
|
||||
ENABLE_LOGIC_OP_FUNC |
|
||||
@@ -961,22 +980,21 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
|
||||
i830->state.Ctx[I830_CTXREG_STENCILTST] = (_3DSTATE_STENCIL_TEST_CMD |
|
||||
ENABLE_STENCIL_PARMS |
|
||||
STENCIL_FAIL_OP(STENCILOP_KEEP) |
|
||||
STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_KEEP) |
|
||||
STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_KEEP) |
|
||||
STENCIL_FAIL_OP(STENCILOP_KEEP)
|
||||
|
|
||||
STENCIL_PASS_DEPTH_FAIL_OP
|
||||
(STENCILOP_KEEP) |
|
||||
STENCIL_PASS_DEPTH_PASS_OP
|
||||
(STENCILOP_KEEP) |
|
||||
ENABLE_STENCIL_TEST_FUNC |
|
||||
STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS) |
|
||||
STENCIL_TEST_FUNC
|
||||
(COMPAREFUNC_ALWAYS) |
|
||||
ENABLE_STENCIL_REF_VALUE |
|
||||
STENCIL_REF_VALUE(0) );
|
||||
STENCIL_REF_VALUE(0));
|
||||
|
||||
i830->state.Ctx[I830_CTXREG_STATE5] = (_3DSTATE_MODES_5_CMD |
|
||||
FLUSH_TEXTURE_CACHE |
|
||||
ENABLE_SPRITE_POINT_TEX |
|
||||
SPRITE_POINT_TEX_OFF |
|
||||
ENABLE_FIXED_LINE_WIDTH |
|
||||
FIXED_LINE_WIDTH(0x2) | /* 1.0 */
|
||||
i830->state.Ctx[I830_CTXREG_STATE5] = (_3DSTATE_MODES_5_CMD | FLUSH_TEXTURE_CACHE | ENABLE_SPRITE_POINT_TEX | SPRITE_POINT_TEX_OFF | ENABLE_FIXED_LINE_WIDTH | FIXED_LINE_WIDTH(0x2) | /* 1.0 */
|
||||
ENABLE_FIXED_POINT_WIDTH |
|
||||
FIXED_POINT_WIDTH(1) );
|
||||
FIXED_POINT_WIDTH(1));
|
||||
|
||||
i830->state.Ctx[I830_CTXREG_IALPHAB] = (_3DSTATE_INDPT_ALPHA_BLEND_CMD |
|
||||
DISABLE_INDPT_ALPHA_BLEND |
|
||||
@@ -1001,24 +1019,17 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
i830->state.Stipple[I830_STPREG_ST0] = _3DSTATE_STIPPLE;
|
||||
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK |
|
||||
BUF_3D_PITCH(screen->front.pitch) | /* pitch in bytes */
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(screen->front.pitch) | /* pitch in bytes */
|
||||
BUF_3D_USE_FENCE);
|
||||
|
||||
|
||||
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) | /* pitch in bytes */
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | BUF_3D_PITCH(screen->depth.pitch) | /* pitch in bytes */
|
||||
BUF_3D_USE_FENCE);
|
||||
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 */
|
||||
@@ -1043,7 +1054,8 @@ static void i830_init_packets( i830ContextPtr i830 )
|
||||
}
|
||||
|
||||
|
||||
void i830InitStateFuncs( struct dd_function_table *functions )
|
||||
void
|
||||
i830InitStateFuncs(struct dd_function_table *functions)
|
||||
{
|
||||
functions->AlphaFunc = i830AlphaFunc;
|
||||
functions->BlendColor = i830BlendColor;
|
||||
@@ -1068,25 +1080,21 @@ 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;
|
||||
|
||||
i830_init_packets( i830 );
|
||||
i830_init_packets(i830);
|
||||
|
||||
intelInitState( ctx );
|
||||
intelInitState(ctx);
|
||||
|
||||
memcpy( &i830->initial, &i830->state, sizeof(i830->state) );
|
||||
memcpy(&i830->initial, &i830->state, sizeof(i830->state));
|
||||
|
||||
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);
|
||||
I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -45,261 +45,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static void
|
||||
i830TexEnv(GLcontext * ctx, GLenum target,
|
||||
GLenum pname, const GLfloat * param)
|
||||
{
|
||||
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:
|
||||
@@ -319,13 +71,16 @@ static void i830TexEnv( GLcontext *ctx, GLenum target,
|
||||
case GL_ALPHA_SCALE:
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_LOD_BIAS: {
|
||||
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;
|
||||
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] |=
|
||||
i830->lodbias_tm0s3[unit] =
|
||||
((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK);
|
||||
break;
|
||||
}
|
||||
@@ -335,22 +90,11 @@ static void i830TexEnv( GLcontext *ctx, GLenum target,
|
||||
}
|
||||
}
|
||||
|
||||
static void i830BindTexture( GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj )
|
||||
|
||||
|
||||
|
||||
void
|
||||
i830InitTextureFuncs(struct dd_function_table *functions)
|
||||
{
|
||||
i830TextureObjectPtr tex;
|
||||
|
||||
if (!texObj->DriverData)
|
||||
i830AllocTexObj( texObj );
|
||||
|
||||
tex = (i830TextureObjectPtr)texObj->DriverData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i830InitTextureFuncs( struct dd_function_table *functions )
|
||||
{
|
||||
functions->BindTexture = i830BindTexture;
|
||||
functions->TexEnv = i830TexEnv;
|
||||
functions->TexParameter = i830TexParameter;
|
||||
}
|
||||
|
||||
@@ -46,39 +46,35 @@
|
||||
/* ================================================================
|
||||
* Texture combine functions
|
||||
*/
|
||||
static GLuint pass_through( GLuint *state, GLuint blendUnit )
|
||||
static GLuint
|
||||
pass_through(GLuint * state, GLuint blendUnit)
|
||||
{
|
||||
state[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
|
||||
TEXPIPE_COLOR |
|
||||
ENABLE_TEXOUTPUT_WRT_SEL |
|
||||
TEXOP_OUTPUT_CURRENT |
|
||||
DISABLE_TEX_CNTRL_STAGE |
|
||||
TEXOP_SCALE_1X |
|
||||
TEXOP_MODIFY_PARMS |
|
||||
TEXBLENDOP_ARG1);
|
||||
TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
|
||||
state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
|
||||
TEXPIPE_ALPHA |
|
||||
ENABLE_TEXOUTPUT_WRT_SEL |
|
||||
TEXOP_OUTPUT_CURRENT |
|
||||
TEXOP_SCALE_1X |
|
||||
TEXOP_MODIFY_PARMS |
|
||||
TEXBLENDOP_ARG1);
|
||||
TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1);
|
||||
state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
|
||||
TEXPIPE_COLOR |
|
||||
TEXBLEND_ARG1 |
|
||||
TEXBLENDARG_MODIFY_PARMS |
|
||||
TEXBLENDARG_CURRENT);
|
||||
TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT);
|
||||
state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
|
||||
TEXPIPE_ALPHA |
|
||||
TEXBLEND_ARG1 |
|
||||
TEXBLENDARG_MODIFY_PARMS |
|
||||
TEXBLENDARG_CURRENT);
|
||||
TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count,
|
||||
const GLfloat *factor )
|
||||
static GLuint
|
||||
emit_factor(GLuint blendUnit, GLuint * state, GLuint count,
|
||||
const GLfloat * factor)
|
||||
{
|
||||
GLubyte r, g, b, a;
|
||||
GLuint col;
|
||||
@@ -101,14 +97,20 @@ 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;
|
||||
case 1: return TEXBLENDARG_TEXEL1;
|
||||
case 2: return TEXBLENDARG_TEXEL2;
|
||||
case 3: return TEXBLENDARG_TEXEL3;
|
||||
default: return TEXBLENDARG_TEXEL0;
|
||||
switch (unit) {
|
||||
case 0:
|
||||
return TEXBLENDARG_TEXEL0;
|
||||
case 1:
|
||||
return TEXBLENDARG_TEXEL1;
|
||||
case 2:
|
||||
return TEXBLENDARG_TEXEL2;
|
||||
case 3:
|
||||
return TEXBLENDARG_TEXEL3;
|
||||
default:
|
||||
return TEXBLENDARG_TEXEL0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,12 +134,10 @@ 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,
|
||||
GLuint *state,
|
||||
const GLfloat *factor )
|
||||
GLuint texel_op, GLuint * state, const GLfloat * factor)
|
||||
{
|
||||
const GLuint numColorArgs = combine->_NumArgsRGB;
|
||||
const GLuint numAlphaArgs = combine->_NumArgsA;
|
||||
@@ -162,7 +162,7 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
TEXPIPE_ALPHA | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS,
|
||||
};
|
||||
|
||||
if(INTEL_DEBUG&DEBUG_TEXTURE)
|
||||
if (INTEL_DEBUG & DEBUG_TEXTURE)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
}
|
||||
|
||||
|
||||
switch(combine->ModeRGB) {
|
||||
switch (combine->ModeRGB) {
|
||||
case GL_REPLACE:
|
||||
blendop = TEXBLENDOP_ARG1;
|
||||
break;
|
||||
@@ -216,15 +216,15 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
blendop = TEXBLENDOP_DOT3;
|
||||
break;
|
||||
default:
|
||||
return pass_through( state, blendUnit );
|
||||
return pass_through(state, blendUnit);
|
||||
}
|
||||
|
||||
blendop |= (rgb_shift << TEXOP_SCALE_SHIFT);
|
||||
|
||||
|
||||
/* Handle RGB args */
|
||||
for(i = 0; i < 3; i++) {
|
||||
switch(combine->SourceRGB[i]) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
switch (combine->SourceRGB[i]) {
|
||||
case GL_TEXTURE:
|
||||
args_RGB[i] = texel_op;
|
||||
break;
|
||||
@@ -232,7 +232,7 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
case GL_TEXTURE1:
|
||||
case GL_TEXTURE2:
|
||||
case GL_TEXTURE3:
|
||||
args_RGB[i] = GetTexelOp( combine->SourceRGB[i] - GL_TEXTURE0 );
|
||||
args_RGB[i] = GetTexelOp(combine->SourceRGB[i] - GL_TEXTURE0);
|
||||
break;
|
||||
case GL_CONSTANT:
|
||||
args_RGB[i] = TEXBLENDARG_FACTOR_N;
|
||||
@@ -245,10 +245,10 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
args_RGB[i] = TEXBLENDARG_CURRENT;
|
||||
break;
|
||||
default:
|
||||
return pass_through( state, blendUnit );
|
||||
return pass_through(state, blendUnit);
|
||||
}
|
||||
|
||||
switch(combine->OperandRGB[i]) {
|
||||
switch (combine->OperandRGB[i]) {
|
||||
case GL_SRC_COLOR:
|
||||
args_RGB[i] |= 0;
|
||||
break;
|
||||
@@ -259,11 +259,10 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
args_RGB[i] |= TEXBLENDARG_REPLICATE_ALPHA;
|
||||
break;
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA |
|
||||
TEXBLENDARG_INV_ARG);
|
||||
args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA | TEXBLENDARG_INV_ARG);
|
||||
break;
|
||||
default:
|
||||
return pass_through( state, blendUnit );
|
||||
return pass_through(state, blendUnit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,15 +274,15 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
* Note - the global factor is set up with alpha == .5, so
|
||||
* the alpha part of the DOT4 calculation should be zero.
|
||||
*/
|
||||
if ( combine->ModeRGB == GL_DOT3_RGBA_EXT ||
|
||||
combine->ModeRGB == GL_DOT3_RGBA ) {
|
||||
if (combine->ModeRGB == GL_DOT3_RGBA_EXT ||
|
||||
combine->ModeRGB == GL_DOT3_RGBA) {
|
||||
ablendop = TEXBLENDOP_DOT4;
|
||||
args_A[0] = TEXBLENDARG_FACTOR; /* the global factor */
|
||||
args_A[1] = TEXBLENDARG_FACTOR;
|
||||
args_A[2] = TEXBLENDARG_FACTOR;
|
||||
}
|
||||
else {
|
||||
switch(combine->ModeA) {
|
||||
switch (combine->ModeA) {
|
||||
case GL_REPLACE:
|
||||
ablendop = TEXBLENDOP_ARG1;
|
||||
break;
|
||||
@@ -303,15 +302,15 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
ablendop = TEXBLENDOP_SUBTRACT;
|
||||
break;
|
||||
default:
|
||||
return pass_through( state, blendUnit );
|
||||
return pass_through(state, blendUnit);
|
||||
}
|
||||
|
||||
|
||||
ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT);
|
||||
|
||||
/* Handle A args */
|
||||
for(i = 0; i < 3; i++) {
|
||||
switch(combine->SourceA[i]) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
switch (combine->SourceA[i]) {
|
||||
case GL_TEXTURE:
|
||||
args_A[i] = texel_op;
|
||||
break;
|
||||
@@ -319,7 +318,7 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
case GL_TEXTURE1:
|
||||
case GL_TEXTURE2:
|
||||
case GL_TEXTURE3:
|
||||
args_A[i] = GetTexelOp( combine->SourceA[i] - GL_TEXTURE0 );
|
||||
args_A[i] = GetTexelOp(combine->SourceA[i] - GL_TEXTURE0);
|
||||
break;
|
||||
case GL_CONSTANT:
|
||||
args_A[i] = TEXBLENDARG_FACTOR_N;
|
||||
@@ -332,10 +331,10 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
args_A[i] = TEXBLENDARG_CURRENT;
|
||||
break;
|
||||
default:
|
||||
return pass_through( state, blendUnit );
|
||||
return pass_through(state, blendUnit);
|
||||
}
|
||||
|
||||
switch(combine->OperandA[i]) {
|
||||
switch (combine->OperandA[i]) {
|
||||
case GL_SRC_ALPHA:
|
||||
args_A[i] |= 0;
|
||||
break;
|
||||
@@ -343,7 +342,7 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
args_A[i] |= TEXBLENDARG_INV_ARG;
|
||||
break;
|
||||
default:
|
||||
return pass_through( state, blendUnit );
|
||||
return pass_through(state, blendUnit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,83 +365,83 @@ i830SetTexEnvCombine(i830ContextPtr i830,
|
||||
TEXPIPE_COLOR |
|
||||
ENABLE_TEXOUTPUT_WRT_SEL |
|
||||
TEXOP_OUTPUT_CURRENT |
|
||||
DISABLE_TEX_CNTRL_STAGE |
|
||||
TEXOP_MODIFY_PARMS |
|
||||
blendop);
|
||||
DISABLE_TEX_CNTRL_STAGE | TEXOP_MODIFY_PARMS | blendop);
|
||||
state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) |
|
||||
TEXPIPE_ALPHA |
|
||||
ENABLE_TEXOUTPUT_WRT_SEL |
|
||||
TEXOP_OUTPUT_CURRENT |
|
||||
TEXOP_MODIFY_PARMS |
|
||||
ablendop);
|
||||
TEXOP_OUTPUT_CURRENT | TEXOP_MODIFY_PARMS | ablendop);
|
||||
|
||||
for ( i = 0 ; i < numColorArgs ; i++ ) {
|
||||
for (i = 0; i < numColorArgs; i++) {
|
||||
state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
|
||||
tex_blend_rgb[i] | args_RGB[i]);
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < numAlphaArgs ; i++ ) {
|
||||
for (i = 0; i < numAlphaArgs; i++) {
|
||||
state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) |
|
||||
tex_blend_a[i] | args_A[i]);
|
||||
}
|
||||
|
||||
|
||||
if (need_factor)
|
||||
return emit_factor( blendUnit, state, used, factor );
|
||||
return emit_factor(blendUnit, state, used, factor);
|
||||
else
|
||||
return used;
|
||||
}
|
||||
|
||||
|
||||
static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit,
|
||||
GLboolean last_stage )
|
||||
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];
|
||||
GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz;
|
||||
|
||||
|
||||
if (0) fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
|
||||
if (0)
|
||||
fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
|
||||
|
||||
/* Update i830->state.TexBlend
|
||||
*/
|
||||
tmp_sz = i830SetTexEnvCombine(i830, texUnit->_CurrentCombine, blendUnit,
|
||||
GetTexelOp(unit), tmp,
|
||||
texUnit->EnvColor );
|
||||
GetTexelOp(unit), tmp, texUnit->EnvColor);
|
||||
|
||||
if (last_stage)
|
||||
tmp[0] |= TEXOP_LAST_STAGE;
|
||||
|
||||
if (tmp_sz != i830->state.TexBlendWordsUsed[blendUnit] ||
|
||||
memcmp( tmp, i830->state.TexBlend[blendUnit], tmp_sz * sizeof(GLuint))) {
|
||||
memcmp(tmp, i830->state.TexBlend[blendUnit],
|
||||
tmp_sz * sizeof(GLuint))) {
|
||||
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_TEXBLEND(blendUnit) );
|
||||
memcpy( i830->state.TexBlend[blendUnit], tmp, tmp_sz * sizeof(GLuint));
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(blendUnit));
|
||||
memcpy(i830->state.TexBlend[blendUnit], tmp, tmp_sz * sizeof(GLuint));
|
||||
i830->state.TexBlendWordsUsed[blendUnit] = tmp_sz;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
tmp_sz = pass_through( tmp, unit );
|
||||
tmp_sz = pass_through(tmp, unit);
|
||||
tmp[0] |= TEXOP_LAST_STAGE;
|
||||
|
||||
if (tmp_sz != i830->state.TexBlendWordsUsed[unit] ||
|
||||
memcmp( tmp, i830->state.TexBlend[unit], tmp_sz * sizeof(GLuint))) {
|
||||
memcmp(tmp, i830->state.TexBlend[unit], tmp_sz * sizeof(GLuint))) {
|
||||
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_TEXBLEND(unit) );
|
||||
memcpy( i830->state.TexBlend[unit], tmp, tmp_sz * sizeof(GLuint));
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(unit));
|
||||
memcpy(i830->state.TexBlend[unit], tmp, tmp_sz * sizeof(GLuint));
|
||||
i830->state.TexBlendWordsUsed[unit] = tmp_sz;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -450,16 +449,15 @@ void i830EmitTextureBlend( i830ContextPtr i830 )
|
||||
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND_ALL, GL_FALSE);
|
||||
|
||||
if (ctx->Texture._EnabledUnits) {
|
||||
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
|
||||
if (ctx->Texture.Unit[unit]._ReallyEnabled)
|
||||
last_stage = unit;
|
||||
|
||||
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
|
||||
if (ctx->Texture.Unit[unit]._ReallyEnabled)
|
||||
emit_texblend( i830, unit, blendunit++, last_stage == unit );
|
||||
emit_texblend(i830, unit, blendunit++, last_stage == unit);
|
||||
}
|
||||
else {
|
||||
emit_passthrough( i830 );
|
||||
emit_passthrough(i830);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,446 +38,279 @@
|
||||
#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.
|
||||
|
||||
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
static GLuint
|
||||
translate_wrap_mode(GLenum wrap)
|
||||
{
|
||||
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:
|
||||
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;
|
||||
return TEXCOORDMODE_WRAP;
|
||||
}
|
||||
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 )
|
||||
/* 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)
|
||||
{
|
||||
if(INTEL_DEBUG&DEBUG_TEXTURE)
|
||||
fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit);
|
||||
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];
|
||||
|
||||
if (i830->intel.CurrentTexObj[unit])
|
||||
i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit);
|
||||
memset(state, 0, sizeof(state));
|
||||
|
||||
i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t;
|
||||
t->intel.base.bound |= (1 << unit);
|
||||
if (!intel_finalize_mipmap_tree(intel, unit))
|
||||
return GL_FALSE;
|
||||
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) );
|
||||
/* 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[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
|
||||
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);
|
||||
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];
|
||||
/* state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */
|
||||
/* t->intel.TextureOffset); */
|
||||
|
||||
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);
|
||||
state[I830_TEXREG_TM0S1] =
|
||||
(((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
|
||||
((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) |
|
||||
translate_texture_format(firstImage->TexFormat->MesaFormat));
|
||||
|
||||
t->intel.dirty &= ~I830_UPLOAD_TEX(unit);
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static GLboolean enable_tex_common( 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;
|
||||
|
||||
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
{
|
||||
GLuint minFilt, mipFilt, magFilt;
|
||||
|
||||
/* Fallback if there's a texture border */
|
||||
if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
|
||||
fprintf(stderr, "Texture border\n");
|
||||
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;
|
||||
}
|
||||
|
||||
/* Upload teximages (not pipelined)
|
||||
*/
|
||||
if (t->intel.base.dirty_images[0]) {
|
||||
if (!i830SetTexImages( i830, tObj )) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update state if this is a different texture object to last
|
||||
* time.
|
||||
state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit];
|
||||
|
||||
#if 0
|
||||
/* YUV conversion:
|
||||
*/
|
||||
if (i830->intel.CurrentTexObj[unit] != &t->intel ||
|
||||
(t->intel.dirty & I830_UPLOAD_TEX(unit))) {
|
||||
i830_import_tex_unit( i830, t, unit);
|
||||
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));
|
||||
}
|
||||
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean disable_tex( GLcontext *ctx, GLuint unit )
|
||||
|
||||
|
||||
void
|
||||
i830UpdateTextureState(struct intel_context *intel)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(ctx);
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
GLboolean ok = GL_TRUE;
|
||||
GLuint i;
|
||||
|
||||
/* 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) {
|
||||
for (i = 0; i < I830_TEX_UNITS && ok; i++) {
|
||||
switch (intel->ctx.Texture.Unit[i]._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 ));
|
||||
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:
|
||||
return disable_tex( ctx, unit );
|
||||
if (i830->state.active & I830_UPLOAD_TEX(i))
|
||||
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE);
|
||||
break;
|
||||
case TEXTURE_3D_BIT:
|
||||
default:
|
||||
return GL_FALSE;
|
||||
ok = GL_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok);
|
||||
|
||||
if (ok)
|
||||
i830EmitTextureBlend( i830 );
|
||||
i830EmitTextureBlend(i830);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,14 +28,15 @@
|
||||
|
||||
#include "i830_context.h"
|
||||
#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,
|
||||
GLuint expected );
|
||||
#define FILE_DEBUG_FLAG DEBUG_STATE
|
||||
|
||||
static GLboolean i830_check_vertex_size(struct intel_context *intel,
|
||||
GLuint expected);
|
||||
|
||||
#define SZ_TO_HW(sz) ((sz-2)&0x3)
|
||||
#define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
|
||||
@@ -59,10 +60,11 @@ 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;
|
||||
DECLARE_RENDERINPUTS(index_bitset);
|
||||
@@ -70,7 +72,7 @@ static void i830_render_start( intelContextPtr intel )
|
||||
GLuint v2 = _3DSTATE_VFT1_CMD;
|
||||
GLuint mcsb1 = 0;
|
||||
|
||||
RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
|
||||
RENDERINPUTS_COPY(index_bitset, tnl->render_inputs_bitset);
|
||||
|
||||
/* Important:
|
||||
*/
|
||||
@@ -80,42 +82,42 @@ static void i830_render_start( intelContextPtr intel )
|
||||
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
|
||||
* build up a hardware vertex.
|
||||
*/
|
||||
if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW );
|
||||
if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) {
|
||||
EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW);
|
||||
intel->coloroffset = 4;
|
||||
}
|
||||
else {
|
||||
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ );
|
||||
EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ);
|
||||
intel->coloroffset = 3;
|
||||
}
|
||||
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH );
|
||||
if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_POINTSIZE)) {
|
||||
EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH);
|
||||
}
|
||||
|
||||
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE );
|
||||
EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE);
|
||||
|
||||
intel->specoffset = 0;
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
|
||||
RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
|
||||
if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1) ||
|
||||
RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG)) {
|
||||
if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_COLOR1)) {
|
||||
intel->specoffset = intel->coloroffset + 1;
|
||||
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC );
|
||||
EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC);
|
||||
}
|
||||
else
|
||||
EMIT_PAD( 3 );
|
||||
EMIT_PAD(3);
|
||||
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
|
||||
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC );
|
||||
if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_FOG))
|
||||
EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC);
|
||||
else
|
||||
EMIT_PAD( 1 );
|
||||
EMIT_PAD(1);
|
||||
}
|
||||
|
||||
if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
|
||||
if (RENDERINPUTS_TEST_RANGE(index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX)) {
|
||||
int i, count = 0;
|
||||
|
||||
for (i = 0; i < I830_TEX_UNITS; i++) {
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
|
||||
if (RENDERINPUTS_TEST(index_bitset, _TNL_ATTRIB_TEX(i))) {
|
||||
GLuint sz = VB->TexCoordPtr[i]->size;
|
||||
GLuint emit;
|
||||
GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] &
|
||||
@@ -143,9 +145,9 @@ static void i830_render_start( intelContextPtr intel )
|
||||
};
|
||||
|
||||
|
||||
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, emit, 0 );
|
||||
EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, emit, 0);
|
||||
v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz));
|
||||
mcsb1 |= (count+8)<<(i*4);
|
||||
mcsb1 |= (count + 8) << (i * 4);
|
||||
|
||||
if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) {
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_TEX(i));
|
||||
@@ -165,42 +167,43 @@ static void i830_render_start( intelContextPtr intel )
|
||||
if (v0 != i830->state.Ctx[I830_CTXREG_VF] ||
|
||||
v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
|
||||
mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
|
||||
!RENDERINPUTS_EQUAL( index_bitset, i830->last_index_bitset )) {
|
||||
!RENDERINPUTS_EQUAL(index_bitset, i830->last_index_bitset)) {
|
||||
int k;
|
||||
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_CTX );
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_CTX);
|
||||
|
||||
/* Must do this *after* statechange, so as not to affect
|
||||
* buffered vertices reliant on the old state:
|
||||
*/
|
||||
intel->vertex_size =
|
||||
_tnl_install_attrs( ctx,
|
||||
_tnl_install_attrs(ctx,
|
||||
intel->vertex_attrs,
|
||||
intel->vertex_attr_count,
|
||||
intel->ViewportMatrix.m, 0 );
|
||||
intel->ViewportMatrix.m, 0);
|
||||
|
||||
intel->vertex_size >>= 2;
|
||||
|
||||
i830->state.Ctx[I830_CTXREG_VF] = v0;
|
||||
i830->state.Ctx[I830_CTXREG_VF2] = v2;
|
||||
i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
|
||||
RENDERINPUTS_COPY( i830->last_index_bitset, index_bitset );
|
||||
RENDERINPUTS_COPY(i830->last_index_bitset, index_bitset);
|
||||
|
||||
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,
|
||||
GLenum rprim )
|
||||
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;
|
||||
|
||||
switch (rprim) {
|
||||
case GL_TRIANGLES:
|
||||
if (intel->ctx.Polygon.StippleFlag &&
|
||||
intel->hw_stipple)
|
||||
if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple)
|
||||
st1 |= ST1_ENABLE;
|
||||
break;
|
||||
case GL_LINES:
|
||||
@@ -212,6 +215,8 @@ static void i830_reduced_primitive_state( intelContextPtr intel,
|
||||
i830->intel.reduced_primitive = rprim;
|
||||
|
||||
if (st1 != i830->state.Stipple[I830_STPREG_ST1]) {
|
||||
INTEL_FIREVERTICES(intel);
|
||||
|
||||
I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE);
|
||||
i830->state.Stipple[I830_STPREG_ST1] = st1;
|
||||
}
|
||||
@@ -220,36 +225,56 @@ 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,
|
||||
GLuint expected )
|
||||
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;
|
||||
int i, sz = 0;
|
||||
|
||||
switch (vft0 & VFT0_XYZW_MASK) {
|
||||
case VFT0_XY: sz = 2; break;
|
||||
case VFT0_XYZ: sz = 3; break;
|
||||
case VFT0_XYW: sz = 3; break;
|
||||
case VFT0_XYZW: sz = 4; break;
|
||||
case VFT0_XY:
|
||||
sz = 2;
|
||||
break;
|
||||
case VFT0_XYZ:
|
||||
sz = 3;
|
||||
break;
|
||||
case VFT0_XYW:
|
||||
sz = 3;
|
||||
break;
|
||||
case VFT0_XYZW:
|
||||
sz = 4;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "no xyzw specified\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vft0 & VFT0_SPEC) sz++;
|
||||
if (vft0 & VFT0_DIFFUSE) sz++;
|
||||
if (vft0 & VFT0_DEPTH_OFFSET) sz++;
|
||||
if (vft0 & VFT0_POINT_WIDTH) sz++;
|
||||
if (vft0 & VFT0_SPEC)
|
||||
sz++;
|
||||
if (vft0 & VFT0_DIFFUSE)
|
||||
sz++;
|
||||
if (vft0 & VFT0_DEPTH_OFFSET)
|
||||
sz++;
|
||||
if (vft0 & VFT0_POINT_WIDTH)
|
||||
sz++;
|
||||
|
||||
for (i = 0 ; i < nrtex ; i++) {
|
||||
for (i = 0; i < nrtex; i++) {
|
||||
switch (vft1 & VFT1_TEX0_MASK) {
|
||||
case TEXCOORDFMT_2D: sz += 2; break;
|
||||
case TEXCOORDFMT_3D: sz += 3; break;
|
||||
case TEXCOORDFMT_4D: sz += 4; break;
|
||||
case TEXCOORDFMT_1D: sz += 1; break;
|
||||
case TEXCOORDFMT_2D:
|
||||
sz += 2;
|
||||
break;
|
||||
case TEXCOORDFMT_3D:
|
||||
sz += 3;
|
||||
break;
|
||||
case TEXCOORDFMT_4D:
|
||||
sz += 4;
|
||||
break;
|
||||
case TEXCOORDFMT_1D:
|
||||
sz += 1;
|
||||
break;
|
||||
}
|
||||
vft1 >>= VFT1_TEX1_SHIFT;
|
||||
}
|
||||
@@ -260,16 +285,12 @@ 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(40, 0);
|
||||
|
||||
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
|
||||
OUT_BATCH(0);
|
||||
@@ -282,9 +303,7 @@ static void i830_emit_invarient_state( intelContextPtr intel )
|
||||
|
||||
OUT_BATCH(_3DSTATE_FOG_MODE_CMD);
|
||||
OUT_BATCH(FOGFUNC_ENABLE |
|
||||
FOG_LINEAR_CONST |
|
||||
FOGSRC_INDEX_Z |
|
||||
ENABLE_FOG_DENSITY);
|
||||
FOG_LINEAR_CONST | FOGSRC_INDEX_Z | ENABLE_FOG_DENSITY);
|
||||
OUT_BATCH(0);
|
||||
OUT_BATCH(0);
|
||||
|
||||
@@ -330,15 +349,7 @@ static void i830_emit_invarient_state( intelContextPtr intel )
|
||||
ENABLE_TRI_FAN_PROVOKE_VRTX |
|
||||
ENABLE_TRI_STRIP_PROVOKE_VRTX |
|
||||
LINE_STRIP_PROVOKE_VRTX(1) |
|
||||
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);
|
||||
TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2));
|
||||
|
||||
OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM);
|
||||
OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE);
|
||||
@@ -358,18 +369,24 @@ 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)
|
||||
|
||||
static GLuint get_state_size( struct i830_hw_state *state )
|
||||
static GLuint
|
||||
get_state_size(struct i830_hw_state *state)
|
||||
{
|
||||
GLuint dirty = state->active & ~state->emitted;
|
||||
GLuint sz = 0;
|
||||
GLuint i;
|
||||
|
||||
if (dirty & I830_UPLOAD_INVARIENT)
|
||||
sz += 40 * sizeof(int);
|
||||
|
||||
if (dirty & I830_UPLOAD_CTX)
|
||||
sz += sizeof(state->Ctx);
|
||||
|
||||
@@ -393,135 +410,197 @@ static GLuint get_state_size( struct i830_hw_state *state )
|
||||
|
||||
/* 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 = state->active & ~state->emitted;
|
||||
GLuint counter = intel->batch.counter;
|
||||
GLuint dirty;
|
||||
BATCH_LOCALS;
|
||||
|
||||
if (intel->batch.space < get_state_size(state)) {
|
||||
intelFlushBatch(intel, GL_TRUE);
|
||||
/* We don't hold the lock at this point, so want to make sure that
|
||||
* there won't be a buffer wrap.
|
||||
*
|
||||
* It might be better to talk about explicit places where
|
||||
* scheduling is allowed, rather than assume that it is whenever a
|
||||
* batchbuffer fills up.
|
||||
*/
|
||||
intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
|
||||
|
||||
/* Do this here as we may have flushed the batchbuffer above,
|
||||
* causing more state to be dirty!
|
||||
*/
|
||||
dirty = state->active & ~state->emitted;
|
||||
counter = intel->batch.counter;
|
||||
|
||||
if (dirty & I830_UPLOAD_INVARIENT) {
|
||||
DBG("I830_UPLOAD_INVARIENT:\n");
|
||||
i830_emit_invarient_state(intel);
|
||||
}
|
||||
|
||||
if (dirty & I830_UPLOAD_CTX) {
|
||||
if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n");
|
||||
emit( i830, state->Ctx, sizeof(state->Ctx) );
|
||||
DBG("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) );
|
||||
DBG("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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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");
|
||||
emit( i830, state->Stipple, sizeof(state->Stipple) );
|
||||
DBG("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]));
|
||||
DBG("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_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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);
|
||||
emit( i830, state->TexBlend[i],
|
||||
state->TexBlendWordsUsed[i] * 4 );
|
||||
DBG("I830_UPLOAD_TEXBLEND(%d): %d words\n", i,
|
||||
state->TexBlendWordsUsed[i]);
|
||||
emit(i830, state->TexBlend[i], state->TexBlendWordsUsed[i] * 4);
|
||||
}
|
||||
}
|
||||
|
||||
state->emitted |= dirty;
|
||||
intel->batch.last_emit_state = counter;
|
||||
assert(counter == intel->batch.counter);
|
||||
}
|
||||
|
||||
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_color_region(intelContextPtr intel, const intelRegion *region)
|
||||
i830_set_draw_region(struct intel_context *intel,
|
||||
struct intel_region *draw_region,
|
||||
struct intel_region *depth_region)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
|
||||
intel_region_release(intel->intelScreen, &i830->state.draw_region);
|
||||
intel_region_release(intel->intelScreen, &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_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR2] = region->offset;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i830_set_z_region(intelContextPtr intel, const intelRegion *region)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS );
|
||||
(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(draw_region->pitch) |
|
||||
BUF_3D_USE_FENCE);
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR2] = region->offset;
|
||||
(BUF_3D_ID_DEPTH | BUF_3D_PITCH(depth_region->pitch) |
|
||||
BUF_3D_USE_FENCE);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void
|
||||
i830_update_color_z_regions(intelContextPtr intel,
|
||||
const intelRegion *colorRegion,
|
||||
const intelRegion *depthRegion)
|
||||
const intelRegion * colorRegion,
|
||||
const intelRegion * depthRegion)
|
||||
{
|
||||
i830ContextPtr i830 = I830_CONTEXT(intel);
|
||||
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) | BUF_3D_USE_FENCE);
|
||||
(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) |
|
||||
BUF_3D_USE_FENCE);
|
||||
i830->state.Buffer[I830_DESTREG_CBUFADDR2] = colorRegion->offset;
|
||||
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH | BUF_3D_PITCH(depthRegion->pitch) | BUF_3D_USE_FENCE);
|
||||
i830->state.Buffer[I830_DESTREG_DBUFADDR2] = depthRegion->offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* 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 )
|
||||
static void
|
||||
i830_assert_not_dirty( struct intel_context *intel )
|
||||
{
|
||||
struct i830_context *i830 = i830_context(&intel->ctx);
|
||||
struct i830_hw_state *state = i830->current;
|
||||
GLuint dirty = state->active & ~state->emitted;
|
||||
assert(!dirty);
|
||||
}
|
||||
|
||||
|
||||
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.rotate_window = i830RotateWindow;
|
||||
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_color_region = i830_set_color_region;
|
||||
i830->intel.vtbl.set_z_region = i830_set_z_region;
|
||||
i830->intel.vtbl.update_color_z_regions = i830_update_color_z_regions;
|
||||
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;
|
||||
i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty;
|
||||
}
|
||||
|
||||
@@ -41,31 +41,36 @@
|
||||
#include "utils.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
#include "intel_regions.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
|
||||
/***************************************
|
||||
* Mesa's Driver Functions
|
||||
***************************************/
|
||||
|
||||
static const struct dri_extension i915_extensions[] =
|
||||
{
|
||||
{ "GL_ARB_depth_texture", NULL },
|
||||
{ "GL_ARB_fragment_program", NULL },
|
||||
{ "GL_ARB_shadow", NULL },
|
||||
{ "GL_EXT_shadow_funcs", NULL },
|
||||
static const struct dri_extension i915_extensions[] = {
|
||||
{"GL_ARB_depth_texture", NULL},
|
||||
{"GL_ARB_fragment_program", NULL},
|
||||
{"GL_ARB_shadow", NULL},
|
||||
{"GL_ARB_texture_env_crossbar", NULL},
|
||||
{"GL_ARB_texture_non_power_of_two", NULL},
|
||||
{"GL_EXT_shadow_funcs", NULL},
|
||||
/* ARB extn won't work if not enabled */
|
||||
{ "GL_SGIX_depth_texture", NULL },
|
||||
{ NULL, NULL }
|
||||
{"GL_SGIX_depth_texture", NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Override intel default.
|
||||
*/
|
||||
static void i915InvalidateState( GLcontext *ctx, GLuint new_state )
|
||||
static void
|
||||
i915InvalidateState(GLcontext * ctx, GLuint new_state)
|
||||
{
|
||||
_swrast_InvalidateState( ctx, new_state );
|
||||
_swsetup_InvalidateState( ctx, 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;
|
||||
_swrast_InvalidateState(ctx, new_state);
|
||||
_swsetup_InvalidateState(ctx, 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;
|
||||
|
||||
/* Todo: gather state values under which tracked parameters become
|
||||
* invalidated, add callbacks for things like
|
||||
@@ -73,45 +78,51 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state )
|
||||
*/
|
||||
{
|
||||
struct i915_fragment_program *p =
|
||||
(struct i915_fragment_program *)ctx->FragmentProgram._Current;
|
||||
(struct i915_fragment_program *) ctx->FragmentProgram._Current;
|
||||
if (p && p->nr_params)
|
||||
p->params_uptodate = 0;
|
||||
}
|
||||
|
||||
if (new_state & (_NEW_FOG|_NEW_HINT|_NEW_PROGRAM))
|
||||
if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM))
|
||||
i915_update_fog(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void i915InitDriverFunctions( struct dd_function_table *functions )
|
||||
static void
|
||||
i915InitDriverFunctions(struct dd_function_table *functions)
|
||||
{
|
||||
intelInitDriverFunctions( functions );
|
||||
i915InitStateFunctions( functions );
|
||||
i915InitTextureFuncs( functions );
|
||||
i915InitFragProgFuncs( functions );
|
||||
intelInitDriverFunctions(functions);
|
||||
i915InitStateFunctions(functions);
|
||||
i915InitTextureFuncs(functions);
|
||||
i915InitFragProgFuncs(functions);
|
||||
functions->UpdateState = i915InvalidateState;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
GLboolean
|
||||
i915CreateContext(const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
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;
|
||||
GLuint i;
|
||||
|
||||
if (!i915) return GL_FALSE;
|
||||
if (!i915)
|
||||
return GL_FALSE;
|
||||
|
||||
i915InitVtbl( i915 );
|
||||
_mesa_printf("\ntexmem-0-3 branch\n\n");
|
||||
|
||||
i915InitDriverFunctions( &functions );
|
||||
i915InitVtbl(i915);
|
||||
i915InitMetaFuncs(i915);
|
||||
|
||||
if (!intelInitContext( intel, mesaVis, driContextPriv,
|
||||
sharedContextPrivate, &functions )) {
|
||||
i915InitDriverFunctions(&functions);
|
||||
|
||||
if (!intelInitContext(intel, mesaVis, driContextPriv,
|
||||
sharedContextPrivate, &functions)) {
|
||||
FREE(i915);
|
||||
return GL_FALSE;
|
||||
}
|
||||
@@ -120,42 +131,21 @@ 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,
|
||||
(unsigned *) & 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.MaxTextureLevels = 12;
|
||||
ctx->Const.Max3DTextureLevels = 9;
|
||||
ctx->Const.MaxCubeTextureLevels = 12;
|
||||
ctx->Const.MaxTextureRectSize = (1 << 11);
|
||||
ctx->Const.MaxTextureUnits = I915_TEX_UNITS;
|
||||
i = driQueryOptioni( &intel->intelScreen->optionCache, "allow_large_textures");
|
||||
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,
|
||||
i );
|
||||
|
||||
/* 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;
|
||||
@@ -163,20 +153,22 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
||||
ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN;
|
||||
ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +
|
||||
I915_MAX_TEX_INSN);
|
||||
ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT;
|
||||
ctx->Const.FragmentProgram.MaxNativeTexIndirections =
|
||||
I915_MAX_TEX_INDIRECT;
|
||||
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */
|
||||
|
||||
ctx->_MaintainTexEnvProgram = 1;
|
||||
ctx->_UseTexEnvProgram = 1;
|
||||
|
||||
driInitExtensions( ctx, i915_extensions, GL_FALSE );
|
||||
driInitExtensions(ctx, i915_extensions, GL_FALSE);
|
||||
|
||||
|
||||
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
|
||||
36 * sizeof(GLfloat) );
|
||||
_tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12,
|
||||
36 * sizeof(GLfloat));
|
||||
|
||||
intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf;
|
||||
|
||||
i915InitState( i915 );
|
||||
i915InitState(i915);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,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
|
||||
@@ -54,10 +56,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
|
||||
@@ -88,7 +88,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
|
||||
@@ -96,6 +95,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))
|
||||
|
||||
@@ -106,7 +114,8 @@
|
||||
/* Hardware version of a parsed fragment program. "Derived" from the
|
||||
* mesa fragment_program struct.
|
||||
*/
|
||||
struct i915_fragment_program {
|
||||
struct i915_fragment_program
|
||||
{
|
||||
struct gl_fragment_program FragProg;
|
||||
|
||||
GLboolean translated;
|
||||
@@ -158,15 +167,14 @@ struct i915_fragment_program {
|
||||
GLuint wpos_tex;
|
||||
GLboolean depth_written;
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
GLuint reg; /* Hardware constant idx */
|
||||
const GLfloat *values; /* Pointer to tracked values */
|
||||
} param[I915_MAX_CONSTANT];
|
||||
GLuint nr_params;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Helpers for i915_texprog.c:
|
||||
*/
|
||||
GLuint src_texture; /* Reg containing sampled texture color,
|
||||
@@ -187,27 +195,37 @@ 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
|
||||
|
||||
|
||||
struct i915_hw_state {
|
||||
struct i915_hw_state
|
||||
{
|
||||
GLuint Ctx[I915_CTX_SETUP_SIZE];
|
||||
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...
|
||||
*/
|
||||
struct _DriBufferObject *tex_buffer[I915_TEX_UNITS];
|
||||
GLuint tex_offset[I915_TEX_UNITS];
|
||||
|
||||
|
||||
GLuint active; /* I915_UPLOAD_* */
|
||||
GLuint emitted; /* I915_UPLOAD_* */
|
||||
};
|
||||
@@ -222,6 +240,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;
|
||||
@@ -230,24 +250,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); \
|
||||
@@ -259,7 +269,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);
|
||||
|
||||
|
||||
|
||||
@@ -288,70 +304,64 @@ do { \
|
||||
/*======================================================================
|
||||
* i915_context.c
|
||||
*/
|
||||
extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
void *sharedContextPrivate);
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* i915_texprog.c
|
||||
*/
|
||||
extern void i915ValidateTextureProgram( i915ContextPtr i915 );
|
||||
extern void i915ValidateTextureProgram(struct i915_context *i915);
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* i915_debug.c
|
||||
*/
|
||||
extern void i915_disassemble_program( const GLuint *program, GLuint sz );
|
||||
extern void i915_print_ureg( const char *msg, GLuint ureg );
|
||||
extern void i915_disassemble_program(const GLuint * program, GLuint sz);
|
||||
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 i915_update_fog(GLcontext *ctxx);
|
||||
extern void i915InitStateFunctions(struct dd_function_table *functions);
|
||||
extern void i915InitState(struct i915_context *i915);
|
||||
extern void i915_update_fog(GLcontext * ctx);
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* i915_tex.c
|
||||
*/
|
||||
extern void i915UpdateTextureState( intelContextPtr intel );
|
||||
extern void i915InitTextureFuncs( struct dd_function_table *functions );
|
||||
extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj );
|
||||
extern void i915UpdateTextureState(struct intel_context *intel);
|
||||
extern void i915InitTextureFuncs(struct dd_function_table *functions);
|
||||
|
||||
/*======================================================================
|
||||
* 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 );
|
||||
void i915InitMetaFuncs(struct i915_context *i915);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
extern void
|
||||
i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
|
||||
GLuint srcBuf);
|
||||
|
||||
/*======================================================================
|
||||
* i915_fragprog.c
|
||||
*/
|
||||
extern void i915ValidateFragmentProgram( i915ContextPtr i915 );
|
||||
extern void i915InitFragProgFuncs( struct dd_function_table *functions );
|
||||
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
|
||||
|
||||
|
||||
@@ -113,15 +113,24 @@ static const char *regname[0x8] = {
|
||||
"UNKNOWN",
|
||||
};
|
||||
|
||||
static void print_reg_type_nr( GLuint type, GLuint nr )
|
||||
static void
|
||||
print_reg_type_nr(GLuint type, GLuint nr)
|
||||
{
|
||||
switch (type) {
|
||||
case REG_TYPE_T:
|
||||
switch (nr) {
|
||||
case T_DIFFUSE: fprintf(stderr, "T_DIFFUSE"); return;
|
||||
case T_SPECULAR: fprintf(stderr, "T_SPECULAR"); return;
|
||||
case T_FOG_W: fprintf(stderr, "T_FOG_W"); return;
|
||||
default: fprintf(stderr, "T_TEX%d", nr); return;
|
||||
case T_DIFFUSE:
|
||||
fprintf(stderr, "T_DIFFUSE");
|
||||
return;
|
||||
case T_SPECULAR:
|
||||
fprintf(stderr, "T_SPECULAR");
|
||||
return;
|
||||
case T_FOG_W:
|
||||
fprintf(stderr, "T_FOG_W");
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr, "T_TEX%d", nr);
|
||||
return;
|
||||
}
|
||||
case REG_TYPE_OC:
|
||||
if (nr == 0) {
|
||||
@@ -151,7 +160,8 @@ static void print_reg_type_nr( GLuint type, GLuint nr )
|
||||
(SRC_W << A2_SRC2_CHANNEL_W_SHIFT))
|
||||
|
||||
|
||||
static void print_reg_neg_swizzle( GLuint reg )
|
||||
static void
|
||||
print_reg_neg_swizzle(GLuint reg)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -161,50 +171,71 @@ static void print_reg_neg_swizzle( GLuint reg )
|
||||
|
||||
fprintf(stderr, ".");
|
||||
|
||||
for (i = 3 ; i >= 0; i--) {
|
||||
if (reg & (1<<((i*4)+3)))
|
||||
for (i = 3; i >= 0; i--) {
|
||||
if (reg & (1 << ((i * 4) + 3)))
|
||||
fprintf(stderr, "-");
|
||||
|
||||
switch ((reg>>(i*4)) & 0x7) {
|
||||
case 0: fprintf(stderr, "x"); break;
|
||||
case 1: fprintf(stderr, "y"); break;
|
||||
case 2: fprintf(stderr, "z"); break;
|
||||
case 3: fprintf(stderr, "w"); break;
|
||||
case 4: fprintf(stderr, "0"); break;
|
||||
case 5: fprintf(stderr, "1"); break;
|
||||
default: fprintf(stderr, "?"); break;
|
||||
switch ((reg >> (i * 4)) & 0x7) {
|
||||
case 0:
|
||||
fprintf(stderr, "x");
|
||||
break;
|
||||
case 1:
|
||||
fprintf(stderr, "y");
|
||||
break;
|
||||
case 2:
|
||||
fprintf(stderr, "z");
|
||||
break;
|
||||
case 3:
|
||||
fprintf(stderr, "w");
|
||||
break;
|
||||
case 4:
|
||||
fprintf(stderr, "0");
|
||||
break;
|
||||
case 5:
|
||||
fprintf(stderr, "1");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void print_src_reg( GLuint dword )
|
||||
static void
|
||||
print_src_reg(GLuint dword)
|
||||
{
|
||||
GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK;
|
||||
GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK;
|
||||
print_reg_type_nr( type, nr );
|
||||
print_reg_neg_swizzle( dword );
|
||||
print_reg_type_nr(type, nr);
|
||||
print_reg_neg_swizzle(dword);
|
||||
}
|
||||
|
||||
void i915_print_ureg( const char *msg, GLuint ureg )
|
||||
void
|
||||
i915_print_ureg(const char *msg, GLuint ureg)
|
||||
{
|
||||
fprintf(stderr, "%s: ", msg);
|
||||
print_src_reg( ureg >> 8 );
|
||||
print_src_reg(ureg >> 8);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void print_dest_reg( GLuint dword )
|
||||
static void
|
||||
print_dest_reg(GLuint dword)
|
||||
{
|
||||
GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK;
|
||||
GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK;
|
||||
print_reg_type_nr( type, nr );
|
||||
print_reg_type_nr(type, nr);
|
||||
if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL)
|
||||
return;
|
||||
fprintf(stderr, ".");
|
||||
if (dword & A0_DEST_CHANNEL_X) fprintf(stderr, "x");
|
||||
if (dword & A0_DEST_CHANNEL_Y) fprintf(stderr, "y");
|
||||
if (dword & A0_DEST_CHANNEL_Z) fprintf(stderr, "z");
|
||||
if (dword & A0_DEST_CHANNEL_W) fprintf(stderr, "w");
|
||||
if (dword & A0_DEST_CHANNEL_X)
|
||||
fprintf(stderr, "x");
|
||||
if (dword & A0_DEST_CHANNEL_Y)
|
||||
fprintf(stderr, "y");
|
||||
if (dword & A0_DEST_CHANNEL_Z)
|
||||
fprintf(stderr, "z");
|
||||
if (dword & A0_DEST_CHANNEL_W)
|
||||
fprintf(stderr, "w");
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +244,8 @@ static void print_dest_reg( GLuint dword )
|
||||
#define GET_SRC2_REG(r) (r)
|
||||
|
||||
|
||||
static void print_arith_op( GLuint opcode, const GLuint *program )
|
||||
static void
|
||||
print_arith_op(GLuint opcode, const GLuint * program)
|
||||
{
|
||||
if (opcode != A0_NOP) {
|
||||
print_dest_reg(program[0]);
|
||||
@@ -245,22 +277,24 @@ static void print_arith_op( GLuint opcode, const GLuint *program )
|
||||
}
|
||||
|
||||
|
||||
static void print_tex_op( GLuint opcode, const GLuint *program )
|
||||
static void
|
||||
print_tex_op(GLuint opcode, const GLuint * program)
|
||||
{
|
||||
print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL);
|
||||
fprintf(stderr, " = ");
|
||||
|
||||
fprintf(stderr, "%s ", opcodes[opcode]);
|
||||
|
||||
fprintf(stderr, "S[%d],",
|
||||
program[0] & T0_SAMPLER_NR_MASK);
|
||||
fprintf(stderr, "S[%d],", program[0] & T0_SAMPLER_NR_MASK);
|
||||
|
||||
print_reg_type_nr( (program[1]>>T1_ADDRESS_REG_TYPE_SHIFT) & REG_TYPE_MASK,
|
||||
(program[1]>>T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK );
|
||||
print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) &
|
||||
REG_TYPE_MASK,
|
||||
(program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void print_dcl_op( GLuint opcode, const GLuint *program )
|
||||
static void
|
||||
print_dcl_op(GLuint opcode, const GLuint * program)
|
||||
{
|
||||
fprintf(stderr, "%s ", opcodes[opcode]);
|
||||
print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL);
|
||||
@@ -268,22 +302,23 @@ static void print_dcl_op( GLuint opcode, const GLuint *program )
|
||||
}
|
||||
|
||||
|
||||
void i915_disassemble_program( const GLuint *program, GLuint sz )
|
||||
void
|
||||
i915_disassemble_program(const GLuint * program, GLuint sz)
|
||||
{
|
||||
GLuint size = program[0] & 0x1ff;
|
||||
GLint i;
|
||||
|
||||
fprintf(stderr, "BEGIN\n");
|
||||
|
||||
if (size+2 != sz) {
|
||||
if (size + 2 != sz) {
|
||||
fprintf(stderr, "%s: program size mismatch %d/%d\n", __FUNCTION__,
|
||||
size+2, sz);
|
||||
size + 2, sz);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
program ++;
|
||||
for (i = 1 ; i < sz ; i+=3, program+=3) {
|
||||
GLuint opcode = program[0] & (0x1f<<24);
|
||||
program++;
|
||||
for (i = 1; i < sz; i += 3, program += 3) {
|
||||
GLuint opcode = program[0] & (0x1f << 24);
|
||||
|
||||
if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT)
|
||||
print_arith_op(opcode >> 24, program);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,17 +34,20 @@
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_rotate.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 ) \
|
||||
@@ -54,25 +57,25 @@ do { \
|
||||
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 |
|
||||
@@ -81,12 +84,34 @@ 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,
|
||||
GLuint s_mask,
|
||||
GLuint s_clear)
|
||||
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;
|
||||
|
||||
@@ -95,13 +120,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;
|
||||
@@ -109,7 +127,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 |
|
||||
@@ -138,12 +155,13 @@ 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 |
|
||||
S5_WRITEDISABLE_ALPHA);
|
||||
S5_WRITEDISABLE_BLUE | S5_WRITEDISABLE_ALPHA);
|
||||
|
||||
/* Copy colormask state from "regular" hw context.
|
||||
*/
|
||||
@@ -160,6 +178,31 @@ 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))
|
||||
|
||||
@@ -211,69 +254,64 @@ 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,
|
||||
|
||||
/* Declare incoming diffuse color:
|
||||
*/
|
||||
(D0_DCL |
|
||||
D0_DECL_REG( REG_T_DIFFUSE ) |
|
||||
D0_CHANNEL_ALL),
|
||||
(D0_DCL | D0_DECL_REG(REG_T_DIFFUSE) | D0_CHANNEL_ALL),
|
||||
D1_MBZ,
|
||||
D2_MBZ,
|
||||
|
||||
/* output-color = mov(t_diffuse)
|
||||
*/
|
||||
(A0_MOV |
|
||||
A0_DEST_REG( REG_OC ) |
|
||||
A0_DEST_CHANNEL_ALL |
|
||||
A0_SRC0_REG( REG_T_DIFFUSE )),
|
||||
A0_DEST_REG(REG_OC) |
|
||||
A0_DEST_CHANNEL_ALL | A0_SRC0_REG(REG_T_DIFFUSE)),
|
||||
(A1_SRC0_XYZW),
|
||||
0,
|
||||
};
|
||||
|
||||
|
||||
memcpy( i915->meta.Program, prog, sizeof(prog) );
|
||||
memcpy(i915->meta.Program, prog, sizeof(prog));
|
||||
i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
|
||||
i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
|
||||
i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
|
||||
/* Declare the sampler:
|
||||
*/
|
||||
(D0_DCL |
|
||||
D0_DECL_REG( REG_S(0) ) |
|
||||
D0_SAMPLE_TYPE_2D |
|
||||
D0_CHANNEL_NONE),
|
||||
(D0_DCL | D0_DECL_REG(REG_S(0)) | D0_SAMPLE_TYPE_2D | D0_CHANNEL_NONE),
|
||||
D1_MBZ,
|
||||
D2_MBZ,
|
||||
|
||||
/* Declare the interpolated texture coordinate:
|
||||
*/
|
||||
(D0_DCL |
|
||||
D0_DECL_REG( REG_T_TEX(0) ) |
|
||||
D0_CHANNEL_ALL),
|
||||
(D0_DCL | D0_DECL_REG(REG_T_TEX(0)) | D0_CHANNEL_ALL),
|
||||
D1_MBZ,
|
||||
D2_MBZ,
|
||||
|
||||
/* output-color = texld(sample0, texcoord0)
|
||||
*/
|
||||
(T0_TEXLD |
|
||||
T0_DEST_REG( REG_OC ) |
|
||||
T0_SAMPLER( 0 )),
|
||||
(T0_TEXLD | T0_DEST_REG(REG_OC) | T0_SAMPLER(0)),
|
||||
T1_ADDRESS_REG(REG_TYPE_T, 0),
|
||||
T2_MBZ
|
||||
};
|
||||
|
||||
memcpy( i915->meta.Program, prog, sizeof(prog) );
|
||||
memcpy(i915->meta.Program, prog, sizeof(prog));
|
||||
i915->meta.ProgramSize = sizeof(prog) / sizeof(*prog);
|
||||
i915->meta.Program[0] |= i915->meta.ProgramSize - 2;
|
||||
i915->meta.emitted &= ~I915_UPLOAD_PROGRAM;
|
||||
@@ -286,85 +324,125 @@ 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,
|
||||
static GLboolean
|
||||
meta_tex_rect_source(struct intel_context *intel,
|
||||
struct _DriBufferObject *buffer,
|
||||
GLuint offset,
|
||||
GLuint width,
|
||||
GLuint height,
|
||||
GLuint pitch, /* in bytes! */
|
||||
GLuint textureFormat )
|
||||
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;
|
||||
|
||||
#if 0
|
||||
printf("TexRect source offset 0x%x pitch %d\n", offset, pitch);
|
||||
#endif
|
||||
/* 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) |
|
||||
((((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));
|
||||
|
||||
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));
|
||||
(unit << SS3_TEXTUREMAP_INDEX_SHIFT));
|
||||
|
||||
state[I915_TEXREG_SS4] = 0;
|
||||
|
||||
i915->meta.emitted &= ~I915_UPLOAD_TEX(0);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Select between front and back draw buffers.
|
||||
/**
|
||||
* Set the color and depth drawing region for meta ops.
|
||||
*/
|
||||
static void set_draw_region( i915ContextPtr i915, const intelRegion *region )
|
||||
static void
|
||||
meta_draw_region(struct intel_context *intel,
|
||||
struct intel_region *color_region,
|
||||
struct intel_region *depth_region)
|
||||
{
|
||||
#if 0
|
||||
printf("Rotate into region: offset 0x%x pitch %d\n",
|
||||
region->offset, region->pitch);
|
||||
#endif
|
||||
i915->meta.Buffer[I915_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
|
||||
i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = region->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)
|
||||
static void
|
||||
set_vertex_format(struct intel_context *intel)
|
||||
{
|
||||
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);
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
|
||||
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 )
|
||||
{
|
||||
i915->meta.Ctx[I915_CTXREG_LIS2] =
|
||||
(S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) |
|
||||
S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |
|
||||
@@ -377,324 +455,55 @@ static void set_vertex_format( i915ContextPtr i915 )
|
||||
|
||||
i915->meta.Ctx[I915_CTXREG_LIS4] &= ~S4_VFMT_MASK;
|
||||
|
||||
i915->meta.Ctx[I915_CTXREG_LIS4] |=
|
||||
(S4_VFMT_COLOR |
|
||||
S4_VFMT_SPEC_FOG |
|
||||
S4_VFMT_XYZW);
|
||||
i915->meta.Ctx[I915_CTXREG_LIS4] |= (S4_VFMT_COLOR | 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);
|
||||
}
|
||||
|
||||
|
||||
static void draw_poly(i915ContextPtr i915,
|
||||
GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha,
|
||||
GLuint numVerts,
|
||||
/*const*/ GLfloat verts[][2],
|
||||
/*const*/ GLfloat texcoords[][2])
|
||||
static void
|
||||
leave_meta_state(struct intel_context *intel)
|
||||
{
|
||||
GLuint vertex_size = 8;
|
||||
GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,
|
||||
PRIM3D_TRIFAN,
|
||||
numVerts * vertex_size,
|
||||
vertex_size );
|
||||
intelVertex tmp;
|
||||
int i, k;
|
||||
|
||||
/* initial constant vertex fields */
|
||||
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;
|
||||
|
||||
for (k = 0; k < numVerts; k++) {
|
||||
tmp.v.x = verts[k][0];
|
||||
tmp.v.y = verts[k][1];
|
||||
tmp.v.u0 = texcoords[k][0];
|
||||
tmp.v.v0 = texcoords[k][1];
|
||||
|
||||
for (i = 0 ; i < vertex_size ; i++)
|
||||
vb[i] = tmp.ui[i];
|
||||
|
||||
vb += vertex_size;
|
||||
}
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
intel_region_release(intel->intelScreen, &i915->meta.draw_region);
|
||||
intel_region_release(intel->intelScreen, &i915->meta.depth_region);
|
||||
/* intel_region_release(intel, &i915->meta.tex_region[0]); */
|
||||
SET_STATE(i915, state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
i915ClearWithTris(intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch)
|
||||
i915InitMetaFuncs(struct i915_context *i915)
|
||||
{
|
||||
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_region( i915, &screen->front );
|
||||
|
||||
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_region( i915, &screen->back );
|
||||
|
||||
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_region( i915, &screen->front ); /* 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 );
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the window contents named by dPriv to the rotated (or reflected)
|
||||
* color buffer.
|
||||
* srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
|
||||
*/
|
||||
void
|
||||
i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
|
||||
GLuint srcBuf)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT( intel );
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
const GLuint cpp = screen->cpp;
|
||||
drm_clip_rect_t fullRect;
|
||||
GLuint textureFormat, srcOffset, srcPitch;
|
||||
const drm_clip_rect_t *clipRects;
|
||||
int numClipRects;
|
||||
int i;
|
||||
|
||||
int xOrig, yOrig;
|
||||
int origNumClipRects;
|
||||
drm_clip_rect_t *origRects;
|
||||
|
||||
/*
|
||||
* set up hardware state
|
||||
*/
|
||||
intelFlush( &intel->ctx );
|
||||
|
||||
SET_STATE( i915, meta );
|
||||
set_initial_state( i915 );
|
||||
set_no_texture( i915 );
|
||||
set_vertex_format( i915 );
|
||||
set_no_depth_stencil_write( i915 );
|
||||
set_color_mask( i915, GL_TRUE );
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
/* save current drawing origin and cliprects (restored at end) */
|
||||
xOrig = intel->drawX;
|
||||
yOrig = intel->drawY;
|
||||
origNumClipRects = intel->numClipRects;
|
||||
origRects = intel->pClipRects;
|
||||
|
||||
if (!intel->numClipRects)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* set drawing origin, cliprects for full-screen access to rotated screen
|
||||
*/
|
||||
fullRect.x1 = 0;
|
||||
fullRect.y1 = 0;
|
||||
fullRect.x2 = screen->rotatedWidth;
|
||||
fullRect.y2 = screen->rotatedHeight;
|
||||
intel->drawX = 0;
|
||||
intel->drawY = 0;
|
||||
intel->numClipRects = 1;
|
||||
intel->pClipRects = &fullRect;
|
||||
|
||||
set_draw_region( i915, &screen->rotated );
|
||||
|
||||
if (cpp == 4)
|
||||
textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888;
|
||||
else
|
||||
textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565;
|
||||
|
||||
if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
|
||||
srcPitch = screen->front.pitch; /* in bytes */
|
||||
srcOffset = screen->front.offset; /* bytes */
|
||||
clipRects = dPriv->pClipRects;
|
||||
numClipRects = dPriv->numClipRects;
|
||||
}
|
||||
else {
|
||||
srcPitch = screen->back.pitch; /* in bytes */
|
||||
srcOffset = screen->back.offset; /* bytes */
|
||||
clipRects = dPriv->pBackClipRects;
|
||||
numClipRects = dPriv->numBackClipRects;
|
||||
}
|
||||
|
||||
/* set the whole screen up as a texture to avoid alignment issues */
|
||||
set_tex_rect_source(i915,
|
||||
srcOffset,
|
||||
screen->width,
|
||||
screen->height,
|
||||
srcPitch,
|
||||
textureFormat);
|
||||
|
||||
enable_texture_blend_replace(i915);
|
||||
|
||||
/*
|
||||
* loop over the source window's cliprects
|
||||
*/
|
||||
for (i = 0; i < numClipRects; i++) {
|
||||
int srcX0 = clipRects[i].x1;
|
||||
int srcY0 = clipRects[i].y1;
|
||||
int srcX1 = clipRects[i].x2;
|
||||
int srcY1 = clipRects[i].y2;
|
||||
GLfloat verts[4][2], tex[4][2];
|
||||
int j;
|
||||
|
||||
/* build vertices for four corners of clip rect */
|
||||
verts[0][0] = srcX0; verts[0][1] = srcY0;
|
||||
verts[1][0] = srcX1; verts[1][1] = srcY0;
|
||||
verts[2][0] = srcX1; verts[2][1] = srcY1;
|
||||
verts[3][0] = srcX0; verts[3][1] = srcY1;
|
||||
|
||||
/* .. and texcoords */
|
||||
tex[0][0] = srcX0; tex[0][1] = srcY0;
|
||||
tex[1][0] = srcX1; tex[1][1] = srcY0;
|
||||
tex[2][0] = srcX1; tex[2][1] = srcY1;
|
||||
tex[3][0] = srcX0; tex[3][1] = srcY1;
|
||||
|
||||
/* transform coords to rotated screen coords */
|
||||
for (j = 0; j < 4; j++) {
|
||||
matrix23TransformCoordf(&screen->rotMatrix,
|
||||
&verts[j][0], &verts[j][1]);
|
||||
}
|
||||
|
||||
/* draw polygon to map source image to dest region */
|
||||
draw_poly(i915, 255, 255, 255, 255, 4, verts, tex);
|
||||
|
||||
} /* cliprect loop */
|
||||
|
||||
intelFlushBatchLocked( intel, GL_FALSE, GL_FALSE, GL_FALSE );
|
||||
|
||||
done:
|
||||
/* restore original drawing origin and cliprects */
|
||||
intel->drawX = xOrig;
|
||||
intel->drawY = yOrig;
|
||||
intel->numClipRects = origNumClipRects;
|
||||
intel->pClipRects = origRects;
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
SET_STATE( i915, state );
|
||||
}
|
||||
|
||||
|
||||
@@ -72,58 +72,62 @@
|
||||
|
||||
#define I915_CONSTFLAG_PARAM 0x1f
|
||||
|
||||
GLuint i915_get_temp( struct i915_fragment_program *p )
|
||||
GLuint
|
||||
i915_get_temp(struct i915_fragment_program *p)
|
||||
{
|
||||
int bit = ffs( ~p->temp_flag );
|
||||
int bit = ffs(~p->temp_flag);
|
||||
if (!bit) {
|
||||
fprintf(stderr, "%s: out of temporaries\n", __FILE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p->temp_flag |= 1<<(bit-1);
|
||||
return UREG(REG_TYPE_R, (bit-1));
|
||||
p->temp_flag |= 1 << (bit - 1);
|
||||
return UREG(REG_TYPE_R, (bit - 1));
|
||||
}
|
||||
|
||||
|
||||
GLuint i915_get_utemp( struct i915_fragment_program *p )
|
||||
GLuint
|
||||
i915_get_utemp(struct i915_fragment_program * p)
|
||||
{
|
||||
int bit = ffs( ~p->utemp_flag );
|
||||
int bit = ffs(~p->utemp_flag);
|
||||
if (!bit) {
|
||||
fprintf(stderr, "%s: out of temporaries\n", __FILE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p->utemp_flag |= 1<<(bit-1);
|
||||
return UREG(REG_TYPE_U, (bit-1));
|
||||
p->utemp_flag |= 1 << (bit - 1);
|
||||
return UREG(REG_TYPE_U, (bit - 1));
|
||||
}
|
||||
|
||||
void i915_release_utemps( struct i915_fragment_program *p )
|
||||
void
|
||||
i915_release_utemps(struct i915_fragment_program *p)
|
||||
{
|
||||
p->utemp_flag = ~0x7;
|
||||
}
|
||||
|
||||
|
||||
GLuint i915_emit_decl( struct i915_fragment_program *p,
|
||||
GLuint type, GLuint nr, GLuint d0_flags )
|
||||
GLuint
|
||||
i915_emit_decl(struct i915_fragment_program *p,
|
||||
GLuint type, GLuint nr, GLuint d0_flags)
|
||||
{
|
||||
GLuint reg = UREG(type, nr);
|
||||
|
||||
if (type == REG_TYPE_T) {
|
||||
if (p->decl_t & (1<<nr))
|
||||
if (p->decl_t & (1 << nr))
|
||||
return reg;
|
||||
|
||||
p->decl_t |= (1<<nr);
|
||||
p->decl_t |= (1 << nr);
|
||||
}
|
||||
else if (type == REG_TYPE_S) {
|
||||
if (p->decl_s & (1<<nr))
|
||||
if (p->decl_s & (1 << nr))
|
||||
return reg;
|
||||
|
||||
p->decl_s |= (1<<nr);
|
||||
p->decl_s |= (1 << nr);
|
||||
}
|
||||
else
|
||||
return reg;
|
||||
|
||||
*(p->decl++) = (D0_DCL | D0_DEST( reg ) | d0_flags);
|
||||
*(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags);
|
||||
*(p->decl++) = D1_MBZ;
|
||||
*(p->decl++) = D2_MBZ;
|
||||
|
||||
@@ -131,24 +135,26 @@ GLuint i915_emit_decl( struct i915_fragment_program *p,
|
||||
return reg;
|
||||
}
|
||||
|
||||
GLuint i915_emit_arith( struct i915_fragment_program *p,
|
||||
GLuint
|
||||
i915_emit_arith(struct i915_fragment_program * p,
|
||||
GLuint op,
|
||||
GLuint dest,
|
||||
GLuint mask,
|
||||
GLuint saturate,
|
||||
GLuint src0,
|
||||
GLuint src1,
|
||||
GLuint src2 )
|
||||
GLuint saturate, GLuint src0, GLuint src1, GLuint src2)
|
||||
{
|
||||
GLuint c[3];
|
||||
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;
|
||||
if (GET_UREG_TYPE(src2) == REG_TYPE_CONST) c[nr_const++] = 2;
|
||||
if (GET_UREG_TYPE(src0) == REG_TYPE_CONST)
|
||||
c[nr_const++] = 0;
|
||||
if (GET_UREG_TYPE(src1) == REG_TYPE_CONST)
|
||||
c[nr_const++] = 1;
|
||||
if (GET_UREG_TYPE(src2) == REG_TYPE_CONST)
|
||||
c[nr_const++] = 2;
|
||||
|
||||
/* Recursively call this function to MOV additional const values
|
||||
* into temporary registers. Use utemp registers for this -
|
||||
@@ -164,12 +170,12 @@ GLuint i915_emit_arith( struct i915_fragment_program *p,
|
||||
old_utemp_flag = p->utemp_flag;
|
||||
|
||||
first = GET_UREG_NR(s[c[0]]);
|
||||
for (i = 1 ; i < nr_const ; i++) {
|
||||
for (i = 1; i < nr_const; i++) {
|
||||
if (GET_UREG_NR(s[c[i]]) != first) {
|
||||
GLuint tmp = i915_get_utemp(p);
|
||||
|
||||
i915_emit_arith( p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0,
|
||||
s[c[i]], 0, 0 );
|
||||
i915_emit_arith(p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0,
|
||||
s[c[i]], 0, 0);
|
||||
s[c[i]] = tmp;
|
||||
}
|
||||
}
|
||||
@@ -180,15 +186,9 @@ GLuint i915_emit_arith( struct i915_fragment_program *p,
|
||||
p->utemp_flag = old_utemp_flag; /* restore */
|
||||
}
|
||||
|
||||
*(p->csr++) = (op |
|
||||
A0_DEST( dest ) |
|
||||
mask |
|
||||
saturate |
|
||||
A0_SRC0( src0 ));
|
||||
*(p->csr++) = (A1_SRC0( src0 ) |
|
||||
A1_SRC1( src1 ));
|
||||
*(p->csr++) = (A2_SRC1( src1 ) |
|
||||
A2_SRC2( src2 ));
|
||||
*(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0));
|
||||
*(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1));
|
||||
*(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2));
|
||||
|
||||
p->nr_alu_insn++;
|
||||
return dest;
|
||||
@@ -201,6 +201,24 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
|
||||
GLuint coord,
|
||||
GLuint op )
|
||||
{
|
||||
if (coord != UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord))) {
|
||||
/* No real way to work around this in the general case - need to
|
||||
* allocate and declare a new temporary register (a utemp won't
|
||||
* do). Will fallback for now.
|
||||
*/
|
||||
i915_program_error(p, "Can't (yet) swizzle TEX arguments");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't worry about saturate as we only support
|
||||
*/
|
||||
if (destmask != A0_DEST_CHANNEL_ALL) {
|
||||
GLuint tmp = i915_get_utemp(p);
|
||||
i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, op );
|
||||
i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 );
|
||||
return dest;
|
||||
}
|
||||
else {
|
||||
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
|
||||
assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));
|
||||
|
||||
@@ -210,7 +228,6 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
|
||||
|
||||
*(p->csr++) = (op |
|
||||
T0_DEST( dest ) |
|
||||
destmask |
|
||||
T0_SAMPLER( sampler ));
|
||||
|
||||
*(p->csr++) = T1_ADDRESS_REG( coord );
|
||||
@@ -218,26 +235,31 @@ GLuint i915_emit_texld( struct i915_fragment_program *p,
|
||||
|
||||
p->nr_tex_insn++;
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLuint i915_emit_const1f( struct i915_fragment_program *p, GLfloat c0 )
|
||||
GLuint
|
||||
i915_emit_const1f(struct i915_fragment_program * p, GLfloat c0)
|
||||
{
|
||||
GLint reg, idx;
|
||||
|
||||
if (c0 == 0.0) return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO);
|
||||
if (c0 == 1.0) return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE );
|
||||
if (c0 == 0.0)
|
||||
return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO);
|
||||
if (c0 == 1.0)
|
||||
return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE);
|
||||
|
||||
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
|
||||
if (p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
|
||||
continue;
|
||||
for (idx = 0; idx < 4; idx++) {
|
||||
if (!(p->constant_flags[reg] & (1<<idx)) ||
|
||||
if (!(p->constant_flags[reg] & (1 << idx)) ||
|
||||
p->constant[reg][idx] == c0) {
|
||||
p->constant[reg][idx] = c0;
|
||||
p->constant_flags[reg] |= 1<<idx;
|
||||
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
|
||||
return swizzle(UREG(REG_TYPE_CONST, reg),idx,ZERO,ZERO,ONE);
|
||||
p->constant_flags[reg] |= 1 << idx;
|
||||
if (reg + 1 > p->nr_constants)
|
||||
p->nr_constants = reg + 1;
|
||||
return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,28 +269,34 @@ GLuint i915_emit_const1f( struct i915_fragment_program *p, GLfloat c0 )
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint i915_emit_const2f( struct i915_fragment_program *p,
|
||||
GLfloat c0, GLfloat c1 )
|
||||
GLuint
|
||||
i915_emit_const2f(struct i915_fragment_program * p, GLfloat c0, GLfloat c1)
|
||||
{
|
||||
GLint reg, idx;
|
||||
|
||||
if (c0 == 0.0) return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W);
|
||||
if (c0 == 1.0) return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W);
|
||||
if (c0 == 0.0)
|
||||
return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W);
|
||||
if (c0 == 1.0)
|
||||
return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W);
|
||||
|
||||
if (c1 == 0.0) return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W);
|
||||
if (c1 == 1.0) return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W);
|
||||
if (c1 == 0.0)
|
||||
return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W);
|
||||
if (c1 == 1.0)
|
||||
return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W);
|
||||
|
||||
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) {
|
||||
if (p->constant_flags[reg] == 0xf ||
|
||||
p->constant_flags[reg] == I915_CONSTFLAG_PARAM)
|
||||
continue;
|
||||
for (idx = 0; idx < 3; idx++) {
|
||||
if (!(p->constant_flags[reg] & (3<<idx))) {
|
||||
if (!(p->constant_flags[reg] & (3 << idx))) {
|
||||
p->constant[reg][idx] = c0;
|
||||
p->constant[reg][idx+1] = c1;
|
||||
p->constant_flags[reg] |= 3<<idx;
|
||||
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
|
||||
return swizzle(UREG(REG_TYPE_CONST, reg),idx,idx+1,ZERO,ONE);
|
||||
p->constant[reg][idx + 1] = c1;
|
||||
p->constant_flags[reg] |= 3 << idx;
|
||||
if (reg + 1 > p->nr_constants)
|
||||
p->nr_constants = reg + 1;
|
||||
return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO,
|
||||
ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,8 +308,9 @@ GLuint i915_emit_const2f( struct i915_fragment_program *p,
|
||||
|
||||
|
||||
|
||||
GLuint i915_emit_const4f( struct i915_fragment_program *p,
|
||||
GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3 )
|
||||
GLuint
|
||||
i915_emit_const4f(struct i915_fragment_program * p,
|
||||
GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3)
|
||||
{
|
||||
GLint reg;
|
||||
|
||||
@@ -289,8 +318,7 @@ GLuint i915_emit_const4f( struct i915_fragment_program *p,
|
||||
if (p->constant_flags[reg] == 0xf &&
|
||||
p->constant[reg][0] == c0 &&
|
||||
p->constant[reg][1] == c1 &&
|
||||
p->constant[reg][2] == c2 &&
|
||||
p->constant[reg][3] == c3) {
|
||||
p->constant[reg][2] == c2 && p->constant[reg][3] == c3) {
|
||||
return UREG(REG_TYPE_CONST, reg);
|
||||
}
|
||||
else if (p->constant_flags[reg] == 0) {
|
||||
@@ -299,7 +327,8 @@ GLuint i915_emit_const4f( struct i915_fragment_program *p,
|
||||
p->constant[reg][2] = c2;
|
||||
p->constant[reg][3] = c3;
|
||||
p->constant_flags[reg] = 0xf;
|
||||
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
|
||||
if (reg + 1 > p->nr_constants)
|
||||
p->nr_constants = reg + 1;
|
||||
return UREG(REG_TYPE_CONST, reg);
|
||||
}
|
||||
}
|
||||
@@ -310,14 +339,15 @@ GLuint i915_emit_const4f( struct i915_fragment_program *p,
|
||||
}
|
||||
|
||||
|
||||
GLuint i915_emit_const4fv( struct i915_fragment_program *p, const GLfloat *c )
|
||||
GLuint
|
||||
i915_emit_const4fv(struct i915_fragment_program * p, const GLfloat * c)
|
||||
{
|
||||
return i915_emit_const4f( p, c[0], c[1], c[2], c[3] );
|
||||
return i915_emit_const4f(p, c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
|
||||
|
||||
GLuint i915_emit_param4fv( struct i915_fragment_program *p,
|
||||
const GLfloat *values )
|
||||
GLuint
|
||||
i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values)
|
||||
{
|
||||
GLint reg, i;
|
||||
|
||||
@@ -336,7 +366,8 @@ GLuint i915_emit_param4fv( struct i915_fragment_program *p,
|
||||
p->param[i].reg = reg;
|
||||
p->params_uptodate = 0;
|
||||
|
||||
if (reg+1 > p->nr_constants) p->nr_constants = reg+1;
|
||||
if (reg + 1 > p->nr_constants)
|
||||
p->nr_constants = reg + 1;
|
||||
return UREG(REG_TYPE_CONST, reg);
|
||||
}
|
||||
}
|
||||
@@ -349,7 +380,8 @@ GLuint i915_emit_param4fv( struct i915_fragment_program *p,
|
||||
|
||||
|
||||
|
||||
void i915_program_error( struct i915_fragment_program *p, const char *msg )
|
||||
void
|
||||
i915_program_error(struct i915_fragment_program *p, const char *msg)
|
||||
{
|
||||
/* XXX we shouldn't print anything to stdout, record GL error or
|
||||
* call _mesa_problem()
|
||||
@@ -358,10 +390,11 @@ 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 );
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
|
||||
p->translated = 0;
|
||||
p->params_uptodate = 0;
|
||||
@@ -374,7 +407,7 @@ void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p )
|
||||
p->nr_decl_insn = 0;
|
||||
|
||||
p->ctx = ctx;
|
||||
memset( p->constant_flags, 0, sizeof(p->constant_flags) );
|
||||
memset(p->constant_flags, 0, sizeof(p->constant_flags));
|
||||
|
||||
p->nr_constants = 0;
|
||||
p->csr = p->program;
|
||||
@@ -396,7 +429,8 @@ void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p )
|
||||
}
|
||||
|
||||
|
||||
void i915_fini_program( struct i915_fragment_program *p )
|
||||
void
|
||||
i915_fini_program(struct i915_fragment_program *p)
|
||||
{
|
||||
GLuint program_size = p->csr - p->program;
|
||||
GLuint decl_size = p->decl - p->declarations;
|
||||
@@ -431,22 +465,24 @@ 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;
|
||||
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_PROGRAM, p->error );
|
||||
FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, p->error);
|
||||
|
||||
/* Could just go straight to the batchbuffer from here:
|
||||
*/
|
||||
if (i915->state.ProgramSize != (program_size + decl_size) ||
|
||||
memcmp(i915->state.Program + decl_size, p->program,
|
||||
program_size*sizeof(int)) != 0) {
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_PROGRAM );
|
||||
memcpy(i915->state.Program, p->declarations, decl_size*sizeof(int));
|
||||
program_size * sizeof(int)) != 0) {
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_PROGRAM);
|
||||
memcpy(i915->state.Program, p->declarations, decl_size * sizeof(int));
|
||||
memcpy(i915->state.Program + decl_size, p->program,
|
||||
program_size*sizeof(int));
|
||||
program_size * sizeof(int));
|
||||
i915->state.ProgramSize = decl_size + program_size;
|
||||
}
|
||||
|
||||
@@ -456,13 +492,13 @@ void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p )
|
||||
if (p->nr_constants) {
|
||||
GLuint nr = p->nr_constants;
|
||||
|
||||
I915_ACTIVESTATE( i915, I915_UPLOAD_CONSTANTS, 1 );
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_CONSTANTS );
|
||||
I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1);
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS);
|
||||
|
||||
i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4);
|
||||
i915->state.Constant[1] = (1<<(nr-1)) | ((1<<(nr-1))-1);
|
||||
i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1);
|
||||
|
||||
memcpy(&i915->state.Constant[2], p->constant, 4*sizeof(int)*(nr));
|
||||
memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr));
|
||||
i915->state.ConstantSize = 2 + (nr) * 4;
|
||||
|
||||
if (0) {
|
||||
@@ -470,14 +506,12 @@ void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p )
|
||||
for (i = 0; i < nr; i++) {
|
||||
fprintf(stderr, "const[%d]: %f %f %f %f\n", i,
|
||||
p->constant[i][0],
|
||||
p->constant[i][1],
|
||||
p->constant[i][2],
|
||||
p->constant[i][3]);
|
||||
p->constant[i][1], p->constant[i][2], p->constant[i][3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
I915_ACTIVESTATE( i915, I915_UPLOAD_CONSTANTS, 0 );
|
||||
I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0);
|
||||
}
|
||||
|
||||
p->on_hardware = 1;
|
||||
|
||||
@@ -84,78 +84,75 @@
|
||||
|
||||
/* 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 ) |
|
||||
CHANNEL_SRC( GET_CHANNEL_SRC( reg, y ), 1 ) |
|
||||
CHANNEL_SRC( GET_CHANNEL_SRC( reg, z ), 2 ) |
|
||||
CHANNEL_SRC( GET_CHANNEL_SRC( reg, w ), 3 ));
|
||||
CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) |
|
||||
CHANNEL_SRC(GET_CHANNEL_SRC(reg, y), 1) |
|
||||
CHANNEL_SRC(GET_CHANNEL_SRC(reg, z), 2) |
|
||||
CHANNEL_SRC(GET_CHANNEL_SRC(reg, w), 3));
|
||||
}
|
||||
|
||||
/* 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)|
|
||||
((z&1)<<UREG_CHANNEL_Z_NEGATE_SHIFT)|
|
||||
((w&1)<<UREG_CHANNEL_W_NEGATE_SHIFT));
|
||||
return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) |
|
||||
((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) |
|
||||
((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) |
|
||||
((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT));
|
||||
}
|
||||
|
||||
|
||||
extern GLuint i915_get_temp( struct i915_fragment_program *p );
|
||||
extern GLuint i915_get_utemp( struct i915_fragment_program *p );
|
||||
extern void i915_release_utemps( struct i915_fragment_program *p );
|
||||
extern GLuint i915_get_temp(struct i915_fragment_program *p);
|
||||
extern GLuint i915_get_utemp(struct i915_fragment_program *p);
|
||||
extern void i915_release_utemps(struct i915_fragment_program *p);
|
||||
|
||||
|
||||
extern GLuint i915_emit_texld( struct i915_fragment_program *p,
|
||||
extern GLuint i915_emit_texld(struct i915_fragment_program *p,
|
||||
GLuint dest,
|
||||
GLuint destmask,
|
||||
GLuint sampler,
|
||||
GLuint coord,
|
||||
GLuint op );
|
||||
GLuint sampler, GLuint coord, GLuint op);
|
||||
|
||||
extern GLuint i915_emit_arith( struct i915_fragment_program *p,
|
||||
extern GLuint i915_emit_arith(struct i915_fragment_program *p,
|
||||
GLuint op,
|
||||
GLuint dest,
|
||||
GLuint mask,
|
||||
GLuint saturate,
|
||||
GLuint src0,
|
||||
GLuint src1,
|
||||
GLuint src2 );
|
||||
GLuint src0, GLuint src1, GLuint src2);
|
||||
|
||||
extern GLuint i915_emit_decl( struct i915_fragment_program *p,
|
||||
GLuint type, GLuint nr, GLuint d0_flags );
|
||||
extern GLuint i915_emit_decl(struct i915_fragment_program *p,
|
||||
GLuint type, GLuint nr, GLuint d0_flags);
|
||||
|
||||
|
||||
extern GLuint i915_emit_const1f( struct i915_fragment_program *p,
|
||||
GLfloat c0 );
|
||||
extern GLuint i915_emit_const1f(struct i915_fragment_program *p, GLfloat c0);
|
||||
|
||||
extern GLuint i915_emit_const2f( struct i915_fragment_program *p,
|
||||
GLfloat c0, GLfloat c1 );
|
||||
extern GLuint i915_emit_const2f(struct i915_fragment_program *p,
|
||||
GLfloat c0, GLfloat c1);
|
||||
|
||||
extern GLuint i915_emit_const4fv( struct i915_fragment_program *p,
|
||||
const GLfloat *c );
|
||||
extern GLuint i915_emit_const4fv(struct i915_fragment_program *p,
|
||||
const GLfloat * c);
|
||||
|
||||
extern GLuint i915_emit_const4f( struct i915_fragment_program *p,
|
||||
extern GLuint i915_emit_const4f(struct i915_fragment_program *p,
|
||||
GLfloat c0, GLfloat c1,
|
||||
GLfloat c2, GLfloat c3 );
|
||||
GLfloat c2, GLfloat c3);
|
||||
|
||||
|
||||
extern GLuint i915_emit_param4fv( struct i915_fragment_program *p,
|
||||
const GLfloat *values );
|
||||
extern GLuint i915_emit_param4fv(struct i915_fragment_program *p,
|
||||
const GLfloat * values);
|
||||
|
||||
extern void i915_program_error( struct i915_fragment_program *p,
|
||||
const char *msg );
|
||||
extern void i915_program_error(struct i915_fragment_program *p,
|
||||
const char *msg);
|
||||
|
||||
extern void i915_init_program( i915ContextPtr i915,
|
||||
struct i915_fragment_program *p );
|
||||
extern void i915_init_program(struct i915_context *i915,
|
||||
struct i915_fragment_program *p);
|
||||
|
||||
extern void i915_upload_program( i915ContextPtr i915,
|
||||
struct i915_fragment_program *p );
|
||||
extern void i915_upload_program(struct i915_context *i915,
|
||||
struct i915_fragment_program *p);
|
||||
|
||||
extern void i915_fini_program( struct i915_fragment_program *p );
|
||||
extern void i915_fini_program(struct i915_fragment_program *p);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -425,8 +425,10 @@
|
||||
#define S7_DEPTH_OFFSET_CONST_MASK ~0
|
||||
|
||||
/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */
|
||||
/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */
|
||||
|
||||
/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */
|
||||
#define _3DSTATE_MAP_PALETTE_LOAD_32 (CMD_3D|(0x1d<<24)|(0x8f<<16))
|
||||
/* subsequent dwords up to length (max 16) are ARGB8888 color values */
|
||||
|
||||
/* _3DSTATE_MODES_4, p218 */
|
||||
#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x0d<<24))
|
||||
@@ -435,7 +437,7 @@
|
||||
#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)&0xff)
|
||||
@@ -826,10 +828,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 INHIBIT_FLUSH_RENDER_CACHE (1<<2)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,25 +36,25 @@
|
||||
|
||||
#include "texmem.h"
|
||||
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_screen.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
|
||||
#include "i915_context.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_STATE
|
||||
|
||||
static void
|
||||
i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
|
||||
GLuint mask)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func( func );
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func(func);
|
||||
|
||||
mask = mask & 0xff;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
|
||||
DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(func), ref, mask);
|
||||
|
||||
|
||||
@@ -67,16 +67,16 @@ i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
|
||||
S5_STENCIL_TEST_FUNC_MASK);
|
||||
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) |
|
||||
(test << S5_STENCIL_TEST_FUNC_SHIFT));
|
||||
(test <<
|
||||
S5_STENCIL_TEST_FUNC_SHIFT));
|
||||
}
|
||||
|
||||
static void
|
||||
i915StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
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);
|
||||
DBG("%s : mask 0x%x\n", __FUNCTION__, mask);
|
||||
|
||||
mask = mask & 0xff;
|
||||
|
||||
@@ -88,20 +88,18 @@ i915StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
|
||||
|
||||
|
||||
static void
|
||||
i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
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);
|
||||
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
|
||||
DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(fail),
|
||||
_mesa_lookup_enum_by_nr(zfail),
|
||||
_mesa_lookup_enum_by_nr(zpass));
|
||||
_mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass));
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
|
||||
@@ -110,14 +108,17 @@ i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
|
||||
S5_STENCIL_PASS_Z_PASS_MASK);
|
||||
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) |
|
||||
(dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
|
||||
(dpop << S5_STENCIL_PASS_Z_PASS_SHIFT));
|
||||
(dfop <<
|
||||
S5_STENCIL_PASS_Z_FAIL_SHIFT) |
|
||||
(dpop <<
|
||||
S5_STENCIL_PASS_Z_PASS_SHIFT));
|
||||
}
|
||||
|
||||
static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
static void
|
||||
i915AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func( func );
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func(func);
|
||||
GLubyte refByte;
|
||||
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref);
|
||||
@@ -126,7 +127,8 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK |
|
||||
S6_ALPHA_REF_MASK);
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) |
|
||||
(((GLuint)refByte) << S6_ALPHA_REF_SHIFT));
|
||||
(((GLuint) refByte) <<
|
||||
S6_ALPHA_REF_SHIFT));
|
||||
}
|
||||
|
||||
/* This function makes sure that the proper enables are
|
||||
@@ -135,33 +137,36 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
|
||||
* could change the LogicOp or Independant Alpha Blend without subsequent
|
||||
* calls to glEnable.
|
||||
*/
|
||||
static void i915EvalLogicOpBlendState(GLcontext *ctx)
|
||||
static void
|
||||
i915EvalLogicOpBlendState(GLcontext * ctx)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
|
||||
if (ctx->Color._LogicOpEnabled) {
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE;
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE;
|
||||
|
||||
if (ctx->Color.BlendEnabled) {
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void i915BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
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)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]);
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]);
|
||||
@@ -169,7 +174,8 @@ static void i915BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = (a<<24) | (r<<16) | (g<<8) | b;
|
||||
i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] =
|
||||
(a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
|
||||
@@ -180,31 +186,37 @@ static void i915BlendColor(GLcontext *ctx, const GLfloat color[4])
|
||||
|
||||
|
||||
|
||||
static GLuint translate_blend_equation( GLenum mode )
|
||||
static GLuint
|
||||
translate_blend_equation(GLenum mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case GL_FUNC_ADD: return BLENDFUNC_ADD;
|
||||
case GL_MIN: return BLENDFUNC_MIN;
|
||||
case GL_MAX: return BLENDFUNC_MAX;
|
||||
case GL_FUNC_SUBTRACT: return BLENDFUNC_SUBTRACT;
|
||||
case GL_FUNC_REVERSE_SUBTRACT: return BLENDFUNC_REVERSE_SUBTRACT;
|
||||
default: return 0;
|
||||
case GL_FUNC_ADD:
|
||||
return BLENDFUNC_ADD;
|
||||
case GL_MIN:
|
||||
return BLENDFUNC_MIN;
|
||||
case GL_MAX:
|
||||
return BLENDFUNC_MAX;
|
||||
case GL_FUNC_SUBTRACT:
|
||||
return BLENDFUNC_SUBTRACT;
|
||||
case GL_FUNC_REVERSE_SUBTRACT:
|
||||
return BLENDFUNC_REVERSE_SUBTRACT;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void i915UpdateBlendState( GLcontext *ctx )
|
||||
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 |
|
||||
(BLENDFUNC_MASK << IAB_FUNC_SHIFT) |
|
||||
IAB_ENABLE));
|
||||
(BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE));
|
||||
|
||||
GLuint lis6 = (i915->state.Ctx[I915_CTXREG_LIS6] &
|
||||
~(S6_CBUF_SRC_BLEND_FACT_MASK |
|
||||
S6_CBUF_DST_BLEND_FACT_MASK |
|
||||
S6_CBUF_BLEND_FUNC_MASK));
|
||||
S6_CBUF_DST_BLEND_FACT_MASK | S6_CBUF_BLEND_FUNC_MASK));
|
||||
|
||||
GLuint eqRGB = ctx->Color.BlendEquationRGB;
|
||||
GLuint eqA = ctx->Color.BlendEquationA;
|
||||
@@ -223,11 +235,11 @@ static void i915UpdateBlendState( GLcontext *ctx )
|
||||
|
||||
lis6 |= SRC_BLND_FACT(intel_translate_blend_factor(srcRGB));
|
||||
lis6 |= DST_BLND_FACT(intel_translate_blend_factor(dstRGB));
|
||||
lis6 |= translate_blend_equation( eqRGB ) << S6_CBUF_BLEND_FUNC_SHIFT;
|
||||
lis6 |= translate_blend_equation(eqRGB) << S6_CBUF_BLEND_FUNC_SHIFT;
|
||||
|
||||
iab |= SRC_ABLND_FACT(intel_translate_blend_factor(srcA));
|
||||
iab |= DST_ABLND_FACT(intel_translate_blend_factor(dstA));
|
||||
iab |= translate_blend_equation( eqA ) << IAB_FUNC_SHIFT;
|
||||
iab |= translate_blend_equation(eqA) << IAB_FUNC_SHIFT;
|
||||
|
||||
if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB)
|
||||
iab |= IAB_ENABLE;
|
||||
@@ -244,40 +256,40 @@ static void i915UpdateBlendState( GLcontext *ctx )
|
||||
}
|
||||
|
||||
|
||||
static void i915BlendFuncSeparate(GLcontext *ctx, GLenum srcRGB,
|
||||
GLenum dstRGB, GLenum srcA,
|
||||
GLenum dstA )
|
||||
static void
|
||||
i915BlendFuncSeparate(GLcontext * ctx, GLenum srcRGB,
|
||||
GLenum dstRGB, GLenum srcA, GLenum dstA)
|
||||
{
|
||||
i915UpdateBlendState( ctx );
|
||||
i915UpdateBlendState(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB,
|
||||
GLenum eqA)
|
||||
static void
|
||||
i915BlendEquationSeparate(GLcontext * ctx, GLenum eqRGB, GLenum eqA)
|
||||
{
|
||||
i915UpdateBlendState( ctx );
|
||||
i915UpdateBlendState(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void i915DepthFunc(GLcontext *ctx, GLenum func)
|
||||
static void
|
||||
i915DepthFunc(GLcontext * ctx, GLenum func)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func( func );
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
int test = intel_translate_compare_func(func);
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK;
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT;
|
||||
}
|
||||
|
||||
static void i915DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
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);
|
||||
DBG("%s flag (%d)\n", __FUNCTION__, flag);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
|
||||
@@ -293,12 +305,13 @@ static void i915DepthMask(GLcontext *ctx, GLboolean flag)
|
||||
* The i915 supports a 4x4 stipple natively, GL wants 32x32.
|
||||
* Fortunately stipple is usually a repeating pattern.
|
||||
*/
|
||||
static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
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;
|
||||
int i, j, k;
|
||||
int active = (ctx->Polygon.StippleFlag &&
|
||||
i915->intel.reduced_primitive == GL_TRIANGLES);
|
||||
GLuint newMask;
|
||||
@@ -308,14 +321,18 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE;
|
||||
}
|
||||
|
||||
p[0] = mask[12] & 0xf; p[0] |= p[0] << 4;
|
||||
p[1] = mask[8] & 0xf; p[1] |= p[1] << 4;
|
||||
p[2] = mask[4] & 0xf; p[2] |= p[2] << 4;
|
||||
p[3] = mask[0] & 0xf; p[3] |= p[3] << 4;
|
||||
p[0] = mask[12] & 0xf;
|
||||
p[0] |= p[0] << 4;
|
||||
p[1] = mask[8] & 0xf;
|
||||
p[1] |= p[1] << 4;
|
||||
p[2] = mask[4] & 0xf;
|
||||
p[2] |= p[2] << 4;
|
||||
p[3] = mask[0] & 0xf;
|
||||
p[3] |= p[3] << 4;
|
||||
|
||||
for (k = 0 ; k < 8 ; k++)
|
||||
for (j = 3 ; j >= 0; j--)
|
||||
for (i = 0 ; i < 4 ; i++, m++)
|
||||
for (k = 0; k < 8; k++)
|
||||
for (j = 3; j >= 0; j--)
|
||||
for (i = 0; i < 4; i++, m++)
|
||||
if (*m != p[j]) {
|
||||
i915->intel.hw_stipple = 0;
|
||||
return;
|
||||
@@ -323,8 +340,7 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
|
||||
newMask = (((p[0] & 0xf) << 0) |
|
||||
((p[1] & 0xf) << 4) |
|
||||
((p[2] & 0xf) << 8) |
|
||||
((p[3] & 0xf) << 12));
|
||||
((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12));
|
||||
|
||||
|
||||
if (newMask == 0xffff || newMask == 0x0) {
|
||||
@@ -345,48 +361,40 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
|
||||
/* =============================================================
|
||||
* Hardware clipping
|
||||
*/
|
||||
static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
|
||||
GLsizei w, GLsizei h)
|
||||
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;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
|
||||
DBG("[%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);
|
||||
i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
|
||||
}
|
||||
|
||||
static void i915LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
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)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
i915->state.Ctx[I915_CTXREG_STATE4] &= ~LOGICOP_MASK;
|
||||
@@ -395,13 +403,14 @@ static void i915LogicOp(GLcontext *ctx, GLenum opcode)
|
||||
|
||||
|
||||
|
||||
static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
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)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s %d\n", __FUNCTION__,
|
||||
ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0);
|
||||
|
||||
if (!ctx->Polygon.CullFlag) {
|
||||
mode = S4_CULLMODE_NONE;
|
||||
@@ -409,6 +418,8 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) {
|
||||
mode = S4_CULLMODE_CW;
|
||||
|
||||
if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
|
||||
mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW);
|
||||
if (ctx->Polygon.CullFaceMode == GL_FRONT)
|
||||
mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW);
|
||||
if (ctx->Polygon.FrontFace != GL_CCW)
|
||||
@@ -423,16 +434,16 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
|
||||
i915->state.Ctx[I915_CTXREG_LIS4] |= mode;
|
||||
}
|
||||
|
||||
static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
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;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
width = (int)(widthf * 2);
|
||||
width = (int) (widthf * 2);
|
||||
CLAMP_SELF(width, 1, 0xf);
|
||||
lis4 |= width << S4_LINE_WIDTH_SHIFT;
|
||||
|
||||
@@ -442,14 +453,14 @@ static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
|
||||
}
|
||||
}
|
||||
|
||||
static void i915PointSize(GLcontext *ctx, GLfloat size)
|
||||
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;
|
||||
GLint point_size = (int) size;
|
||||
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
CLAMP_SELF(point_size, 1, 255);
|
||||
lis4 |= point_size << S4_POINT_WIDTH_SHIFT;
|
||||
@@ -465,20 +476,24 @@ static void i915PointSize(GLcontext *ctx, GLfloat size)
|
||||
* Color masks
|
||||
*/
|
||||
|
||||
static void i915ColorMask(GLcontext *ctx,
|
||||
GLboolean r, GLboolean g,
|
||||
GLboolean b, GLboolean a)
|
||||
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)
|
||||
fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a);
|
||||
DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b,
|
||||
a);
|
||||
|
||||
if (!r) tmp |= S5_WRITEDISABLE_RED;
|
||||
if (!g) tmp |= S5_WRITEDISABLE_GREEN;
|
||||
if (!b) tmp |= S5_WRITEDISABLE_BLUE;
|
||||
if (!a) tmp |= S5_WRITEDISABLE_ALPHA;
|
||||
if (!r)
|
||||
tmp |= S5_WRITEDISABLE_RED;
|
||||
if (!g)
|
||||
tmp |= S5_WRITEDISABLE_GREEN;
|
||||
if (!b)
|
||||
tmp |= S5_WRITEDISABLE_BLUE;
|
||||
if (!a)
|
||||
tmp |= S5_WRITEDISABLE_ALPHA;
|
||||
|
||||
if (tmp != i915->state.Ctx[I915_CTXREG_LIS5]) {
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
|
||||
@@ -486,35 +501,37 @@ static void i915ColorMask(GLcontext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void update_specular( GLcontext *ctx )
|
||||
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;
|
||||
}
|
||||
|
||||
static void i915LightModelfv(GLcontext *ctx, GLenum pname,
|
||||
const GLfloat *param)
|
||||
static void
|
||||
i915LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param)
|
||||
{
|
||||
if (INTEL_DEBUG&DEBUG_DRI)
|
||||
fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
|
||||
update_specular( ctx );
|
||||
update_specular(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void i915ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
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) {
|
||||
i915->state.Ctx[I915_CTXREG_LIS4] &= ~(S4_FLATSHADE_ALPHA |
|
||||
S4_FLATSHADE_COLOR |
|
||||
S4_FLATSHADE_SPECULAR);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
i915->state.Ctx[I915_CTXREG_LIS4] |= (S4_FLATSHADE_ALPHA |
|
||||
S4_FLATSHADE_COLOR |
|
||||
S4_FLATSHADE_SPECULAR);
|
||||
@@ -524,9 +541,10 @@ static void i915ShadeModel(GLcontext *ctx, GLenum mode)
|
||||
/* =============================================================
|
||||
* Fog
|
||||
*/
|
||||
void i915_update_fog( GLcontext *ctx )
|
||||
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;
|
||||
@@ -542,9 +560,7 @@ void i915_update_fog( GLcontext *ctx )
|
||||
enabled = ctx->Fog.Enabled;
|
||||
mode = ctx->Fog.Mode;
|
||||
|
||||
try_pixel_fog = (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT &&
|
||||
ctx->Hint.Fog == GL_NICEST &&
|
||||
0); /* XXX - DISABLE -- Need ortho fallback */
|
||||
try_pixel_fog = (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && ctx->Hint.Fog == GL_NICEST && 0); /* XXX - DISABLE -- Need ortho fallback */
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
@@ -567,19 +583,24 @@ void i915_update_fog( GLcontext *ctx )
|
||||
i915->vertex_fog = I915_FOG_VERTEX;
|
||||
}
|
||||
else {
|
||||
GLfloat c1 = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
|
||||
GLfloat c2 = 1.0/(ctx->Fog.End-ctx->Fog.Start);
|
||||
GLfloat c1 = ctx->Fog.End / (ctx->Fog.End - ctx->Fog.Start);
|
||||
GLfloat c2 = 1.0 / (ctx->Fog.End - ctx->Fog.Start);
|
||||
|
||||
i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_C1_MASK;
|
||||
i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_LINEAR;
|
||||
i915->state.Fog[I915_FOGREG_MODE1] |=
|
||||
((GLuint)(c1 * FMC1_C1_ONE)) & FMC1_C1_MASK;
|
||||
((GLuint) (c1 * FMC1_C1_ONE)) & FMC1_C1_MASK;
|
||||
|
||||
if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) {
|
||||
i915->state.Fog[I915_FOGREG_MODE2] = (GLuint)(c2 * FMC2_C2_ONE);
|
||||
i915->state.Fog[I915_FOGREG_MODE2] =
|
||||
(GLuint) (c2 * FMC2_C2_ONE);
|
||||
}
|
||||
else {
|
||||
union { float f; int i; } fi;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
int i;
|
||||
} fi;
|
||||
fi.f = c2;
|
||||
i915->state.Fog[I915_FOGREG_MODE2] = fi.i;
|
||||
}
|
||||
@@ -595,7 +616,8 @@ void i915_update_fog( GLcontext *ctx )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* if (i915->vertex_fog != I915_FOG_VERTEX) */ {
|
||||
else { /* if (i915->vertex_fog != I915_FOG_VERTEX) */
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_FOG);
|
||||
i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK;
|
||||
i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX;
|
||||
@@ -612,14 +634,15 @@ void i915_update_fog( GLcontext *ctx )
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
_tnl_allow_vertex_fog( ctx, (i915->vertex_fog == I915_FOG_VERTEX) );
|
||||
_tnl_allow_pixel_fog( ctx, (i915->vertex_fog != I915_FOG_VERTEX) );
|
||||
_tnl_allow_vertex_fog(ctx, (i915->vertex_fog == I915_FOG_VERTEX));
|
||||
_tnl_allow_pixel_fog(ctx, (i915->vertex_fog != I915_FOG_VERTEX));
|
||||
}
|
||||
}
|
||||
|
||||
static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
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:
|
||||
@@ -632,11 +655,15 @@ static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_FOG);
|
||||
|
||||
if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) {
|
||||
i915->state.Fog[I915_FOGREG_MODE3] = (GLuint)(ctx->Fog.Density *
|
||||
i915->state.Fog[I915_FOGREG_MODE3] = (GLuint) (ctx->Fog.Density *
|
||||
FMC3_D_ONE);
|
||||
}
|
||||
else {
|
||||
union { float f; int i; } fi;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
int i;
|
||||
} fi;
|
||||
fi.f = ctx->Fog.Density;
|
||||
i915->state.Fog[I915_FOGREG_MODE3] = fi.i;
|
||||
}
|
||||
@@ -646,9 +673,9 @@ static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_FOG);
|
||||
i915->state.Fog[I915_FOGREG_COLOR] =
|
||||
(_3DSTATE_FOG_COLOR_CMD |
|
||||
((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) |
|
||||
((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) |
|
||||
((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0));
|
||||
((GLubyte) (ctx->Fog.Color[0] * 255.0F) << 16) |
|
||||
((GLubyte) (ctx->Fog.Color[1] * 255.0F) << 8) |
|
||||
((GLubyte) (ctx->Fog.Color[2] * 255.0F) << 0));
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -656,7 +683,8 @@ static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
|
||||
}
|
||||
}
|
||||
|
||||
static void i915Hint(GLcontext *ctx, GLenum target, GLenum state)
|
||||
static void
|
||||
i915Hint(GLcontext * ctx, GLenum target, GLenum state)
|
||||
{
|
||||
switch (target) {
|
||||
case GL_FOG_HINT:
|
||||
@@ -669,17 +697,18 @@ static void i915Hint(GLcontext *ctx, GLenum target, GLenum state)
|
||||
/* =============================================================
|
||||
*/
|
||||
|
||||
static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
static void
|
||||
i915Enable(GLcontext * ctx, GLenum cap, GLboolean state)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(ctx);
|
||||
struct i915_context *i915 = I915_CONTEXT(ctx);
|
||||
|
||||
switch(cap) {
|
||||
switch (cap) {
|
||||
case GL_TEXTURE_2D:
|
||||
break;
|
||||
|
||||
case GL_LIGHTING:
|
||||
case GL_COLOR_SUM:
|
||||
update_specular( ctx );
|
||||
update_specular(ctx);
|
||||
break;
|
||||
|
||||
case GL_ALPHA_TEST:
|
||||
@@ -699,8 +728,8 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
|
||||
/* Logicop doesn't seem to work at 16bpp:
|
||||
*/
|
||||
if (i915->intel.intelScreen->cpp == 2)
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_LOGICOP, state );
|
||||
if (i915->intel.intelScreen->cpp == 2) /* XXX FBO fix */
|
||||
FALLBACK(&i915->intel, I915_FALLBACK_LOGICOP, state);
|
||||
break;
|
||||
|
||||
case GL_FRAGMENT_PROGRAM_ARB:
|
||||
@@ -721,17 +750,17 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
else
|
||||
i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_ENABLE;
|
||||
|
||||
i915DepthMask( ctx, ctx->Depth.Mask );
|
||||
i915DepthMask(ctx, ctx->Depth.Mask);
|
||||
break;
|
||||
|
||||
case GL_SCISSOR_TEST:
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
|
||||
if (state)
|
||||
i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
ENABLE_SCISSOR_RECT);
|
||||
i915->state.Buffer[I915_DESTREG_SENABLE] =
|
||||
(_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT);
|
||||
else
|
||||
i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
DISABLE_SCISSOR_RECT);
|
||||
i915->state.Buffer[I915_DESTREG_SENABLE] =
|
||||
(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
|
||||
break;
|
||||
|
||||
case GL_LINE_SMOOTH:
|
||||
@@ -750,7 +779,14 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
break;
|
||||
|
||||
case GL_STENCIL_TEST:
|
||||
if (i915->intel.hw_stencil) {
|
||||
{
|
||||
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 |
|
||||
@@ -758,8 +794,10 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
else
|
||||
i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
|
||||
S5_STENCIL_WRITE_ENABLE);
|
||||
} else {
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state );
|
||||
}
|
||||
else {
|
||||
FALLBACK(&i915->intel, I915_FALLBACK_STENCIL, state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -769,8 +807,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
* supports it. Disabled for now.
|
||||
*/
|
||||
if (i915->intel.hw_stipple &&
|
||||
i915->intel.reduced_primitive == GL_TRIANGLES)
|
||||
{
|
||||
i915->intel.reduced_primitive == GL_TRIANGLES) {
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
|
||||
if (state)
|
||||
i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE;
|
||||
@@ -780,11 +817,9 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
|
||||
break;
|
||||
|
||||
case GL_POLYGON_SMOOTH:
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_POLYGON_SMOOTH, state );
|
||||
break;
|
||||
|
||||
case GL_POINT_SMOOTH:
|
||||
FALLBACK( &i915->intel, I915_FALLBACK_POINT_SMOOTH, state );
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -793,7 +828,8 @@ 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;
|
||||
|
||||
@@ -809,14 +845,12 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
i915->state.Ctx[I915_CTXREG_LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
|
||||
I1_LOAD_S(2) |
|
||||
I1_LOAD_S(4) |
|
||||
I1_LOAD_S(5) |
|
||||
I1_LOAD_S(6) |
|
||||
(4));
|
||||
I1_LOAD_S(5) | I1_LOAD_S(6) | (4));
|
||||
i915->state.Ctx[I915_CTXREG_LIS2] = 0;
|
||||
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;
|
||||
|
||||
|
||||
@@ -831,14 +865,12 @@ 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 | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR);
|
||||
|
||||
i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
|
||||
IAB_MODIFY_ENABLE |
|
||||
IAB_MODIFY_FUNC |
|
||||
IAB_MODIFY_SRC_FACTOR |
|
||||
IAB_MODIFY_DST_FACTOR);
|
||||
|
||||
i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] = _3DSTATE_CONST_BLEND_COLOR_CMD;
|
||||
i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] =
|
||||
_3DSTATE_CONST_BLEND_COLOR_CMD;
|
||||
i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0;
|
||||
|
||||
}
|
||||
@@ -866,27 +898,20 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
|
||||
/* color buffer offset/stride */
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK |
|
||||
BUF_3D_PITCH(screen->front.pitch) | /* pitch in bytes */
|
||||
/* 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) | /* pitch in bytes */
|
||||
BUF_3D_USE_FENCE);
|
||||
/*i915->state.Buffer[I915_DESTREG_CBUFADDR2] is the offset */
|
||||
|
||||
|
||||
/* depth/Z buffer offset/stride */
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH |
|
||||
BUF_3D_PITCH(screen->depth.pitch) | /* pitch in bytes */
|
||||
/* 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) | /* pitch in bytes */
|
||||
BUF_3D_USE_FENCE);
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset;
|
||||
|
||||
|
||||
i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
|
||||
|
||||
/* color/depth pixel format */
|
||||
/* 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 */
|
||||
@@ -905,26 +930,42 @@ static void i915_init_packets( i915ContextPtr i915 )
|
||||
DEPTH_FRMT_24_FIXED_8_OTHER);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* scissor */
|
||||
i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
DISABLE_SCISSOR_RECT);
|
||||
i915->state.Buffer[I915_DESTREG_SENABLE] =
|
||||
(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
|
||||
i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD;
|
||||
i915->state.Buffer[I915_DESTREG_SR1] = 0;
|
||||
i915->state.Buffer[I915_DESTREG_SR2] = 0;
|
||||
}
|
||||
|
||||
|
||||
#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_BUFFERS | I915_UPLOAD_INVARIENT);
|
||||
}
|
||||
|
||||
void i915InitStateFunctions( struct dd_function_table *functions )
|
||||
void
|
||||
i915InitStateFunctions(struct dd_function_table *functions)
|
||||
{
|
||||
functions->AlphaFunc = i915AlphaFunc;
|
||||
functions->BlendColor = i915BlendColor;
|
||||
@@ -951,21 +992,15 @@ void i915InitStateFunctions( struct dd_function_table *functions )
|
||||
}
|
||||
|
||||
|
||||
void i915InitState( i915ContextPtr i915 )
|
||||
void
|
||||
i915InitState(struct i915_context *i915)
|
||||
{
|
||||
GLcontext *ctx = &i915->intel.ctx;
|
||||
|
||||
i915_init_packets( i915 );
|
||||
i915_init_packets(i915);
|
||||
|
||||
intelInitState( ctx );
|
||||
intelInitState(ctx);
|
||||
|
||||
memcpy( &i915->initial, &i915->state, sizeof(i915->state) );
|
||||
memcpy(&i915->initial, &i915->state, sizeof(i915->state));
|
||||
i915->current = &i915->state;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -45,76 +45,11 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
static void
|
||||
i915TexEnv(GLcontext * ctx, GLenum target,
|
||||
GLenum pname, const GLfloat * param)
|
||||
{
|
||||
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 */
|
||||
@@ -138,13 +73,15 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
|
||||
i915->tex_program.translated = 0;
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_LOD_BIAS: {
|
||||
int b = (int) ((*param) * 16.0);
|
||||
if (b > 255) b = 255;
|
||||
if (b < -256) b = -256;
|
||||
case GL_TEXTURE_LOD_BIAS:{
|
||||
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] |=
|
||||
i915->lodbias_ss2[unit] =
|
||||
((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
|
||||
break;
|
||||
}
|
||||
@@ -155,21 +92,10 @@ static void i915TexEnv( GLcontext *ctx, GLenum target,
|
||||
}
|
||||
|
||||
|
||||
static void i915BindTexture( GLcontext *ctx, GLenum target,
|
||||
struct gl_texture_object *texObj )
|
||||
static void
|
||||
i915BindTexture(GLcontext * ctx, GLenum target,
|
||||
struct gl_texture_object *texobj)
|
||||
{
|
||||
i915TextureObjectPtr tex;
|
||||
|
||||
if (!texObj->DriverData)
|
||||
i915AllocTexObj( texObj );
|
||||
|
||||
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:
|
||||
@@ -179,9 +105,9 @@ static void i915BindTexture( GLcontext *ctx, GLenum target,
|
||||
|
||||
|
||||
|
||||
void i915InitTextureFuncs( struct dd_function_table *functions )
|
||||
void
|
||||
i915InitTextureFuncs(struct dd_function_table *functions)
|
||||
{
|
||||
functions->BindTexture = i915BindTexture;
|
||||
functions->TexEnv = i915TexEnv;
|
||||
functions->TexParameter = i915TexParameter;
|
||||
}
|
||||
|
||||
380
src/mesa/drivers/dri/i915/i915_tex_layout.c
Normal file
380
src/mesa/drivers/dri/i915/i915_tex_layout.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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"
|
||||
#include "intel_context.h"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
|
||||
|
||||
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 level;
|
||||
|
||||
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 (level = mt->first_level; level <= mt->last_level; level++)
|
||||
intel_miptree_set_level_info(mt, level, 6,
|
||||
0, 0,
|
||||
mt->pitch, mt->total_height, 1);
|
||||
|
||||
for (face = 0; face < 6; face++) {
|
||||
GLuint x = initial_offsets[face][0] * dim;
|
||||
GLuint y = initial_offsets[face][1] * dim;
|
||||
GLuint d = dim;
|
||||
|
||||
for (level = mt->first_level; level <= mt->last_level; level++) {
|
||||
intel_miptree_set_image_offset(mt, level, face, x, y);
|
||||
|
||||
if (d == 0)
|
||||
_mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
|
||||
face, level, 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;
|
||||
GLuint stack_height = 0;
|
||||
|
||||
/* Calculate the size of a single slice.
|
||||
*/
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
|
||||
/* XXX: hardware expects/requires 9 levels at minimum.
|
||||
*/
|
||||
for (level = mt->first_level; level <= MAX2(8, mt->last_level);
|
||||
level++) {
|
||||
intel_miptree_set_level_info(mt, level, 1, 0, mt->total_height,
|
||||
width, height, depth);
|
||||
|
||||
|
||||
stack_height += MAX2(2, height);
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
depth = minify(depth);
|
||||
}
|
||||
|
||||
/* Fixup depth image_offsets:
|
||||
*/
|
||||
depth = mt->depth0;
|
||||
for (level = mt->first_level; level <= mt->last_level; level++) {
|
||||
GLuint i;
|
||||
for (i = 0; i < depth; i++)
|
||||
intel_miptree_set_image_offset(mt, level, i,
|
||||
0, i * stack_height);
|
||||
|
||||
depth = minify(depth);
|
||||
}
|
||||
|
||||
|
||||
/* 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 = stack_height * mt->depth0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:{
|
||||
GLuint width = mt->width0;
|
||||
GLuint height = mt->height0;
|
||||
GLuint img_height;
|
||||
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = 0;
|
||||
|
||||
for (level = mt->first_level; level <= mt->last_level; level++) {
|
||||
intel_miptree_set_level_info(mt, level, 1,
|
||||
0, mt->total_height,
|
||||
width, height, 1);
|
||||
|
||||
if (mt->compressed)
|
||||
img_height = MAX2(1, height / 4);
|
||||
else
|
||||
img_height = MAX2(2, height);
|
||||
|
||||
mt->total_height += img_height;
|
||||
mt->total_height += 1;
|
||||
mt->total_height &= ~1;
|
||||
|
||||
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 level;
|
||||
|
||||
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;
|
||||
|
||||
/* Set all the levels to effectively occupy the whole rectangular region.
|
||||
*/
|
||||
for (level = mt->first_level; level <= mt->last_level; level++)
|
||||
intel_miptree_set_level_info(mt, level, 6,
|
||||
0, 0,
|
||||
mt->pitch, mt->total_height, 1);
|
||||
|
||||
|
||||
|
||||
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 (level = mt->first_level; level <= mt->last_level; level++) {
|
||||
intel_miptree_set_image_offset(mt, level, face, x, y);
|
||||
|
||||
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 pack_x_pitch, pack_x_nr;
|
||||
GLuint pack_y_pitch;
|
||||
GLuint level;
|
||||
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = 0;
|
||||
|
||||
pack_y_pitch = MAX2(mt->height0, 2);
|
||||
pack_x_pitch = mt->pitch;
|
||||
pack_x_nr = 1;
|
||||
|
||||
for (level = mt->first_level; level <= mt->last_level; level++) {
|
||||
GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6;
|
||||
GLint x = 0;
|
||||
GLint y = 0;
|
||||
GLint q, j;
|
||||
|
||||
intel_miptree_set_level_info(mt, level, nr_images,
|
||||
0, mt->total_height,
|
||||
width, height, depth);
|
||||
|
||||
for (q = 0; q < nr_images;) {
|
||||
for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
|
||||
intel_miptree_set_image_offset(mt, level, q, x, y);
|
||||
x += pack_x_pitch;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y += pack_y_pitch;
|
||||
}
|
||||
|
||||
|
||||
mt->total_height += y;
|
||||
|
||||
if (pack_x_pitch > 4) {
|
||||
pack_x_pitch >>= 1;
|
||||
pack_x_nr <<= 1;
|
||||
assert(pack_x_pitch * pack_x_nr <= mt->pitch);
|
||||
}
|
||||
|
||||
if (pack_y_pitch > 2) {
|
||||
pack_y_pitch >>= 1;
|
||||
}
|
||||
|
||||
width = minify(width);
|
||||
height = minify(height);
|
||||
depth = minify(depth);
|
||||
}
|
||||
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;
|
||||
GLint align_h = 2;
|
||||
|
||||
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
|
||||
mt->total_height = 0;
|
||||
|
||||
for (level = mt->first_level; level <= mt->last_level; level++) {
|
||||
GLuint img_height;
|
||||
|
||||
intel_miptree_set_level_info(mt, level, 1,
|
||||
x, y,
|
||||
width,
|
||||
mt->compressed ? height/4 : height, 1);
|
||||
|
||||
|
||||
if (mt->compressed)
|
||||
img_height = MAX2(1, height / 4);
|
||||
else
|
||||
img_height = MAX2(align_h, height);
|
||||
|
||||
/* LPT change: step right after second mipmap.
|
||||
*/
|
||||
if (level == mt->first_level + 1) {
|
||||
x += mt->pitch / 2;
|
||||
x = (x + 3) & ~3;
|
||||
}
|
||||
else {
|
||||
y += img_height;
|
||||
y += align_h - 1;
|
||||
y &= ~(align_h - 1);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,671 +0,0 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 <strings.h>
|
||||
|
||||
#include "glheader.h"
|
||||
#include "macros.h"
|
||||
#include "enums.h"
|
||||
|
||||
#include "tnl/t_context.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
|
||||
#include "i915_reg.h"
|
||||
#include "i915_context.h"
|
||||
#include "i915_program.h"
|
||||
|
||||
static GLuint translate_tex_src_bit( struct i915_fragment_program *p,
|
||||
GLubyte bit )
|
||||
{
|
||||
switch (bit) {
|
||||
case TEXTURE_1D_BIT: return D0_SAMPLE_TYPE_2D;
|
||||
case TEXTURE_2D_BIT: return D0_SAMPLE_TYPE_2D;
|
||||
case TEXTURE_RECT_BIT: return D0_SAMPLE_TYPE_2D;
|
||||
case TEXTURE_3D_BIT: return D0_SAMPLE_TYPE_VOLUME;
|
||||
case TEXTURE_CUBE_BIT: return D0_SAMPLE_TYPE_CUBE;
|
||||
default: i915_program_error(p, "TexSrcBit"); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint get_source( struct i915_fragment_program *p,
|
||||
GLenum src, GLuint unit )
|
||||
{
|
||||
switch (src) {
|
||||
case GL_TEXTURE:
|
||||
if (p->src_texture == UREG_BAD) {
|
||||
|
||||
/* TODO: Use D0_CHANNEL_XY where possible.
|
||||
*/
|
||||
GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled);
|
||||
GLuint sampler = i915_emit_decl(p, REG_TYPE_S, unit, dim);
|
||||
GLuint texcoord = i915_emit_decl(p, REG_TYPE_T, unit, D0_CHANNEL_ALL);
|
||||
GLuint tmp = i915_get_temp( p );
|
||||
GLuint op = T0_TEXLD;
|
||||
|
||||
if (p->VB->TexCoordPtr[unit]->size == 4)
|
||||
op = T0_TEXLDP;
|
||||
|
||||
p->src_texture = i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL,
|
||||
sampler, texcoord, op );
|
||||
}
|
||||
|
||||
return p->src_texture;
|
||||
|
||||
/* Crossbar: */
|
||||
case GL_TEXTURE0:
|
||||
case GL_TEXTURE1:
|
||||
case GL_TEXTURE2:
|
||||
case GL_TEXTURE3:
|
||||
case GL_TEXTURE4:
|
||||
case GL_TEXTURE5:
|
||||
case GL_TEXTURE6:
|
||||
case GL_TEXTURE7: {
|
||||
return UREG_BAD;
|
||||
}
|
||||
|
||||
case GL_CONSTANT:
|
||||
return i915_emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor );
|
||||
case GL_PRIMARY_COLOR:
|
||||
return i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
|
||||
case GL_PREVIOUS:
|
||||
default:
|
||||
i915_emit_decl(p,
|
||||
GET_UREG_TYPE(p->src_previous),
|
||||
GET_UREG_NR(p->src_previous), D0_CHANNEL_ALL);
|
||||
return p->src_previous;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GLuint emit_combine_source( struct i915_fragment_program *p,
|
||||
GLuint mask,
|
||||
GLuint unit,
|
||||
GLenum source,
|
||||
GLenum operand )
|
||||
{
|
||||
GLuint arg, src;
|
||||
|
||||
src = get_source(p, source, unit);
|
||||
|
||||
switch (operand) {
|
||||
case GL_ONE_MINUS_SRC_COLOR:
|
||||
/* Get unused tmp,
|
||||
* Emit tmp = 1.0 + arg.-x-y-z-w
|
||||
*/
|
||||
arg = i915_get_temp( p );
|
||||
return i915_emit_arith( p, A0_ADD, arg, mask, 0,
|
||||
swizzle(src, ONE, ONE, ONE, ONE ),
|
||||
negate(src, 1,1,1,1), 0);
|
||||
|
||||
case GL_SRC_ALPHA:
|
||||
if (mask == A0_DEST_CHANNEL_W)
|
||||
return src;
|
||||
else
|
||||
return swizzle( src, W, W, W, W );
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
/* Get unused tmp,
|
||||
* Emit tmp = 1.0 + arg.-w-w-w-w
|
||||
*/
|
||||
arg = i915_get_temp( p );
|
||||
return i915_emit_arith( p, A0_ADD, arg, mask, 0,
|
||||
swizzle(src, ONE, ONE, ONE, ONE ),
|
||||
negate( swizzle(src,W,W,W,W), 1,1,1,1), 0);
|
||||
case GL_SRC_COLOR:
|
||||
default:
|
||||
return src;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int nr_args( GLenum mode )
|
||||
{
|
||||
switch (mode) {
|
||||
case GL_REPLACE: return 1;
|
||||
case GL_MODULATE: return 2;
|
||||
case GL_ADD: return 2;
|
||||
case GL_ADD_SIGNED: return 2;
|
||||
case GL_INTERPOLATE: return 3;
|
||||
case GL_SUBTRACT: return 2;
|
||||
case GL_DOT3_RGB_EXT: return 2;
|
||||
case GL_DOT3_RGBA_EXT: return 2;
|
||||
case GL_DOT3_RGB: return 2;
|
||||
case GL_DOT3_RGBA: return 2;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static GLboolean args_match( struct gl_texture_unit *texUnit )
|
||||
{
|
||||
int i, nr = nr_args(texUnit->Combine.ModeRGB);
|
||||
|
||||
for (i = 0 ; i < nr ; i++) {
|
||||
if (texUnit->Combine.SourceA[i] != texUnit->Combine.SourceRGB[i])
|
||||
return GL_FALSE;
|
||||
|
||||
switch(texUnit->Combine.OperandA[i]) {
|
||||
case GL_SRC_ALPHA:
|
||||
switch(texUnit->Combine.OperandRGB[i]) {
|
||||
case GL_SRC_COLOR:
|
||||
case GL_SRC_ALPHA:
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
switch(texUnit->Combine.OperandRGB[i]) {
|
||||
case GL_ONE_MINUS_SRC_COLOR:
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return GL_FALSE; /* impossible */
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static GLuint emit_combine( struct i915_fragment_program *p,
|
||||
GLuint dest,
|
||||
GLuint mask,
|
||||
GLuint saturate,
|
||||
GLuint unit,
|
||||
GLenum mode,
|
||||
const GLenum *source,
|
||||
const GLenum *operand)
|
||||
{
|
||||
int tmp, src[3], nr = nr_args(mode);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr; i++)
|
||||
src[i] = emit_combine_source( p, mask, unit, source[i], operand[i] );
|
||||
|
||||
switch (mode) {
|
||||
case GL_REPLACE:
|
||||
if (mask == A0_DEST_CHANNEL_ALL && !saturate)
|
||||
return src[0];
|
||||
else
|
||||
return i915_emit_arith( p, A0_MOV, dest, mask, saturate, src[0], 0, 0 );
|
||||
case GL_MODULATE:
|
||||
return i915_emit_arith( p, A0_MUL, dest, mask, saturate,
|
||||
src[0], src[1], 0 );
|
||||
case GL_ADD:
|
||||
return i915_emit_arith( p, A0_ADD, dest, mask, saturate,
|
||||
src[0], src[1], 0 );
|
||||
case GL_ADD_SIGNED:
|
||||
/* tmp = arg0 + arg1
|
||||
* result = tmp + -.5
|
||||
*/
|
||||
tmp = i915_emit_const1f(p, .5);
|
||||
tmp = negate(swizzle(tmp,X,X,X,X),1,1,1,1);
|
||||
i915_emit_arith( p, A0_ADD, dest, mask, 0, src[0], src[1], 0 );
|
||||
i915_emit_arith( p, A0_ADD, dest, mask, saturate, dest, tmp, 0 );
|
||||
return dest;
|
||||
case GL_INTERPOLATE: /* TWO INSTRUCTIONS */
|
||||
/* Arg0 * (Arg2) + Arg1 * (1-Arg2)
|
||||
*
|
||||
* Arg0*Arg2 + Arg1 - Arg1Arg2
|
||||
*
|
||||
* tmp = Arg0*Arg2 + Arg1,
|
||||
* result = (-Arg1)Arg2 + tmp
|
||||
*/
|
||||
tmp = i915_get_temp( p );
|
||||
i915_emit_arith( p, A0_MAD, tmp, mask, 0, src[0], src[2], src[1] );
|
||||
i915_emit_arith( p, A0_MAD, dest, mask, saturate,
|
||||
negate(src[1], 1,1,1,1), src[2], tmp );
|
||||
return dest;
|
||||
case GL_SUBTRACT:
|
||||
/* negate src[1] */
|
||||
return i915_emit_arith( p, A0_ADD, dest, mask, saturate, src[0],
|
||||
negate(src[1],1,1,1,1), 0 );
|
||||
|
||||
case GL_DOT3_RGBA:
|
||||
case GL_DOT3_RGBA_EXT:
|
||||
case GL_DOT3_RGB_EXT:
|
||||
case GL_DOT3_RGB: {
|
||||
GLuint tmp0 = i915_get_temp( p );
|
||||
GLuint tmp1 = i915_get_temp( p );
|
||||
GLuint neg1 = negate(swizzle(i915_emit_const1f(p, 1),X,X,X,X), 1,1,1,1);
|
||||
GLuint two = swizzle(i915_emit_const1f(p, 2),X,X,X,X);
|
||||
i915_emit_arith( p, A0_MAD, tmp0, A0_DEST_CHANNEL_ALL, 0,
|
||||
two, src[0], neg1);
|
||||
if (src[0] == src[1])
|
||||
tmp1 = tmp0;
|
||||
else
|
||||
i915_emit_arith( p, A0_MAD, tmp1, A0_DEST_CHANNEL_ALL, 0,
|
||||
two, src[1], neg1);
|
||||
i915_emit_arith( p, A0_DP3, dest, mask, saturate, tmp0, tmp1, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
default:
|
||||
return src[0];
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint get_dest( struct i915_fragment_program *p, int unit )
|
||||
{
|
||||
if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
|
||||
return i915_get_temp( p );
|
||||
else if (unit != p->last_tex_stage)
|
||||
return i915_get_temp( p );
|
||||
else
|
||||
return UREG(REG_TYPE_OC, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static GLuint emit_texenv( struct i915_fragment_program *p, int unit )
|
||||
{
|
||||
struct gl_texture_unit *texUnit = &p->ctx->Texture.Unit[unit];
|
||||
GLenum envMode = texUnit->EnvMode;
|
||||
struct gl_texture_object *tObj = texUnit->_Current;
|
||||
GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
|
||||
GLuint saturate = unit < p->last_tex_stage ? A0_DEST_SATURATE : 0;
|
||||
|
||||
switch(envMode) {
|
||||
case GL_BLEND: {
|
||||
const int cf = get_source(p, GL_PREVIOUS, unit);
|
||||
const int cc = get_source(p, GL_CONSTANT, unit);
|
||||
const int cs = get_source(p, GL_TEXTURE, unit);
|
||||
const int out = get_dest(p, unit);
|
||||
|
||||
if (format == GL_INTENSITY) {
|
||||
/* cv = cf(1 - cs) + cc.cs
|
||||
* cv = cf - cf.cs + cc.cs
|
||||
*/
|
||||
/* u[2] = MAD( -cf * cs + cf )
|
||||
* cv = MAD( cc * cs + u[2] )
|
||||
*/
|
||||
|
||||
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
|
||||
negate(cf,1,1,1,1), cs, cf );
|
||||
|
||||
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
|
||||
cc, cs, out );
|
||||
|
||||
return out;
|
||||
} else {
|
||||
/* cv = cf(1 - cs) + cc.cs
|
||||
* cv = cf - cf.cs + cc.cs
|
||||
* av = af.as
|
||||
*/
|
||||
/* u[2] = MAD( cf.-x-y-zw * cs.xyzw + cf.xyz0 )
|
||||
* oC = MAD( cc.xyz0 * cs.xyz0 + u[2].xyzw )
|
||||
*/
|
||||
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
|
||||
negate(cf,1,1,1,0),
|
||||
cs,
|
||||
swizzle(cf,X,Y,Z,ZERO) );
|
||||
|
||||
|
||||
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
|
||||
swizzle(cc,X,Y,Z,ZERO),
|
||||
swizzle(cs,X,Y,Z,ZERO),
|
||||
out );
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
case GL_DECAL: {
|
||||
if (format == GL_RGB ||
|
||||
format == GL_RGBA) {
|
||||
int cf = get_source( p, GL_PREVIOUS, unit );
|
||||
int cs = get_source( p, GL_TEXTURE, unit );
|
||||
int out = get_dest(p, unit);
|
||||
|
||||
/* cv = cf(1-as) + cs.as
|
||||
* cv = cf.(-as) + cf + cs.as
|
||||
* av = af
|
||||
*/
|
||||
|
||||
/* u[2] = mad( cf.xyzw * cs.-w-w-w1 + cf.xyz0 )
|
||||
* oc = mad( cs.xyz0 * cs.www0 + u[2].xyzw )
|
||||
*/
|
||||
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,
|
||||
cf,
|
||||
negate(swizzle(cs,W,W,W,ONE),1,1,1,0),
|
||||
swizzle(cf,X,Y,Z,ZERO) );
|
||||
|
||||
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
|
||||
swizzle(cs,X,Y,Z,ZERO),
|
||||
swizzle(cs,W,W,W,ZERO),
|
||||
out );
|
||||
return out;
|
||||
}
|
||||
else {
|
||||
return get_source( p, GL_PREVIOUS, unit );
|
||||
}
|
||||
}
|
||||
|
||||
case GL_REPLACE: {
|
||||
const int cs = get_source( p, GL_TEXTURE, unit ); /* saturated */
|
||||
switch (format) {
|
||||
case GL_ALPHA: {
|
||||
const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */
|
||||
i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_XYZ, 0, cf, 0, 0 );
|
||||
return cs;
|
||||
}
|
||||
case GL_RGB:
|
||||
case GL_LUMINANCE: {
|
||||
const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */
|
||||
i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_W, 0, cf, 0, 0 );
|
||||
return cs;
|
||||
}
|
||||
default:
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
case GL_MODULATE: {
|
||||
const int cf = get_source( p, GL_PREVIOUS, unit );
|
||||
const int cs = get_source( p, GL_TEXTURE, unit );
|
||||
const int out = get_dest(p, unit);
|
||||
switch (format) {
|
||||
case GL_ALPHA:
|
||||
i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate,
|
||||
swizzle(cs, ONE, ONE, ONE, W), cf, 0 );
|
||||
break;
|
||||
default:
|
||||
i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate,
|
||||
cs, cf, 0 );
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
case GL_ADD: {
|
||||
int cf = get_source( p, GL_PREVIOUS, unit );
|
||||
int cs = get_source( p, GL_TEXTURE, unit );
|
||||
const int out = get_dest( p, unit );
|
||||
|
||||
if (format == GL_INTENSITY) {
|
||||
/* output-color.rgba = add( incoming, u[1] )
|
||||
*/
|
||||
i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, saturate,
|
||||
cs, cf, 0 );
|
||||
return out;
|
||||
}
|
||||
else {
|
||||
/* cv.xyz = cf.xyz + cs.xyz
|
||||
* cv.w = cf.w * cs.w
|
||||
*
|
||||
* cv.xyzw = MAD( cf.111w * cs.xyzw + cf.xyz0 )
|
||||
*/
|
||||
i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,
|
||||
swizzle(cf,ONE,ONE,ONE,W),
|
||||
cs,
|
||||
swizzle(cf,X,Y,Z,ZERO) );
|
||||
return out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GL_COMBINE: {
|
||||
GLuint rgb_shift, alpha_shift, out, shift;
|
||||
GLuint dest = get_dest(p, unit);
|
||||
|
||||
/* The EXT version of the DOT3 extension does not support the
|
||||
* scale factor, but the ARB version (and the version in OpenGL
|
||||
* 1.3) does.
|
||||
*/
|
||||
switch (texUnit->Combine.ModeRGB) {
|
||||
case GL_DOT3_RGB_EXT:
|
||||
alpha_shift = texUnit->Combine.ScaleShiftA;
|
||||
rgb_shift = 0;
|
||||
break;
|
||||
|
||||
case GL_DOT3_RGBA_EXT:
|
||||
alpha_shift = 0;
|
||||
rgb_shift = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
rgb_shift = texUnit->Combine.ScaleShiftRGB;
|
||||
alpha_shift = texUnit->Combine.ScaleShiftA;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Emit the RGB and A combine ops
|
||||
*/
|
||||
if (texUnit->Combine.ModeRGB == texUnit->Combine.ModeA &&
|
||||
args_match( texUnit )) {
|
||||
out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate,
|
||||
unit,
|
||||
texUnit->Combine.ModeRGB,
|
||||
texUnit->Combine.SourceRGB,
|
||||
texUnit->Combine.OperandRGB );
|
||||
}
|
||||
else if (texUnit->Combine.ModeRGB == GL_DOT3_RGBA_EXT ||
|
||||
texUnit->Combine.ModeRGB == GL_DOT3_RGBA) {
|
||||
|
||||
out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate,
|
||||
unit,
|
||||
texUnit->Combine.ModeRGB,
|
||||
texUnit->Combine.SourceRGB,
|
||||
texUnit->Combine.OperandRGB );
|
||||
}
|
||||
else {
|
||||
/* Need to do something to stop from re-emitting identical
|
||||
* argument calculations here:
|
||||
*/
|
||||
out = emit_combine( p, dest, A0_DEST_CHANNEL_XYZ, saturate,
|
||||
unit,
|
||||
texUnit->Combine.ModeRGB,
|
||||
texUnit->Combine.SourceRGB,
|
||||
texUnit->Combine.OperandRGB );
|
||||
out = emit_combine( p, dest, A0_DEST_CHANNEL_W, saturate,
|
||||
unit,
|
||||
texUnit->Combine.ModeA,
|
||||
texUnit->Combine.SourceA,
|
||||
texUnit->Combine.OperandA );
|
||||
}
|
||||
|
||||
/* Deal with the final shift:
|
||||
*/
|
||||
if (alpha_shift || rgb_shift) {
|
||||
if (rgb_shift == alpha_shift) {
|
||||
shift = i915_emit_const1f(p, 1<<rgb_shift);
|
||||
shift = swizzle(shift,X,X,X,X);
|
||||
}
|
||||
else {
|
||||
shift = i915_emit_const2f(p, 1<<rgb_shift, 1<<alpha_shift);
|
||||
shift = swizzle(shift,X,X,X,Y);
|
||||
}
|
||||
return i915_emit_arith( p, A0_MUL, dest, A0_DEST_CHANNEL_ALL,
|
||||
saturate, out, shift, 0 );
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
default:
|
||||
return get_source(p, GL_PREVIOUS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void emit_program_fini( struct i915_fragment_program *p )
|
||||
{
|
||||
int cf = get_source( p, GL_PREVIOUS, 0 );
|
||||
int out = UREG( REG_TYPE_OC, 0 );
|
||||
|
||||
if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
|
||||
/* Emit specular add.
|
||||
*/
|
||||
GLuint s = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_ALL);
|
||||
i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, 0, cf,
|
||||
swizzle(s, X,Y,Z,ZERO), 0 );
|
||||
}
|
||||
else if (cf != out) {
|
||||
/* Will wind up in here if no texture enabled or a couple of
|
||||
* other scenarios (GL_REPLACE for instance).
|
||||
*/
|
||||
i915_emit_arith( p, A0_MOV, out, A0_DEST_CHANNEL_ALL, 0, cf, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void i915EmitTextureProgram( i915ContextPtr i915 )
|
||||
{
|
||||
GLcontext *ctx = &i915->intel.ctx;
|
||||
struct i915_fragment_program *p = &i915->tex_program;
|
||||
GLuint unit;
|
||||
|
||||
if (0) fprintf(stderr, "%s\n", __FUNCTION__);
|
||||
|
||||
i915_init_program( i915, p );
|
||||
|
||||
if (ctx->Texture._EnabledUnits) {
|
||||
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
|
||||
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
|
||||
p->last_tex_stage = unit;
|
||||
}
|
||||
|
||||
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
|
||||
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
|
||||
p->src_previous = emit_texenv( p, unit );
|
||||
p->src_texture = UREG_BAD;
|
||||
p->temp_flag = 0xffff000;
|
||||
p->temp_flag |= 1 << GET_UREG_NR(p->src_previous);
|
||||
}
|
||||
}
|
||||
|
||||
emit_program_fini( p );
|
||||
|
||||
i915_fini_program( p );
|
||||
i915_upload_program( i915, p );
|
||||
|
||||
p->translated = 1;
|
||||
}
|
||||
|
||||
|
||||
void i915ValidateTextureProgram( i915ContextPtr i915 )
|
||||
{
|
||||
intelContextPtr intel = &i915->intel;
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
struct vertex_buffer *VB = &tnl->vb;
|
||||
DECLARE_RENDERINPUTS(index_bitset);
|
||||
int i, offset;
|
||||
GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
|
||||
GLuint s2 = S2_TEXCOORD_NONE;
|
||||
|
||||
RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
|
||||
|
||||
/* Important:
|
||||
*/
|
||||
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
|
||||
intel->vertex_attr_count = 0;
|
||||
intel->coloroffset = 0;
|
||||
intel->specoffset = 0;
|
||||
offset = 0;
|
||||
|
||||
if (i915->vertex_fog == I915_FOG_PIXEL) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 );
|
||||
RENDERINPUTS_CLEAR( index_bitset, _TNL_ATTRIB_FOG );
|
||||
}
|
||||
else if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 );
|
||||
}
|
||||
else {
|
||||
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12 );
|
||||
}
|
||||
|
||||
/* How undefined is undefined? */
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
|
||||
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4 );
|
||||
}
|
||||
|
||||
intel->coloroffset = offset / 4;
|
||||
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4 );
|
||||
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
|
||||
RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
|
||||
intel->specoffset = offset / 4;
|
||||
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3 );
|
||||
} else
|
||||
EMIT_PAD( 3 );
|
||||
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
|
||||
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1 );
|
||||
else
|
||||
EMIT_PAD( 1 );
|
||||
}
|
||||
|
||||
if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
|
||||
int sz = VB->TexCoordPtr[i]->size;
|
||||
|
||||
s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
|
||||
s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz));
|
||||
|
||||
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_SZ(sz), 0, sz * 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Only need to change the vertex emit code if there has been a
|
||||
* statechange to a new hardware vertex format:
|
||||
*/
|
||||
if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] ||
|
||||
s4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
|
||||
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_CTX );
|
||||
|
||||
i915->tex_program.translated = 0;
|
||||
|
||||
/* Must do this *after* statechange, so as not to affect
|
||||
* buffered vertices reliant on the old state:
|
||||
*/
|
||||
intel->vertex_size = _tnl_install_attrs( ctx,
|
||||
intel->vertex_attrs,
|
||||
intel->vertex_attr_count,
|
||||
intel->ViewportMatrix.m, 0 );
|
||||
|
||||
intel->vertex_size >>= 2;
|
||||
|
||||
i915->state.Ctx[I915_CTXREG_LIS2] = s2;
|
||||
i915->state.Ctx[I915_CTXREG_LIS4] = s4;
|
||||
|
||||
assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size ));
|
||||
}
|
||||
|
||||
if (!i915->tex_program.translated ||
|
||||
i915->last_ReallyEnabled != ctx->Texture._EnabledUnits) {
|
||||
i915EmitTextureProgram( i915 );
|
||||
i915->last_ReallyEnabled = ctx->Texture._EnabledUnits;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,34 +37,32 @@
|
||||
#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 );
|
||||
else
|
||||
i915ValidateTextureProgram( i915 );
|
||||
i915ValidateFragmentProgram(i915);
|
||||
}
|
||||
|
||||
|
||||
static void i915_reduced_primitive_state( intelContextPtr intel,
|
||||
GLenum rprim )
|
||||
static void
|
||||
i915_reduced_primitive_state(struct intel_context *intel, GLenum rprim)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1];
|
||||
|
||||
st1 &= ~ST1_ENABLE;
|
||||
|
||||
switch (rprim) {
|
||||
case GL_TRIANGLES:
|
||||
if (intel->ctx.Polygon.StippleFlag &&
|
||||
intel->hw_stipple)
|
||||
if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple)
|
||||
st1 |= ST1_ENABLE;
|
||||
break;
|
||||
case GL_LINES:
|
||||
@@ -76,6 +74,8 @@ static void i915_reduced_primitive_state( intelContextPtr intel,
|
||||
i915->intel.reduced_primitive = rprim;
|
||||
|
||||
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) {
|
||||
INTEL_FIREVERTICES(intel);
|
||||
|
||||
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
|
||||
i915->state.Stipple[I915_STPREG_ST1] = st1;
|
||||
}
|
||||
@@ -85,39 +85,65 @@ static void i915_reduced_primitive_state( intelContextPtr intel,
|
||||
/* 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,
|
||||
GLuint expected )
|
||||
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;
|
||||
|
||||
switch (lis4 & S4_VFMT_XYZW_MASK) {
|
||||
case S4_VFMT_XY: sz = 2; break;
|
||||
case S4_VFMT_XYZ: sz = 3; break;
|
||||
case S4_VFMT_XYW: sz = 3; break;
|
||||
case S4_VFMT_XYZW: sz = 4; break;
|
||||
case S4_VFMT_XY:
|
||||
sz = 2;
|
||||
break;
|
||||
case S4_VFMT_XYZ:
|
||||
sz = 3;
|
||||
break;
|
||||
case S4_VFMT_XYW:
|
||||
sz = 3;
|
||||
break;
|
||||
case S4_VFMT_XYZW:
|
||||
sz = 4;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "no xyzw specified\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lis4 & S4_VFMT_SPEC_FOG) sz++;
|
||||
if (lis4 & S4_VFMT_COLOR) sz++;
|
||||
if (lis4 & S4_VFMT_DEPTH_OFFSET) sz++;
|
||||
if (lis4 & S4_VFMT_POINT_WIDTH) sz++;
|
||||
if (lis4 & S4_VFMT_FOG_PARAM) sz++;
|
||||
if (lis4 & S4_VFMT_SPEC_FOG)
|
||||
sz++;
|
||||
if (lis4 & S4_VFMT_COLOR)
|
||||
sz++;
|
||||
if (lis4 & S4_VFMT_DEPTH_OFFSET)
|
||||
sz++;
|
||||
if (lis4 & S4_VFMT_POINT_WIDTH)
|
||||
sz++;
|
||||
if (lis4 & S4_VFMT_FOG_PARAM)
|
||||
sz++;
|
||||
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
switch (lis2 & S2_TEXCOORD_FMT0_MASK) {
|
||||
case TEXCOORDFMT_2D: sz += 2; break;
|
||||
case TEXCOORDFMT_3D: sz += 3; break;
|
||||
case TEXCOORDFMT_4D: sz += 4; break;
|
||||
case TEXCOORDFMT_1D: sz += 1; break;
|
||||
case TEXCOORDFMT_2D_16: sz += 1; break;
|
||||
case TEXCOORDFMT_4D_16: sz += 2; break;
|
||||
case TEXCOORDFMT_NOT_PRESENT: break;
|
||||
case TEXCOORDFMT_2D:
|
||||
sz += 2;
|
||||
break;
|
||||
case TEXCOORDFMT_3D:
|
||||
sz += 3;
|
||||
break;
|
||||
case TEXCOORDFMT_4D:
|
||||
sz += 4;
|
||||
break;
|
||||
case TEXCOORDFMT_1D:
|
||||
sz += 1;
|
||||
break;
|
||||
case TEXCOORDFMT_2D_16:
|
||||
sz += 1;
|
||||
break;
|
||||
case TEXCOORDFMT_4D_16:
|
||||
sz += 2;
|
||||
break;
|
||||
case TEXCOORDFMT_NOT_PRESENT:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "bad texcoord fmt %d\n", i);
|
||||
return GL_FALSE;
|
||||
@@ -132,17 +158,17 @@ 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 |
|
||||
AA_LINE_ECAAR_WIDTH_1_0 |
|
||||
AA_LINE_REGION_WIDTH_ENABLE |
|
||||
AA_LINE_REGION_WIDTH_1_0);
|
||||
AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0);
|
||||
|
||||
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
|
||||
OUT_BATCH(0);
|
||||
@@ -159,10 +185,7 @@ static void i915_emit_invarient_state( intelContextPtr intel )
|
||||
CSB_TCB(1, 1) |
|
||||
CSB_TCB(2, 2) |
|
||||
CSB_TCB(3, 3) |
|
||||
CSB_TCB(4, 4) |
|
||||
CSB_TCB(5, 5) |
|
||||
CSB_TCB(6, 6) |
|
||||
CSB_TCB(7, 7));
|
||||
CSB_TCB(4, 4) | CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7));
|
||||
|
||||
OUT_BATCH(_3DSTATE_RASTER_RULES_CMD |
|
||||
ENABLE_POINT_RASTER_RULE |
|
||||
@@ -170,20 +193,15 @@ static void i915_emit_invarient_state( intelContextPtr intel )
|
||||
ENABLE_LINE_STRIP_PROVOKE_VRTX |
|
||||
ENABLE_TRI_FAN_PROVOKE_VRTX |
|
||||
LINE_STRIP_PROVOKE_VRTX(1) |
|
||||
TRI_FAN_PROVOKE_VRTX(2) |
|
||||
ENABLE_TEXKILL_3D_4D |
|
||||
TEXKILL_4D);
|
||||
TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D);
|
||||
|
||||
/* Need to initialize this to zero.
|
||||
*/
|
||||
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
|
||||
I1_LOAD_S(3) |
|
||||
(1));
|
||||
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (1));
|
||||
OUT_BATCH(0);
|
||||
|
||||
/* XXX: Use this */
|
||||
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |
|
||||
DISABLE_SCISSOR_RECT);
|
||||
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT);
|
||||
|
||||
OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD);
|
||||
OUT_BATCH(0);
|
||||
@@ -196,24 +214,17 @@ static void i915_emit_invarient_state( intelContextPtr intel )
|
||||
|
||||
|
||||
/* Don't support twosided stencil yet */
|
||||
OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS |
|
||||
BFO_ENABLE_STENCIL_TWO_SIDE |
|
||||
0 );
|
||||
OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
|
||||
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
|
||||
#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 )
|
||||
|
||||
static GLuint get_dirty( struct i915_hw_state *state )
|
||||
static GLuint
|
||||
get_dirty(struct i915_hw_state *state)
|
||||
{
|
||||
GLuint dirty;
|
||||
|
||||
@@ -224,12 +235,12 @@ static GLuint get_dirty( struct i915_hw_state *state )
|
||||
if (dirty & I915_UPLOAD_TEX_ALL)
|
||||
state->emitted &= ~I915_UPLOAD_TEX_ALL;
|
||||
dirty = state->active & ~state->emitted;
|
||||
|
||||
return dirty;
|
||||
}
|
||||
|
||||
|
||||
static GLuint get_state_size( struct i915_hw_state *state )
|
||||
static GLuint
|
||||
get_state_size(struct i915_hw_state *state)
|
||||
{
|
||||
GLuint dirty = get_dirty(state);
|
||||
GLuint i;
|
||||
@@ -253,7 +264,7 @@ static GLuint get_state_size( struct i915_hw_state *state )
|
||||
if (dirty & I915_UPLOAD_TEX(i))
|
||||
nr++;
|
||||
|
||||
sz += (2+nr*3) * sizeof(GLuint) * 2;
|
||||
sz += (2 + nr * 3) * sizeof(GLuint) * 2;
|
||||
}
|
||||
|
||||
if (dirty & I915_UPLOAD_CONSTANTS)
|
||||
@@ -268,42 +279,83 @@ static GLuint get_state_size( struct i915_hw_state *state )
|
||||
|
||||
/* 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 = get_dirty(state);
|
||||
GLuint counter = intel->batch.counter;
|
||||
GLuint dirty;
|
||||
BATCH_LOCALS;
|
||||
|
||||
if (intel->batch.space < get_state_size(state)) {
|
||||
intelFlushBatch(intel, GL_TRUE);
|
||||
dirty = get_dirty(state);
|
||||
counter = intel->batch.counter;
|
||||
}
|
||||
/* We don't hold the lock at this point, so want to make sure that
|
||||
* there won't be a buffer wrap.
|
||||
*
|
||||
* It might be better to talk about explicit places where
|
||||
* scheduling is allowed, rather than assume that it is whenever a
|
||||
* batchbuffer fills up.
|
||||
*/
|
||||
intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
|
||||
|
||||
if (VERBOSE)
|
||||
/* Do this here as we may have flushed the batchbuffer above,
|
||||
* causing more state to be dirty!
|
||||
*/
|
||||
dirty = get_dirty(state);
|
||||
|
||||
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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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
|
||||
@@ -316,21 +368,33 @@ static void i915_emit_state( intelContextPtr intel )
|
||||
if (dirty & I915_UPLOAD_TEX(i))
|
||||
nr++;
|
||||
|
||||
BEGIN_BATCH(2+nr*3);
|
||||
OUT_BATCH(_3DSTATE_MAP_STATE | (3*nr));
|
||||
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++)
|
||||
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_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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);
|
||||
OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3*nr));
|
||||
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++)
|
||||
for (i = 0; i < I915_TEX_UNITS; i++)
|
||||
if (dirty & I915_UPLOAD_TEX(i)) {
|
||||
OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]);
|
||||
OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]);
|
||||
@@ -340,114 +404,146 @@ 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);
|
||||
assert((state->Program[0] & 0x1ff) + 2 == state->ProgramSize);
|
||||
|
||||
emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) );
|
||||
if (VERBOSE)
|
||||
i915_disassemble_program( state->Program, state->ProgramSize );
|
||||
emit(intel, state->Program, state->ProgramSize * sizeof(GLuint));
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
i915_disassemble_program(state->Program, state->ProgramSize);
|
||||
}
|
||||
|
||||
state->emitted |= dirty;
|
||||
intel->batch.last_emit_state = counter;
|
||||
assert(counter == intel->batch.counter);
|
||||
}
|
||||
|
||||
static void i915_destroy_context( intelContextPtr intel )
|
||||
static void
|
||||
i915_destroy_context(struct intel_context *intel)
|
||||
{
|
||||
_tnl_free_vertices(&intel->ctx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the color buffer drawing region.
|
||||
* 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.
|
||||
*/
|
||||
static void
|
||||
i915_set_color_region( intelContextPtr intel, const intelRegion *region)
|
||||
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);
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS );
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR2] = region->offset;
|
||||
}
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
GLuint value;
|
||||
|
||||
ASSERT(state == &i915->state || state == &i915->meta);
|
||||
|
||||
/**
|
||||
* specify the z-buffer/stencil region
|
||||
if (state->draw_region != color_region) {
|
||||
intel_region_release(intel->intelScreen, &state->draw_region);
|
||||
intel_region_reference(&state->draw_region, color_region);
|
||||
}
|
||||
if (state->depth_region != depth_region) {
|
||||
intel_region_release(intel->intelScreen, &state->depth_region);
|
||||
intel_region_reference(&state->depth_region, depth_region);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set stride/cpp values
|
||||
*/
|
||||
static void
|
||||
i915_set_z_region( intelContextPtr intel, const intelRegion *region)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS );
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE);
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR2] = region->offset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set both the color and Z/stencil drawing regions.
|
||||
* Similar to two previous functions, but don't use I915_STATECHANGE()
|
||||
*/
|
||||
static void
|
||||
i915_update_color_z_regions(intelContextPtr intel,
|
||||
const intelRegion *colorRegion,
|
||||
const intelRegion *depthRegion)
|
||||
{
|
||||
i915ContextPtr i915 = I915_CONTEXT(intel);
|
||||
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR1] =
|
||||
(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) | BUF_3D_USE_FENCE);
|
||||
i915->state.Buffer[I915_DESTREG_CBUFADDR2] = colorRegion->offset;
|
||||
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR1] =
|
||||
(BUF_3D_ID_DEPTH |
|
||||
BUF_3D_PITCH(depthRegion->pitch) | /* pitch in bytes */
|
||||
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);
|
||||
i915->state.Buffer[I915_DESTREG_DBUFADDR2] = depthRegion->offset;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static void i915_lost_hardware( intelContextPtr intel )
|
||||
static void
|
||||
i915_set_draw_region(struct intel_context *intel,
|
||||
struct intel_region *color_region,
|
||||
struct intel_region *depth_region)
|
||||
{
|
||||
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();
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
i915_state_draw_region(intel, &i915->state, color_region, depth_region);
|
||||
}
|
||||
|
||||
|
||||
void i915InitVtbl( i915ContextPtr i915 )
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
i915_assert_not_dirty( struct intel_context *intel )
|
||||
{
|
||||
struct i915_context *i915 = i915_context(&intel->ctx);
|
||||
struct i915_hw_state *state = i915->current;
|
||||
GLuint dirty = get_dirty(state);
|
||||
assert(!dirty);
|
||||
}
|
||||
|
||||
|
||||
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.rotate_window = i915RotateWindow;
|
||||
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_color_region = i915_set_color_region;
|
||||
i915->intel.vtbl.set_z_region = i915_set_z_region;
|
||||
i915->intel.vtbl.update_color_z_regions = i915_update_color_z_regions;
|
||||
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;
|
||||
i915->intel.vtbl.assert_not_dirty = i915_assert_not_dirty;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,126 +1,123 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "dri_bufmgr.h"
|
||||
|
||||
struct intel_context;
|
||||
|
||||
#define BATCH_LOCALS GLubyte *batch_ptr;
|
||||
#define BATCH_SZ 4096
|
||||
#define BATCH_RESERVED 16
|
||||
|
||||
/* #define VERBOSE 0 */
|
||||
#ifndef VERBOSE
|
||||
extern int VERBOSE;
|
||||
#endif
|
||||
#define MAX_RELOCS 100
|
||||
|
||||
#define INTEL_BATCH_NO_CLIPRECTS 0x1
|
||||
#define INTEL_BATCH_CLIPRECTS 0x2
|
||||
|
||||
#define BEGIN_BATCH(n) \
|
||||
do { \
|
||||
if (VERBOSE) fprintf(stderr, \
|
||||
"BEGIN_BATCH(%ld) in %s, %d dwords free\n", \
|
||||
((unsigned long)n), __FUNCTION__, \
|
||||
intel->batch.space/4); \
|
||||
if (intel->batch.space < (n)*4) \
|
||||
intelFlushBatch(intel, GL_TRUE); \
|
||||
if (intel->batch.space == intel->batch.size) intel->batch.func = __FUNCTION__; \
|
||||
batch_ptr = intel->batch.ptr; \
|
||||
} while (0)
|
||||
|
||||
#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)
|
||||
|
||||
#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)
|
||||
|
||||
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,
|
||||
const drm_clip_rect_t *rect);
|
||||
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 )
|
||||
struct buffer_reloc
|
||||
{
|
||||
GLuint sz = dwords * sizeof(GLuint);
|
||||
GLuint *ptr;
|
||||
struct _DriBufferObject *buf;
|
||||
GLuint offset;
|
||||
GLuint delta; /* not needed? */
|
||||
};
|
||||
|
||||
if (intel->batch.space < sz) {
|
||||
intelWrapInlinePrimitive( intel );
|
||||
/* assert(intel->batch.space >= sz); */
|
||||
}
|
||||
struct intel_batchbuffer
|
||||
{
|
||||
struct bufmgr *bm;
|
||||
struct intel_context *intel;
|
||||
|
||||
/* assert(intel->prim.primitive != ~0); */
|
||||
ptr = (GLuint *)intel->batch.ptr;
|
||||
intel->batch.ptr += sz;
|
||||
intel->batch.space -= sz;
|
||||
struct _DriBufferObject *buffer;
|
||||
struct _DriFenceObject *last_fence;
|
||||
GLuint flags;
|
||||
|
||||
return ptr;
|
||||
drmBOList 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);
|
||||
|
||||
|
||||
void intel_batchbuffer_finish(struct intel_batchbuffer *batch);
|
||||
|
||||
struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer
|
||||
*batch);
|
||||
|
||||
void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
|
||||
GLuint bytes);
|
||||
|
||||
GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
|
||||
struct _DriBufferObject *buffer,
|
||||
GLuint flags,
|
||||
GLuint mask, GLuint offset);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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,mask,delta) do { \
|
||||
assert((delta) >= 0); \
|
||||
intel_batchbuffer_emit_reloc(intel->batch, buf, flags, mask, delta); \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_BATCH() do { } while(0)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
416
src/mesa/drivers/dri/i915/intel_batchpool.c
Normal file
416
src/mesa/drivers/dri/i915/intel_batchpool.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "imports.h"
|
||||
#include "glthread.h"
|
||||
#include "dri_bufpool.h"
|
||||
#include "dri_bufmgr.h"
|
||||
#include "intel_screen.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drmMMListHead head;
|
||||
struct _BPool *parent;
|
||||
struct _DriFenceObject *fence;
|
||||
unsigned long start;
|
||||
int unfenced;
|
||||
int mapped;
|
||||
} BBuf;
|
||||
|
||||
typedef struct _BPool
|
||||
{
|
||||
_glthread_Mutex mutex;
|
||||
unsigned long bufSize;
|
||||
unsigned poolSize;
|
||||
unsigned numFree;
|
||||
unsigned numTot;
|
||||
unsigned numDelayed;
|
||||
unsigned checkDelayed;
|
||||
drmMMListHead free;
|
||||
drmMMListHead delayed;
|
||||
drmMMListHead head;
|
||||
drmBO kernelBO;
|
||||
void *virtual;
|
||||
BBuf *bufs;
|
||||
} BPool;
|
||||
|
||||
|
||||
static BPool *
|
||||
createBPool(int fd, unsigned long bufSize, unsigned numBufs, unsigned flags,
|
||||
unsigned checkDelayed)
|
||||
{
|
||||
BPool *p = (BPool *) malloc(sizeof(*p));
|
||||
BBuf *buf;
|
||||
int i;
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
p->bufs = (BBuf *) malloc(numBufs * sizeof(*p->bufs));
|
||||
if (!p->bufs) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DRMINITLISTHEAD(&p->free);
|
||||
DRMINITLISTHEAD(&p->head);
|
||||
DRMINITLISTHEAD(&p->delayed);
|
||||
|
||||
p->numTot = numBufs;
|
||||
p->numFree = numBufs;
|
||||
p->bufSize = bufSize;
|
||||
p->numDelayed = 0;
|
||||
p->checkDelayed = checkDelayed;
|
||||
|
||||
_glthread_INIT_MUTEX(p->mutex);
|
||||
|
||||
if (drmBOCreate(fd, NULL, 0, numBufs * bufSize, NULL, drm_bo_type_dc,
|
||||
flags, 0, &p->kernelBO)) {
|
||||
free(p->bufs);
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
if (drmBOMap(fd, &p->kernelBO, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0,
|
||||
&p->virtual)) {
|
||||
drmBODestroy(fd, &p->kernelBO);
|
||||
free(p->bufs);
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We unmap the buffer so that we can validate it later. Note that this is
|
||||
* just a synchronizing operation. The buffer will have a virtual mapping
|
||||
* until it is destroyed.
|
||||
*/
|
||||
|
||||
drmBOUnmap(fd, &p->kernelBO);
|
||||
|
||||
buf = p->bufs;
|
||||
for (i = 0; i < numBufs; ++i) {
|
||||
buf->parent = p;
|
||||
buf->fence = NULL;
|
||||
buf->start = i * bufSize;
|
||||
buf->mapped = 0;
|
||||
buf->unfenced = 0;
|
||||
DRMLISTADDTAIL(&buf->head, &p->free);
|
||||
buf++;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pool_checkFree(BPool * p, int wait)
|
||||
{
|
||||
drmMMListHead *list, *prev;
|
||||
BBuf *buf;
|
||||
int signaled = 0;
|
||||
int i;
|
||||
|
||||
list = p->delayed.next;
|
||||
|
||||
if (p->numDelayed > 3) {
|
||||
for (i = 0; i < p->numDelayed; i += 3) {
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
prev = list->prev;
|
||||
for (; list != &p->delayed; list = prev, prev = list->prev) {
|
||||
|
||||
buf = DRMLISTENTRY(BBuf, list, head);
|
||||
|
||||
if (!signaled) {
|
||||
if (wait) {
|
||||
driFenceFinish(buf->fence, DRM_FENCE_TYPE_EXE, 1);
|
||||
signaled = 1;
|
||||
}
|
||||
else {
|
||||
signaled = driFenceSignaled(buf->fence, DRM_FENCE_TYPE_EXE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!signaled)
|
||||
break;
|
||||
|
||||
driFenceUnReference(buf->fence);
|
||||
buf->fence = NULL;
|
||||
DRMLISTDEL(list);
|
||||
p->numDelayed--;
|
||||
DRMLISTADD(list, &p->free);
|
||||
p->numFree++;
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
pool_create(struct _DriBufferPool *pool,
|
||||
unsigned long size, unsigned flags, unsigned hint,
|
||||
unsigned alignment)
|
||||
{
|
||||
BPool *p = (BPool *) pool->data;
|
||||
|
||||
drmMMListHead *item;
|
||||
|
||||
if (alignment && (alignment != 4096))
|
||||
return NULL;
|
||||
|
||||
_glthread_LOCK_MUTEX(p->mutex);
|
||||
|
||||
if (p->numFree == 0)
|
||||
pool_checkFree(p, GL_TRUE);
|
||||
|
||||
if (p->numFree == 0) {
|
||||
fprintf(stderr, "Out of fixed size buffer objects\n");
|
||||
BM_CKFATAL(-ENOMEM);
|
||||
}
|
||||
|
||||
item = p->free.next;
|
||||
|
||||
if (item == &p->free) {
|
||||
fprintf(stderr, "Fixed size buffer pool corruption\n");
|
||||
}
|
||||
|
||||
DRMLISTDEL(item);
|
||||
--p->numFree;
|
||||
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
return (void *) DRMLISTENTRY(BBuf, item, head);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pool_destroy(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
BBuf *buf = (BBuf *) private;
|
||||
BPool *p = buf->parent;
|
||||
|
||||
_glthread_LOCK_MUTEX(p->mutex);
|
||||
|
||||
if (buf->fence) {
|
||||
DRMLISTADDTAIL(&buf->head, &p->delayed);
|
||||
p->numDelayed++;
|
||||
}
|
||||
else {
|
||||
buf->unfenced = 0;
|
||||
DRMLISTADD(&buf->head, &p->free);
|
||||
p->numFree++;
|
||||
}
|
||||
|
||||
if ((p->numDelayed % p->checkDelayed) == 0)
|
||||
pool_checkFree(p, 0);
|
||||
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
|
||||
int hint, void **virtual)
|
||||
{
|
||||
|
||||
BBuf *buf = (BBuf *) private;
|
||||
BPool *p = buf->parent;
|
||||
|
||||
_glthread_LOCK_MUTEX(p->mutex);
|
||||
|
||||
/*
|
||||
* Currently Mesa doesn't have any condition variables to resolve this
|
||||
* cleanly in a multithreading environment.
|
||||
* We bail out instead.
|
||||
*/
|
||||
|
||||
if (buf->mapped) {
|
||||
fprintf(stderr, "Trying to map already mapped buffer object\n");
|
||||
BM_CKFATAL(-EINVAL);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (buf->unfenced && !(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) {
|
||||
fprintf(stderr, "Trying to map an unfenced buffer object 0x%08x"
|
||||
" 0x%08x %d\n", hint, flags, buf->start);
|
||||
BM_CKFATAL(-EINVAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (buf->fence) {
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
buf->mapped = GL_TRUE;
|
||||
*virtual = (unsigned char *) p->virtual + buf->start;
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
|
||||
{
|
||||
BBuf *buf = (BBuf *) private;
|
||||
driFenceFinish(buf->fence, 0, lazy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pool_unmap(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
BBuf *buf = (BBuf *) private;
|
||||
|
||||
buf->mapped = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
pool_offset(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
BBuf *buf = (BBuf *) private;
|
||||
BPool *p = buf->parent;
|
||||
|
||||
return p->kernelBO.offset + buf->start;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
pool_flags(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
BPool *p = (BPool *) pool->data;
|
||||
|
||||
return p->kernelBO.flags;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
pool_size(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
BPool *p = (BPool *) pool->data;
|
||||
|
||||
return p->bufSize;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pool_fence(struct _DriBufferPool *pool, void *private,
|
||||
struct _DriFenceObject *fence)
|
||||
{
|
||||
BBuf *buf = (BBuf *) private;
|
||||
BPool *p = buf->parent;
|
||||
|
||||
_glthread_LOCK_MUTEX(p->mutex);
|
||||
if (buf->fence) {
|
||||
driFenceUnReference(buf->fence);
|
||||
}
|
||||
buf->fence = fence;
|
||||
buf->unfenced = 0;
|
||||
driFenceReference(buf->fence);
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static drmBO *
|
||||
pool_kernel(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
BBuf *buf = (BBuf *) private;
|
||||
BPool *p = buf->parent;
|
||||
|
||||
return &p->kernelBO;
|
||||
}
|
||||
|
||||
static int
|
||||
pool_validate(struct _DriBufferPool *pool, void *private)
|
||||
{
|
||||
BBuf *buf = (BBuf *) private;
|
||||
BPool *p = buf->parent;
|
||||
_glthread_LOCK_MUTEX(p->mutex);
|
||||
buf->unfenced = GL_TRUE;
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pool_takedown(struct _DriBufferPool *pool)
|
||||
{
|
||||
BPool *p = (BPool *) pool->data;
|
||||
|
||||
/*
|
||||
* Wait on outstanding fences.
|
||||
*/
|
||||
|
||||
_glthread_LOCK_MUTEX(p->mutex);
|
||||
while ((p->numFree < p->numTot) && p->numDelayed) {
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
sched_yield();
|
||||
pool_checkFree(p, GL_TRUE);
|
||||
_glthread_LOCK_MUTEX(p->mutex);
|
||||
}
|
||||
|
||||
drmBODestroy(pool->fd, &p->kernelBO);
|
||||
free(p->bufs);
|
||||
_glthread_UNLOCK_MUTEX(p->mutex);
|
||||
free(p);
|
||||
free(pool);
|
||||
}
|
||||
|
||||
|
||||
struct _DriBufferPool *
|
||||
driBatchPoolInit(int fd, unsigned flags,
|
||||
unsigned long bufSize,
|
||||
unsigned numBufs, unsigned checkDelayed)
|
||||
{
|
||||
struct _DriBufferPool *pool;
|
||||
|
||||
pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
pool->data = createBPool(fd, bufSize, numBufs, flags, checkDelayed);
|
||||
|
||||
pool->fd = fd;
|
||||
pool->map = &pool_map;
|
||||
pool->unmap = &pool_unmap;
|
||||
pool->destroy = &pool_destroy;
|
||||
pool->offset = &pool_offset;
|
||||
pool->flags = &pool_flags;
|
||||
pool->size = &pool_size;
|
||||
pool->create = &pool_create;
|
||||
pool->fence = &pool_fence;
|
||||
pool->kernel = &pool_kernel;
|
||||
pool->validate = &pool_validate;
|
||||
pool->waitIdle = &pool_waitIdle;
|
||||
pool->setstatic = NULL;
|
||||
pool->takeDown = &pool_takedown;
|
||||
return pool;
|
||||
}
|
||||
516
src/mesa/drivers/dri/i915/intel_blit.c
Normal file
516
src/mesa/drivers/dri/i915/intel_blit.c
Normal file
@@ -0,0 +1,516 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "vblank.h"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_BLIT
|
||||
|
||||
/**
|
||||
* Copy the back color buffer to the front color buffer.
|
||||
* Used for SwapBuffers().
|
||||
*/
|
||||
void
|
||||
intelCopyBuffer(const __DRIdrawablePrivate * dPriv,
|
||||
const drm_clip_rect_t * rect)
|
||||
{
|
||||
|
||||
struct intel_context *intel;
|
||||
GLboolean missed_target;
|
||||
int64_t ust;
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
assert(dPriv);
|
||||
|
||||
intel = intelScreenContext(dPriv->driScreenPriv->private);
|
||||
if (!intel)
|
||||
return;
|
||||
|
||||
if (intel->last_swap_fence) {
|
||||
driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
|
||||
driFenceUnReference(intel->last_swap_fence);
|
||||
intel->last_swap_fence = NULL;
|
||||
}
|
||||
intel->last_swap_fence = intel->first_swap_fence;
|
||||
intel->first_swap_fence = NULL;
|
||||
|
||||
if (!rect) {
|
||||
driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags,
|
||||
&missed_target);
|
||||
}
|
||||
|
||||
|
||||
/* 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++) {
|
||||
drm_clip_rect_t box;
|
||||
|
||||
if (pbox->x1 > pbox->x2 ||
|
||||
pbox->y1 > pbox->y2 ||
|
||||
pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height)
|
||||
continue;
|
||||
|
||||
box = *pbox;
|
||||
|
||||
if (rect) {
|
||||
if (rect->x1 > box.x1)
|
||||
box.x1 = rect->x1;
|
||||
if (rect->y1 > box.y1)
|
||||
box.y1 = rect->y1;
|
||||
if (rect->x2 < box.x2)
|
||||
box.x2 = rect->x2;
|
||||
if (rect->y2 < box.y2)
|
||||
box.y2 = rect->y2;
|
||||
|
||||
if (box.x1 > box.x2 || box.y1 > box.y2)
|
||||
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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
|
||||
else
|
||||
OUT_RELOC(backRegion->buffer,
|
||||
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
|
||||
else
|
||||
OUT_RELOC(frontRegion->buffer,
|
||||
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
|
||||
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
if (intel->first_swap_fence)
|
||||
driFenceUnReference(intel->first_swap_fence);
|
||||
intel->first_swap_fence = intel_batchbuffer_flush(intel->batch);
|
||||
driFenceReference(intel->first_swap_fence);
|
||||
}
|
||||
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
if (!rect) {
|
||||
intel->swap_count++;
|
||||
(*dri_interface->getUST) (&ust);
|
||||
if (missed_target) {
|
||||
intel->swap_missed_count++;
|
||||
intel->swap_missed_ust = ust - intel->swap_ust;
|
||||
}
|
||||
|
||||
intel->swap_ust = ust;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
intelEmitFillBlit(struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLshort dst_pitch,
|
||||
struct _DriBufferObject *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;
|
||||
}
|
||||
|
||||
DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
|
||||
__FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h);
|
||||
|
||||
|
||||
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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset);
|
||||
OUT_BATCH(color);
|
||||
ADVANCE_BATCH();
|
||||
}
|
||||
|
||||
|
||||
/* Copy BitBlt
|
||||
*/
|
||||
void
|
||||
intelEmitCopyBlit(struct intel_context *intel,
|
||||
GLuint cpp,
|
||||
GLshort src_pitch,
|
||||
struct _DriBufferObject *src_buffer,
|
||||
GLuint src_offset,
|
||||
GLshort dst_pitch,
|
||||
struct _DriBufferObject *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(%p)/%d+%d %d,%d dst:buf(%p)/%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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset);
|
||||
OUT_BATCH((src_y << 16) | src_x);
|
||||
OUT_BATCH(((GLint) src_pitch & 0xffff));
|
||||
OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE,
|
||||
dst_offset + dst_y * dst_pitch);
|
||||
OUT_BATCH((0 << 16) | src_x);
|
||||
OUT_BATCH(((GLint) src_pitch & 0xffff));
|
||||
OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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;
|
||||
|
||||
DBG("%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;
|
||||
|
||||
/* Refresh the cx/y/w/h values as they may have been invalidated
|
||||
* by a new window position or size picked up when we did
|
||||
* LOCK_HARDWARE above. The values passed by mesa are not
|
||||
* reliable.
|
||||
*/
|
||||
{
|
||||
cx = ctx->DrawBuffer->_Xmin;
|
||||
cy = ctx->DrawBuffer->_Ymin;
|
||||
ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
|
||||
cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
|
||||
}
|
||||
|
||||
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);
|
||||
struct _DriBufferObject *write_buffer =
|
||||
intel_region_buffer(intel->intelScreen, irb->region,
|
||||
all ? INTEL_WRITE_FULL :
|
||||
INTEL_WRITE_PART);
|
||||
|
||||
GLuint clearVal;
|
||||
GLint pitch, cpp;
|
||||
GLuint BR13, CMD;
|
||||
|
||||
ASSERT(irb);
|
||||
ASSERT(irb->region);
|
||||
|
||||
pitch = irb->region->pitch;
|
||||
cpp = irb->region->cpp;
|
||||
|
||||
DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
|
||||
__FUNCTION__,
|
||||
irb->region->buffer, (pitch * cpp),
|
||||
irb->region->draw_offset,
|
||||
b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1);
|
||||
|
||||
|
||||
/* 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(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
|
||||
DRM_BO_MASK_MEM | DRM_BO_FLAG_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);
|
||||
}
|
||||
63
src/mesa/drivers/dri/i915/intel_blit.h
Normal file
63
src/mesa/drivers/dri/i915/intel_blit.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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"
|
||||
#include "dri_bufmgr.h"
|
||||
|
||||
extern void intelCopyBuffer(const __DRIdrawablePrivate * dpriv,
|
||||
const drm_clip_rect_t * rect);
|
||||
|
||||
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,
|
||||
struct _DriBufferObject *src_buffer,
|
||||
GLuint src_offset,
|
||||
GLshort dst_pitch,
|
||||
struct _DriBufferObject *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,
|
||||
struct _DriBufferObject *dst_buffer,
|
||||
GLuint dst_offset,
|
||||
GLshort x, GLshort y,
|
||||
GLshort w, GLshort h, GLuint color);
|
||||
|
||||
|
||||
#endif
|
||||
250
src/mesa/drivers/dri/i915/intel_buffer_objects.c
Normal file
250
src/mesa/drivers/dri/i915/intel_buffer_objects.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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_regions.h"
|
||||
#include "dri_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 = CALLOC_STRUCT(intel_buffer_object);
|
||||
|
||||
_mesa_initialize_buffer_object(&obj->Base, name, target);
|
||||
|
||||
driGenBuffers(intel->intelScreen->regionPool,
|
||||
"bufferobj", 1, &obj->buffer, 64, 0, 0);
|
||||
|
||||
return &obj->Base;
|
||||
}
|
||||
|
||||
|
||||
/* Break the COW tie to the region. The region gets to keep the data.
|
||||
*/
|
||||
void
|
||||
intel_bufferobj_release_region(struct intel_context *intel,
|
||||
struct intel_buffer_object *intel_obj)
|
||||
{
|
||||
assert(intel_obj->region->buffer == intel_obj->buffer);
|
||||
intel_obj->region->pbo = NULL;
|
||||
intel_obj->region = NULL;
|
||||
driBOUnReference(intel_obj->buffer);
|
||||
intel_obj->buffer = NULL;
|
||||
|
||||
/* This leads to a large number of buffer deletion/creation events.
|
||||
* Currently the drm doesn't like that:
|
||||
*/
|
||||
driGenBuffers(intel->intelScreen->regionPool,
|
||||
"buffer object", 1, &intel_obj->buffer, 64, 0, 0);
|
||||
driBOData(intel_obj->buffer, intel_obj->Base.Size, NULL, 0);
|
||||
}
|
||||
|
||||
/* Break the COW tie to the region. Both the pbo and the region end
|
||||
* up with a copy of the data.
|
||||
*/
|
||||
void
|
||||
intel_bufferobj_cow(struct intel_context *intel,
|
||||
struct intel_buffer_object *intel_obj)
|
||||
{
|
||||
assert(intel_obj->region);
|
||||
intel_region_cow(intel->intelScreen, intel_obj->region);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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->region) {
|
||||
intel_bufferobj_release_region(intel, intel_obj);
|
||||
}
|
||||
else if (intel_obj->buffer) {
|
||||
driDeleteBuffers(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);
|
||||
|
||||
intel_obj->Base.Size = size;
|
||||
intel_obj->Base.Usage = usage;
|
||||
|
||||
if (intel_obj->region)
|
||||
intel_bufferobj_release_region(intel, intel_obj);
|
||||
|
||||
driBOData(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);
|
||||
|
||||
if (intel_obj->region)
|
||||
intel_bufferobj_cow(intel, intel_obj);
|
||||
|
||||
driBOSubData(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_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
assert(intel_obj);
|
||||
driBOGetSubData(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);
|
||||
|
||||
if (intel_obj->region)
|
||||
intel_bufferobj_cow(intel, intel_obj);
|
||||
|
||||
obj->Pointer = driBOMap(intel_obj->buffer,
|
||||
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
|
||||
return obj->Pointer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via glMapBufferARB().
|
||||
*/
|
||||
static GLboolean
|
||||
intel_bufferobj_unmap(GLcontext * ctx,
|
||||
GLenum target, struct gl_buffer_object *obj)
|
||||
{
|
||||
struct intel_buffer_object *intel_obj = intel_buffer_object(obj);
|
||||
|
||||
assert(intel_obj);
|
||||
assert(obj->Pointer);
|
||||
driBOUnmap(intel_obj->buffer);
|
||||
obj->Pointer = NULL;
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
struct _DriBufferObject *
|
||||
intel_bufferobj_buffer(struct intel_context *intel,
|
||||
struct intel_buffer_object *intel_obj, GLuint flag)
|
||||
{
|
||||
if (intel_obj->region) {
|
||||
if (flag == INTEL_WRITE_PART)
|
||||
intel_bufferobj_cow(intel, intel_obj);
|
||||
else if (flag == INTEL_WRITE_FULL)
|
||||
intel_bufferobj_release_region(intel, 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;
|
||||
}
|
||||
86
src/mesa/drivers/dri/i915/intel_buffer_objects.h
Normal file
86
src/mesa/drivers/dri/i915/intel_buffer_objects.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 intel_region;
|
||||
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;
|
||||
struct _DriBufferObject *buffer; /* the low-level buffer manager's buffer handle */
|
||||
|
||||
struct intel_region *region; /* Is there a zero-copy texture
|
||||
associated with this (pixel)
|
||||
buffer object? */
|
||||
};
|
||||
|
||||
|
||||
/* Get the bm buffer associated with a GL bufferobject:
|
||||
*/
|
||||
struct _DriBufferObject *intel_bufferobj_buffer(struct intel_context *intel,
|
||||
struct intel_buffer_object
|
||||
*obj, GLuint flag);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Helpers for zerocopy image uploads. See also intel_regions.h:
|
||||
*/
|
||||
void intel_bufferobj_cow(struct intel_context *intel,
|
||||
struct intel_buffer_object *intel_obj);
|
||||
void intel_bufferobj_release_region(struct intel_context *intel,
|
||||
struct intel_buffer_object *intel_obj);
|
||||
|
||||
|
||||
#endif
|
||||
968
src/mesa/drivers/dri/i915/intel_buffers.c
Normal file
968
src/mesa/drivers/dri/i915/intel_buffers.c
Normal file
@@ -0,0 +1,968 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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_BLIT)
|
||||
_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);
|
||||
|
||||
|
||||
/* Refresh the cx/y/w/h values as they may have been invalidated
|
||||
* by a new window position or size picked up when we did
|
||||
* LOCK_HARDWARE above. The values passed by mesa are not
|
||||
* reliable.
|
||||
*/
|
||||
{
|
||||
cx = ctx->DrawBuffer->_Xmin;
|
||||
cy = ctx->DrawBuffer->_Ymin;
|
||||
ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
|
||||
cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
|
||||
}
|
||||
|
||||
/* note: regardless of 'all', cx, cy, cw, ch are now 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Copy the window contents named by dPriv to the rotated (or reflected)
|
||||
* color buffer.
|
||||
* srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
|
||||
*/
|
||||
void
|
||||
intelRotateWindow(struct intel_context *intel,
|
||||
__DRIdrawablePrivate * dPriv, GLuint srcBuf)
|
||||
{
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
drm_clip_rect_t fullRect;
|
||||
struct intel_region *src;
|
||||
const drm_clip_rect_t *clipRects;
|
||||
int numClipRects;
|
||||
int i;
|
||||
GLenum format, type;
|
||||
|
||||
int xOrig, yOrig;
|
||||
int origNumClipRects;
|
||||
drm_clip_rect_t *origRects;
|
||||
|
||||
/*
|
||||
* set up hardware state
|
||||
*/
|
||||
intelFlush(&intel->ctx);
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
if (!intel->numClipRects) {
|
||||
UNLOCK_HARDWARE(intel);
|
||||
return;
|
||||
}
|
||||
|
||||
intel->vtbl.install_meta_state(intel);
|
||||
|
||||
intel->vtbl.meta_no_depth_write(intel);
|
||||
intel->vtbl.meta_no_stencil_write(intel);
|
||||
intel->vtbl.meta_color_mask(intel, GL_FALSE);
|
||||
|
||||
|
||||
/* save current drawing origin and cliprects (restored at end) */
|
||||
xOrig = intel->drawX;
|
||||
yOrig = intel->drawY;
|
||||
origNumClipRects = intel->numClipRects;
|
||||
origRects = intel->pClipRects;
|
||||
|
||||
/*
|
||||
* set drawing origin, cliprects for full-screen access to rotated screen
|
||||
*/
|
||||
fullRect.x1 = 0;
|
||||
fullRect.y1 = 0;
|
||||
fullRect.x2 = screen->rotatedWidth;
|
||||
fullRect.y2 = screen->rotatedHeight;
|
||||
intel->drawX = 0;
|
||||
intel->drawY = 0;
|
||||
intel->numClipRects = 1;
|
||||
intel->pClipRects = &fullRect;
|
||||
|
||||
intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL); /* ? */
|
||||
|
||||
if (srcBuf == BUFFER_BIT_FRONT_LEFT) {
|
||||
src = intel->intelScreen->front_region;
|
||||
clipRects = dPriv->pClipRects;
|
||||
numClipRects = dPriv->numClipRects;
|
||||
}
|
||||
else {
|
||||
src = intel->intelScreen->back_region;
|
||||
clipRects = dPriv->pBackClipRects;
|
||||
numClipRects = dPriv->numBackClipRects;
|
||||
}
|
||||
|
||||
if (src->cpp == 4) {
|
||||
format = GL_BGRA;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else {
|
||||
format = GL_BGR;
|
||||
type = GL_UNSIGNED_SHORT_5_6_5_REV;
|
||||
}
|
||||
|
||||
/* set the whole screen up as a texture to avoid alignment issues */
|
||||
intel->vtbl.meta_tex_rect_source(intel,
|
||||
src->buffer,
|
||||
screen->width,
|
||||
screen->height, src->pitch, format, type);
|
||||
|
||||
intel->vtbl.meta_texture_blend_replace(intel);
|
||||
|
||||
/*
|
||||
* loop over the source window's cliprects
|
||||
*/
|
||||
for (i = 0; i < numClipRects; i++) {
|
||||
int srcX0 = clipRects[i].x1;
|
||||
int srcY0 = clipRects[i].y1;
|
||||
int srcX1 = clipRects[i].x2;
|
||||
int srcY1 = clipRects[i].y2;
|
||||
GLfloat verts[4][2], tex[4][2];
|
||||
int j;
|
||||
|
||||
/* build vertices for four corners of clip rect */
|
||||
verts[0][0] = srcX0;
|
||||
verts[0][1] = srcY0;
|
||||
verts[1][0] = srcX1;
|
||||
verts[1][1] = srcY0;
|
||||
verts[2][0] = srcX1;
|
||||
verts[2][1] = srcY1;
|
||||
verts[3][0] = srcX0;
|
||||
verts[3][1] = srcY1;
|
||||
|
||||
/* .. and texcoords */
|
||||
tex[0][0] = srcX0;
|
||||
tex[0][1] = srcY0;
|
||||
tex[1][0] = srcX1;
|
||||
tex[1][1] = srcY0;
|
||||
tex[2][0] = srcX1;
|
||||
tex[2][1] = srcY1;
|
||||
tex[3][0] = srcX0;
|
||||
tex[3][1] = srcY1;
|
||||
|
||||
/* transform coords to rotated screen coords */
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
matrix23TransformCoordf(&screen->rotMatrix,
|
||||
&verts[j][0], &verts[j][1]);
|
||||
}
|
||||
|
||||
/* draw polygon to map source image to dest region */
|
||||
intel_meta_draw_poly(intel, 4, verts, 0, 0, tex);
|
||||
|
||||
} /* cliprect loop */
|
||||
|
||||
intel->vtbl.leave_meta_state(intel);
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
|
||||
/* restore original drawing origin and cliprects */
|
||||
intel->drawX = xOrig;
|
||||
intel->drawY = yOrig;
|
||||
intel->numClipRects = origNumClipRects;
|
||||
intel->pClipRects = origRects;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#if 0
|
||||
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");
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Trunk version:
|
||||
*/
|
||||
void
|
||||
intelSwapBuffers(__DRIdrawablePrivate * dPriv)
|
||||
{
|
||||
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
struct intel_context *intel;
|
||||
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
intel = intel_context(ctx);
|
||||
|
||||
if (ctx->Visual.doubleBufferMode) {
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
_mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
|
||||
if (0 /*intel->doPageFlip */ ) { /* doPageFlip is never set !!! */
|
||||
intelPageFlip(dPriv);
|
||||
}
|
||||
else {
|
||||
intelCopyBuffer(dPriv, NULL);
|
||||
}
|
||||
if (screen->current_rotation != 0) {
|
||||
intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
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__);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
|
||||
{
|
||||
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
|
||||
struct intel_context *intel =
|
||||
(struct intel_context *) dPriv->driContextPriv->driverPrivate;
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
|
||||
if (ctx->Visual.doubleBufferMode) {
|
||||
drm_clip_rect_t rect;
|
||||
rect.x1 = x + dPriv->x;
|
||||
rect.y1 = (dPriv->h - y - h) + dPriv->y;
|
||||
rect.x2 = rect.x1 + w;
|
||||
rect.y2 = rect.y1 + h;
|
||||
_mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
|
||||
intelCopyBuffer(dPriv, &rect);
|
||||
}
|
||||
}
|
||||
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__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* Update culling direction which changes depending on the
|
||||
* orientation of the buffer:
|
||||
*/
|
||||
if (ctx->Driver.FrontFace)
|
||||
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
|
||||
else
|
||||
ctx->NewState |= _NEW_POLYGON;
|
||||
|
||||
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->intelScreen->depth_region != depthRegion) {
|
||||
intel_region_release(intel, &intel->intelScreen->depth_region);
|
||||
intel_region_reference(&intel->intelScreen->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;
|
||||
}
|
||||
56
src/mesa/drivers/dri/i915/intel_buffers.h
Normal file
56
src/mesa/drivers/dri/i915/intel_buffers.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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);
|
||||
|
||||
extern void
|
||||
intelRotateWindow(struct intel_context *intel,
|
||||
__DRIdrawablePrivate * dPriv, GLuint srcBuf);
|
||||
|
||||
#endif /* INTEL_BUFFERS_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,88 +48,132 @@
|
||||
#define DV_PF_565 (2<<8)
|
||||
#define DV_PF_8888 (3<<8)
|
||||
|
||||
#define INTEL_CONTEXT(ctx) ((intelContextPtr)(ctx))
|
||||
struct intel_region;
|
||||
struct intel_context;
|
||||
struct _DriBufferObject;
|
||||
|
||||
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) (struct intel_context *, intelVertex *,
|
||||
intelVertex *);
|
||||
typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *);
|
||||
typedef void (*intel_point_func)(intelContextPtr, 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
|
||||
|
||||
#define INTEL_WRITE_PART 0x1
|
||||
#define INTEL_WRITE_FULL 0x2
|
||||
#define INTEL_READ 0x4
|
||||
|
||||
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 );
|
||||
struct
|
||||
{
|
||||
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_color_region)( intelContextPtr intel, const intelRegion *reg );
|
||||
void (*set_z_region)( intelContextPtr intel, const intelRegion *reg );
|
||||
void (*update_color_z_regions)(intelContextPtr intel,
|
||||
const intelRegion *colorRegion,
|
||||
const intelRegion *depthRegion);
|
||||
void (*emit_flush)( intelContextPtr intel );
|
||||
void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim );
|
||||
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);
|
||||
|
||||
GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected );
|
||||
GLuint(*flush_cmd) (void);
|
||||
|
||||
void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask,
|
||||
GLboolean all,
|
||||
GLint cx, GLint cy, GLint cw, GLint ch);
|
||||
void (*reduced_primitive_state) (struct intel_context * intel,
|
||||
GLenum rprim);
|
||||
|
||||
void (*rotate_window)( intelContextPtr intel,
|
||||
__DRIdrawablePrivate *dPriv, GLuint srcBuf);
|
||||
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,
|
||||
struct _DriBufferObject * buffer,
|
||||
GLuint offset,
|
||||
GLuint pitch,
|
||||
GLuint height,
|
||||
GLenum format, GLenum type);
|
||||
void (*rotate_window) (struct intel_context * intel,
|
||||
__DRIdrawablePrivate * dPriv, GLuint srcBuf);
|
||||
|
||||
void (*assert_not_dirty) (struct intel_context *intel);
|
||||
|
||||
} vtbl;
|
||||
|
||||
@@ -137,68 +181,45 @@ struct intel_context
|
||||
GLuint Fallback;
|
||||
GLuint NewGLState;
|
||||
|
||||
struct {
|
||||
GLuint start_offset;
|
||||
GLint size;
|
||||
GLint space;
|
||||
GLubyte *ptr;
|
||||
GLuint counter;
|
||||
GLuint last_emit_state;
|
||||
GLboolean contains_geometry;
|
||||
const char *func;
|
||||
GLuint last_swap;
|
||||
} batch;
|
||||
struct _DriFenceObject *last_swap_fence;
|
||||
struct _DriFenceObject *first_swap_fence;
|
||||
|
||||
struct {
|
||||
void *ptr;
|
||||
GLint size;
|
||||
GLuint offset;
|
||||
GLuint active_buf;
|
||||
GLuint irq_emitted;
|
||||
} alloc;
|
||||
struct intel_batchbuffer *batch;
|
||||
|
||||
struct {
|
||||
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;
|
||||
GLboolean strict_conformance;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
@@ -207,8 +228,15 @@ struct intel_context
|
||||
GLenum render_primitive;
|
||||
GLenum reduced_primitive;
|
||||
GLuint vertex_size;
|
||||
unsigned char *verts; /* points to tnl->clipspace.vertex_buf */
|
||||
GLubyte *verts; /* points to tnl->clipspace.vertex_buf */
|
||||
|
||||
#if 0
|
||||
struct intel_region *front_region; /* XXX FBO: obsolete */
|
||||
struct intel_region *rotated_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 */
|
||||
#endif
|
||||
|
||||
/* Fallback rasterization functions
|
||||
*/
|
||||
@@ -216,17 +244,13 @@ struct intel_context
|
||||
intel_line_func draw_line;
|
||||
intel_tri_func draw_tri;
|
||||
|
||||
/* Drawing buffer state
|
||||
/* These refer to the current drawing buffer:
|
||||
*/
|
||||
intelRegion *drawRegion; /* current drawing buffer */
|
||||
intelRegion *readRegion; /* current reading buffer */
|
||||
|
||||
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;
|
||||
|
||||
GLuint do_usleeps;
|
||||
@@ -234,10 +258,6 @@ struct intel_context
|
||||
GLuint irqsEmitted;
|
||||
drm_i915_irq_wait_t iw;
|
||||
|
||||
GLboolean scissor;
|
||||
drm_clip_rect_t draw_rect;
|
||||
drm_clip_rect_t scissor_rect;
|
||||
|
||||
drm_context_t hHWContext;
|
||||
drmLock *driHwLock;
|
||||
int driFd;
|
||||
@@ -247,6 +267,8 @@ struct intel_context
|
||||
intelScreenPrivate *intelScreen;
|
||||
drmI830Sarea *sarea;
|
||||
|
||||
GLuint lastStamp;
|
||||
|
||||
/**
|
||||
* Configuration cache
|
||||
*/
|
||||
@@ -262,87 +284,15 @@ struct intel_context
|
||||
|
||||
GLuint swap_count;
|
||||
GLuint swap_missed_count;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define DEBUG_LOCKING 1
|
||||
|
||||
#if DEBUG_LOCKING
|
||||
extern char *prevLockFile;
|
||||
extern int prevLockLine;
|
||||
|
||||
#define DEBUG_LOCK() \
|
||||
do { \
|
||||
prevLockFile = (__FILE__); \
|
||||
prevLockLine = (__LINE__); \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_RESET() \
|
||||
do { \
|
||||
prevLockFile = 0; \
|
||||
prevLockLine = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Slightly less broken way of detecting recursive locking in a
|
||||
* threaded environment. The right way to do this would be to make
|
||||
* prevLockFile, prevLockLine thread-local.
|
||||
*
|
||||
* This technique instead checks to see if the same context is
|
||||
* requesting the lock twice -- this will not catch application
|
||||
* breakages where the same context is active in two different threads
|
||||
* at once, but it will catch driver breakages (recursive locking) in
|
||||
* threaded apps.
|
||||
/* These are functions now:
|
||||
*/
|
||||
#define DEBUG_CHECK_LOCK() \
|
||||
do { \
|
||||
if ( *((volatile int *)intel->driHwLock) == \
|
||||
(DRM_LOCK_HELD | intel->hHWContext) ) { \
|
||||
fprintf( stderr, \
|
||||
"LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
|
||||
prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
void LOCK_HARDWARE( struct intel_context *intel );
|
||||
void UNLOCK_HARDWARE( struct intel_context *intel );
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_LOCK()
|
||||
#define DEBUG_RESET()
|
||||
#define DEBUG_CHECK_LOCK()
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Lock the hardware and validate our state.
|
||||
*/
|
||||
#define LOCK_HARDWARE( intel ) \
|
||||
do { \
|
||||
char __ret=0; \
|
||||
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(); \
|
||||
(intel)->locked = 1; \
|
||||
}while (0)
|
||||
|
||||
|
||||
/* Unlock the hardware using the global current context
|
||||
*/
|
||||
#define UNLOCK_HARDWARE(intel) \
|
||||
do { \
|
||||
intel->locked = 0; \
|
||||
if (0) { \
|
||||
intel->perf_boxes |= intel->sarea->perf_boxes; \
|
||||
intel->sarea->perf_boxes = 0; \
|
||||
} \
|
||||
DRM_UNLOCK((intel)->driFd, (intel)->driHwLock, (intel)->hHWContext); \
|
||||
DEBUG_RESET(); \
|
||||
} while (0)
|
||||
extern char *__progname;
|
||||
|
||||
|
||||
#define SUBPIXEL_X 0.125
|
||||
@@ -351,7 +301,7 @@ do { \
|
||||
#define INTEL_FIREVERTICES(intel) \
|
||||
do { \
|
||||
if ((intel)->prim.flush) \
|
||||
(intel)->prim.flush(&(intel)->ctx); \
|
||||
(intel)->prim.flush(intel); \
|
||||
} while (0)
|
||||
|
||||
/* ================================================================
|
||||
@@ -372,34 +322,26 @@ 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__(
|
||||
"rep ; movsl\n\t"
|
||||
__asm__ __volatile__("rep ; movsl\n\t"
|
||||
"testb $2,%b4\n\t"
|
||||
"je 1f\n\t"
|
||||
"movsw\n"
|
||||
"1:\ttestb $1,%b4\n\t"
|
||||
"je 2f\n\t"
|
||||
"movsb\n"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
|
||||
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
|
||||
: "memory");
|
||||
"movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
|
||||
:"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
|
||||
:"memory");
|
||||
return (to);
|
||||
}
|
||||
#else
|
||||
@@ -421,16 +363,18 @@ extern int INTEL_DEBUG;
|
||||
#define DEBUG_TEXTURE 0x1
|
||||
#define DEBUG_STATE 0x2
|
||||
#define DEBUG_IOCTL 0x4
|
||||
#define DEBUG_PRIMS 0x8
|
||||
#define DEBUG_VERTS 0x10
|
||||
#define DEBUG_BLIT 0x8
|
||||
#define DEBUG_MIPTREE 0x10
|
||||
#define DEBUG_FALLBACKS 0x20
|
||||
#define DEBUG_VERBOSE 0x40
|
||||
#define DEBUG_DRI 0x80
|
||||
#define DEBUG_DMA 0x100
|
||||
#define DEBUG_SANITY 0x200
|
||||
#define DEBUG_SYNC 0x400
|
||||
#define DEBUG_SLEEP 0x800
|
||||
#define DEBUG_PIXEL 0x1000
|
||||
#define DEBUG_BATCH 0x80
|
||||
#define DEBUG_PIXEL 0x100
|
||||
#define DEBUG_BUFMGR 0x200
|
||||
#define DEBUG_REGION 0x400
|
||||
#define DEBUG_FBO 0x800
|
||||
#define DEBUG_LOCK 0x1000
|
||||
|
||||
#define DBG(...) do { if (INTEL_DEBUG & FILE_DEBUG_FLAG) _mesa_printf(__VA_ARGS__); } while(0)
|
||||
|
||||
|
||||
#define PCI_CHIP_845_G 0x2562
|
||||
@@ -447,27 +391,25 @@ extern int INTEL_DEBUG;
|
||||
* intel_context.c:
|
||||
*/
|
||||
|
||||
extern void intelInitDriverFunctions( struct dd_function_table *functions );
|
||||
|
||||
extern GLboolean intelInitContext( intelContextPtr intel,
|
||||
const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
extern GLboolean intelInitContext(struct intel_context *intel,
|
||||
const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
void *sharedContextPrivate,
|
||||
struct dd_function_table *functions );
|
||||
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 intelInitState(GLcontext * ctx);
|
||||
extern void intelFinish(GLcontext * ctx);
|
||||
extern void intelFlush(GLcontext * ctx);
|
||||
|
||||
extern void intelInitDriverFunctions(struct dd_function_table *functions);
|
||||
|
||||
|
||||
/* ================================================================
|
||||
* intel_state.c:
|
||||
*/
|
||||
extern void intelInitStateFuncs( struct dd_function_table *functions );
|
||||
extern void intelInitStateFuncs(struct dd_function_table *functions);
|
||||
|
||||
#define COMPAREFUNC_ALWAYS 0
|
||||
#define COMPAREFUNC_NEVER 0x1
|
||||
@@ -521,27 +463,39 @@ extern void intelInitStateFuncs( struct dd_function_table *functions );
|
||||
#define BLENDFACT_INV_CONST_ALPHA 0x0f
|
||||
#define BLENDFACT_MASK 0x0f
|
||||
|
||||
|
||||
extern int intel_translate_compare_func( GLenum func );
|
||||
extern int intel_translate_stencil_op( GLenum op );
|
||||
extern int intel_translate_blend_factor( GLenum factor );
|
||||
extern int intel_translate_logic_op( GLenum opcode );
|
||||
#define MI_BATCH_BUFFER_END (0xA<<23)
|
||||
|
||||
|
||||
/* ================================================================
|
||||
* intel_ioctl.c:
|
||||
extern int intel_translate_compare_func(GLenum func);
|
||||
extern int intel_translate_stencil_op(GLenum op);
|
||||
extern int intel_translate_blend_factor(GLenum factor);
|
||||
extern int intel_translate_logic_op(GLenum opcode);
|
||||
|
||||
|
||||
/*======================================================================
|
||||
* 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
|
||||
|
||||
|
||||
282
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal file
282
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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->intelScreen, depthRb->region);
|
||||
depthRb->pfMap = depthRb->region->map;
|
||||
depthRb->pfPitch = depthRb->region->pitch;
|
||||
}
|
||||
if (stencilRb && stencilRb->region) {
|
||||
intel_region_map(intel->intelScreen, 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->intelScreen, depthRb->region);
|
||||
depthRb->pfMap = NULL;
|
||||
depthRb->pfPitch = 0;
|
||||
}
|
||||
if (stencilRb && stencilRb->region) {
|
||||
intel_region_unmap(intel->intelScreen, 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.
|
||||
*/
|
||||
}
|
||||
14
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal file
14
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
#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 */
|
||||
621
src/mesa/drivers/dri/i915/intel_fbo.c
Normal file
621
src/mesa/drivers/dri/i915/intel_fbo.c
Normal file
@@ -0,0 +1,621 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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_depthstencil.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_span.h"
|
||||
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_FBO
|
||||
|
||||
#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->intelScreen, &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->intelScreen, &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 */
|
||||
DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
|
||||
height, pitch);
|
||||
|
||||
irb->region = intel_region_alloc(intel->intelScreen, 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 / cpp; /* in pixels */
|
||||
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
DBG("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;
|
||||
DBG("Render to RGBA8 texture OK\n");
|
||||
}
|
||||
else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
|
||||
irb->Base._ActualFormat = GL_RGB5;
|
||||
irb->Base._BaseFormat = GL_RGB;
|
||||
DBG("Render to RGB5 texture OK\n");
|
||||
}
|
||||
else if (texImage->TexFormat == &_mesa_texformat_z16) {
|
||||
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
|
||||
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
|
||||
DBG("Render to DEPTH16 texture OK\n");
|
||||
}
|
||||
else {
|
||||
DBG("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;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("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) {
|
||||
const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
|
||||
att->TextureLevel);
|
||||
imageOffset += offsets[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);
|
||||
|
||||
DBG("End render texture (tid %u) tex %u\n", _glthread_GetID(), att->Texture->Name);
|
||||
|
||||
if (irb) {
|
||||
/* just release the region */
|
||||
intel_region_release(intel->intelScreen, &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;
|
||||
}
|
||||
80
src/mesa/drivers/dri/i915/intel_fbo.h
Normal file
80
src/mesa/drivers/dri/i915/intel_fbo.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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,623 +38,101 @@
|
||||
#include "intel_context.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_regions.h"
|
||||
#include "drm.h"
|
||||
|
||||
u_int32_t intelGetLastFrame (intelContextPtr intel)
|
||||
{
|
||||
int ret;
|
||||
u_int32_t frame;
|
||||
drm_i915_getparam_t gp;
|
||||
#define FILE_DEBUG_FLAG DEBUG_IOCTL
|
||||
|
||||
gp.param = I915_PARAM_LAST_DISPATCH;
|
||||
gp.value = (int *)&frame;
|
||||
ret = drmCommandWriteRead( intel->driFd, DRM_I915_GETPARAM,
|
||||
&gp, sizeof(gp) );
|
||||
return frame;
|
||||
}
|
||||
|
||||
int intelEmitIrqLocked( intelContextPtr intel )
|
||||
int
|
||||
intelEmitIrqLocked(struct intel_context *intel)
|
||||
{
|
||||
drmI830IrqEmit ie;
|
||||
int ret, seq;
|
||||
|
||||
assert(((*(int *)intel->driHwLock) & ~DRM_LOCK_CONT) ==
|
||||
(DRM_LOCK_HELD|intel->hHWContext));
|
||||
assert(((*(int *) intel->driHwLock) & ~DRM_LOCK_CONT) ==
|
||||
(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 );
|
||||
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 );
|
||||
DBG("%s --> %d\n", __FUNCTION__, seq);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
void intelWaitIrq( intelContextPtr intel, int seq )
|
||||
void
|
||||
intelWaitIrq(struct intel_context *intel, int seq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (0)
|
||||
fprintf(stderr, "%s %d\n", __FUNCTION__, seq );
|
||||
DBG("%s %d\n", __FUNCTION__, seq);
|
||||
|
||||
intel->iw.irq_seq = seq;
|
||||
|
||||
do {
|
||||
ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, sizeof(intel->iw) );
|
||||
ret =
|
||||
drmCommandWrite(intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw,
|
||||
sizeof(intel->iw));
|
||||
} while (ret == -EAGAIN || ret == -EINTR);
|
||||
|
||||
if ( ret ) {
|
||||
fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret );
|
||||
if (0)
|
||||
intel_dump_batchbuffer( intel->alloc.offset,
|
||||
intel->alloc.ptr,
|
||||
intel->alloc.size );
|
||||
if (ret) {
|
||||
fprintf(stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret);
|
||||
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 = (unsigned char *)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 (started in %s)\n",
|
||||
DBG("%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,
|
||||
intel->batch.func);
|
||||
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 );
|
||||
sched_yield();
|
||||
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) {
|
||||
|
||||
if (intel->sarea->ctxOwner != intel->hHWContext) {
|
||||
intel->perf_boxes |= I830_BOX_LOST_CONTEXT;
|
||||
intel->sarea->ctxOwner = intel->hHWContext;
|
||||
}
|
||||
|
||||
batch.start = intel->batch.start_offset;
|
||||
batch.used = intel->batch.size - intel->batch.space;
|
||||
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));
|
||||
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;
|
||||
}
|
||||
}
|
||||
DBG("%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
|
||||
__FUNCTION__,
|
||||
batch.start,
|
||||
batch.start + batch.used * 4, batch.DR4, batch.num_cliprects);
|
||||
|
||||
if (0)
|
||||
intel_dump_batchbuffer( batch.start,
|
||||
(int *)(intel->batch.ptr - batch.used),
|
||||
batch.used );
|
||||
|
||||
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,
|
||||
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.
|
||||
*/
|
||||
if (intel->batch.contains_geometry)
|
||||
assert(intel->batch.last_emit_state == intel->batch.counter);
|
||||
|
||||
intel->batch.counter++;
|
||||
intel->batch.contains_geometry = 0;
|
||||
intel->batch.func = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if we need to rotate/warp the front color buffer to the
|
||||
* rotated screen. We generally need to do this when we get a glFlush
|
||||
* or glFinish after drawing to the front color buffer.
|
||||
*/
|
||||
static void
|
||||
intelCheckFrontRotate(GLcontext *ctx)
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
if (screen->current_rotation != 0) {
|
||||
__DRIdrawablePrivate *dPriv = intel->driDrawable;
|
||||
intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* NOT directly called via glFlush.
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via glFlush.
|
||||
*/
|
||||
void intelglFlush( GLcontext *ctx )
|
||||
{
|
||||
intelFlush(ctx);
|
||||
intelCheckFrontRotate(ctx);
|
||||
}
|
||||
|
||||
|
||||
void intelFinish( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
intelFlush( ctx );
|
||||
intelWaitForIdle( intel );
|
||||
intelCheckFrontRotate(ctx);
|
||||
}
|
||||
|
||||
|
||||
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) != 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
|
||||
intelRotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv,
|
||||
GLuint srcBuffer)
|
||||
{
|
||||
if (intel->vtbl.rotate_window) {
|
||||
intel->vtbl.rotate_window(intel, dPriv, srcBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *intelAllocateAGP( intelContextPtr intel, GLsizei size )
|
||||
{
|
||||
int region_offset;
|
||||
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 );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tmp = intel->sarea->last_enqueue;
|
||||
intelRefillBatchLocked( intel );
|
||||
UNLOCK_HARDWARE( intel );
|
||||
|
||||
|
||||
intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer );
|
||||
#endif
|
||||
intel->vtbl.lost_hardware(intel);
|
||||
}
|
||||
|
||||
@@ -30,44 +30,11 @@
|
||||
|
||||
#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 intelRotateWindow(intelContextPtr intel,
|
||||
__DRIdrawablePrivate *dPriv, GLuint srcBuffer);
|
||||
|
||||
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 intelglFlush( 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 );
|
||||
|
||||
extern void intelWaitIrq( intelContextPtr intel, int seq );
|
||||
extern u_int32_t intelGetLastFrame (intelContextPtr intel);
|
||||
extern int intelEmitIrqLocked( intelContextPtr intel );
|
||||
void intel_batch_ioctl(struct intel_context *intel,
|
||||
GLuint start_offset,
|
||||
GLuint used,
|
||||
GLboolean ignore_cliprects, GLboolean allow_unlock);
|
||||
#endif
|
||||
|
||||
341
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal file
341
src/mesa/drivers/dri/i915/intel_mipmap_tree.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "enums.h"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
|
||||
|
||||
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 = compressed ? 2 : cpp;
|
||||
mt->compressed = compressed;
|
||||
mt->refcount = 0; /*Allow for unused miptrees */
|
||||
|
||||
switch (intel->intelScreen->deviceID) {
|
||||
case PCI_CHIP_I945_G:
|
||||
case PCI_CHIP_I945_GM:
|
||||
ok = i945_miptree_layout(mt);
|
||||
break;
|
||||
case PCI_CHIP_I915_G:
|
||||
case PCI_CHIP_I915_GM:
|
||||
case PCI_CHIP_I830_M:
|
||||
case PCI_CHIP_I855_GM:
|
||||
case PCI_CHIP_I865_G:
|
||||
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->intelScreen,
|
||||
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;
|
||||
DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount);
|
||||
}
|
||||
|
||||
void
|
||||
intel_miptree_release(struct intel_context *intel,
|
||||
struct intel_mipmap_tree **mt)
|
||||
{
|
||||
if (!*mt)
|
||||
return;
|
||||
|
||||
DBG("%s %p refcount will be %d\n", __FUNCTION__, *mt, (*mt)->refcount - 1);
|
||||
if (--(*mt)->refcount <= 0) {
|
||||
GLuint i;
|
||||
|
||||
DBG("%s deleting %p\n", __FUNCTION__, *mt);
|
||||
|
||||
intel_region_release(intel->intelScreen, &((*mt)->region));
|
||||
|
||||
for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
|
||||
if ((*mt)->level[i].image_offset)
|
||||
free((*mt)->level[i].image_offset);
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* 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->level[level].width ||
|
||||
image->Height != mt->level[level].height ||
|
||||
image->Depth != mt->level[level].depth)
|
||||
return GL_FALSE;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
|
||||
GLuint level,
|
||||
GLuint nr_images,
|
||||
GLuint x, GLuint y, GLuint w, GLuint h, GLuint d)
|
||||
{
|
||||
|
||||
mt->level[level].width = w;
|
||||
mt->level[level].height = h;
|
||||
mt->level[level].depth = d;
|
||||
mt->level[level].level_offset = (x + y * mt->pitch) * mt->cpp;
|
||||
mt->level[level].nr_images = nr_images;
|
||||
|
||||
DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
|
||||
level, w, h, d, x, y, mt->level[level].level_offset);
|
||||
|
||||
/* Not sure when this would happen, but anyway:
|
||||
*/
|
||||
if (mt->level[level].image_offset) {
|
||||
free(mt->level[level].image_offset);
|
||||
mt->level[level].image_offset = NULL;
|
||||
}
|
||||
|
||||
assert(nr_images);
|
||||
|
||||
mt->level[level].image_offset = malloc(nr_images * sizeof(GLuint));
|
||||
mt->level[level].image_offset[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
|
||||
GLuint level, GLuint img, GLuint x, GLuint y)
|
||||
{
|
||||
if (img == 0 && level == 0)
|
||||
assert(x == 0 && y == 0);
|
||||
|
||||
assert(img < mt->level[level].nr_images);
|
||||
|
||||
mt->level[level].image_offset[img] = (x + y * mt->pitch);
|
||||
|
||||
DBG("%s level %d img %d pos %d,%d image_offset %x\n",
|
||||
__FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
|
||||
}
|
||||
|
||||
|
||||
/* Although we use the image_offset[] array to store relative offsets
|
||||
* to cube faces, Mesa doesn't know anything about this and expects
|
||||
* each cube face to be treated as a separate image.
|
||||
*
|
||||
* These functions present that view to mesa:
|
||||
*/
|
||||
const GLuint *
|
||||
intel_miptree_depth_offsets(struct intel_mipmap_tree *mt, GLuint level)
|
||||
{
|
||||
static const GLuint zero = 0;
|
||||
|
||||
if (mt->target != GL_TEXTURE_3D || mt->level[level].nr_images == 1)
|
||||
return &zero;
|
||||
else
|
||||
return mt->level[level].image_offset;
|
||||
}
|
||||
|
||||
|
||||
GLuint
|
||||
intel_miptree_image_offset(struct intel_mipmap_tree * mt,
|
||||
GLuint face, GLuint level)
|
||||
{
|
||||
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
|
||||
return (mt->level[level].level_offset +
|
||||
mt->level[level].image_offset[face] * mt->cpp);
|
||||
else
|
||||
return mt->level[level].level_offset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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_offsets)
|
||||
{
|
||||
DBG("%s \n", __FUNCTION__);
|
||||
|
||||
if (row_stride)
|
||||
*row_stride = mt->pitch * mt->cpp;
|
||||
|
||||
if (image_offsets)
|
||||
memcpy(image_offsets, mt->level[level].image_offset,
|
||||
mt->level[level].depth * sizeof(GLuint));
|
||||
|
||||
return (intel_region_map(intel->intelScreen, 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->intelScreen, 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->level[level].depth;
|
||||
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
|
||||
const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
|
||||
GLuint i;
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
for (i = 0; i < depth; i++) {
|
||||
intel_region_data(intel->intelScreen, dst->region, dst_offset + dst_depth_offset[i], 0, 0, src, src_row_pitch, 0, 0, /* source x,y */
|
||||
dst->level[level].width, dst->level[level].height);
|
||||
|
||||
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->level[level].width;
|
||||
GLuint height = src->level[level].height;
|
||||
GLuint depth = src->level[level].depth;
|
||||
GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
|
||||
GLuint src_offset = intel_miptree_image_offset(src, face, level);
|
||||
const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
|
||||
const GLuint *src_depth_offset = intel_miptree_depth_offsets(src, level);
|
||||
GLuint i;
|
||||
|
||||
for (i = 0; i < depth; i++) {
|
||||
intel_region_copy(intel->intelScreen,
|
||||
dst->region, dst_offset + dst_depth_offset[i],
|
||||
0,
|
||||
0,
|
||||
src->region, src_offset + src_depth_offset[i],
|
||||
0, 0, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
198
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal file
198
src/mesa/drivers/dri/i915/intel_mipmap_tree.h
Normal file
@@ -0,0 +1,198 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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_level
|
||||
{
|
||||
GLuint level_offset;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
GLuint depth;
|
||||
GLuint nr_images;
|
||||
|
||||
/* Explicitly store the offset of each image for each cube face or
|
||||
* depth value. Pretty much have to accept that hardware formats
|
||||
* are going to be so diverse that there is no unified way to
|
||||
* compute the offsets of depth/cube images within a mipmap level,
|
||||
* so have to store them as a lookup table:
|
||||
*/
|
||||
GLuint *image_offset;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
/* Includes image offset tables:
|
||||
*/
|
||||
struct intel_mipmap_level level[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);
|
||||
|
||||
/* Return pointers to each 2d slice within an image. Indexed by depth
|
||||
* value.
|
||||
*/
|
||||
const GLuint *intel_miptree_depth_offsets(struct intel_mipmap_tree *mt,
|
||||
GLuint level);
|
||||
|
||||
|
||||
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
|
||||
GLuint level,
|
||||
GLuint nr_images,
|
||||
GLuint x, GLuint y,
|
||||
GLuint w, GLuint h, GLuint d);
|
||||
|
||||
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
|
||||
GLuint level,
|
||||
GLuint img, GLuint x, GLuint y);
|
||||
|
||||
|
||||
/* 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,58 +25,29 @@
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#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__);
|
||||
|
||||
if ( (pitch & 63) ||
|
||||
ctx->_ImageTransferState ||
|
||||
packing->SwapBytes ||
|
||||
packing->LsbFirst) {
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: failed 1\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
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__);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s: failed\n", __FUNCTION__);
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
check_color_per_fragment_ops( const GLcontext *ctx )
|
||||
{
|
||||
int result;
|
||||
result = (!( ctx->Color.AlphaEnabled ||
|
||||
/* XXX Note: Scissor could be done with the blitter:
|
||||
*/
|
||||
return !(ctx->_ImageTransferState ||
|
||||
ctx->Color.AlphaEnabled ||
|
||||
ctx->Depth.Test ||
|
||||
ctx->Fog.Enabled ||
|
||||
ctx->Scissor.Enabled ||
|
||||
@@ -86,426 +57,63 @@ check_color_per_fragment_ops( const GLcontext *ctx )
|
||||
!ctx->Color.ColorMask[2] ||
|
||||
!ctx->Color.ColorMask[3] ||
|
||||
ctx->Color.ColorLogicOpEnabled ||
|
||||
ctx->Texture._EnabledUnits
|
||||
) &&
|
||||
ctx->Current.RasterPosValid);
|
||||
|
||||
return result;
|
||||
ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clip the given rectangle against the buffer's bounds (including scissor).
|
||||
* \param size returns the
|
||||
* \return GL_TRUE if any pixels remain, GL_FALSE if totally clipped.
|
||||
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.
|
||||
*
|
||||
* XXX Replace this with _mesa_clip_drawpixels() and _mesa_clip_readpixels()
|
||||
* from Mesa 6.4. We shouldn't apply scissor for ReadPixels.
|
||||
* \param format as given to glDraw/ReadPixels
|
||||
* \param type as given to glDraw/ReadPixels
|
||||
*/
|
||||
static GLboolean
|
||||
clip_pixelrect( const GLcontext *ctx,
|
||||
const GLframebuffer *buffer,
|
||||
GLint *x, GLint *y,
|
||||
GLsizei *width, GLsizei *height)
|
||||
GLboolean
|
||||
intel_check_blit_format(struct intel_region * region,
|
||||
GLenum format, GLenum type)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute intersection of a clipping rectangle and pixel rectangle,
|
||||
* returning results in x/y/w/hOut vars.
|
||||
* \return GL_TRUE if there's intersection, GL_FALSE if disjoint.
|
||||
*/
|
||||
static INLINE GLboolean
|
||||
intersect_region(const drm_clip_rect_t *box,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height,
|
||||
GLint *xOut, GLint *yOut, GLint *wOut, GLint *hOut)
|
||||
{
|
||||
GLint bx = box->x1;
|
||||
GLint by = box->y1;
|
||||
GLint bw = box->x2 - bx;
|
||||
GLint bh = box->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;
|
||||
|
||||
*xOut = bx;
|
||||
*yOut = by;
|
||||
*wOut = bw;
|
||||
*hOut = bh;
|
||||
|
||||
if (bw <= 0) return GL_FALSE;
|
||||
if (bh <= 0) return GL_FALSE;
|
||||
|
||||
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; /* not really used */
|
||||
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 drawing offset 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->readRegion->offset;
|
||||
int src_pitch = intel->intelScreen->front.pitch;
|
||||
int dst_offset = intelAgpOffsetFromVirtual( intel, pixels);
|
||||
drm_clip_rect_t *box = dPriv->pClipRects;
|
||||
int i;
|
||||
|
||||
assert(dst_offset != ~0); /* should have been caught above */
|
||||
|
||||
if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height)) {
|
||||
UNLOCK_HARDWARE( intel );
|
||||
if (INTEL_DEBUG & DEBUG_PIXEL)
|
||||
fprintf(stderr, "%s totally clipped -- nothing to do\n",
|
||||
__FUNCTION__);
|
||||
if (region->cpp == 4 &&
|
||||
(type == GL_UNSIGNED_INT_8_8_8_8_REV ||
|
||||
type == GL_UNSIGNED_BYTE) && format == GL_BGRA) {
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/* convert to screen coords (y=0=top) */
|
||||
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);
|
||||
|
||||
/* We don't really have to do window clipping for readpixels.
|
||||
* The OpenGL spec says that pixels read from outside the
|
||||
* visible window region (pixel ownership) have undefined value.
|
||||
*/
|
||||
for (i = 0 ; i < nbox ; i++)
|
||||
{
|
||||
GLint bx, by, bw, bh;
|
||||
if (intersect_region(box+i, x, y, width, height,
|
||||
&bx, &by, &bw, &bh)) {
|
||||
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 src_offset = intelAgpOffsetFromVirtual( intel, pixels);
|
||||
int src_pitch = pitch;
|
||||
|
||||
assert(src_offset != ~0); /* should be caught earlier */
|
||||
|
||||
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)) {
|
||||
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, by, bw, bh;
|
||||
if (intersect_region(box + i, x, y, width, height,
|
||||
&bx, &by, &bw, &bh)) {
|
||||
intelEmitCopyBlitLocked( intel,
|
||||
intel->intelScreen->cpp,
|
||||
src_pitch, src_offset,
|
||||
intel->intelScreen->front.pitch,
|
||||
intel->drawRegion->offset,
|
||||
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->drawRegion->offset;
|
||||
|
||||
/* 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 );
|
||||
if (region->cpp == 2 &&
|
||||
type == GL_UNSIGNED_SHORT_5_6_5_REV && format == GL_BGR) {
|
||||
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;
|
||||
|
||||
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__);
|
||||
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));
|
||||
|
||||
if (!intelTryDrawPixels( ctx, x, y, width, height, format, type,
|
||||
unpack, pixels ))
|
||||
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
|
||||
unpack, pixels );
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
void
|
||||
intelInitPixelFuncs(struct dd_function_table *functions)
|
||||
{
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
63
src/mesa/drivers/dri/i915/intel_pixel.h
Normal file
63
src/mesa/drivers/dri/i915/intel_pixel.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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
|
||||
380
src/mesa/drivers/dri/i915/intel_pixel_copy.c
Normal file
380
src/mesa/drivers/dri/i915/intel_pixel_copy.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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 "state.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"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_PIXEL
|
||||
|
||||
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->intelScreen->depth_region &&
|
||||
intel->intelScreen->depth_region->cpp == 2)
|
||||
return intel->intelScreen->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->intelScreen->depth_region;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if any fragment operations are in effect which might effect
|
||||
* glCopyPixels. Differs from intel_check_blit_fragment_ops in that
|
||||
* we allow Scissor.
|
||||
*/
|
||||
static GLboolean
|
||||
intel_check_copypixel_blit_fragment_ops(GLcontext * ctx)
|
||||
{
|
||||
if (ctx->NewState)
|
||||
_mesa_update_state(ctx);
|
||||
|
||||
/* Could do logicop with the blitter:
|
||||
*/
|
||||
return !(ctx->_ImageTransferState ||
|
||||
ctx->Color.AlphaEnabled ||
|
||||
ctx->Depth.Test ||
|
||||
ctx->Fog.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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
DBG("%s %d,%d %dx%d --> %d,%d\n", __FUNCTION__,
|
||||
srcx, srcy, width, height, dstx, dsty);
|
||||
|
||||
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.
|
||||
*/
|
||||
if (src->buffer == dst->buffer) {
|
||||
drm_clip_rect_t srcbox;
|
||||
drm_clip_rect_t dstbox;
|
||||
drm_clip_rect_t tmp;
|
||||
|
||||
srcbox.x1 = srcx;
|
||||
srcbox.y1 = srcy;
|
||||
srcbox.x2 = srcx + width;
|
||||
srcbox.y2 = srcy + height;
|
||||
|
||||
dstbox.x1 = dstx;
|
||||
dstbox.y1 = dsty;
|
||||
dstbox.x2 = dstx + width * ctx->Pixel.ZoomX;
|
||||
dstbox.y2 = dsty + height * ctx->Pixel.ZoomY;
|
||||
|
||||
DBG("src %d,%d %d,%d\n", srcbox.x1, srcbox.y1, srcbox.x2, srcbox.y2);
|
||||
DBG("dst %d,%d %d,%d (%dx%d) (%f,%f)\n", dstbox.x1, dstbox.y1, dstbox.x2, dstbox.y2,
|
||||
width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
|
||||
|
||||
if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) {
|
||||
DBG("%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->intelScreen->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);
|
||||
|
||||
DBG("%s: success\n", __FUNCTION__);
|
||||
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_copypixel_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);
|
||||
|
||||
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;
|
||||
|
||||
/* Do scissoring in GL coordinates:
|
||||
*/
|
||||
if (ctx->Scissor.Enabled)
|
||||
{
|
||||
GLint x = ctx->Scissor.X;
|
||||
GLint y = ctx->Scissor.Y;
|
||||
GLuint w = ctx->Scissor.Width;
|
||||
GLuint h = ctx->Scissor.Height;
|
||||
GLint dx = dstx - srcx;
|
||||
GLint dy = dsty - srcy;
|
||||
|
||||
if (!_mesa_clip_to_region(x, y, x+w, y+h, &dstx, &dsty, &width, &height))
|
||||
goto out;
|
||||
|
||||
srcx = dstx - dx;
|
||||
srcy = dsty - dy;
|
||||
}
|
||||
|
||||
/* Convert from GL to hardware coordinates:
|
||||
*/
|
||||
dsty = dPriv->h - dsty - height;
|
||||
srcy = dPriv->h - srcy - height;
|
||||
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.
|
||||
*/
|
||||
{
|
||||
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);
|
||||
|
||||
DBG("%s: success\n", __FUNCTION__);
|
||||
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;
|
||||
|
||||
DBG("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"
|
||||
|
||||
|
||||
|
||||
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->intelScreen->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;
|
||||
struct _DriFenceObject *fence = NULL;
|
||||
|
||||
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;
|
||||
struct _DriBufferObject *src_buffer =
|
||||
intel_bufferobj_buffer(intel, src, INTEL_READ);
|
||||
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,
|
||||
src_buffer, 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);
|
||||
driFenceReference(fence);
|
||||
}
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE);
|
||||
|
||||
driFenceUnReference(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);
|
||||
}
|
||||
317
src/mesa/drivers/dri/i915/intel_pixel_read.c
Normal file
317
src/mesa/drivers/dri/i915/intel_pixel_read.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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"
|
||||
|
||||
/* 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;
|
||||
struct _DriFenceObject *fence = NULL;
|
||||
|
||||
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) {
|
||||
GLboolean all = (width * height * src->cpp == dst->Base.Size &&
|
||||
x == 0 && dst_offset == 0);
|
||||
|
||||
struct _DriBufferObject *dst_buffer =
|
||||
intel_bufferobj_buffer(intel, dst, all ? INTEL_WRITE_FULL :
|
||||
INTEL_WRITE_PART);
|
||||
__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,
|
||||
dst_buffer, 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);
|
||||
driFenceReference(fence);
|
||||
|
||||
}
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
if (intel->driDrawable->numClipRects)
|
||||
driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
|
||||
GL_FALSE);
|
||||
|
||||
driFenceUnReference(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);
|
||||
}
|
||||
458
src/mesa/drivers/dri/i915/intel_regions.c
Normal file
458
src/mesa/drivers/dri/i915/intel_regions.c
Normal file
@@ -0,0 +1,458 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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_buffer_objects.h"
|
||||
#include "dri_bufmgr.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_REGION
|
||||
|
||||
void
|
||||
intel_region_idle(intelScreenPrivate *intelScreen, struct intel_region *region)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
if (region && region->buffer)
|
||||
driBOWaitIdle(region->buffer, GL_FALSE);
|
||||
}
|
||||
|
||||
/* XXX: Thread safety?
|
||||
*/
|
||||
GLubyte *
|
||||
intel_region_map(intelScreenPrivate *intelScreen, struct intel_region *region)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
if (!region->map_refcount++) {
|
||||
if (region->pbo)
|
||||
intel_region_cow(intelScreen, region);
|
||||
|
||||
region->map = driBOMap(region->buffer,
|
||||
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
|
||||
}
|
||||
|
||||
return region->map;
|
||||
}
|
||||
|
||||
void
|
||||
intel_region_unmap(intelScreenPrivate *intelScreen, struct intel_region *region)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
if (!--region->map_refcount) {
|
||||
driBOUnmap(region->buffer);
|
||||
region->map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_region *
|
||||
intel_region_alloc(intelScreenPrivate *intelScreen,
|
||||
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;
|
||||
|
||||
driGenBuffers(intelScreen->regionPool,
|
||||
"region", 1, ®ion->buffer, 64, 0, 0);
|
||||
driBOData(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(intelScreenPrivate *intelScreen,
|
||||
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);
|
||||
|
||||
if ((*region)->pbo)
|
||||
(*region)->pbo->region = NULL;
|
||||
(*region)->pbo = NULL;
|
||||
driBOUnReference((*region)->buffer);
|
||||
free(*region);
|
||||
}
|
||||
*region = NULL;
|
||||
}
|
||||
|
||||
|
||||
struct intel_region *
|
||||
intel_region_create_static(intelScreenPrivate *intelScreen,
|
||||
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.
|
||||
*/
|
||||
|
||||
driGenBuffers(intelScreen->staticPool, "static region", 1,
|
||||
®ion->buffer, 64,
|
||||
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_EVICT |
|
||||
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
|
||||
driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
intel_region_update_static(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region,
|
||||
GLuint mem_type,
|
||||
GLuint offset,
|
||||
void *virtual,
|
||||
GLuint cpp, GLuint pitch, GLuint height)
|
||||
{
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
region->cpp = cpp;
|
||||
region->pitch = pitch;
|
||||
region->height = height; /* needed? */
|
||||
|
||||
/*
|
||||
* We use a "shared" buffer type to indicate buffers created and
|
||||
* shared by others.
|
||||
*/
|
||||
|
||||
driDeleteBuffers(1, ®ion->buffer);
|
||||
driGenBuffers(intelScreen->staticPool, "static region", 1,
|
||||
®ion->buffer, 64,
|
||||
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_EVICT |
|
||||
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
|
||||
driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *dst,
|
||||
GLuint dst_offset,
|
||||
GLuint dstx, GLuint dsty,
|
||||
void *src, GLuint src_pitch,
|
||||
GLuint srcx, GLuint srcy, GLuint width, GLuint height)
|
||||
{
|
||||
struct intel_context *intel = intelScreenContext(intelScreen);
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (intel == NULL)
|
||||
return;
|
||||
|
||||
if (dst->pbo) {
|
||||
if (dstx == 0 &&
|
||||
dsty == 0 && width == dst->pitch && height == dst->height)
|
||||
intel_region_release_pbo(intelScreen, dst);
|
||||
else
|
||||
intel_region_cow(intelScreen, dst);
|
||||
}
|
||||
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
_mesa_copy_rect(intel_region_map(intelScreen, dst) + dst_offset,
|
||||
dst->cpp,
|
||||
dst->pitch,
|
||||
dstx, dsty, width, height, src, src_pitch, srcx, srcy);
|
||||
|
||||
intel_region_unmap(intelScreen, 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(intelScreenPrivate *intelScreen,
|
||||
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)
|
||||
{
|
||||
struct intel_context *intel = intelScreenContext(intelScreen);
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (intel == NULL)
|
||||
return;
|
||||
|
||||
if (dst->pbo) {
|
||||
if (dstx == 0 &&
|
||||
dsty == 0 && width == dst->pitch && height == dst->height)
|
||||
intel_region_release_pbo(intelScreen, dst);
|
||||
else
|
||||
intel_region_cow(intelScreen, dst);
|
||||
}
|
||||
|
||||
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(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *dst,
|
||||
GLuint dst_offset,
|
||||
GLuint dstx, GLuint dsty,
|
||||
GLuint width, GLuint height, GLuint color)
|
||||
{
|
||||
struct intel_context *intel = intelScreenContext(intelScreen);
|
||||
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
if (intel == NULL)
|
||||
return;
|
||||
|
||||
if (dst->pbo) {
|
||||
if (dstx == 0 &&
|
||||
dsty == 0 && width == dst->pitch && height == dst->height)
|
||||
intel_region_release_pbo(intelScreen, dst);
|
||||
else
|
||||
intel_region_cow(intelScreen, dst);
|
||||
}
|
||||
|
||||
intelEmitFillBlit(intel,
|
||||
dst->cpp,
|
||||
dst->pitch, dst->buffer, dst_offset,
|
||||
dstx, dsty, width, height, color);
|
||||
}
|
||||
|
||||
/* Attach to a pbo, discarding our data. Effectively zero-copy upload
|
||||
* the pbo's data.
|
||||
*/
|
||||
void
|
||||
intel_region_attach_pbo(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region,
|
||||
struct intel_buffer_object *pbo)
|
||||
{
|
||||
if (region->pbo == pbo)
|
||||
return;
|
||||
|
||||
/* If there is already a pbo attached, break the cow tie now.
|
||||
* Don't call intel_region_release_pbo() as that would
|
||||
* unnecessarily allocate a new buffer we would have to immediately
|
||||
* discard.
|
||||
*/
|
||||
if (region->pbo) {
|
||||
region->pbo->region = NULL;
|
||||
region->pbo = NULL;
|
||||
}
|
||||
|
||||
if (region->buffer) {
|
||||
driDeleteBuffers(1, ®ion->buffer);
|
||||
region->buffer = NULL;
|
||||
}
|
||||
|
||||
region->pbo = pbo;
|
||||
region->pbo->region = region;
|
||||
region->buffer = driBOReference(pbo->buffer);
|
||||
}
|
||||
|
||||
|
||||
/* Break the COW tie to the pbo. The pbo gets to keep the data.
|
||||
*/
|
||||
void
|
||||
intel_region_release_pbo(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region)
|
||||
{
|
||||
assert(region->buffer == region->pbo->buffer);
|
||||
region->pbo->region = NULL;
|
||||
region->pbo = NULL;
|
||||
driBOUnReference(region->buffer);
|
||||
region->buffer = NULL;
|
||||
|
||||
driGenBuffers(intelScreen->regionPool,
|
||||
"region", 1, ®ion->buffer, 64, 0, 0);
|
||||
driBOData(region->buffer,
|
||||
region->cpp * region->pitch * region->height, NULL, 0);
|
||||
}
|
||||
|
||||
/* Break the COW tie to the pbo. Both the pbo and the region end up
|
||||
* with a copy of the data.
|
||||
*/
|
||||
void
|
||||
intel_region_cow(intelScreenPrivate *intelScreen, struct intel_region *region)
|
||||
{
|
||||
struct intel_context *intel = intelScreenContext(intelScreen);
|
||||
struct intel_buffer_object *pbo = region->pbo;
|
||||
|
||||
if (intel == NULL)
|
||||
return;
|
||||
|
||||
intel_region_release_pbo(intelScreen, region);
|
||||
|
||||
assert(region->cpp * region->pitch * region->height == pbo->Base.Size);
|
||||
|
||||
DBG("%s (%d bytes)\n", __FUNCTION__, pbo->Base.Size);
|
||||
|
||||
/* Now blit from the texture buffer to the new buffer:
|
||||
*/
|
||||
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
|
||||
if (!intel->locked) {
|
||||
LOCK_HARDWARE(intel);
|
||||
intelEmitCopyBlit(intel,
|
||||
region->cpp,
|
||||
region->pitch,
|
||||
region->buffer, 0,
|
||||
region->pitch,
|
||||
pbo->buffer, 0,
|
||||
0, 0, 0, 0, region->pitch, region->height);
|
||||
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
UNLOCK_HARDWARE(intel);
|
||||
}
|
||||
else {
|
||||
intelEmitCopyBlit(intel,
|
||||
region->cpp,
|
||||
region->pitch,
|
||||
region->buffer, 0,
|
||||
region->pitch,
|
||||
pbo->buffer, 0,
|
||||
0, 0, 0, 0, region->pitch, region->height);
|
||||
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
}
|
||||
}
|
||||
|
||||
struct _DriBufferObject *
|
||||
intel_region_buffer(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region, GLuint flag)
|
||||
{
|
||||
if (region->pbo) {
|
||||
if (flag == INTEL_WRITE_PART)
|
||||
intel_region_cow(intelScreen, region);
|
||||
else if (flag == INTEL_WRITE_FULL)
|
||||
intel_region_release_pbo(intelScreen, region);
|
||||
}
|
||||
|
||||
return region->buffer;
|
||||
}
|
||||
142
src/mesa/drivers/dri/i915/intel_regions.h
Normal file
142
src/mesa/drivers/dri/i915/intel_regions.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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_screen.h"
|
||||
|
||||
struct intel_context;
|
||||
struct intel_buffer_object;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
struct _DriBufferObject *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 */
|
||||
|
||||
struct intel_buffer_object *pbo; /* zero-copy uploads */
|
||||
};
|
||||
|
||||
|
||||
/* Allocate a refcounted region. Pointers to regions should only be
|
||||
* copied by calling intel_reference_region().
|
||||
*/
|
||||
struct intel_region *intel_region_alloc(intelScreenPrivate *intelScreen,
|
||||
GLuint cpp,
|
||||
GLuint pitch, GLuint height);
|
||||
|
||||
void intel_region_reference(struct intel_region **dst,
|
||||
struct intel_region *src);
|
||||
|
||||
void intel_region_release(intelScreenPrivate *intelScreen,
|
||||
struct intel_region **ib);
|
||||
|
||||
extern struct intel_region
|
||||
*intel_region_create_static(intelScreenPrivate *intelScreen,
|
||||
GLuint mem_type,
|
||||
GLuint offset,
|
||||
void *virtual,
|
||||
GLuint cpp,
|
||||
GLuint pitch, GLuint height);
|
||||
extern void
|
||||
intel_region_update_static(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region,
|
||||
GLuint mem_type,
|
||||
GLuint offset,
|
||||
void *virtual,
|
||||
GLuint cpp, GLuint pitch, GLuint height);
|
||||
|
||||
|
||||
void intel_region_idle(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *ib);
|
||||
|
||||
/* Map/unmap regions. This is refcounted also:
|
||||
*/
|
||||
GLubyte *intel_region_map(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *ib);
|
||||
|
||||
void intel_region_unmap(intelScreenPrivate *intelScreen, struct intel_region *ib);
|
||||
|
||||
|
||||
/* Upload data to a rectangular sub-region
|
||||
*/
|
||||
void intel_region_data(intelScreenPrivate *intelScreen,
|
||||
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(intelScreenPrivate *intelScreen,
|
||||
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(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *dest,
|
||||
GLuint dest_offset,
|
||||
GLuint destx, GLuint desty,
|
||||
GLuint width, GLuint height, GLuint color);
|
||||
|
||||
/* Helpers for zerocopy uploads, particularly texture image uploads:
|
||||
*/
|
||||
void intel_region_attach_pbo(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region,
|
||||
struct intel_buffer_object *pbo);
|
||||
void intel_region_release_pbo(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region);
|
||||
void intel_region_cow(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region);
|
||||
|
||||
struct _DriBufferObject *intel_region_buffer(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region,
|
||||
GLuint flag);
|
||||
|
||||
#endif
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
#define HAVE_ELTS 0
|
||||
|
||||
static GLuint hw_prim[GL_POLYGON+1] = {
|
||||
static GLuint hw_prim[GL_POLYGON + 1] = {
|
||||
0,
|
||||
PRIM3D_LINELIST,
|
||||
PRIM3D_LINESTRIP,
|
||||
@@ -79,7 +79,7 @@ static GLuint hw_prim[GL_POLYGON+1] = {
|
||||
PRIM3D_POLY
|
||||
};
|
||||
|
||||
static const GLenum reduced_prim[GL_POLYGON+1] = {
|
||||
static const GLenum reduced_prim[GL_POLYGON + 1] = {
|
||||
GL_POINTS,
|
||||
GL_LINES,
|
||||
GL_LINES,
|
||||
@@ -92,7 +92,7 @@ static const GLenum reduced_prim[GL_POLYGON+1] = {
|
||||
GL_TRIANGLES
|
||||
};
|
||||
|
||||
static const int scale_prim[GL_POLYGON+1] = {
|
||||
static const int scale_prim[GL_POLYGON + 1] = {
|
||||
0, /* fallback case */
|
||||
1,
|
||||
2,
|
||||
@@ -106,24 +106,27 @@ 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));
|
||||
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] );
|
||||
intel->vtbl.reduced_primitive_state(intel, reduced_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() INTEL_FIREVERTICES(intel)
|
||||
|
||||
#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,8 +145,8 @@ do { \
|
||||
|
||||
/* Heuristic to choose between the two render paths:
|
||||
*/
|
||||
static GLboolean choose_render( intelContextPtr intel,
|
||||
struct vertex_buffer *VB )
|
||||
static GLboolean
|
||||
choose_render(struct intel_context *intel, struct vertex_buffer *VB)
|
||||
{
|
||||
int vertsz = intel->vertex_size;
|
||||
int cost_render = 0;
|
||||
@@ -154,7 +157,7 @@ static GLboolean choose_render( intelContextPtr intel,
|
||||
int rprim = intel->reduced_primitive;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0 ; i < VB->PrimitiveCount ; i++) {
|
||||
for (i = 0; i < VB->PrimitiveCount; i++) {
|
||||
GLuint prim = VB->Primitive[i].mode;
|
||||
GLuint length = VB->Primitive[i].count;
|
||||
|
||||
@@ -191,10 +194,10 @@ static GLboolean choose_render( intelContextPtr intel,
|
||||
}
|
||||
|
||||
|
||||
static GLboolean intel_run_render( GLcontext *ctx,
|
||||
struct tnl_pipeline_stage *stage )
|
||||
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;
|
||||
@@ -202,17 +205,15 @@ static GLboolean intel_run_render( GLcontext *ctx,
|
||||
/* Don't handle clipping or indexed vertices.
|
||||
*/
|
||||
if (intel->RenderIndex != 0 ||
|
||||
!intel_validate_render( ctx, VB ) ||
|
||||
!choose_render( intel, VB )) {
|
||||
!intel_validate_render(ctx, VB) || !choose_render(intel, VB)) {
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
tnl->clipspace.new_inputs |= VERT_BIT_POS;
|
||||
|
||||
tnl->Driver.Render.Start( ctx );
|
||||
tnl->Driver.Render.Start(ctx);
|
||||
|
||||
for (i = 0 ; i < VB->PrimitiveCount ; i++)
|
||||
{
|
||||
for (i = 0; i < VB->PrimitiveCount; i++) {
|
||||
GLuint prim = VB->Primitive[i].mode;
|
||||
GLuint start = VB->Primitive[i].start;
|
||||
GLuint length = VB->Primitive[i].count;
|
||||
@@ -220,17 +221,18 @@ static GLboolean intel_run_render( GLcontext *ctx,
|
||||
if (!length)
|
||||
continue;
|
||||
|
||||
intel_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
|
||||
prim );
|
||||
intel_render_tab_verts[prim & PRIM_MODE_MASK] (ctx, start,
|
||||
start + length, prim);
|
||||
}
|
||||
|
||||
tnl->Driver.Render.Finish( ctx );
|
||||
tnl->Driver.Render.Finish(ctx);
|
||||
|
||||
INTEL_FIREVERTICES(intel);
|
||||
|
||||
return GL_FALSE; /* finished the pipe */
|
||||
}
|
||||
|
||||
const struct tnl_pipeline_stage _intel_render_stage =
|
||||
{
|
||||
const struct tnl_pipeline_stage _intel_render_stage = {
|
||||
"intel render",
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
|
||||
void
|
||||
matrix23Set(struct matrix23 *m,
|
||||
int m00, int m01, int m02,
|
||||
int m10, int m11, int m12)
|
||||
int m00, int m01, int m02, int m10, int m11, int m12)
|
||||
{
|
||||
m->m00 = m00; m->m01 = m01; m->m02 = m02;
|
||||
m->m10 = m10; m->m11 = m11; m->m12 = m12;
|
||||
m->m00 = m00;
|
||||
m->m01 = m01;
|
||||
m->m02 = m02;
|
||||
m->m10 = m10;
|
||||
m->m11 = m11;
|
||||
m->m12 = m12;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +79,8 @@ matrix23TransformDistance(const struct matrix23 *m, int *xDist, int *yDist)
|
||||
* Transform the rect defined by (x, y, w, h) by m.
|
||||
*/
|
||||
void
|
||||
matrix23TransformRect(const struct matrix23 *m, int *x, int *y, int *w, int *h)
|
||||
matrix23TransformRect(const struct matrix23 *m, int *x, int *y, int *w,
|
||||
int *h)
|
||||
{
|
||||
int x0 = *x, y0 = *y;
|
||||
int x1 = *x + *w, y1 = *y;
|
||||
@@ -117,7 +121,7 @@ matrix23Rotate(struct matrix23 *m, int width, int height, int angle)
|
||||
matrix23Set(m, 0, -1, height, 1, 0, 0);
|
||||
break;
|
||||
default:
|
||||
/*abort()*/;
|
||||
/*abort() */ ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,16 +133,24 @@ void
|
||||
matrix23Flip(struct matrix23 *m, int width, int height, int xflip, int yflip)
|
||||
{
|
||||
if (xflip) {
|
||||
m->m00 = -1; m->m01 = 0; m->m02 = width - 1;
|
||||
m->m00 = -1;
|
||||
m->m01 = 0;
|
||||
m->m02 = width - 1;
|
||||
}
|
||||
else {
|
||||
m->m00 = 1; m->m01 = 0; m->m02 = 0;
|
||||
m->m00 = 1;
|
||||
m->m01 = 0;
|
||||
m->m02 = 0;
|
||||
}
|
||||
if (yflip) {
|
||||
m->m10 = 0; m->m11 = -1; m->m12 = height - 1;
|
||||
m->m10 = 0;
|
||||
m->m11 = -1;
|
||||
m->m12 = height - 1;
|
||||
}
|
||||
else {
|
||||
m->m10 = 0; m->m11 = 1; m->m12 = 0;
|
||||
m->m10 = 0;
|
||||
m->m11 = 1;
|
||||
m->m12 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,10 +185,14 @@ main(int argc, char *argv[])
|
||||
int coords[4][2];
|
||||
|
||||
/* four corner coords to test with */
|
||||
coords[0][0] = 0; coords[0][1] = 0;
|
||||
coords[1][0] = width-1; coords[1][1] = 0;
|
||||
coords[2][0] = width-1; coords[2][1] = height-1;
|
||||
coords[3][0] = 0; coords[3][1] = height-1;
|
||||
coords[0][0] = 0;
|
||||
coords[0][1] = 0;
|
||||
coords[1][0] = width - 1;
|
||||
coords[1][1] = 0;
|
||||
coords[2][0] = width - 1;
|
||||
coords[2][1] = height - 1;
|
||||
coords[3][0] = 0;
|
||||
coords[3][1] = height - 1;
|
||||
|
||||
|
||||
for (rot = 0; rot < 360; rot += 90) {
|
||||
|
||||
@@ -11,11 +11,9 @@ struct matrix23
|
||||
|
||||
extern void
|
||||
matrix23Set(struct matrix23 *m,
|
||||
int m00, int m01, int m02,
|
||||
int m10, int m11, int m12);
|
||||
int m00, int m01, int m02, int m10, int m11, int m12);
|
||||
|
||||
extern void
|
||||
matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y);
|
||||
extern void matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y);
|
||||
|
||||
extern void
|
||||
matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y);
|
||||
|
||||
@@ -38,46 +38,47 @@
|
||||
|
||||
#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"
|
||||
#include "dri_bufpool.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
PUBLIC const char __driConfigOptions[] =
|
||||
DRI_CONF_BEGIN
|
||||
DRI_CONF_SECTION_PERFORMANCE
|
||||
DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
|
||||
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
|
||||
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
|
||||
DRI_CONF_SECTION_END
|
||||
DRI_CONF_SECTION_QUALITY
|
||||
DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
|
||||
DRI_CONF_FORCE_S3TC_ENABLE(false)
|
||||
DRI_CONF_ALLOW_LARGE_TEXTURES(1)
|
||||
DRI_CONF_SECTION_END
|
||||
DRI_CONF_END;
|
||||
const GLuint __driNConfigOptions = 4;
|
||||
DRI_CONF_SECTION_END DRI_CONF_END;
|
||||
const GLuint __driNConfigOptions = 4;
|
||||
|
||||
#ifdef USE_NEW_INTERFACE
|
||||
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
|
||||
#endif /*USE_NEW_INTERFACE*/
|
||||
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
|
||||
#endif /*USE_NEW_INTERFACE */
|
||||
|
||||
extern const struct dri_extension card_extensions[];
|
||||
extern const struct dri_extension card_extensions[];
|
||||
|
||||
/**
|
||||
* Map all the memory regions described by the screen.
|
||||
* \return GL_TRUE if success, GL_FALSE if error.
|
||||
*/
|
||||
GLboolean
|
||||
intelMapScreenRegions(__DRIscreenPrivate *sPriv)
|
||||
intelMapScreenRegions(__DRIscreenPrivate * sPriv)
|
||||
{
|
||||
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
|
||||
intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
|
||||
|
||||
if (intelScreen->front.handle) {
|
||||
if (drmMap(sPriv->fd,
|
||||
intelScreen->front.handle,
|
||||
intelScreen->front.size,
|
||||
(drmAddress *)&intelScreen->front.map) != 0) {
|
||||
(drmAddress *) & intelScreen->front.map) != 0) {
|
||||
_mesa_problem(NULL, "drmMap(frontbuffer) failed!");
|
||||
return GL_FALSE;
|
||||
}
|
||||
@@ -86,42 +87,140 @@ intelMapScreenRegions(__DRIscreenPrivate *sPriv)
|
||||
_mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!");
|
||||
}
|
||||
|
||||
_mesa_printf("Back 0x%08x ", intelScreen->back.handle);
|
||||
if (drmMap(sPriv->fd,
|
||||
intelScreen->back.handle,
|
||||
intelScreen->back.size,
|
||||
(drmAddress *)&intelScreen->back.map) != 0) {
|
||||
(drmAddress *) & intelScreen->back.map) != 0) {
|
||||
intelUnmapScreenRegions(intelScreen);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
_mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);
|
||||
if (drmMap(sPriv->fd,
|
||||
intelScreen->depth.handle,
|
||||
intelScreen->depth.size,
|
||||
(drmAddress *)&intelScreen->depth.map) != 0) {
|
||||
(drmAddress *) & intelScreen->depth.map) != 0) {
|
||||
intelUnmapScreenRegions(intelScreen);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
_mesa_printf("TEX 0x%08x ", intelScreen->tex.handle);
|
||||
if (drmMap(sPriv->fd,
|
||||
intelScreen->tex.handle,
|
||||
intelScreen->tex.size,
|
||||
(drmAddress *)&intelScreen->tex.map) != 0) {
|
||||
(drmAddress *) & intelScreen->tex.map) != 0) {
|
||||
intelUnmapScreenRegions(intelScreen);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (0)
|
||||
printf("Mappings: front: %p back: %p depth: %p tex: %p\n",
|
||||
intelScreen->front.map,
|
||||
intelScreen->back.map,
|
||||
intelScreen->depth.map,
|
||||
intelScreen->tex.map);
|
||||
intelScreen->depth.map, intelScreen->tex.map);
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static struct intel_region *
|
||||
intel_recreate_static(intelScreenPrivate *intelScreen,
|
||||
struct intel_region *region,
|
||||
GLuint mem_type,
|
||||
GLuint offset,
|
||||
void *virtual,
|
||||
GLuint cpp, GLuint pitch, GLuint height)
|
||||
{
|
||||
if (region) {
|
||||
intel_region_update_static(intelScreen, region, mem_type, offset,
|
||||
virtual, cpp, pitch, height);
|
||||
} else {
|
||||
region = intel_region_create_static(intelScreen, mem_type, offset,
|
||||
virtual, cpp, pitch, height);
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
|
||||
/* Create intel_region structs to describe the static front,back,depth
|
||||
* buffers created by the xserver.
|
||||
*
|
||||
* Although FBO's mean we now no longer use these as render targets in
|
||||
* all circumstances, they won't go away until the back and depth
|
||||
* buffers become private, and the front and rotated buffers will
|
||||
* remain even then.
|
||||
*
|
||||
* Note that these don't allocate video memory, just describe
|
||||
* allocations alread made by the X server.
|
||||
*/
|
||||
static void
|
||||
intel_recreate_static_regions(intelScreenPrivate *intelScreen)
|
||||
{
|
||||
intelScreen->front_region =
|
||||
intel_recreate_static(intelScreen,
|
||||
intelScreen->front_region,
|
||||
DRM_BO_FLAG_MEM_TT,
|
||||
intelScreen->front.offset,
|
||||
intelScreen->front.map,
|
||||
intelScreen->cpp,
|
||||
intelScreen->front.pitch / intelScreen->cpp,
|
||||
intelScreen->height);
|
||||
|
||||
intelScreen->rotated_region =
|
||||
intel_recreate_static(intelScreen,
|
||||
intelScreen->rotated_region,
|
||||
DRM_BO_FLAG_MEM_TT,
|
||||
intelScreen->rotated.offset,
|
||||
intelScreen->rotated.map,
|
||||
intelScreen->cpp,
|
||||
intelScreen->rotated.pitch /
|
||||
intelScreen->cpp, intelScreen->height);
|
||||
|
||||
|
||||
intelScreen->back_region =
|
||||
intel_recreate_static(intelScreen,
|
||||
intelScreen->back_region,
|
||||
DRM_BO_FLAG_MEM_TT,
|
||||
intelScreen->back.offset,
|
||||
intelScreen->back.map,
|
||||
intelScreen->cpp,
|
||||
intelScreen->back.pitch / intelScreen->cpp,
|
||||
intelScreen->height);
|
||||
|
||||
/* Still assuming front.cpp == depth.cpp
|
||||
*/
|
||||
intelScreen->depth_region =
|
||||
intel_recreate_static(intelScreen,
|
||||
intelScreen->depth_region,
|
||||
DRM_BO_FLAG_MEM_TT,
|
||||
intelScreen->depth.offset,
|
||||
intelScreen->depth.map,
|
||||
intelScreen->cpp,
|
||||
intelScreen->depth.pitch / intelScreen->cpp,
|
||||
intelScreen->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the information in the sarea to update the screen parameters
|
||||
* related to screen rotation. Needs to be called locked.
|
||||
*/
|
||||
void
|
||||
intelUnmapScreenRegions(intelScreenPrivate *intelScreen)
|
||||
intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
|
||||
{
|
||||
intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
|
||||
|
||||
intelUnmapScreenRegions(intelScreen);
|
||||
intelUpdateScreenFromSAREA(intelScreen, sarea);
|
||||
if (!intelMapScreenRegions(sPriv)) {
|
||||
fprintf(stderr, "ERROR Remapping screen regions!!!\n");
|
||||
}
|
||||
intel_recreate_static_regions(intelScreen);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
intelUnmapScreenRegions(intelScreenPrivate * intelScreen)
|
||||
{
|
||||
#define REALLY_UNMAP 1
|
||||
if (intelScreen->front.map) {
|
||||
@@ -154,9 +253,8 @@ intelUnmapScreenRegions(intelScreenPrivate *intelScreen)
|
||||
|
||||
|
||||
static void
|
||||
intelPrintDRIInfo(intelScreenPrivate *intelScreen,
|
||||
__DRIscreenPrivate *sPriv,
|
||||
I830DRIPtr gDRIPriv)
|
||||
intelPrintDRIInfo(intelScreenPrivate * intelScreen,
|
||||
__DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
|
||||
{
|
||||
fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
|
||||
intelScreen->front.size, intelScreen->front.offset,
|
||||
@@ -177,9 +275,10 @@ intelPrintDRIInfo(intelScreenPrivate *intelScreen,
|
||||
|
||||
|
||||
static void
|
||||
intelPrintSAREA(const drmI830Sarea *sarea)
|
||||
intelPrintSAREA(const drmI830Sarea * sarea)
|
||||
{
|
||||
fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, sarea->height);
|
||||
fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width,
|
||||
sarea->height);
|
||||
fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
|
||||
fprintf(stderr,
|
||||
"SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
|
||||
@@ -193,8 +292,7 @@ intelPrintSAREA(const drmI830Sarea *sarea)
|
||||
sarea->depth_offset, sarea->depth_size,
|
||||
(unsigned) sarea->depth_handle);
|
||||
fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
|
||||
sarea->tex_offset, sarea->tex_size,
|
||||
(unsigned) sarea->tex_handle);
|
||||
sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
|
||||
fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
|
||||
fprintf(stderr,
|
||||
"SAREA: rotated offset: 0x%08x size: 0x%x\n",
|
||||
@@ -208,8 +306,8 @@ intelPrintSAREA(const drmI830Sarea *sarea)
|
||||
* information in the SAREA. This function updates those parameters.
|
||||
*/
|
||||
void
|
||||
intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen,
|
||||
drmI830Sarea *sarea)
|
||||
intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
|
||||
drmI830Sarea * sarea)
|
||||
{
|
||||
intelScreen->width = sarea->width;
|
||||
intelScreen->height = sarea->height;
|
||||
@@ -248,58 +346,87 @@ intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen,
|
||||
}
|
||||
|
||||
|
||||
static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
static GLboolean
|
||||
intelInitDriver(__DRIscreenPrivate * sPriv)
|
||||
{
|
||||
intelScreenPrivate *intelScreen;
|
||||
I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv;
|
||||
I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
|
||||
drmI830Sarea *sarea;
|
||||
PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
|
||||
(PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension"));
|
||||
void * const psc = sPriv->psc->screenConfigs;
|
||||
(PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->
|
||||
getProcAddress("glxEnableExtension"));
|
||||
void *const psc = sPriv->psc->screenConfigs;
|
||||
|
||||
if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
|
||||
fprintf(stderr,"\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
|
||||
fprintf(stderr,
|
||||
"\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
/* Allocate the private area */
|
||||
intelScreen = (intelScreenPrivate *)CALLOC(sizeof(intelScreenPrivate));
|
||||
intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate));
|
||||
if (!intelScreen) {
|
||||
fprintf(stderr,"\nERROR! Allocating private area failed\n");
|
||||
fprintf(stderr, "\nERROR! Allocating private area failed\n");
|
||||
return GL_FALSE;
|
||||
}
|
||||
/* parse information in __driConfigOptions */
|
||||
driParseOptionInfo (&intelScreen->optionCache,
|
||||
driParseOptionInfo(&intelScreen->optionCache,
|
||||
__driConfigOptions, __driNConfigOptions);
|
||||
|
||||
intelScreen->driScrnPriv = sPriv;
|
||||
sPriv->private = (void *)intelScreen;
|
||||
sPriv->private = (void *) intelScreen;
|
||||
intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset;
|
||||
sarea = (drmI830Sarea *)
|
||||
(((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
|
||||
(((GLubyte *) sPriv->pSAREA) + intelScreen->sarea_priv_offset);
|
||||
|
||||
intelScreen->deviceID = gDRIPriv->deviceID;
|
||||
intelScreen->mem = gDRIPriv->mem;
|
||||
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;
|
||||
case 16:
|
||||
intelScreen->fbFormat = DV_PF_565;
|
||||
break;
|
||||
case 32:
|
||||
intelScreen->fbFormat = DV_PF_8888;
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
|
||||
intelUpdateScreenFromSAREA(intelScreen, sarea);
|
||||
|
||||
if (0)
|
||||
intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
|
||||
|
||||
if (!intelMapScreenRegions(sPriv)) {
|
||||
fprintf(stderr,"\nERROR! mapping regions\n");
|
||||
fprintf(stderr, "\nERROR! mapping regions\n");
|
||||
_mesa_free(intelScreen);
|
||||
sPriv->private = NULL;
|
||||
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;
|
||||
intelScreen->tex.size = gDRIPriv->textureSize;
|
||||
|
||||
#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 (1)
|
||||
intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
|
||||
|
||||
intelScreen->drmMinor = sPriv->drmMinor;
|
||||
|
||||
/* Determine if IRQs are active? */
|
||||
@@ -310,7 +437,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
gp.param = I830_PARAM_IRQ_ACTIVE;
|
||||
gp.value = &intelScreen->irq_active;
|
||||
|
||||
ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
|
||||
ret = drmCommandWriteRead(sPriv->fd, DRM_I830_GETPARAM,
|
||||
&gp, sizeof(gp));
|
||||
if (ret) {
|
||||
fprintf(stderr, "drmI830GetParam: %d\n", ret);
|
||||
@@ -326,7 +453,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
gp.param = I830_PARAM_ALLOW_BATCHBUFFER;
|
||||
gp.value = &intelScreen->allow_batchbuffer;
|
||||
|
||||
ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM,
|
||||
ret = drmCommandWriteRead(sPriv->fd, DRM_I830_GETPARAM,
|
||||
&gp, sizeof(gp));
|
||||
if (ret) {
|
||||
fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret);
|
||||
@@ -335,116 +462,132 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
|
||||
}
|
||||
|
||||
if (glx_enable_extension != NULL) {
|
||||
(*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
|
||||
(*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
|
||||
(*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
|
||||
(*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
|
||||
(*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
|
||||
(*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
|
||||
(*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" );
|
||||
(*glx_enable_extension) (psc, "GLX_SGI_swap_control");
|
||||
(*glx_enable_extension) (psc, "GLX_SGI_video_sync");
|
||||
(*glx_enable_extension) (psc, "GLX_MESA_swap_control");
|
||||
(*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage");
|
||||
(*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
|
||||
}
|
||||
|
||||
sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA;
|
||||
sPriv->psc->freeMemory = (void *) intelFreeMemoryMESA;
|
||||
sPriv->psc->memoryOffset = (void *) intelGetMemoryOffsetMESA;
|
||||
intelScreen->regionPool = driDRMPoolInit(sPriv->fd);
|
||||
if (!intelScreen->regionPool)
|
||||
return GL_FALSE;
|
||||
intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
|
||||
if (!intelScreen->staticPool)
|
||||
return GL_FALSE;
|
||||
intelScreen->texPool = intelScreen->regionPool;
|
||||
intelScreen->batchPool = driBatchPoolInit(sPriv->fd,
|
||||
DRM_BO_FLAG_EXE |
|
||||
DRM_BO_FLAG_MEM_TT |
|
||||
DRM_BO_FLAG_MEM_LOCAL,
|
||||
4096, 100, 5);
|
||||
intel_recreate_static_regions(intelScreen);
|
||||
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void intelDestroyScreen(__DRIscreenPrivate *sPriv)
|
||||
static void
|
||||
intelDestroyScreen(__DRIscreenPrivate * sPriv)
|
||||
{
|
||||
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
|
||||
intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private;
|
||||
|
||||
intelUnmapScreenRegions(intelScreen);
|
||||
|
||||
driPoolTakeDown(intelScreen->regionPool);
|
||||
driPoolTakeDown(intelScreen->staticPool);
|
||||
driPoolTakeDown(intelScreen->batchPool);
|
||||
FREE(intelScreen);
|
||||
sPriv->private = NULL;
|
||||
}
|
||||
|
||||
|
||||
static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
|
||||
__DRIdrawablePrivate *driDrawPriv,
|
||||
const __GLcontextModes *mesaVis,
|
||||
GLboolean isPixmap )
|
||||
/**
|
||||
* 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, GLboolean isPixmap)
|
||||
{
|
||||
intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private;
|
||||
|
||||
if (isPixmap) {
|
||||
return GL_FALSE; /* not implemented */
|
||||
} else {
|
||||
}
|
||||
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,
|
||||
screen->front.map,
|
||||
struct intel_renderbuffer *frontRb
|
||||
= intel_create_renderbuffer(rgbFormat,
|
||||
screen->width, screen->height,
|
||||
screen->front.offset,
|
||||
screen->front.pitch,
|
||||
screen->cpp,
|
||||
screen->front.offset, screen->front.pitch,
|
||||
driDrawPriv);
|
||||
intelSetSpanFunctions(frontRb, mesaVis);
|
||||
screen->front.map);
|
||||
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,
|
||||
struct intel_renderbuffer *backRb
|
||||
= intel_create_renderbuffer(rgbFormat,
|
||||
screen->width, screen->height,
|
||||
screen->back.offset,
|
||||
screen->back.pitch,
|
||||
screen->cpp,
|
||||
screen->back.offset, screen->back.pitch,
|
||||
driDrawPriv);
|
||||
intelSetSpanFunctions(backRb, mesaVis);
|
||||
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);
|
||||
}
|
||||
|
||||
_mesa_add_soft_renderbuffers(fb,
|
||||
GL_FALSE, /* color */
|
||||
GL_FALSE, /* depth */
|
||||
swStencil,
|
||||
mesaVis->accumRedBits > 0,
|
||||
GL_FALSE, /* alpha */
|
||||
GL_FALSE /* aux */);
|
||||
/* now add any/all software-based renderbuffers we may need */
|
||||
_mesa_add_soft_renderbuffers(fb, GL_FALSE, /* never sw color */
|
||||
GL_FALSE, /* never sw depth */
|
||||
swStencil, mesaVis->accumRedBits > 0, GL_FALSE, /* never sw alpha */
|
||||
GL_FALSE /* never sw aux */ );
|
||||
driDrawPriv->driverPrivate = (void *) fb;
|
||||
|
||||
return (driDrawPriv->driverPrivate != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
|
||||
static void
|
||||
intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
|
||||
{
|
||||
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
|
||||
}
|
||||
@@ -454,13 +597,13 @@ static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
|
||||
* Get information about previous buffer swaps.
|
||||
*/
|
||||
static int
|
||||
intelGetSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
|
||||
intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
|
||||
{
|
||||
intelContextPtr intel;
|
||||
struct intel_context *intel;
|
||||
|
||||
if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
|
||||
if ((dPriv == NULL) || (dPriv->driContextPriv == NULL)
|
||||
|| (dPriv->driContextPriv->driverPrivate == NULL)
|
||||
|| (sInfo == NULL) ) {
|
||||
|| (sInfo == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -470,7 +613,7 @@ intelGetSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
|
||||
sInfo->swap_missed_count = intel->swap_missed_count;
|
||||
|
||||
sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
|
||||
? driCalculateSwapUsage( dPriv, 0, intel->swap_missed_ust )
|
||||
? driCalculateSwapUsage(dPriv, 0, intel->swap_missed_ust)
|
||||
: 0.0;
|
||||
|
||||
return 0;
|
||||
@@ -481,38 +624,39 @@ intelGetSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
|
||||
* init-designated function to register chipids and createcontext
|
||||
* functions.
|
||||
*/
|
||||
extern GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
extern GLboolean i830CreateContext(const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
void *sharedContextPrivate);
|
||||
|
||||
extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
extern GLboolean i915CreateContext(const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
void *sharedContextPrivate);
|
||||
|
||||
|
||||
|
||||
|
||||
static GLboolean intelCreateContext( const __GLcontextModes *mesaVis,
|
||||
__DRIcontextPrivate *driContextPriv,
|
||||
static GLboolean
|
||||
intelCreateContext(const __GLcontextModes * mesaVis,
|
||||
__DRIcontextPrivate * driContextPriv,
|
||||
void *sharedContextPrivate)
|
||||
{
|
||||
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
|
||||
intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
|
||||
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:
|
||||
case PCI_CHIP_I865_G:
|
||||
return i830CreateContext( mesaVis, driContextPriv,
|
||||
sharedContextPrivate );
|
||||
return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
|
||||
|
||||
case PCI_CHIP_I915_G:
|
||||
case PCI_CHIP_I915_GM:
|
||||
case PCI_CHIP_I945_G:
|
||||
case PCI_CHIP_I945_GM:
|
||||
return i915CreateContext( mesaVis, driContextPriv,
|
||||
sharedContextPrivate );
|
||||
return i915CreateContext(mesaVis, driContextPriv, sharedContextPrivate);
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID);
|
||||
@@ -541,11 +685,11 @@ static const struct __DriverAPIRec intelAPI = {
|
||||
|
||||
|
||||
static __GLcontextModes *
|
||||
intelFillInModes( unsigned pixel_bits, unsigned depth_bits,
|
||||
unsigned stencil_bits, GLboolean have_back_buffer )
|
||||
intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
|
||||
unsigned stencil_bits, GLboolean have_back_buffer)
|
||||
{
|
||||
__GLcontextModes * modes;
|
||||
__GLcontextModes * m;
|
||||
__GLcontextModes *modes;
|
||||
__GLcontextModes *m;
|
||||
unsigned num_modes;
|
||||
unsigned depth_buffer_factor;
|
||||
unsigned back_buffer_factor;
|
||||
@@ -580,7 +724,7 @@ intelFillInModes( unsigned pixel_bits, unsigned depth_bits,
|
||||
|
||||
num_modes = depth_buffer_factor * back_buffer_factor * 4;
|
||||
|
||||
if ( pixel_bits == 16 ) {
|
||||
if (pixel_bits == 16) {
|
||||
fb_format = GL_RGB;
|
||||
fb_type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
}
|
||||
@@ -589,29 +733,31 @@ intelFillInModes( unsigned pixel_bits, unsigned depth_bits,
|
||||
fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
|
||||
modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
|
||||
modes =
|
||||
(*dri_interface->createContextModes) (num_modes,
|
||||
sizeof(__GLcontextModes));
|
||||
m = modes;
|
||||
if ( ! driFillInModes( & m, fb_format, fb_type,
|
||||
depth_bits_array, stencil_bits_array, depth_buffer_factor,
|
||||
back_buffer_modes, back_buffer_factor,
|
||||
GLX_TRUE_COLOR ) ) {
|
||||
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
|
||||
__func__, __LINE__ );
|
||||
if (!driFillInModes(&m, fb_format, fb_type,
|
||||
depth_bits_array, stencil_bits_array,
|
||||
depth_buffer_factor, back_buffer_modes,
|
||||
back_buffer_factor, GLX_TRUE_COLOR)) {
|
||||
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
|
||||
__LINE__);
|
||||
return NULL;
|
||||
}
|
||||
if ( ! driFillInModes( & m, fb_format, fb_type,
|
||||
depth_bits_array, stencil_bits_array, depth_buffer_factor,
|
||||
back_buffer_modes, back_buffer_factor,
|
||||
GLX_DIRECT_COLOR ) ) {
|
||||
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
|
||||
__func__, __LINE__ );
|
||||
if (!driFillInModes(&m, fb_format, fb_type,
|
||||
depth_bits_array, stencil_bits_array,
|
||||
depth_buffer_factor, back_buffer_modes,
|
||||
back_buffer_factor, GLX_DIRECT_COLOR)) {
|
||||
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
|
||||
__LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Mark the visual as slow if there are "fake" stencil bits.
|
||||
*/
|
||||
for ( m = modes ; m != NULL ; m = m->next ) {
|
||||
if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
|
||||
for (m = modes; m != NULL; m = m->next) {
|
||||
if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
|
||||
m->visualRating = GLX_SLOW_CONFIG;
|
||||
}
|
||||
}
|
||||
@@ -630,8 +776,9 @@ intelFillInModes( unsigned pixel_bits, unsigned depth_bits,
|
||||
* \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
|
||||
* failure.
|
||||
*/
|
||||
PUBLIC
|
||||
void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
|
||||
PUBLIC void *
|
||||
__driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
|
||||
__DRIscreen * psc,
|
||||
const __GLcontextModes * modes,
|
||||
const __DRIversion * ddx_version,
|
||||
const __DRIversion * dri_version,
|
||||
@@ -640,20 +787,19 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc
|
||||
drmAddress pSAREA, int fd,
|
||||
int internal_api_version,
|
||||
const __DRIinterfaceMethods * interface,
|
||||
__GLcontextModes ** driver_modes )
|
||||
|
||||
__GLcontextModes ** driver_modes)
|
||||
{
|
||||
__DRIscreenPrivate *psp;
|
||||
static const __DRIversion ddx_expected = { 1, 5, 0 };
|
||||
static const __DRIversion dri_expected = { 4, 0, 0 };
|
||||
static const __DRIversion drm_expected = { 1, 4, 0 };
|
||||
static const __DRIversion drm_expected = { 1, 6, 0 };
|
||||
|
||||
dri_interface = interface;
|
||||
|
||||
if ( ! driCheckDriDdxDrmVersions2( "i915",
|
||||
dri_version, & dri_expected,
|
||||
ddx_version, & ddx_expected,
|
||||
drm_version, & drm_expected ) ) {
|
||||
if (!driCheckDriDdxDrmVersions2("i915",
|
||||
dri_version, &dri_expected,
|
||||
ddx_version, &ddx_expected,
|
||||
drm_version, &drm_expected)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -661,12 +807,11 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc
|
||||
ddx_version, dri_version, drm_version,
|
||||
frame_buffer, pSAREA, fd,
|
||||
internal_api_version, &intelAPI);
|
||||
if ( psp != NULL ) {
|
||||
if (psp != NULL) {
|
||||
I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
|
||||
*driver_modes = intelFillInModes( dri_priv->cpp * 8,
|
||||
*driver_modes = intelFillInModes(dri_priv->cpp * 8,
|
||||
(dri_priv->cpp == 2) ? 16 : 24,
|
||||
(dri_priv->cpp == 2) ? 0 : 8,
|
||||
1 );
|
||||
(dri_priv->cpp == 2) ? 0 : 8, 1);
|
||||
|
||||
/* Calling driInitExtensions here, with a NULL context pointer, does not actually
|
||||
* enable the extensions. It just makes sure that all the dispatch offsets for all
|
||||
@@ -676,8 +821,24 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc
|
||||
*
|
||||
* Hello chicken. Hello egg. How are you two today?
|
||||
*/
|
||||
driInitExtensions( NULL, card_extensions, GL_FALSE );
|
||||
driInitExtensions(NULL, card_extensions, GL_FALSE);
|
||||
}
|
||||
|
||||
return (void *) psp;
|
||||
}
|
||||
|
||||
struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen)
|
||||
{
|
||||
/*
|
||||
* This should probably change to have the screen allocate a dummy
|
||||
* context at screen creation. For now just use the current context.
|
||||
*/
|
||||
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
if (ctx == NULL) {
|
||||
_mesa_problem(NULL, "No current context in intelScreenContext\n");
|
||||
return NULL;
|
||||
}
|
||||
return intel_context(ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,14 +29,17 @@
|
||||
#define _INTEL_INIT_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "xmlconfig.h"
|
||||
#include "dri_util.h"
|
||||
#include "intel_rotate.h"
|
||||
#include "i830_common.h"
|
||||
#include "xmlconfig.h"
|
||||
#include "dri_bufpool.h"
|
||||
|
||||
|
||||
/* This roughly corresponds to a gl_renderbuffer (Mesa 6.4) */
|
||||
typedef struct {
|
||||
/* XXX: change name or eliminate to avoid conflict with "struct
|
||||
* intel_region"!!!
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
drm_handle_t handle;
|
||||
drmSize size; /* region size in bytes */
|
||||
char *map; /* memory map */
|
||||
@@ -52,13 +55,19 @@ typedef struct
|
||||
intelRegion depth;
|
||||
intelRegion tex;
|
||||
|
||||
struct intel_region *front_region;
|
||||
struct intel_region *back_region;
|
||||
struct intel_region *depth_region;
|
||||
struct intel_region *rotated_region;
|
||||
|
||||
int deviceID;
|
||||
int width;
|
||||
int height;
|
||||
int mem; /* unused */
|
||||
|
||||
int cpp; /* for front and back buffers */
|
||||
int fbFormat;
|
||||
/* int bitsPerPixel; */
|
||||
int fbFormat; /* XXX FBO: this is obsolete - remove after i830 updates */
|
||||
|
||||
int logTextureGranularity;
|
||||
|
||||
@@ -79,34 +88,44 @@ typedef struct
|
||||
* Configuration cache with default values for all contexts
|
||||
*/
|
||||
driOptionCache optionCache;
|
||||
struct _DriBufferPool *batchPool;
|
||||
struct _DriBufferPool *texPool;
|
||||
struct _DriBufferPool *regionPool;
|
||||
struct _DriBufferPool *staticPool;
|
||||
} intelScreenPrivate;
|
||||
|
||||
|
||||
extern GLboolean
|
||||
intelMapScreenRegions(__DRIscreenPrivate *sPriv);
|
||||
|
||||
extern GLboolean intelMapScreenRegions(__DRIscreenPrivate * sPriv);
|
||||
|
||||
extern void intelUnmapScreenRegions(intelScreenPrivate * intelScreen);
|
||||
|
||||
extern void
|
||||
intelUnmapScreenRegions(intelScreenPrivate *intelScreen);
|
||||
intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,
|
||||
drmI830Sarea * sarea);
|
||||
|
||||
extern void
|
||||
intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen,
|
||||
drmI830Sarea *sarea);
|
||||
extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv);
|
||||
|
||||
extern void
|
||||
intelDestroyContext(__DRIcontextPrivate *driContextPriv);
|
||||
extern GLboolean intelUnbindContext(__DRIcontextPrivate * driContextPriv);
|
||||
|
||||
extern GLboolean
|
||||
intelUnbindContext(__DRIcontextPrivate *driContextPriv);
|
||||
intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
|
||||
__DRIdrawablePrivate * driDrawPriv,
|
||||
__DRIdrawablePrivate * driReadPriv);
|
||||
|
||||
extern GLboolean
|
||||
intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
|
||||
__DRIdrawablePrivate *driDrawPriv,
|
||||
__DRIdrawablePrivate *driReadPriv);
|
||||
extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
|
||||
|
||||
extern void
|
||||
intelSwapBuffers(__DRIdrawablePrivate *dPriv);
|
||||
intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h);
|
||||
|
||||
extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags,
|
||||
unsigned long bufSize,
|
||||
unsigned numBufs,
|
||||
unsigned checkDelayed);
|
||||
|
||||
extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen);
|
||||
|
||||
extern void
|
||||
intelCopySubBuffer( __DRIdrawablePrivate *dPriv, int x, int y, int w, int h );
|
||||
intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,195 +30,346 @@
|
||||
#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; \
|
||||
GLuint height = dPriv->h; \
|
||||
char *buf = (char *) drb->Base.Data + \
|
||||
dPriv->x * drb->cpp + \
|
||||
dPriv->y * pitch; \
|
||||
GLushort p; \
|
||||
(void) buf; (void) p
|
||||
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; \
|
||||
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; \
|
||||
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
|
||||
*/
|
||||
/**
|
||||
** 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 = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
|
||||
tmp &= 0xff000000; \
|
||||
tmp |= (d) & 0xffffff; \
|
||||
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
|
||||
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"
|
||||
|
||||
|
||||
/**
|
||||
** 8-bit stencil function (XXX FBO: This is obsolete)
|
||||
**/
|
||||
#define WRITE_STENCIL( _x, _y, d ) { \
|
||||
GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
|
||||
GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch]; \
|
||||
tmp &= 0xffffff; \
|
||||
tmp |= ((d)<<24); \
|
||||
*(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
|
||||
tmp |= ((d) << 24); \
|
||||
((GLuint *) buf)[(_x) + (_y) * pitch] = tmp; \
|
||||
}
|
||||
|
||||
#define READ_STENCIL( d, _x, _y ) \
|
||||
d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) >> 24;
|
||||
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.
|
||||
*/
|
||||
void intelSpanRenderStart( GLcontext *ctx )
|
||||
static void
|
||||
intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
GLuint i, j;
|
||||
struct intel_renderbuffer *irb;
|
||||
|
||||
intelFlush(&intel->ctx);
|
||||
/* 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->intelScreen, irb->region);
|
||||
else
|
||||
intel_region_unmap(intel->intelScreen, 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->intelScreen, irb->region);
|
||||
else
|
||||
intel_region_unmap(intel->intelScreen, 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->intelScreen, irb->region);
|
||||
irb->pfMap = irb->region->map;
|
||||
irb->pfPitch = irb->region->pitch;
|
||||
}
|
||||
else {
|
||||
intel_region_unmap(intel->intelScreen, 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->intelScreen, irb->region);
|
||||
irb->pfMap = irb->region->map;
|
||||
irb->pfPitch = irb->region->pitch;
|
||||
}
|
||||
else {
|
||||
intel_region_unmap(intel->intelScreen, 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)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
GLuint i;
|
||||
|
||||
intelFinish(&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->intelScreen, intel->front_region);
|
||||
intel_region_map(intel->intelScreen, intel->back_region);
|
||||
intel_region_map(intel->intelScreen, intel->intelScreen->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);
|
||||
}
|
||||
|
||||
void intelSpanRenderFinish( GLcontext *ctx )
|
||||
/**
|
||||
* Called when done softare rendering. Unmap the buffers we mapped in
|
||||
* the above function.
|
||||
*/
|
||||
void
|
||||
intelSpanRenderFinish(GLcontext * ctx)
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT( ctx );
|
||||
_swrast_flush( ctx );
|
||||
UNLOCK_HARDWARE( intel );
|
||||
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->intelScreen->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 )
|
||||
|
||||
void
|
||||
intelInitSpanFuncs(GLcontext * ctx)
|
||||
{
|
||||
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
|
||||
swdd->SpanRenderStart = intelSpanRenderStart;
|
||||
@@ -227,32 +378,32 @@ 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);
|
||||
if (rb->_ActualFormat == GL_RGB5) {
|
||||
/* 565 RGB */
|
||||
intelInitPointers_RGB565(rb);
|
||||
}
|
||||
else if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
|
||||
intelInitPointers_565(&drb->Base);
|
||||
else if (rb->_ActualFormat == GL_RGBA8) {
|
||||
/* 8888 RGBA */
|
||||
intelInitPointers_ARGB8888(rb);
|
||||
}
|
||||
else if (rb->_ActualFormat == GL_DEPTH_COMPONENT16) {
|
||||
intelInitDepthPointers_z16(rb);
|
||||
}
|
||||
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 {
|
||||
assert(vis->redBits == 8);
|
||||
assert(vis->greenBits == 8);
|
||||
assert(vis->blueBits == 8);
|
||||
intelInitPointers_8888(&drb->Base);
|
||||
}
|
||||
}
|
||||
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
|
||||
intelInitDepthPointers_z16(&drb->Base);
|
||||
}
|
||||
else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
|
||||
intelInitDepthPointers_z24_s8(&drb->Base);
|
||||
}
|
||||
else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
|
||||
intelInitStencilPointers_z24_s8(&drb->Base);
|
||||
_mesa_problem(NULL,
|
||||
"Unexpected _ActualFormat in intelSetSpanFunctions");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,14 +28,11 @@
|
||||
#ifndef _INTEL_SPAN_H
|
||||
#define _INTEL_SPAN_H
|
||||
|
||||
#include "drirenderbuffer.h"
|
||||
extern void intelInitSpanFuncs(GLcontext * ctx);
|
||||
|
||||
extern void intelInitSpanFuncs( GLcontext *ctx );
|
||||
extern void intelSpanRenderFinish(GLcontext * ctx);
|
||||
extern void intelSpanRenderStart(GLcontext * ctx);
|
||||
|
||||
extern void intelSpanRenderFinish( GLcontext *ctx );
|
||||
extern void intelSpanRenderStart( GLcontext *ctx );
|
||||
|
||||
extern void
|
||||
intelSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis);
|
||||
extern void intel_set_span_functions(struct gl_renderbuffer *rb);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,15 +30,19 @@
|
||||
#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 )
|
||||
int
|
||||
intel_translate_compare_func(GLenum func)
|
||||
{
|
||||
switch(func) {
|
||||
switch (func) {
|
||||
case GL_NEVER:
|
||||
return COMPAREFUNC_NEVER;
|
||||
case GL_LESS:
|
||||
@@ -61,9 +65,10 @@ int intel_translate_compare_func( GLenum func )
|
||||
return COMPAREFUNC_ALWAYS;
|
||||
}
|
||||
|
||||
int intel_translate_stencil_op( GLenum op )
|
||||
int
|
||||
intel_translate_stencil_op(GLenum op)
|
||||
{
|
||||
switch(op) {
|
||||
switch (op) {
|
||||
case GL_KEEP:
|
||||
return STENCILOP_KEEP;
|
||||
case GL_ZERO:
|
||||
@@ -85,9 +90,10 @@ int intel_translate_stencil_op( GLenum op )
|
||||
}
|
||||
}
|
||||
|
||||
int intel_translate_blend_factor( GLenum factor )
|
||||
int
|
||||
intel_translate_blend_factor(GLenum factor)
|
||||
{
|
||||
switch(factor) {
|
||||
switch (factor) {
|
||||
case GL_ZERO:
|
||||
return BLENDFACT_ZERO;
|
||||
case GL_SRC_ALPHA:
|
||||
@@ -124,9 +130,10 @@ int intel_translate_blend_factor( GLenum factor )
|
||||
return BLENDFACT_ZERO;
|
||||
}
|
||||
|
||||
int intel_translate_logic_op( GLenum opcode )
|
||||
int
|
||||
intel_translate_logic_op(GLenum opcode)
|
||||
{
|
||||
switch(opcode) {
|
||||
switch (opcode) {
|
||||
case GL_CLEAR:
|
||||
return LOGICOP_CLEAR;
|
||||
case GL_AND:
|
||||
@@ -164,118 +171,193 @@ int intel_translate_logic_op( GLenum opcode )
|
||||
}
|
||||
}
|
||||
|
||||
static void intelDrawBuffer(GLcontext *ctx, GLenum mode )
|
||||
|
||||
static void
|
||||
intelClearColor(GLcontext * ctx, const GLfloat color[4])
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
int front = 0;
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
GLubyte clear[4];
|
||||
|
||||
if (!ctx->DrawBuffer)
|
||||
return;
|
||||
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]);
|
||||
|
||||
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->drawRegion = &intel->intelScreen->front;
|
||||
intel->readRegion = &intel->intelScreen->front;
|
||||
} else {
|
||||
intel->drawRegion = &intel->intelScreen->back;
|
||||
intel->readRegion = &intel->intelScreen->back;
|
||||
}
|
||||
|
||||
intel->vtbl.set_color_region( intel, intel->drawRegion );
|
||||
}
|
||||
|
||||
static void intelReadBuffer( GLcontext *ctx, GLenum mode )
|
||||
{
|
||||
/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
|
||||
/* 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]);
|
||||
}
|
||||
|
||||
|
||||
static void intelClearColor(GLcontext *ctx, const GLfloat color[4])
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
intelScreenPrivate *screen = intel->intelScreen;
|
||||
|
||||
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]);
|
||||
|
||||
intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat,
|
||||
intel->clear_red,
|
||||
intel->clear_green,
|
||||
intel->clear_blue,
|
||||
intel->clear_alpha);
|
||||
}
|
||||
|
||||
|
||||
static void intelCalcViewport( GLcontext *ctx )
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
const GLfloat *v = ctx->Viewport._WindowMap.m;
|
||||
GLfloat *m = intel->ViewportMatrix.m;
|
||||
GLint h = 0;
|
||||
|
||||
if (intel->driDrawable)
|
||||
h = intel->driDrawable->h + SUBPIXEL_Y;
|
||||
|
||||
/* See also intel_translate_vertex. SUBPIXEL adjustments can be done
|
||||
* via state vars, too.
|
||||
/**
|
||||
* Update the viewport transformation matrix. Depends on:
|
||||
* - viewport pos/size
|
||||
* - depthrange
|
||||
* - window pos/size or FBO size
|
||||
*/
|
||||
static void
|
||||
intelCalcViewport(GLcontext * 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;
|
||||
GLfloat yScale, yBias;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_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,
|
||||
GLint x, GLint y,
|
||||
GLsizei width, GLsizei height )
|
||||
static void
|
||||
intelViewport(GLcontext * ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height)
|
||||
{
|
||||
intelCalcViewport( ctx );
|
||||
intelCalcViewport(ctx);
|
||||
}
|
||||
|
||||
static void intelDepthRange( GLcontext *ctx,
|
||||
GLclampd nearval, GLclampd farval )
|
||||
static void
|
||||
intelDepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval)
|
||||
{
|
||||
intelCalcViewport( ctx );
|
||||
intelCalcViewport(ctx);
|
||||
}
|
||||
|
||||
/* Fallback to swrast for select and feedback.
|
||||
*/
|
||||
static void intelRenderMode( GLcontext *ctx, GLenum mode )
|
||||
static void
|
||||
intelRenderMode(GLcontext * ctx, GLenum mode)
|
||||
{
|
||||
intelContextPtr intel = INTEL_CONTEXT(ctx);
|
||||
FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER));
|
||||
}
|
||||
|
||||
|
||||
void intelInitStateFuncs( struct dd_function_table *functions )
|
||||
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,854 +1,161 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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"
|
||||
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
|
||||
|
||||
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)
|
||||
|
||||
intelIsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
int texelBytes;
|
||||
#if 0
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_object *intelObj = intel_texture_object(texObj);
|
||||
|
||||
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
|
||||
intelObj->mt &&
|
||||
intelObj->mt->region &&
|
||||
intel_is_region_resident(intel, intelObj->mt->region);
|
||||
#endif
|
||||
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 )
|
||||
static struct gl_texture_image *
|
||||
intelNewTextureImage(GLcontext * ctx)
|
||||
{
|
||||
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);
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
(void) ctx;
|
||||
return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image);
|
||||
}
|
||||
|
||||
|
||||
/* Handles 2D, CUBE, RECT:
|
||||
*/
|
||||
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 struct gl_texture_object *
|
||||
intelNewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
GLuint face;
|
||||
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
_mesa_initialize_texture_object(&obj->base, name, target);
|
||||
|
||||
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);
|
||||
}
|
||||
return &obj->base;
|
||||
}
|
||||
|
||||
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 )
|
||||
static void
|
||||
intelDeleteTextureObject(GLcontext *ctx,
|
||||
struct gl_texture_object *texObj)
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
GLuint face;
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_object *intelObj = intel_texture_object(texObj);
|
||||
|
||||
/* 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 (intelObj->mt)
|
||||
intel_miptree_release(intel, &intelObj->mt);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
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 ); /* 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);
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
|
||||
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);
|
||||
_mesa_delete_texture_object(ctx, texObj);
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) texObj->DriverData;
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_texture_image *intelImage = intel_texture_image(texImage);
|
||||
|
||||
assert( t ); /* this _should_ be true */
|
||||
driSwapOutTextureObject( t );
|
||||
DBG("%s\n", __FUNCTION__);
|
||||
|
||||
_mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset,
|
||||
width, height, depth,
|
||||
format, type, pixels, packing, texObj, texImage);
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_release(intel, &intelImage->mt);
|
||||
}
|
||||
|
||||
t->dirty_images[0] |= (1 << level);
|
||||
if (texImage->Data) {
|
||||
free(texImage->Data);
|
||||
texImage->Data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
|
||||
#ifndef __x86_64__
|
||||
static unsigned
|
||||
fastrdtsc(void)
|
||||
{
|
||||
driTextureObject * t = (driTextureObject *) tObj->DriverData;
|
||||
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");
|
||||
|
||||
if ( t != NULL ) {
|
||||
intelFlush( ctx );
|
||||
driDestroyTextureObject( t );
|
||||
}
|
||||
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");
|
||||
|
||||
/* Free mipmap images and the texture object itself */
|
||||
_mesa_delete_texture_object(ctx, tObj);
|
||||
return eax;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned
|
||||
time_diff(unsigned t, unsigned t2)
|
||||
{
|
||||
return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1));
|
||||
}
|
||||
|
||||
|
||||
static const struct gl_texture_format *
|
||||
intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
|
||||
GLenum format, GLenum type )
|
||||
/* 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 *
|
||||
do_memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
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;
|
||||
if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
|
||||
return __memcpy(dest, src, n);
|
||||
}
|
||||
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_z16;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unexpected texture format %s in %s\n",
|
||||
_mesa_lookup_enum_by_nr(internalFormat),
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL; /* never get here */
|
||||
return memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t)
|
||||
static void *
|
||||
timed_memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
unsigned i;
|
||||
void *ret;
|
||||
unsigned t1, t2;
|
||||
double rate;
|
||||
|
||||
if ( intel == NULL )
|
||||
return;
|
||||
if ((((unsigned) src) & 63) || (((unsigned) dest) & 63))
|
||||
_mesa_printf("Warning - non-aligned texture copy!\n");
|
||||
|
||||
if ( t->age > intel->dirtyAge )
|
||||
intel->dirtyAge = t->age;
|
||||
t1 = fastrdtsc();
|
||||
ret = do_memcpy(dest, src, n);
|
||||
t2 = fastrdtsc();
|
||||
|
||||
for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
|
||||
if ( t == intel->CurrentTexObj[ i ] )
|
||||
intel->CurrentTexObj[ i ] = NULL;
|
||||
}
|
||||
rate = time_diff(t1, t2);
|
||||
rate /= (double) n;
|
||||
_mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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 )
|
||||
void
|
||||
intelInitTextureFuncs(struct dd_function_table *functions)
|
||||
{
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* Time for another vtbl entry:
|
||||
*/
|
||||
else if (intel->intelScreen->deviceID == PCI_CHIP_I945_G ||
|
||||
intel->intelScreen->deviceID == PCI_CHIP_I945_GM) {
|
||||
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) {
|
||||
memcpy( dst, src, row_len * image->Height * image->Depth );
|
||||
}
|
||||
else {
|
||||
GLuint x = 0, y = 0;
|
||||
|
||||
for (d = 0 ; d < image->Depth ; d++) {
|
||||
GLubyte *dst0 = dst + x + y * t->Pitch;
|
||||
|
||||
for (j = 0 ; j < image->Height ; j++) {
|
||||
__memcpy(dst0, src, row_len );
|
||||
src += row_len;
|
||||
dst0 += t->Pitch;
|
||||
}
|
||||
|
||||
x += MIN2(4, row_len); /* Guess: 4 byte minimum alignment */
|
||||
if (x > t->Pitch) {
|
||||
x = 0;
|
||||
y += image->Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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 = (GLubyte *) (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;
|
||||
@@ -856,16 +163,20 @@ void intelInitTextureFuncs( struct dd_function_table *functions )
|
||||
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;
|
||||
functions->CopyTexImage1D = intelCopyTexImage1D;
|
||||
functions->CopyTexImage2D = intelCopyTexImage2D;
|
||||
functions->CopyTexSubImage1D = intelCopyTexSubImage1D;
|
||||
functions->CopyTexSubImage2D = intelCopyTexSubImage2D;
|
||||
functions->GetTexImage = intelGetTexImage;
|
||||
functions->NewTextureObject = intelNewTextureObject;
|
||||
functions->NewTextureImage = intelNewTextureImage;
|
||||
functions->DeleteTexture = intelDeleteTextureObject;
|
||||
functions->FreeTexImageData = intelFreeTextureImageData;
|
||||
functions->UpdateTexturePalette = 0;
|
||||
functions->IsTextureResident = intelIsTextureResident;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_BUFMGR)
|
||||
functions->TextureMemCpy = timed_memcpy;
|
||||
else
|
||||
functions->TextureMemCpy = do_memcpy;
|
||||
}
|
||||
|
||||
@@ -33,13 +33,102 @@
|
||||
#include "texmem.h"
|
||||
|
||||
|
||||
void intelInitTextureFuncs( struct dd_function_table *functions );
|
||||
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);
|
||||
|
||||
GLboolean
|
||||
intel_driReinitTextureHeap( driTexHeap *heap,
|
||||
unsigned size );
|
||||
#endif
|
||||
|
||||
291
src/mesa/drivers/dri/i915/intel_tex_copy.c
Normal file
291
src/mesa/drivers/dri/i915/intel_tex_copy.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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"
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
146
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal file
146
src/mesa/drivers/dri/i915/intel_tex_format.c
Normal file
@@ -0,0 +1,146 @@
|
||||
#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_BYTE || 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_z16;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unexpected texture format %s in %s\n",
|
||||
_mesa_lookup_enum_by_nr(internalFormat), __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL; /* never get here */
|
||||
}
|
||||
626
src/mesa/drivers/dri/i915/intel_tex_image.c
Normal file
626
src/mesa/drivers/dri/i915/intel_tex_image.c
Normal file
@@ -0,0 +1,626 @@
|
||||
|
||||
#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_buffer_objects.h"
|
||||
#include "intel_batchbuffer.h"
|
||||
#include "intel_tex.h"
|
||||
#include "intel_ioctl.h"
|
||||
#include "intel_blit.h"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* There are actually quite a few combinations this will work for,
|
||||
* more than what I've listed here.
|
||||
*/
|
||||
static GLboolean
|
||||
check_pbo_format(GLint internalFormat,
|
||||
GLenum format, GLenum type,
|
||||
const struct gl_texture_format *mesa_format)
|
||||
{
|
||||
switch (internalFormat) {
|
||||
case 4:
|
||||
case GL_RGBA:
|
||||
return (format == GL_BGRA &&
|
||||
(type == GL_UNSIGNED_BYTE ||
|
||||
type == GL_UNSIGNED_INT_8_8_8_8_REV) &&
|
||||
mesa_format == &_mesa_texformat_argb8888);
|
||||
case 3:
|
||||
case GL_RGB:
|
||||
return (format == GL_RGB &&
|
||||
type == GL_UNSIGNED_SHORT_5_6_5 &&
|
||||
mesa_format == &_mesa_texformat_rgb565);
|
||||
case GL_YCBCR_MESA:
|
||||
return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE);
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* XXX: Do this for TexSubImage also:
|
||||
*/
|
||||
static GLboolean
|
||||
try_pbo_upload(struct intel_context *intel,
|
||||
struct intel_texture_image *intelImage,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height,
|
||||
GLenum format, GLenum type, const void *pixels)
|
||||
{
|
||||
struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
|
||||
GLuint src_offset, src_stride;
|
||||
GLuint dst_offset, dst_stride;
|
||||
|
||||
if (!pbo ||
|
||||
intel->ctx._ImageTransferState ||
|
||||
unpack->SkipPixels || unpack->SkipRows) {
|
||||
_mesa_printf("%s: failure 1\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
src_offset = (GLuint) pixels;
|
||||
|
||||
if (unpack->RowLength > 0)
|
||||
src_stride = unpack->RowLength;
|
||||
else
|
||||
src_stride = width;
|
||||
|
||||
dst_offset = intel_miptree_image_offset(intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level);
|
||||
|
||||
dst_stride = intelImage->mt->pitch;
|
||||
|
||||
intelFlush(&intel->ctx);
|
||||
LOCK_HARDWARE(intel);
|
||||
{
|
||||
struct _DriBufferObject *src_buffer =
|
||||
intel_bufferobj_buffer(intel, pbo, INTEL_READ);
|
||||
struct _DriBufferObject *dst_buffer =
|
||||
intel_region_buffer(intel->intelScreen, intelImage->mt->region,
|
||||
INTEL_WRITE_FULL);
|
||||
|
||||
|
||||
intelEmitCopyBlit(intel,
|
||||
intelImage->mt->cpp,
|
||||
src_stride, src_buffer, src_offset,
|
||||
dst_stride, dst_buffer, dst_offset,
|
||||
0, 0, 0, 0, width, height);
|
||||
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
}
|
||||
UNLOCK_HARDWARE(intel);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static GLboolean
|
||||
try_pbo_zcopy(struct intel_context *intel,
|
||||
struct intel_texture_image *intelImage,
|
||||
const struct gl_pixelstore_attrib *unpack,
|
||||
GLint internalFormat,
|
||||
GLint width, GLint height,
|
||||
GLenum format, GLenum type, const void *pixels)
|
||||
{
|
||||
struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj);
|
||||
GLuint src_offset, src_stride;
|
||||
GLuint dst_offset, dst_stride;
|
||||
|
||||
if (!pbo ||
|
||||
intel->ctx._ImageTransferState ||
|
||||
unpack->SkipPixels || unpack->SkipRows) {
|
||||
_mesa_printf("%s: failure 1\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
src_offset = (GLuint) pixels;
|
||||
|
||||
if (unpack->RowLength > 0)
|
||||
src_stride = unpack->RowLength;
|
||||
else
|
||||
src_stride = width;
|
||||
|
||||
dst_offset = intel_miptree_image_offset(intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level);
|
||||
|
||||
dst_stride = intelImage->mt->pitch;
|
||||
|
||||
if (src_stride != dst_stride || dst_offset != 0 || src_offset != 0) {
|
||||
_mesa_printf("%s: failure 2\n", __FUNCTION__);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
intel_region_attach_pbo(intel->intelScreen, intelImage->mt->region, pbo);
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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) {
|
||||
DBG("guess_and_alloc_mipmap_tree: failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assert(!intelImage->mt);
|
||||
|
||||
if (intelObj->mt &&
|
||||
intel_miptree_match_image(intelObj->mt, &intelImage->base,
|
||||
intelImage->face, intelImage->level)) {
|
||||
|
||||
intel_miptree_reference(&intelImage->mt, intelObj->mt);
|
||||
assert(intelImage->mt);
|
||||
}
|
||||
|
||||
if (!intelImage->mt)
|
||||
DBG("XXX: Image did not fit into tree - storing in local memory!\n");
|
||||
|
||||
/* PBO fastpaths:
|
||||
*/
|
||||
if (dims <= 2 &&
|
||||
intelImage->mt &&
|
||||
intel_buffer_object(unpack->BufferObj) &&
|
||||
check_pbo_format(internalFormat, format,
|
||||
type, intelImage->base.TexFormat)) {
|
||||
|
||||
DBG("trying pbo upload\n");
|
||||
|
||||
/* Attempt to texture directly from PBO data (zero copy upload).
|
||||
*
|
||||
* Currently disable as it can lead to worse as well as better
|
||||
* performance (in particular when intel_region_cow() is
|
||||
* required).
|
||||
*/
|
||||
if (intelObj->mt == intelImage->mt &&
|
||||
intelObj->mt->first_level == level &&
|
||||
intelObj->mt->last_level == level) {
|
||||
|
||||
if (try_pbo_zcopy(intel, intelImage, unpack,
|
||||
internalFormat,
|
||||
width, height, format, type, pixels)) {
|
||||
|
||||
DBG("pbo zcopy upload succeeded\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Otherwise, attempt to use the blitter for PBO image uploads.
|
||||
*/
|
||||
if (try_pbo_upload(intel, intelImage, unpack,
|
||||
internalFormat,
|
||||
width, height, format, type, pixels)) {
|
||||
DBG("pbo upload succeeded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DBG("pbo upload failed\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;
|
||||
|
||||
|
||||
if (intelImage->mt)
|
||||
intel_region_idle(intel->intelScreen, intelImage->mt->region);
|
||||
|
||||
LOCK_HARDWARE(intel);
|
||||
|
||||
if (intelImage->mt) {
|
||||
texImage->Data = intel_miptree_image_map(intel,
|
||||
intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&dstRowStride,
|
||||
intelImage->base.ImageOffsets);
|
||||
}
|
||||
else {
|
||||
/* Allocate regular memory and store the image there temporarily. */
|
||||
if (texImage->IsCompressed) {
|
||||
sizeInBytes = texImage->CompressedSize;
|
||||
dstRowStride =
|
||||
_mesa_compressed_row_stride(texImage->InternalFormat, width);
|
||||
assert(dims != 3);
|
||||
}
|
||||
else {
|
||||
dstRowStride = postConvWidth * texelBytes;
|
||||
sizeInBytes = depth * dstRowStride * postConvHeight;
|
||||
}
|
||||
|
||||
texImage->Data = malloc(sizeInBytes);
|
||||
}
|
||||
|
||||
DBG("Upload image %dx%dx%d row_len %x "
|
||||
"pitch %x\n",
|
||||
width, height, depth, width * texelBytes, dstRowStride);
|
||||
|
||||
/* 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,
|
||||
texImage->ImageOffsets,
|
||||
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 */
|
||||
if (intelImage->mt) {
|
||||
/* Image is stored in hardware format in a buffer managed by the
|
||||
* kernel. Need to explicitly map and unmap it.
|
||||
*/
|
||||
intelImage->base.Data =
|
||||
intel_miptree_image_map(intel,
|
||||
intelImage->mt,
|
||||
intelImage->face,
|
||||
intelImage->level,
|
||||
&intelImage->base.RowStride,
|
||||
intelImage->base.ImageOffsets);
|
||||
}
|
||||
else {
|
||||
/* Otherwise, the image should actually be stored in
|
||||
* intelImage->base.Data. This is pretty confusing for
|
||||
* everybody, I'd much prefer to separate the two functions of
|
||||
* texImage->Data - storage for texture images in main memory
|
||||
* and access (ie mappings) of images. In other words, we'd
|
||||
* create a new texImage->Map field and leave Data simply for
|
||||
* storage.
|
||||
*/
|
||||
assert(intelImage->base.Data);
|
||||
}
|
||||
|
||||
_mesa_get_teximage(ctx, target, level, format, type, pixels,
|
||||
texObj, texImage);
|
||||
|
||||
/* Unmap */
|
||||
if (intelImage->mt) {
|
||||
intel_miptree_image_unmap(intel, intelImage->mt);
|
||||
intelImage->base.Data = NULL;
|
||||
}
|
||||
}
|
||||
183
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal file
183
src/mesa/drivers/dri/i915/intel_tex_subimage.c
Normal file
@@ -0,0 +1,183 @@
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
|
||||
|
||||
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;
|
||||
|
||||
if (intelImage->mt)
|
||||
intel_region_idle(intel->intelScreen, intelImage->mt->region);
|
||||
|
||||
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,
|
||||
texImage->ImageOffsets,
|
||||
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);
|
||||
|
||||
}
|
||||
253
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal file
253
src/mesa/drivers/dri/i915/intel_tex_validate.c
Normal file
@@ -0,0 +1,253 @@
|
||||
#include "mtypes.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_tex.h"
|
||||
|
||||
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
|
||||
|
||||
/**
|
||||
* 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.ImageOffsets);
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "texmem.h"
|
||||
#include "simple_list.h"
|
||||
#include "imports.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include "intel_tex.h"
|
||||
|
||||
static GLuint
|
||||
driLog2( GLuint n )
|
||||
{
|
||||
GLuint log2;
|
||||
|
||||
for ( log2 = 1 ; n > 1 ; log2++ ) {
|
||||
n >>= 1;
|
||||
}
|
||||
|
||||
return log2;
|
||||
}
|
||||
|
||||
static void calculate_heap_size( driTexHeap * heap, unsigned size,
|
||||
unsigned nr_regions, unsigned alignmentShift )
|
||||
{
|
||||
unsigned l;
|
||||
|
||||
l = driLog2( (size - 1) / nr_regions );
|
||||
if ( l < alignmentShift )
|
||||
{
|
||||
l = alignmentShift;
|
||||
}
|
||||
|
||||
heap->logGranularity = l;
|
||||
heap->size = size & ~((1L << l) - 1);
|
||||
}
|
||||
|
||||
|
||||
GLboolean
|
||||
intel_driReinitTextureHeap( driTexHeap *heap,
|
||||
unsigned size )
|
||||
{
|
||||
driTextureObject *t, *tmp;
|
||||
|
||||
/* Kick out everything:
|
||||
*/
|
||||
foreach_s ( t, tmp, & heap->texture_objects ) {
|
||||
if ( t->tObj != NULL ) {
|
||||
driSwapOutTextureObject( t );
|
||||
}
|
||||
else {
|
||||
driDestroyTextureObject( t );
|
||||
}
|
||||
}
|
||||
|
||||
/* Destroy the memory manager:
|
||||
*/
|
||||
mmDestroy( heap->memory_heap );
|
||||
|
||||
/* Recreate the memory manager:
|
||||
*/
|
||||
calculate_heap_size(heap, size, heap->nrRegions, heap->alignmentShift);
|
||||
heap->memory_heap = mmInit( 0, heap->size );
|
||||
if ( heap->memory_heap == NULL ) {
|
||||
fprintf(stderr, "driReinitTextureHeap: couldn't recreate memory heap\n");
|
||||
FREE( heap );
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
make_empty_list( & heap->texture_objects );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,13 +38,117 @@
|
||||
#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);
|
||||
|
||||
/* _mesa_printf("/\n"); */
|
||||
|
||||
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;
|
||||
|
||||
/* Need to make sure at the very least that we don't wrap
|
||||
* batchbuffers in BEGIN_BATCH below, otherwise the primitive will
|
||||
* be emitted to a batchbuffer missing the required full-state
|
||||
* preamble.
|
||||
*/
|
||||
if (intel_batchbuffer_space(intel->batch) < 100) {
|
||||
intel_batchbuffer_flush(intel->batch);
|
||||
intel->vtbl.emit_state(intel);
|
||||
}
|
||||
|
||||
/* _mesa_printf("%s *", __progname); */
|
||||
|
||||
/* 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();
|
||||
|
||||
/* _mesa_printf(">"); */
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
assert(intel->prim.flush == intel_flush_inline_primitive);
|
||||
|
||||
if (intel_batchbuffer_space(intel->batch) < sz)
|
||||
intelWrapInlinePrimitive(intel);
|
||||
|
||||
/* _mesa_printf("."); */
|
||||
|
||||
intel->vtbl.assert_not_dirty(intel);
|
||||
|
||||
ptr = (GLuint *) intel->batch->ptr;
|
||||
intel->batch->ptr += sz;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
static void intelRenderPrimitive( GLcontext *ctx, GLenum prim );
|
||||
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
|
||||
|
||||
/***********************************************************************
|
||||
* Emit primitives as inline vertices *
|
||||
@@ -63,74 +167,68 @@ 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,
|
||||
static void
|
||||
intel_draw_quad(struct intel_context *intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1,
|
||||
intelVertexPtr v2,
|
||||
intelVertexPtr v3 )
|
||||
intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3)
|
||||
{
|
||||
GLuint vertsize = intel->vertex_size;
|
||||
GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize );
|
||||
GLuint *vb = intelExtendInlinePrimitive(intel, 6 * vertsize);
|
||||
int j;
|
||||
|
||||
COPY_DWORDS( j, vb, vertsize, v0 );
|
||||
COPY_DWORDS( j, vb, vertsize, v1 );
|
||||
COPY_DWORDS( j, vb, vertsize, v3 );
|
||||
COPY_DWORDS( j, vb, vertsize, v1 );
|
||||
COPY_DWORDS( j, vb, vertsize, v2 );
|
||||
COPY_DWORDS( j, vb, vertsize, v3 );
|
||||
COPY_DWORDS(j, vb, vertsize, v0);
|
||||
COPY_DWORDS(j, vb, vertsize, v1);
|
||||
COPY_DWORDS(j, vb, vertsize, v3);
|
||||
COPY_DWORDS(j, vb, vertsize, v1);
|
||||
COPY_DWORDS(j, vb, vertsize, v2);
|
||||
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 );
|
||||
GLuint *vb = intelExtendInlinePrimitive(intel, 3 * vertsize);
|
||||
int j;
|
||||
|
||||
COPY_DWORDS( j, vb, vertsize, v0 );
|
||||
COPY_DWORDS( j, vb, vertsize, v1 );
|
||||
COPY_DWORDS( j, vb, vertsize, v2 );
|
||||
COPY_DWORDS(j, vb, vertsize, v0);
|
||||
COPY_DWORDS(j, vb, vertsize, v1);
|
||||
COPY_DWORDS(j, vb, vertsize, v2);
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
GLuint *vb = intelExtendInlinePrimitive(intel, 2 * vertsize);
|
||||
int j;
|
||||
|
||||
COPY_DWORDS( j, vb, vertsize, v0 );
|
||||
COPY_DWORDS( j, vb, vertsize, v1 );
|
||||
COPY_DWORDS(j, vb, vertsize, v0);
|
||||
COPY_DWORDS(j, vb, vertsize, v1);
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
GLuint *vb = intelExtendInlinePrimitive(intel, vertsize);
|
||||
int j;
|
||||
|
||||
/* Adjust for sub pixel position -- still required for conform. */
|
||||
*(float *)&vb[0] = v0->v.x - 0.125;
|
||||
*(float *)&vb[1] = v0->v.y - 0.125;
|
||||
for (j = 2 ; j < vertsize ; j++)
|
||||
*(float *) &vb[0] = v0->v.x - 0.125;
|
||||
*(float *) &vb[1] = v0->v.y - 0.125;
|
||||
for (j = 2; j < vertsize; j++)
|
||||
vb[j] = v0->ui[j];
|
||||
}
|
||||
|
||||
@@ -140,13 +238,17 @@ static __inline__ void intel_draw_point( intelContextPtr intel,
|
||||
* Fixup for ARB_point_parameters *
|
||||
***********************************************************************/
|
||||
|
||||
static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
|
||||
/* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly
|
||||
* represented in the fragment program InputsRead field.
|
||||
*/
|
||||
static void
|
||||
intel_atten_point(struct intel_context *intel, intelVertexPtr v0)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
GLfloat psz[4], col[4], restore_psz, restore_alpha;
|
||||
|
||||
_tnl_get_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz );
|
||||
_tnl_get_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col );
|
||||
_tnl_get_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
|
||||
_tnl_get_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
|
||||
|
||||
restore_psz = psz[0];
|
||||
restore_alpha = col[3];
|
||||
@@ -164,19 +266,19 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
|
||||
psz[0] = 1.0;
|
||||
|
||||
if (restore_psz != psz[0] || restore_alpha != col[3]) {
|
||||
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
|
||||
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col);
|
||||
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
|
||||
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
|
||||
|
||||
intel_draw_point( intel, v0 );
|
||||
intel_draw_point(intel, v0);
|
||||
|
||||
psz[0] = restore_psz;
|
||||
col[3] = restore_alpha;
|
||||
|
||||
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
|
||||
_tnl_set_attr( ctx, v0, _TNL_ATTRIB_COLOR0, col);
|
||||
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
|
||||
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
|
||||
}
|
||||
else
|
||||
intel_draw_point( intel, v0 );
|
||||
intel_draw_point(intel, v0);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,45 +291,44 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 )
|
||||
|
||||
|
||||
|
||||
static void intel_wpos_triangle( intelContextPtr intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1,
|
||||
intelVertexPtr v2 )
|
||||
static void
|
||||
intel_wpos_triangle(struct intel_context *intel,
|
||||
intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2)
|
||||
{
|
||||
GLuint offset = intel->wpos_offset;
|
||||
GLuint size = intel->wpos_size;
|
||||
|
||||
__memcpy( ((char *)v0) + offset, v0, size );
|
||||
__memcpy( ((char *)v1) + offset, v1, size );
|
||||
__memcpy( ((char *)v2) + offset, v2, size );
|
||||
__memcpy(((char *) v0) + offset, v0, size);
|
||||
__memcpy(((char *) v1) + offset, v1, size);
|
||||
__memcpy(((char *) v2) + offset, v2, size);
|
||||
|
||||
intel_draw_triangle( intel, v0, v1, v2 );
|
||||
intel_draw_triangle(intel, v0, v1, v2);
|
||||
}
|
||||
|
||||
|
||||
static void intel_wpos_line( intelContextPtr intel,
|
||||
intelVertexPtr v0,
|
||||
intelVertexPtr v1 )
|
||||
static void
|
||||
intel_wpos_line(struct intel_context *intel,
|
||||
intelVertexPtr v0, intelVertexPtr v1)
|
||||
{
|
||||
GLuint offset = intel->wpos_offset;
|
||||
GLuint size = intel->wpos_size;
|
||||
|
||||
__memcpy( ((char *)v0) + offset, v0, size );
|
||||
__memcpy( ((char *)v1) + offset, v1, size );
|
||||
__memcpy(((char *) v0) + offset, v0, size);
|
||||
__memcpy(((char *) v1) + offset, v1, size);
|
||||
|
||||
intel_draw_line( intel, v0, v1 );
|
||||
intel_draw_line(intel, v0, v1);
|
||||
}
|
||||
|
||||
|
||||
static void intel_wpos_point( intelContextPtr intel,
|
||||
intelVertexPtr v0 )
|
||||
static void
|
||||
intel_wpos_point(struct intel_context *intel, intelVertexPtr v0)
|
||||
{
|
||||
GLuint offset = intel->wpos_offset;
|
||||
GLuint size = intel->wpos_size;
|
||||
|
||||
__memcpy( ((char *)v0) + offset, v0, size );
|
||||
__memcpy(((char *) v0) + offset, v0, size);
|
||||
|
||||
intel_draw_point( intel, v0 );
|
||||
intel_draw_point(intel, v0);
|
||||
}
|
||||
|
||||
|
||||
@@ -284,7 +385,8 @@ do { \
|
||||
#define INTEL_MAX_TRIFUNC 0x10
|
||||
|
||||
|
||||
static struct {
|
||||
static struct
|
||||
{
|
||||
tnl_points_func points;
|
||||
tnl_line_func line;
|
||||
tnl_triangle_func triangle;
|
||||
@@ -349,7 +451,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; \
|
||||
@@ -360,7 +462,7 @@ do { \
|
||||
* Helpers for rendering unfilled primitives *
|
||||
***********************************************************************/
|
||||
|
||||
static const GLuint hw_prim[GL_POLYGON+1] = {
|
||||
static const GLuint hw_prim[GL_POLYGON + 1] = {
|
||||
PRIM3D_POINTLIST,
|
||||
PRIM3D_LINELIST,
|
||||
PRIM3D_LINELIST,
|
||||
@@ -450,7 +552,8 @@ static const GLuint hw_prim[GL_POLYGON+1] = {
|
||||
#include "tnl_dd/t_dd_tritmp.h"
|
||||
|
||||
|
||||
static void init_rast_tab( void )
|
||||
static void
|
||||
init_rast_tab(void)
|
||||
{
|
||||
init();
|
||||
init_offset();
|
||||
@@ -481,10 +584,8 @@ static void init_rast_tab( void )
|
||||
* primitives.
|
||||
*/
|
||||
static void
|
||||
intel_fallback_tri( intelContextPtr intel,
|
||||
intelVertex *v0,
|
||||
intelVertex *v1,
|
||||
intelVertex *v2 )
|
||||
intel_fallback_tri(struct intel_context *intel,
|
||||
intelVertex * v0, intelVertex * v1, intelVertex * v2)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
SWvertex v[3];
|
||||
@@ -492,19 +593,20 @@ intel_fallback_tri( intelContextPtr intel,
|
||||
if (0)
|
||||
fprintf(stderr, "\n%s\n", __FUNCTION__);
|
||||
|
||||
_swsetup_Translate( ctx, v0, &v[0] );
|
||||
_swsetup_Translate( ctx, v1, &v[1] );
|
||||
_swsetup_Translate( ctx, v2, &v[2] );
|
||||
intelSpanRenderStart( ctx );
|
||||
_swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
|
||||
intelSpanRenderFinish( ctx );
|
||||
INTEL_FIREVERTICES(intel);
|
||||
|
||||
_swsetup_Translate(ctx, v0, &v[0]);
|
||||
_swsetup_Translate(ctx, v1, &v[1]);
|
||||
_swsetup_Translate(ctx, v2, &v[2]);
|
||||
intelSpanRenderStart(ctx);
|
||||
_swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
|
||||
intelSpanRenderFinish(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_fallback_line( intelContextPtr intel,
|
||||
intelVertex *v0,
|
||||
intelVertex *v1 )
|
||||
intel_fallback_line(struct intel_context *intel,
|
||||
intelVertex * v0, intelVertex * v1)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
SWvertex v[2];
|
||||
@@ -512,17 +614,18 @@ intel_fallback_line( intelContextPtr intel,
|
||||
if (0)
|
||||
fprintf(stderr, "\n%s\n", __FUNCTION__);
|
||||
|
||||
_swsetup_Translate( ctx, v0, &v[0] );
|
||||
_swsetup_Translate( ctx, v1, &v[1] );
|
||||
intelSpanRenderStart( ctx );
|
||||
_swrast_Line( ctx, &v[0], &v[1] );
|
||||
intelSpanRenderFinish( ctx );
|
||||
INTEL_FIREVERTICES(intel);
|
||||
|
||||
_swsetup_Translate(ctx, v0, &v[0]);
|
||||
_swsetup_Translate(ctx, v1, &v[1]);
|
||||
intelSpanRenderStart(ctx);
|
||||
_swrast_Line(ctx, &v[0], &v[1]);
|
||||
intelSpanRenderFinish(ctx);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
intel_fallback_point( intelContextPtr intel,
|
||||
intelVertex *v0 )
|
||||
intel_fallback_point(struct intel_context *intel,
|
||||
intelVertex * v0)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
SWvertex v[1];
|
||||
@@ -530,12 +633,13 @@ intel_fallback_point( intelContextPtr intel,
|
||||
if (0)
|
||||
fprintf(stderr, "\n%s\n", __FUNCTION__);
|
||||
|
||||
_swsetup_Translate( ctx, v0, &v[0] );
|
||||
intelSpanRenderStart( ctx );
|
||||
_swrast_Point( ctx, &v[0] );
|
||||
intelSpanRenderFinish( ctx );
|
||||
}
|
||||
INTEL_FIREVERTICES(intel);
|
||||
|
||||
_swsetup_Translate(ctx, v0, &v[0]);
|
||||
intelSpanRenderStart(ctx);
|
||||
_swrast_Point(ctx, &v[0]);
|
||||
intelSpanRenderFinish(ctx);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
@@ -552,7 +656,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; \
|
||||
@@ -575,10 +679,10 @@ intel_fallback_point( intelContextPtr intel,
|
||||
|
||||
|
||||
|
||||
static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
|
||||
GLuint n )
|
||||
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;
|
||||
@@ -587,39 +691,40 @@ static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
|
||||
*/
|
||||
{
|
||||
GLuint *tmp = VB->Elts;
|
||||
VB->Elts = (GLuint *)elts;
|
||||
tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n,
|
||||
PRIM_BEGIN|PRIM_END );
|
||||
VB->Elts = (GLuint *) elts;
|
||||
tnl->Driver.Render.PrimTabElts[GL_POLYGON] (ctx, 0, n,
|
||||
PRIM_BEGIN | PRIM_END);
|
||||
VB->Elts = tmp;
|
||||
}
|
||||
|
||||
/* Restore the render primitive
|
||||
*/
|
||||
if (prim != GL_POLYGON)
|
||||
tnl->Driver.Render.PrimitiveNotify( ctx, prim );
|
||||
tnl->Driver.Render.PrimitiveNotify(ctx, prim);
|
||||
}
|
||||
|
||||
static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
|
||||
static void
|
||||
intelRenderClippedLine(GLcontext * ctx, GLuint ii, GLuint jj)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
|
||||
tnl->Driver.Render.Line( ctx, ii, jj );
|
||||
tnl->Driver.Render.Line(ctx, ii, jj);
|
||||
}
|
||||
|
||||
static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
|
||||
GLuint n )
|
||||
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;
|
||||
const GLuint *start = (const GLuint *)V(elts[0]);
|
||||
int i,j;
|
||||
GLuint *vb = intelExtendInlinePrimitive(intel, (n - 2) * 3 * vertsize);
|
||||
GLubyte *vertptr = (GLubyte *) intel->verts;
|
||||
const GLuint *start = (const GLuint *) V(elts[0]);
|
||||
int i, j;
|
||||
|
||||
for (i = 2 ; i < n ; i++) {
|
||||
COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) );
|
||||
COPY_DWORDS( j, vb, vertsize, V(elts[i]) );
|
||||
COPY_DWORDS( j, vb, vertsize, start );
|
||||
for (i = 2; i < n; i++) {
|
||||
COPY_DWORDS(j, vb, vertsize, V(elts[i - 1]));
|
||||
COPY_DWORDS(j, vb, vertsize, V(elts[i]));
|
||||
COPY_DWORDS(j, vb, vertsize, start);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,31 +735,31 @@ 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 | DD_POINT_SMOOTH | DD_TRI_SMOOTH)
|
||||
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
|
||||
|
||||
void intelChooseRenderState(GLcontext *ctx)
|
||||
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;
|
||||
const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
|
||||
GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
|
||||
GLuint index = 0;
|
||||
|
||||
if (INTEL_DEBUG & DEBUG_STATE)
|
||||
fprintf(stderr,"\n%s\n",__FUNCTION__);
|
||||
fprintf(stderr, "\n%s\n", __FUNCTION__);
|
||||
|
||||
if ((flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) || have_wpos) {
|
||||
if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) {
|
||||
|
||||
if (flags & ANY_RASTER_FLAGS) {
|
||||
if (flags & DD_TRI_LIGHT_TWOSIDE) index |= INTEL_TWOSIDE_BIT;
|
||||
if (flags & DD_TRI_OFFSET) index |= INTEL_OFFSET_BIT;
|
||||
if (flags & DD_TRI_UNFILLED) index |= INTEL_UNFILLED_BIT;
|
||||
if (flags & DD_TRI_LIGHT_TWOSIDE)
|
||||
index |= INTEL_TWOSIDE_BIT;
|
||||
if (flags & DD_TRI_OFFSET)
|
||||
index |= INTEL_OFFSET_BIT;
|
||||
if (flags & DD_TRI_UNFILLED)
|
||||
index |= INTEL_UNFILLED_BIT;
|
||||
}
|
||||
|
||||
if (have_wpos) {
|
||||
@@ -674,22 +779,29 @@ void intelChooseRenderState(GLcontext *ctx)
|
||||
|
||||
/* Hook in fallbacks for specific primitives.
|
||||
*/
|
||||
if (flags & ANY_FALLBACK_FLAGS)
|
||||
{
|
||||
if (flags & POINT_FALLBACK)
|
||||
intel->draw_point = intel_fallback_point;
|
||||
|
||||
if (flags & LINE_FALLBACK)
|
||||
if (flags & ANY_FALLBACK_FLAGS) {
|
||||
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;
|
||||
|
||||
if (flags & DD_POINT_ATTEN)
|
||||
if (flags & DD_TRI_SMOOTH) {
|
||||
if (intel->strict_conformance)
|
||||
intel->draw_tri = intel_fallback_tri;
|
||||
}
|
||||
|
||||
if (flags & DD_POINT_ATTEN) {
|
||||
if (0)
|
||||
intel->draw_point = intel_atten_point;
|
||||
else
|
||||
intel->draw_point = intel_fallback_point;
|
||||
}
|
||||
|
||||
if (flags & DD_POINT_SMOOTH) {
|
||||
if (intel->strict_conformance)
|
||||
intel->draw_point = intel_fallback_point;
|
||||
}
|
||||
|
||||
index |= INTEL_FALLBACK_BIT;
|
||||
}
|
||||
@@ -708,7 +820,8 @@ void intelChooseRenderState(GLcontext *ctx)
|
||||
tnl->Driver.Render.PrimTabElts = intel_render_tab_elts;
|
||||
tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
|
||||
tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
|
||||
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
|
||||
tnl->Driver.Render.ClippedLine = intelRenderClippedLine;
|
||||
@@ -717,7 +830,7 @@ void intelChooseRenderState(GLcontext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static const GLenum reduced_prim[GL_POLYGON+1] = {
|
||||
static const GLenum reduced_prim[GL_POLYGON + 1] = {
|
||||
GL_POINTS,
|
||||
GL_LINES,
|
||||
GL_LINES,
|
||||
@@ -738,35 +851,45 @@ static const GLenum reduced_prim[GL_POLYGON+1] = {
|
||||
|
||||
|
||||
|
||||
static void intelRunPipeline( GLcontext *ctx )
|
||||
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) {
|
||||
intel->vtbl.update_texture_state( intel );
|
||||
intel->vtbl.update_texture_state(intel);
|
||||
}
|
||||
|
||||
if (!intel->Fallback) {
|
||||
if (intel->NewGLState & _INTEL_NEW_RENDERSTATE)
|
||||
intelChooseRenderState( ctx );
|
||||
intelChooseRenderState(ctx);
|
||||
}
|
||||
|
||||
intel->NewGLState = 0;
|
||||
}
|
||||
|
||||
_tnl_run_pipeline( ctx );
|
||||
_tnl_run_pipeline(ctx);
|
||||
}
|
||||
|
||||
static void intelRenderStart( 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 )
|
||||
static void
|
||||
intelRenderFinish(GLcontext * ctx)
|
||||
{
|
||||
if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT)
|
||||
_swrast_flush( ctx );
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
|
||||
if (intel->RenderIndex & INTEL_FALLBACK_BIT)
|
||||
_swrast_flush(ctx);
|
||||
|
||||
INTEL_FIREVERTICES(intel);
|
||||
}
|
||||
|
||||
|
||||
@@ -775,28 +898,33 @@ static void intelRenderFinish( GLcontext *ctx )
|
||||
/* System to flush dma and emit state changes based on the rasterized
|
||||
* primitive.
|
||||
*/
|
||||
static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
|
||||
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__,
|
||||
_mesa_lookup_enum_by_nr(rprim), hwprim);
|
||||
|
||||
intel->vtbl.reduced_primitive_state( intel, rprim );
|
||||
intel->vtbl.reduced_primitive_state(intel, rprim);
|
||||
|
||||
/* Start a new primitive. Arrange to have it flushed later on.
|
||||
*/
|
||||
if (hwprim != intel->prim.primitive)
|
||||
intelStartInlinePrimitive( intel, hwprim );
|
||||
if (hwprim != intel->prim.primitive) {
|
||||
INTEL_FIREVERTICES(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));
|
||||
@@ -817,40 +945,49 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
|
||||
|
||||
/* Set some primitive-dependent state and Start? a new primitive.
|
||||
*/
|
||||
intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] );
|
||||
}
|
||||
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[] = {
|
||||
[0] = "Draw buffer",
|
||||
[1] = "Read buffer",
|
||||
[2] = "Depth buffer",
|
||||
[3] = "Stencil buffer",
|
||||
[4] = "User disable",
|
||||
[5] = "Render mode",
|
||||
|
||||
[12] = "Texture",
|
||||
[13] = "Color mask",
|
||||
[14] = "Stencil",
|
||||
[15] = "Stipple",
|
||||
[16] = "Program",
|
||||
[17] = "Logic op",
|
||||
[18] = "Smooth polygon",
|
||||
[19] = "Smooth point",
|
||||
};
|
||||
|
||||
|
||||
static char *getFallbackString(GLuint bit)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
void
|
||||
intelFallback(struct intel_context *intel, GLuint bit, GLboolean mode)
|
||||
{
|
||||
GLcontext *ctx = &intel->ctx;
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
GLuint oldfallback = intel->Fallback;
|
||||
@@ -861,17 +998,17 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
|
||||
intelFlush(ctx);
|
||||
if (INTEL_DEBUG & DEBUG_FALLBACKS)
|
||||
fprintf(stderr, "ENTER FALLBACK %x: %s\n",
|
||||
bit, getFallbackString( bit ));
|
||||
_swsetup_Wakeup( ctx );
|
||||
bit, getFallbackString(bit));
|
||||
_swsetup_Wakeup(ctx);
|
||||
intel->RenderIndex = ~0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
intel->Fallback &= ~bit;
|
||||
if (oldfallback == bit) {
|
||||
_swrast_flush( ctx );
|
||||
_swrast_flush(ctx);
|
||||
if (INTEL_DEBUG & DEBUG_FALLBACKS)
|
||||
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit ));
|
||||
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString(bit));
|
||||
tnl->Driver.Render.Start = intelRenderStart;
|
||||
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
|
||||
tnl->Driver.Render.Finish = intelRenderFinish;
|
||||
@@ -879,18 +1016,89 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
|
||||
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,
|
||||
_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->ViewportMatrix.m, 0);
|
||||
|
||||
intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
union fi
|
||||
{
|
||||
GLfloat f;
|
||||
GLint i;
|
||||
};
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* Used only with the metaops callbacks. */
|
||||
/**********************************************************************/
|
||||
void
|
||||
intel_meta_draw_poly(struct intel_context *intel,
|
||||
GLuint n,
|
||||
GLfloat xy[][2],
|
||||
GLfloat z, GLuint color, GLfloat tex[][2])
|
||||
{
|
||||
union fi *vb;
|
||||
GLint i;
|
||||
|
||||
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, n * 6);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
vb[0].f = xy[i][0];
|
||||
vb[1].f = xy[i][1];
|
||||
vb[2].f = z;
|
||||
vb[3].i = color;
|
||||
vb[4].f = tex[i][0];
|
||||
vb[5].f = tex[i][1];
|
||||
vb += 6;
|
||||
}
|
||||
|
||||
INTEL_FIREVERTICES(intel);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GLfloat xy[4][2];
|
||||
GLfloat tex[4][2];
|
||||
|
||||
xy[0][0] = x0;
|
||||
xy[0][1] = y0;
|
||||
xy[1][0] = x1;
|
||||
xy[1][1] = y0;
|
||||
xy[2][0] = x1;
|
||||
xy[2][1] = y1;
|
||||
xy[3][0] = x0;
|
||||
xy[3][1] = y1;
|
||||
|
||||
tex[0][0] = s0;
|
||||
tex[0][1] = t0;
|
||||
tex[1][0] = s1;
|
||||
tex[1][1] = t0;
|
||||
tex[2][0] = s1;
|
||||
tex[2][1] = t1;
|
||||
tex[3][0] = s0;
|
||||
tex[3][1] = t1;
|
||||
|
||||
intel_meta_draw_poly(intel, 4, xy, z, color, tex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -899,7 +1107,8 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim )
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
void intelInitTriFuncs( GLcontext *ctx )
|
||||
void
|
||||
intelInitTriFuncs(GLcontext * ctx)
|
||||
{
|
||||
TNLcontext *tnl = TNL_CONTEXT(ctx);
|
||||
static int firsttime = 1;
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include "mtypes.h"
|
||||
|
||||
|
||||
|
||||
#define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
|
||||
_DD_NEW_TRI_UNFILLED | \
|
||||
_DD_NEW_TRI_LIGHT_TWOSIDE | \
|
||||
@@ -38,9 +40,30 @@
|
||||
_NEW_PROGRAM | \
|
||||
_NEW_POLYGONSTIPPLE)
|
||||
|
||||
extern void intelInitTriFuncs( GLcontext *ctx );
|
||||
extern void intelInitTriFuncs(GLcontext * ctx);
|
||||
|
||||
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);
|
||||
|
||||
void intel_meta_draw_poly(struct intel_context *intel,
|
||||
GLuint n,
|
||||
GLfloat xy[][2],
|
||||
GLfloat z, GLuint color, GLfloat tex[][2]);
|
||||
|
||||
|
||||
extern void intelPrintRenderState( const char *msg, GLuint state );
|
||||
extern void intelChooseRenderState( GLcontext *ctx );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -276,6 +276,8 @@ _mesa_PushAttrib(GLbitfield mask)
|
||||
struct gl_pixel_attrib *attr;
|
||||
attr = MALLOC_STRUCT( gl_pixel_attrib );
|
||||
MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) );
|
||||
/* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */
|
||||
attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer;
|
||||
newnode = new_attrib_node( GL_PIXEL_MODE_BIT );
|
||||
newnode->data = attr;
|
||||
newnode->next = head;
|
||||
|
||||
@@ -591,11 +591,9 @@ _mesa_ReadBuffer(GLenum buffer)
|
||||
* \note This function should only be called through the GL API, not
|
||||
* from device drivers (as was done in the past).
|
||||
*/
|
||||
void GLAPIENTRY
|
||||
_mesa_ResizeBuffersMESA( void )
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
void _mesa_resizebuffers( GLcontext *ctx )
|
||||
{
|
||||
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx );
|
||||
|
||||
if (MESA_VERBOSE & VERBOSE_API)
|
||||
@@ -637,6 +635,14 @@ _mesa_ResizeBuffersMESA( void )
|
||||
ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_ResizeBuffersMESA( void )
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
_mesa_resizebuffers( ctx );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX move somewhere else someday?
|
||||
|
||||
@@ -78,4 +78,6 @@ extern void
|
||||
_mesa_set_scissor(GLcontext *ctx,
|
||||
GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
extern void _mesa_resizebuffers( GLcontext *ctx );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -704,9 +704,7 @@ alloc_shared_state( GLcontext *ctx )
|
||||
|
||||
ss->ArrayObjects = _mesa_NewHashTable();
|
||||
|
||||
#if FEATURE_ARB_shader_objects
|
||||
ss->GL2Objects = _mesa_NewHashTable ();
|
||||
#endif
|
||||
|
||||
ss->Default1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D);
|
||||
if (!ss->Default1D)
|
||||
@@ -777,10 +775,8 @@ alloc_shared_state( GLcontext *ctx )
|
||||
if (ss->ArrayObjects)
|
||||
_mesa_DeleteHashTable (ss->ArrayObjects);
|
||||
|
||||
#if FEATURE_ARB_shader_objects
|
||||
if (ss->GL2Objects)
|
||||
_mesa_DeleteHashTable (ss->GL2Objects);
|
||||
#endif
|
||||
|
||||
#if FEATURE_EXT_framebuffer_object
|
||||
if (ss->FrameBuffers)
|
||||
@@ -933,9 +929,7 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
|
||||
_mesa_HashDeleteAll(ss->ArrayObjects, delete_arrayobj_cb, ctx);
|
||||
_mesa_DeleteHashTable(ss->ArrayObjects);
|
||||
|
||||
#if FEATURE_ARB_shader_objects
|
||||
_mesa_DeleteHashTable(ss->GL2Objects);
|
||||
#endif
|
||||
|
||||
#if FEATURE_EXT_framebuffer_object
|
||||
_mesa_DeleteHashTable(ss->FrameBuffers);
|
||||
@@ -1713,6 +1707,8 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
|
||||
if (readBuffer != drawBuffer && !readBuffer->Initialized) {
|
||||
initialize_framebuffer_size(newCtx, readBuffer);
|
||||
}
|
||||
|
||||
_mesa_resizebuffers(newCtx);
|
||||
#endif
|
||||
if (newCtx->FirstTimeCurrent) {
|
||||
/* set initial viewport and scissor size now */
|
||||
|
||||
@@ -570,6 +570,11 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
|
||||
}
|
||||
|
||||
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
|
||||
/* The above doesn't fully flush the drivers in the way that a
|
||||
* glFlush does, but that is required here:
|
||||
*/
|
||||
ctx->Driver.Flush(ctx);
|
||||
|
||||
|
||||
if (renderbuffer) {
|
||||
newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
|
||||
@@ -972,7 +977,9 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
|
||||
}
|
||||
|
||||
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
|
||||
|
||||
if (ctx->Driver.Flush) {
|
||||
ctx->Driver.Flush(ctx);
|
||||
}
|
||||
if (framebuffer) {
|
||||
/* Binding a user-created framebuffer object */
|
||||
newFb = _mesa_lookup_framebuffer(ctx, framebuffer);
|
||||
@@ -1047,6 +1054,10 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers)
|
||||
|
||||
ASSERT_OUTSIDE_BEGIN_END(ctx);
|
||||
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
|
||||
/* The above doesn't fully flush the drivers in the way that a
|
||||
* glFlush does, but that is required here:
|
||||
*/
|
||||
ctx->Driver.Flush(ctx);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (framebuffers[i] > 0) {
|
||||
@@ -1262,6 +1273,10 @@ framebuffer_texture(GLuint dims, GLenum target, GLenum attachment,
|
||||
}
|
||||
|
||||
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
|
||||
/* The above doesn't fully flush the drivers in the way that a
|
||||
* glFlush does, but that is required here:
|
||||
*/
|
||||
ctx->Driver.Flush(ctx);
|
||||
|
||||
_glthread_LOCK_MUTEX(fb->Mutex);
|
||||
if (texObj) {
|
||||
@@ -1380,6 +1395,10 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment,
|
||||
}
|
||||
|
||||
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
|
||||
/* The above doesn't fully flush the drivers in the way that a
|
||||
* glFlush does, but that is required here:
|
||||
*/
|
||||
ctx->Driver.Flush(ctx);
|
||||
|
||||
assert(ctx->Driver.FramebufferRenderbuffer);
|
||||
ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
|
||||
@@ -1443,6 +1462,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment,
|
||||
}
|
||||
|
||||
FLUSH_VERTICES(ctx, _NEW_BUFFERS);
|
||||
/* The above doesn't fully flush the drivers in the way that a
|
||||
* glFlush does, but that is required here:
|
||||
*/
|
||||
ctx->Driver.Flush(ctx);
|
||||
|
||||
switch (pname) {
|
||||
case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
|
||||
|
||||
@@ -604,6 +604,17 @@ do { \
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Return 1 if this is a little endian machine, 0 if big endian.
|
||||
*/
|
||||
static INLINE GLboolean
|
||||
_mesa_little_endian(void)
|
||||
{
|
||||
const GLuint ui = 1; /* intentionally not static */
|
||||
return *((const GLubyte *) &ui);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Functions
|
||||
|
||||
@@ -658,7 +658,7 @@ _mesa_free_texture_image_data(GLcontext *ctx,
|
||||
void
|
||||
_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
|
||||
{
|
||||
if (texImage->Data) {
|
||||
if (texImage->Data || ctx->Driver.FreeTexImageData) {
|
||||
ctx->Driver.FreeTexImageData( ctx, texImage );
|
||||
}
|
||||
ASSERT(texImage->Data == NULL);
|
||||
|
||||
@@ -63,11 +63,21 @@
|
||||
#include "texformat.h"
|
||||
#include "teximage.h"
|
||||
#include "texstore.h"
|
||||
#include "enums.h"
|
||||
|
||||
|
||||
static const GLint ZERO = 4, ONE = 5;
|
||||
enum {
|
||||
ZERO = 4,
|
||||
ONE = 5
|
||||
};
|
||||
|
||||
static GLboolean can_swizzle(GLenum logicalBaseFormat)
|
||||
|
||||
/**
|
||||
* Return GL_TRUE if the given image format is one that be converted
|
||||
* to another format by swizzling.
|
||||
*/
|
||||
static GLboolean
|
||||
can_swizzle(GLenum logicalBaseFormat)
|
||||
{
|
||||
switch (logicalBaseFormat) {
|
||||
case GL_RGBA:
|
||||
@@ -76,6 +86,12 @@ static GLboolean can_swizzle(GLenum logicalBaseFormat)
|
||||
case GL_INTENSITY:
|
||||
case GL_ALPHA:
|
||||
case GL_LUMINANCE:
|
||||
case GL_RED:
|
||||
case GL_GREEN:
|
||||
case GL_BLUE:
|
||||
case GL_BGR:
|
||||
case GL_BGRA:
|
||||
case GL_ABGR_EXT:
|
||||
return GL_TRUE;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
@@ -83,89 +99,172 @@ static GLboolean can_swizzle(GLenum logicalBaseFormat)
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum {
|
||||
IDX_LUMINANCE = 0,
|
||||
IDX_ALPHA,
|
||||
IDX_INTENSITY,
|
||||
IDX_LUMINANCE_ALPHA,
|
||||
IDX_RGB,
|
||||
IDX_RGBA,
|
||||
IDX_RED,
|
||||
IDX_GREEN,
|
||||
IDX_BLUE,
|
||||
IDX_BGR,
|
||||
IDX_BGRA,
|
||||
IDX_ABGR,
|
||||
MAX_IDX
|
||||
};
|
||||
|
||||
#define MAP1(x) MAP4(x, ZERO, ZERO, ZERO)
|
||||
#define MAP2(x,y) MAP4(x, y, ZERO, ZERO)
|
||||
#define MAP3(x,y,z) MAP4(x, y, z, ZERO)
|
||||
#define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE }
|
||||
|
||||
|
||||
static const struct {
|
||||
GLubyte format_idx;
|
||||
GLubyte to_rgba[6];
|
||||
GLubyte from_rgba[6];
|
||||
} mappings[MAX_IDX] =
|
||||
{
|
||||
{
|
||||
IDX_LUMINANCE,
|
||||
MAP4(0,0,0,ONE),
|
||||
MAP1(0)
|
||||
},
|
||||
|
||||
{
|
||||
IDX_ALPHA,
|
||||
MAP4(ZERO, ZERO, ZERO, 0),
|
||||
MAP1(3)
|
||||
},
|
||||
|
||||
{
|
||||
IDX_INTENSITY,
|
||||
MAP4(0, 0, 0, 0),
|
||||
MAP1(0),
|
||||
},
|
||||
|
||||
{
|
||||
IDX_LUMINANCE_ALPHA,
|
||||
MAP4(0,0,0,1),
|
||||
MAP2(0,3)
|
||||
},
|
||||
|
||||
{
|
||||
IDX_RGB,
|
||||
MAP4(0,1,2,ONE),
|
||||
MAP3(0,1,2)
|
||||
},
|
||||
|
||||
{
|
||||
IDX_RGBA,
|
||||
MAP4(0,1,2,3),
|
||||
MAP4(0,1,2,3),
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
IDX_RED,
|
||||
MAP4(0, ZERO, ZERO, ONE),
|
||||
MAP1(0),
|
||||
},
|
||||
|
||||
{
|
||||
IDX_GREEN,
|
||||
MAP4(ZERO, 0, ZERO, ONE),
|
||||
MAP1(1),
|
||||
},
|
||||
|
||||
{
|
||||
IDX_BLUE,
|
||||
MAP4(ZERO, ZERO, 0, ONE),
|
||||
MAP1(2),
|
||||
},
|
||||
|
||||
{
|
||||
IDX_BGR,
|
||||
MAP4(2,1,0,ONE),
|
||||
MAP3(2,1,0)
|
||||
},
|
||||
|
||||
{
|
||||
IDX_BGRA,
|
||||
MAP4(2,1,0,3),
|
||||
MAP4(2,1,0,3)
|
||||
},
|
||||
|
||||
{
|
||||
IDX_ABGR,
|
||||
MAP4(3,2,1,0),
|
||||
MAP4(3,2,1,0)
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a GL image format enum to an IDX_* value (see above).
|
||||
*/
|
||||
static int
|
||||
get_map_idx(GLenum value)
|
||||
{
|
||||
switch (value) {
|
||||
case GL_LUMINANCE: return IDX_LUMINANCE;
|
||||
case GL_ALPHA: return IDX_ALPHA;
|
||||
case GL_INTENSITY: return IDX_INTENSITY;
|
||||
case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA;
|
||||
case GL_RGB: return IDX_RGB;
|
||||
case GL_RGBA: return IDX_RGBA;
|
||||
case GL_RED: return IDX_RED;
|
||||
case GL_GREEN: return IDX_GREEN;
|
||||
case GL_BLUE: return IDX_BLUE;
|
||||
case GL_BGR: return IDX_BGR;
|
||||
case GL_BGRA: return IDX_BGRA;
|
||||
case GL_ABGR_EXT: return IDX_ABGR;
|
||||
default:
|
||||
_mesa_problem(NULL, "Unexpected inFormat");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When promoting texture formats (see below) we need to compute the
|
||||
* mapping of dest components back to source components.
|
||||
* This function does that.
|
||||
* \param logicalBaseFormat the logical format of the texture
|
||||
* \param textureBaseFormat the final texture format
|
||||
* \return map[4] the four mapping values
|
||||
* \param inFormat the incoming format of the texture
|
||||
* \param outFormat the final texture format
|
||||
* \return map[6] a full 6-component map
|
||||
*/
|
||||
static void
|
||||
compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat,
|
||||
GLubyte map[6])
|
||||
compute_component_mapping(GLenum inFormat, GLenum outFormat,
|
||||
GLubyte *map)
|
||||
{
|
||||
const int inFmt = get_map_idx(inFormat);
|
||||
const int outFmt = get_map_idx(outFormat);
|
||||
const GLubyte *in2rgba = mappings[inFmt].to_rgba;
|
||||
const GLubyte *rgba2out = mappings[outFmt].from_rgba;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
map[i] = in2rgba[rgba2out[i]];
|
||||
|
||||
map[ZERO] = ZERO;
|
||||
map[ONE] = ONE;
|
||||
|
||||
/* compute mapping from dest components back to src components */
|
||||
switch (textureBaseFormat) {
|
||||
case GL_RGB:
|
||||
case GL_RGBA:
|
||||
switch (logicalBaseFormat) {
|
||||
case GL_LUMINANCE:
|
||||
map[0] = map[1] = map[2] = 0;
|
||||
if (textureBaseFormat == GL_RGBA)
|
||||
map[3] = ONE;
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
ASSERT(textureBaseFormat == GL_RGBA);
|
||||
map[0] = map[1] = map[2] = ZERO;
|
||||
map[3] = 0;
|
||||
break;
|
||||
case GL_INTENSITY:
|
||||
map[0] = map[1] = map[2] = 0;
|
||||
if (textureBaseFormat == GL_RGBA)
|
||||
map[3] = 0;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
ASSERT(textureBaseFormat == GL_RGBA);
|
||||
map[0] = map[1] = map[2] = 0;
|
||||
map[3] = 1;
|
||||
break;
|
||||
case GL_RGB:
|
||||
ASSERT(textureBaseFormat == GL_RGBA);
|
||||
map[0] = 0;
|
||||
map[1] = 1;
|
||||
map[2] = 2;
|
||||
map[3] = ONE;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
ASSERT(textureBaseFormat == GL_RGBA);
|
||||
map[0] = 0;
|
||||
map[1] = 1;
|
||||
map[2] = 2;
|
||||
map[3] = 3;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
|
||||
map[0] = map[1] = map[2] = map[3] = 0;
|
||||
}
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
switch (logicalBaseFormat) {
|
||||
case GL_LUMINANCE:
|
||||
map[0] = 0;
|
||||
map[1] = ONE;
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
map[0] = ZERO;
|
||||
map[1] = 0;
|
||||
break;
|
||||
case GL_INTENSITY:
|
||||
map[0] = 0;
|
||||
map[1] = 0;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
|
||||
map[0] = map[1] = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(NULL, "Unexpected logicalBaseFormat");
|
||||
map[0] = map[1] = 0;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
_mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n",
|
||||
inFormat, _mesa_lookup_enum_by_nr(inFormat),
|
||||
outFormat, _mesa_lookup_enum_by_nr(outFormat),
|
||||
map[0],
|
||||
map[1],
|
||||
map[2],
|
||||
map[3],
|
||||
map[4],
|
||||
map[5]);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -552,14 +651,16 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
|
||||
* \param dstComponents number of color components in destination pixels
|
||||
* \param src source pixels
|
||||
* \param srcComponents number of color components in source pixels
|
||||
* \param map the swizzle mapping
|
||||
* \param map the swizzle mapping. map[X] says where to find the X component
|
||||
* in the source image's pixels. For example, if the source image
|
||||
* is GL_BGRA and X = red, map[0] yields 2.
|
||||
* \param count number of pixels to copy/swizzle.
|
||||
*/
|
||||
static void
|
||||
swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,
|
||||
GLuint srcComponents, const GLubyte *map, GLuint count)
|
||||
{
|
||||
GLubyte tmp[8];
|
||||
GLubyte tmp[6];
|
||||
GLuint i;
|
||||
|
||||
tmp[ZERO] = 0x0;
|
||||
@@ -596,10 +697,60 @@ swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,
|
||||
dst += 2;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (i = 0; i < count; i++) {
|
||||
COPY_4UBV(tmp, src);
|
||||
src += srcComponents;
|
||||
dst[0] = tmp[map[0]];
|
||||
dst += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE };
|
||||
static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE };
|
||||
|
||||
/* Deal with the _REV input types:
|
||||
*/
|
||||
static const GLubyte *
|
||||
type_mapping( GLenum srcType )
|
||||
{
|
||||
switch (srcType) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return map_identity;
|
||||
case GL_UNSIGNED_INT_8_8_8_8:
|
||||
return map_3210;
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
return map_identity;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mapping required if input type is
|
||||
*/
|
||||
static const GLubyte *
|
||||
byteswap_mapping( GLboolean swapBytes,
|
||||
GLenum srcType )
|
||||
{
|
||||
if (!swapBytes)
|
||||
return map_identity;
|
||||
|
||||
switch (srcType) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return map_identity;
|
||||
case GL_UNSIGNED_INT_8_8_8_8:
|
||||
case GL_UNSIGNED_INT_8_8_8_8_REV:
|
||||
return map_3210;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Transfer a GLubyte texture image with component swizzling.
|
||||
*/
|
||||
@@ -607,7 +758,12 @@ static void
|
||||
_mesa_swizzle_ubyte_image(GLcontext *ctx,
|
||||
GLuint dimensions,
|
||||
GLenum srcFormat,
|
||||
const GLubyte *dstmap, GLint dstComponents,
|
||||
GLenum srcType,
|
||||
|
||||
GLenum baseInternalFormat,
|
||||
|
||||
const GLubyte *rgba2dst,
|
||||
GLuint dstComponents,
|
||||
|
||||
GLvoid *dstAddr,
|
||||
GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
|
||||
@@ -619,9 +775,9 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx,
|
||||
const struct gl_pixelstore_attrib *srcPacking )
|
||||
{
|
||||
GLint srcComponents = _mesa_components_in_format(srcFormat);
|
||||
GLubyte srcmap[6], map[4];
|
||||
const GLubyte *srctype2ubyte, *swap;
|
||||
GLubyte map[4], src2base[6], base2rgba[6];
|
||||
GLint i;
|
||||
|
||||
const GLint srcRowStride =
|
||||
_mesa_image_row_stride(srcPacking, srcWidth,
|
||||
srcFormat, GL_UNSIGNED_BYTE);
|
||||
@@ -635,10 +791,20 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx,
|
||||
|
||||
(void) ctx;
|
||||
|
||||
compute_component_mapping(srcFormat, GL_RGBA, srcmap);
|
||||
/* Translate from src->baseInternal->GL_RGBA->dst. This will
|
||||
* correctly deal with RGBA->RGB->RGBA conversions where the final
|
||||
* A value must be 0xff regardless of the incoming alpha values.
|
||||
*/
|
||||
compute_component_mapping(srcFormat, baseInternalFormat, src2base);
|
||||
compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba);
|
||||
swap = byteswap_mapping(srcPacking->SwapBytes, srcType);
|
||||
srctype2ubyte = type_mapping(srcType);
|
||||
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
map[i] = srcmap[dstmap[i]];
|
||||
map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]];
|
||||
|
||||
/* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */
|
||||
|
||||
if (srcRowStride == srcWidth * srcComponents &&
|
||||
dimensions < 3) {
|
||||
@@ -817,6 +983,59 @@ _mesa_texstore_rgba(TEXSTORE_PARAMS)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
_mesa_little_endian() &&
|
||||
CHAN_TYPE == GL_UNSIGNED_BYTE &&
|
||||
(srcType == GL_UNSIGNED_BYTE ||
|
||||
srcType == GL_UNSIGNED_INT_8_8_8_8 ||
|
||||
srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
|
||||
can_swizzle(baseInternalFormat) &&
|
||||
can_swizzle(srcFormat)) {
|
||||
|
||||
const GLubyte *dstmap;
|
||||
GLuint components;
|
||||
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
if (dstFormat == &_mesa_texformat_rgba) {
|
||||
dstmap = mappings[IDX_RGBA].from_rgba;
|
||||
components = 4;
|
||||
}
|
||||
else if (dstFormat == &_mesa_texformat_rgb) {
|
||||
dstmap = mappings[IDX_RGB].from_rgba;
|
||||
components = 3;
|
||||
}
|
||||
else if (dstFormat == &_mesa_texformat_alpha) {
|
||||
dstmap = mappings[IDX_ALPHA].from_rgba;
|
||||
components = 1;
|
||||
}
|
||||
else if (dstFormat == &_mesa_texformat_luminance) {
|
||||
dstmap = mappings[IDX_LUMINANCE].from_rgba;
|
||||
components = 1;
|
||||
}
|
||||
else if (dstFormat == &_mesa_texformat_luminance_alpha) {
|
||||
dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba;
|
||||
components = 2;
|
||||
}
|
||||
else if (dstFormat == &_mesa_texformat_intensity) {
|
||||
dstmap = mappings[IDX_INTENSITY].from_rgba;
|
||||
components = 1;
|
||||
}
|
||||
else {
|
||||
_mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba");
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
srcFormat,
|
||||
srcType,
|
||||
baseInternalFormat,
|
||||
dstmap, components,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcAddr,
|
||||
srcPacking);
|
||||
}
|
||||
else {
|
||||
/* general path */
|
||||
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
|
||||
@@ -1050,13 +1269,14 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
|
||||
*/
|
||||
GLboolean
|
||||
_mesa_texstore_rgba8888(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLuint ui = 1;
|
||||
const GLubyte littleEndian = *((const GLubyte *) &ui);
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
|
||||
(void)littleEndian;
|
||||
ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
|
||||
dstFormat == &_mesa_texformat_rgba8888_rev);
|
||||
ASSERT(dstFormat->TexelBytes == 4);
|
||||
@@ -1066,7 +1286,9 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
|
||||
dstFormat == &_mesa_texformat_rgba8888 &&
|
||||
baseInternalFormat == GL_RGBA &&
|
||||
((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
|
||||
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) {
|
||||
(srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
|
||||
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
|
||||
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) {
|
||||
/* simple memcpy path */
|
||||
memcpy_texture(ctx, dims,
|
||||
dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
@@ -1075,40 +1297,57 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
|
||||
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
}
|
||||
#if 0
|
||||
/* broken? */
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
!srcPacking->SwapBytes &&
|
||||
srcType == GL_UNSIGNED_BYTE &&
|
||||
dstFormat == &_mesa_texformat_rgba8888 &&
|
||||
dstFormat == &_mesa_texformat_rgba8888_rev &&
|
||||
baseInternalFormat == GL_RGBA &&
|
||||
((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) ||
|
||||
(srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) ||
|
||||
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
|
||||
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) {
|
||||
/* simple memcpy path */
|
||||
memcpy_texture(ctx, dims,
|
||||
dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride,
|
||||
dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
}
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
littleEndian &&
|
||||
/* Three texture formats involved: srcFormat,
|
||||
* baseInternalFormat and destFormat (GL_RGBA). Only two
|
||||
* may differ. _mesa_swizzle_ubyte_image can't handle two
|
||||
* propagations at once correctly. */
|
||||
(srcFormat == baseInternalFormat ||
|
||||
baseInternalFormat == GL_RGBA) &&
|
||||
(srcType == GL_UNSIGNED_BYTE ||
|
||||
srcType == GL_UNSIGNED_INT_8_8_8_8 ||
|
||||
srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
|
||||
can_swizzle(baseInternalFormat) &&
|
||||
can_swizzle(srcFormat)) {
|
||||
|
||||
GLubyte dstmap[4];
|
||||
|
||||
/* dstmap - how to swizzle from GL_RGBA to dst format:
|
||||
*
|
||||
* FIXME - add !litteEndian and _rev varients:
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
if (dstFormat == &_mesa_texformat_rgba8888) {
|
||||
dstmap[3] = 0;
|
||||
dstmap[2] = 1;
|
||||
dstmap[1] = 2;
|
||||
dstmap[0] = 3;
|
||||
}
|
||||
else {
|
||||
dstmap[3] = 3;
|
||||
dstmap[2] = 2;
|
||||
dstmap[1] = 1;
|
||||
dstmap[0] = 0;
|
||||
}
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
srcFormat,
|
||||
srcType,
|
||||
baseInternalFormat,
|
||||
dstmap, 4,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageStride,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcAddr,
|
||||
srcPacking);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
/* general path */
|
||||
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
|
||||
@@ -1159,8 +1398,7 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS)
|
||||
GLboolean
|
||||
_mesa_texstore_argb8888(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLuint ui = 1;
|
||||
const GLubyte littleEndian = *((const GLubyte *) &ui);
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
|
||||
dstFormat == &_mesa_texformat_argb8888_rev);
|
||||
@@ -1200,6 +1438,8 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
|
||||
!srcPacking->SwapBytes &&
|
||||
dstFormat == &_mesa_texformat_argb8888 &&
|
||||
srcFormat == GL_RGB &&
|
||||
(baseInternalFormat == GL_RGBA ||
|
||||
baseInternalFormat == GL_RGB) &&
|
||||
srcType == GL_UNSIGNED_BYTE) {
|
||||
|
||||
int img, row, col;
|
||||
@@ -1228,6 +1468,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
|
||||
!srcPacking->SwapBytes &&
|
||||
dstFormat == &_mesa_texformat_argb8888 &&
|
||||
srcFormat == GL_RGBA &&
|
||||
baseInternalFormat == GL_RGBA &&
|
||||
(srcType == GL_UNSIGNED_BYTE && littleEndian)) {
|
||||
GLint img, row, col;
|
||||
/* For some reason, streaming copies to write-combined regions
|
||||
@@ -1262,6 +1503,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
|
||||
!srcPacking->SwapBytes &&
|
||||
dstFormat == &_mesa_texformat_argb8888 &&
|
||||
srcFormat == GL_RGBA &&
|
||||
baseInternalFormat == GL_RGBA &&
|
||||
srcType == GL_UNSIGNED_BYTE) {
|
||||
|
||||
GLint img, row, col;
|
||||
@@ -1287,29 +1529,36 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
|
||||
}
|
||||
}
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
!srcPacking->SwapBytes &&
|
||||
dstFormat == &_mesa_texformat_argb8888 &&
|
||||
srcType == GL_UNSIGNED_BYTE &&
|
||||
littleEndian &&
|
||||
/* Three texture formats involved: srcFormat,
|
||||
* baseInternalFormat and destFormat (GL_RGBA). Only two
|
||||
* may differ. _mesa_swizzle_ubyte_image can't handle two
|
||||
* propagations at once correctly. */
|
||||
(srcFormat == baseInternalFormat ||
|
||||
baseInternalFormat == GL_RGBA) &&
|
||||
(srcType == GL_UNSIGNED_BYTE ||
|
||||
srcType == GL_UNSIGNED_INT_8_8_8_8 ||
|
||||
srcType == GL_UNSIGNED_INT_8_8_8_8_REV) &&
|
||||
can_swizzle(baseInternalFormat) &&
|
||||
can_swizzle(srcFormat)) {
|
||||
|
||||
GLubyte dstmap[4];
|
||||
|
||||
/* dstmap - how to swizzle from GL_RGBA to dst format:
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
if (dstFormat == &_mesa_texformat_argb8888) {
|
||||
dstmap[3] = 3; /* alpha */
|
||||
dstmap[2] = 0; /* red */
|
||||
dstmap[1] = 1; /* green */
|
||||
dstmap[0] = 2; /* blue */
|
||||
}
|
||||
else {
|
||||
assert(dstFormat == &_mesa_texformat_argb8888_rev);
|
||||
dstmap[3] = 2;
|
||||
dstmap[2] = 1;
|
||||
dstmap[1] = 0;
|
||||
dstmap[0] = 3;
|
||||
}
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
srcFormat,
|
||||
srcType,
|
||||
|
||||
baseInternalFormat,
|
||||
dstmap, 4,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride,
|
||||
@@ -1367,8 +1616,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS)
|
||||
GLboolean
|
||||
_mesa_texstore_rgb888(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLuint ui = 1;
|
||||
const GLubyte littleEndian = *((const GLubyte *) &ui);
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_rgb888);
|
||||
ASSERT(dstFormat->TexelBytes == 3);
|
||||
@@ -1413,6 +1661,31 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
littleEndian &&
|
||||
srcType == GL_UNSIGNED_BYTE &&
|
||||
can_swizzle(baseInternalFormat) &&
|
||||
can_swizzle(srcFormat)) {
|
||||
|
||||
GLubyte dstmap[4];
|
||||
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
dstmap[0] = 2;
|
||||
dstmap[1] = 1;
|
||||
dstmap[2] = 0;
|
||||
dstmap[3] = ONE; /* ? */
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
srcFormat,
|
||||
srcType,
|
||||
baseInternalFormat,
|
||||
dstmap, 3,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcAddr,
|
||||
srcPacking);
|
||||
}
|
||||
else {
|
||||
/* general path */
|
||||
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
|
||||
@@ -1469,8 +1742,7 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS)
|
||||
GLboolean
|
||||
_mesa_texstore_bgr888(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLuint ui = 1;
|
||||
const GLubyte littleEndian = *((const GLubyte *) &ui);
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_bgr888);
|
||||
ASSERT(dstFormat->TexelBytes == 3);
|
||||
@@ -1515,6 +1787,31 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
littleEndian &&
|
||||
srcType == GL_UNSIGNED_BYTE &&
|
||||
can_swizzle(baseInternalFormat) &&
|
||||
can_swizzle(srcFormat)) {
|
||||
|
||||
GLubyte dstmap[4];
|
||||
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
dstmap[0] = 0;
|
||||
dstmap[1] = 1;
|
||||
dstmap[2] = 2;
|
||||
dstmap[3] = ONE; /* ? */
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
srcFormat,
|
||||
srcType,
|
||||
baseInternalFormat,
|
||||
dstmap, 3,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcAddr,
|
||||
srcPacking);
|
||||
}
|
||||
else {
|
||||
/* general path */
|
||||
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
|
||||
@@ -1689,8 +1986,7 @@ _mesa_texstore_argb1555(TEXSTORE_PARAMS)
|
||||
GLboolean
|
||||
_mesa_texstore_al88(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLuint ui = 1;
|
||||
const GLubyte littleEndian = *((const GLubyte *) &ui);
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_al88 ||
|
||||
dstFormat == &_mesa_texformat_al88_rev);
|
||||
@@ -1711,6 +2007,37 @@ _mesa_texstore_al88(TEXSTORE_PARAMS)
|
||||
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
}
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
littleEndian &&
|
||||
srcType == GL_UNSIGNED_BYTE &&
|
||||
can_swizzle(baseInternalFormat) &&
|
||||
can_swizzle(srcFormat)) {
|
||||
|
||||
GLubyte dstmap[4];
|
||||
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
if (dstFormat == &_mesa_texformat_al88) {
|
||||
dstmap[0] = 0;
|
||||
dstmap[1] = 3;
|
||||
}
|
||||
else {
|
||||
dstmap[0] = 3;
|
||||
dstmap[1] = 0;
|
||||
}
|
||||
dstmap[2] = ZERO; /* ? */
|
||||
dstmap[3] = ONE; /* ? */
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
srcFormat,
|
||||
srcType,
|
||||
baseInternalFormat,
|
||||
dstmap, 2,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcAddr,
|
||||
srcPacking);
|
||||
}
|
||||
else {
|
||||
/* general path */
|
||||
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
|
||||
@@ -1831,6 +2158,36 @@ _mesa_texstore_a8(TEXSTORE_PARAMS)
|
||||
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
}
|
||||
else if (!ctx->_ImageTransferState &&
|
||||
_mesa_little_endian() &&
|
||||
srcType == GL_UNSIGNED_BYTE &&
|
||||
can_swizzle(baseInternalFormat) &&
|
||||
can_swizzle(srcFormat)) {
|
||||
|
||||
GLubyte dstmap[4];
|
||||
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
if (dstFormat == &_mesa_texformat_a8) {
|
||||
dstmap[0] = 3;
|
||||
}
|
||||
else {
|
||||
dstmap[0] = 0;
|
||||
}
|
||||
dstmap[1] = ZERO; /* ? */
|
||||
dstmap[2] = ZERO; /* ? */
|
||||
dstmap[3] = ONE; /* ? */
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
srcFormat,
|
||||
srcType,
|
||||
baseInternalFormat,
|
||||
dstmap, 1,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcAddr,
|
||||
srcPacking);
|
||||
}
|
||||
else {
|
||||
/* general path */
|
||||
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
|
||||
@@ -1912,8 +2269,7 @@ _mesa_texstore_ci8(TEXSTORE_PARAMS)
|
||||
GLboolean
|
||||
_mesa_texstore_ycbcr(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLuint ui = 1;
|
||||
const GLubyte littleEndian = *((const GLubyte *) &ui);
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
(void) ctx; (void) dims; (void) baseInternalFormat;
|
||||
|
||||
ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
|
||||
@@ -2164,6 +2520,113 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS)
|
||||
}
|
||||
|
||||
|
||||
#if FEATURE_EXT_texture_sRGB
|
||||
GLboolean
|
||||
_mesa_texstore_srgb8(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
const struct gl_texture_format *newDstFormat;
|
||||
StoreTexImageFunc store;
|
||||
GLboolean k;
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_srgb8);
|
||||
|
||||
/* reuse normal rgb texstore code */
|
||||
if (littleEndian) {
|
||||
newDstFormat = &_mesa_texformat_bgr888;
|
||||
store = _mesa_texstore_bgr888;
|
||||
}
|
||||
else {
|
||||
newDstFormat = &_mesa_texformat_rgb888;
|
||||
store = _mesa_texstore_rgb888;
|
||||
}
|
||||
|
||||
k = store(ctx, dims, baseInternalFormat,
|
||||
newDstFormat, dstAddr,
|
||||
dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
GLboolean
|
||||
_mesa_texstore_srgba8(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
const struct gl_texture_format *newDstFormat;
|
||||
GLboolean k;
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_srgba8);
|
||||
|
||||
/* reuse normal rgba texstore code */
|
||||
if (littleEndian)
|
||||
newDstFormat = &_mesa_texformat_rgba8888_rev;
|
||||
else
|
||||
newDstFormat = &_mesa_texformat_rgba8888;
|
||||
|
||||
k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat,
|
||||
newDstFormat, dstAddr,
|
||||
dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
GLboolean
|
||||
_mesa_texstore_sl8(TEXSTORE_PARAMS)
|
||||
{
|
||||
const struct gl_texture_format *newDstFormat;
|
||||
GLboolean k;
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_sl8);
|
||||
|
||||
newDstFormat = &_mesa_texformat_l8;
|
||||
|
||||
/* _mesa_textore_a8 handles luminance8 too */
|
||||
k = _mesa_texstore_a8(ctx, dims, baseInternalFormat,
|
||||
newDstFormat, dstAddr,
|
||||
dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
GLboolean
|
||||
_mesa_texstore_sla8(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
const struct gl_texture_format *newDstFormat;
|
||||
GLboolean k;
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_sla8);
|
||||
|
||||
/* reuse normal luminance/alpha texstore code */
|
||||
if (littleEndian)
|
||||
newDstFormat = &_mesa_texformat_al88;
|
||||
else
|
||||
newDstFormat = &_mesa_texformat_al88_rev;
|
||||
|
||||
k = _mesa_texstore_al88(ctx, dims, baseInternalFormat,
|
||||
newDstFormat, dstAddr,
|
||||
dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth,
|
||||
srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
return k;
|
||||
}
|
||||
|
||||
#endif /* FEATURE_EXT_texture_sRGB */
|
||||
|
||||
|
||||
/**
|
||||
* Check if an unpack PBO is active prior to fetching a texture image.
|
||||
|
||||
@@ -98,7 +98,7 @@ _swrast_update_rasterflags( GLcontext *ctx )
|
||||
rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */
|
||||
}
|
||||
|
||||
if (ctx->FragmentProgram._Active) {
|
||||
if (ctx->FragmentProgram._Enabled) {
|
||||
rasterMask |= FRAGPROG_BIT;
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ _swrast_update_fog_state( GLcontext *ctx )
|
||||
|
||||
/* determine if fog is needed, and if so, which fog mode */
|
||||
swrast->_FogEnabled = GL_FALSE;
|
||||
if (ctx->FragmentProgram._Active) {
|
||||
if (ctx->FragmentProgram._Enabled) {
|
||||
if (ctx->FragmentProgram._Current->Base.Target==GL_FRAGMENT_PROGRAM_ARB) {
|
||||
const struct gl_fragment_program *fp
|
||||
= ctx->FragmentProgram._Current;
|
||||
@@ -230,7 +230,7 @@ _swrast_update_fog_state( GLcontext *ctx )
|
||||
static void
|
||||
_swrast_update_fragment_program( GLcontext *ctx )
|
||||
{
|
||||
if (ctx->FragmentProgram._Active) {
|
||||
if (ctx->FragmentProgram._Enabled) {
|
||||
const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
|
||||
_mesa_load_state_parameters(ctx, fp->Base.Parameters);
|
||||
}
|
||||
@@ -299,7 +299,7 @@ _swrast_validate_triangle( GLcontext *ctx,
|
||||
|
||||
if (ctx->Texture._EnabledUnits == 0
|
||||
&& NEED_SECONDARY_COLOR(ctx)
|
||||
&& !ctx->FragmentProgram._Active) {
|
||||
&& !ctx->FragmentProgram._Enabled) {
|
||||
/* separate specular color, but no texture */
|
||||
swrast->SpecTriangle = swrast->Triangle;
|
||||
swrast->Triangle = _swrast_add_spec_terms_triangle;
|
||||
@@ -322,7 +322,7 @@ _swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 )
|
||||
|
||||
if (ctx->Texture._EnabledUnits == 0
|
||||
&& NEED_SECONDARY_COLOR(ctx)
|
||||
&& !ctx->FragmentProgram._Active) {
|
||||
&& !ctx->FragmentProgram._Enabled) {
|
||||
swrast->SpecLine = swrast->Line;
|
||||
swrast->Line = _swrast_add_spec_terms_line;
|
||||
}
|
||||
@@ -345,7 +345,7 @@ _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 )
|
||||
|
||||
if (ctx->Texture._EnabledUnits == 0
|
||||
&& NEED_SECONDARY_COLOR(ctx)
|
||||
&& !ctx->FragmentProgram._Active) {
|
||||
&& !ctx->FragmentProgram._Enabled) {
|
||||
swrast->SpecPoint = swrast->Point;
|
||||
swrast->Point = _swrast_add_spec_terms_point;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ _swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span )
|
||||
GLuint i;
|
||||
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
|
||||
const GLfloat *tc = ctx->Current.RasterTexCoords[i];
|
||||
if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled) {
|
||||
if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled) {
|
||||
COPY_4V(span->tex[i], tc);
|
||||
}
|
||||
else if (tc[3] > 0.0F) {
|
||||
@@ -410,7 +410,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
|
||||
if (obj) {
|
||||
const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
|
||||
needLambda = (obj->MinFilter != obj->MagFilter)
|
||||
|| ctx->FragmentProgram._Active;
|
||||
|| ctx->FragmentProgram._Enabled;
|
||||
texW = img->WidthScale;
|
||||
texH = img->HeightScale;
|
||||
}
|
||||
@@ -435,7 +435,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
|
||||
GLfloat r = span->tex[u][2];
|
||||
GLfloat q = span->tex[u][3];
|
||||
GLuint i;
|
||||
if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
|
||||
if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
|
||||
ctx->ShaderObjects._FragmentShaderPresent) {
|
||||
/* do perspective correction but don't divide s, t, r by q */
|
||||
const GLfloat dwdx = span->dwdx;
|
||||
@@ -487,7 +487,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
|
||||
GLfloat r = span->tex[u][2];
|
||||
GLfloat q = span->tex[u][3];
|
||||
GLuint i;
|
||||
if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
|
||||
if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
|
||||
ctx->ShaderObjects._FragmentShaderPresent) {
|
||||
/* do perspective correction but don't divide s, t, r by q */
|
||||
const GLfloat dwdx = span->dwdx;
|
||||
@@ -546,7 +546,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
|
||||
if (obj) {
|
||||
const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
|
||||
needLambda = (obj->MinFilter != obj->MagFilter)
|
||||
|| ctx->FragmentProgram._Active;
|
||||
|| ctx->FragmentProgram._Enabled;
|
||||
texW = (GLfloat) img->WidthScale;
|
||||
texH = (GLfloat) img->HeightScale;
|
||||
}
|
||||
@@ -571,7 +571,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
|
||||
GLfloat r = span->tex[0][2];
|
||||
GLfloat q = span->tex[0][3];
|
||||
GLuint i;
|
||||
if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
|
||||
if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
|
||||
ctx->ShaderObjects._FragmentShaderPresent) {
|
||||
/* do perspective correction but don't divide s, t, r by q */
|
||||
const GLfloat dwdx = span->dwdx;
|
||||
@@ -623,7 +623,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
|
||||
GLfloat r = span->tex[0][2];
|
||||
GLfloat q = span->tex[0][3];
|
||||
GLuint i;
|
||||
if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
|
||||
if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
|
||||
ctx->ShaderObjects._FragmentShaderPresent) {
|
||||
/* do perspective correction but don't divide s, t, r by q */
|
||||
const GLfloat dwdx = span->dwdx;
|
||||
@@ -1120,7 +1120,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
|
||||
const GLbitfield origInterpMask = span->interpMask;
|
||||
const GLbitfield origArrayMask = span->arrayMask;
|
||||
const GLboolean deferredTexture = !(ctx->Color.AlphaEnabled ||
|
||||
ctx->FragmentProgram._Active ||
|
||||
ctx->FragmentProgram._Enabled ||
|
||||
ctx->ShaderObjects._FragmentShaderPresent);
|
||||
|
||||
ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE ||
|
||||
@@ -1197,15 +1197,12 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
|
||||
interpolate_fog(ctx, span);
|
||||
|
||||
/* Compute fragment colors with fragment program or texture lookups */
|
||||
#if FEATURE_ARB_fragment_shader
|
||||
if (ctx->ShaderObjects._FragmentShaderPresent) {
|
||||
if (span->interpMask & SPAN_Z)
|
||||
_swrast_span_interpolate_z (ctx, span);
|
||||
_swrast_exec_arbshader (ctx, span);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (ctx->FragmentProgram._Active) {
|
||||
else if (ctx->FragmentProgram._Enabled) {
|
||||
/* frag prog may need Z values */
|
||||
if (span->interpMask & SPAN_Z)
|
||||
_swrast_span_interpolate_z(ctx, span);
|
||||
@@ -1284,15 +1281,12 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
|
||||
if (span->interpMask & SPAN_FOG)
|
||||
interpolate_fog(ctx, span);
|
||||
|
||||
#if FEATURE_ARB_fragment_shader
|
||||
if (ctx->ShaderObjects._FragmentShaderPresent) {
|
||||
if (span->interpMask & SPAN_Z)
|
||||
_swrast_span_interpolate_z (ctx, span);
|
||||
_swrast_exec_arbshader (ctx, span);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (ctx->FragmentProgram._Active)
|
||||
else if (ctx->FragmentProgram._Enabled)
|
||||
_swrast_exec_fragment_program( ctx, span );
|
||||
else if (ctx->ATIFragmentShader._Enabled)
|
||||
_swrast_exec_fragment_shader( ctx, span );
|
||||
|
||||
@@ -1072,7 +1072,7 @@ _swrast_choose_triangle( GLcontext *ctx )
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Active ||
|
||||
if (ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Enabled ||
|
||||
ctx->ATIFragmentShader._Enabled || ctx->ShaderObjects._FragmentShaderPresent) {
|
||||
/* Ugh, we do a _lot_ of tests to pick the best textured tri func */
|
||||
const struct gl_texture_object *texObj2D;
|
||||
@@ -1088,7 +1088,7 @@ _swrast_choose_triangle( GLcontext *ctx )
|
||||
|
||||
/* First see if we can use an optimized 2-D texture function */
|
||||
if (ctx->Texture._EnabledCoordUnits == 0x1
|
||||
&& !ctx->FragmentProgram._Active
|
||||
&& !ctx->FragmentProgram._Enabled
|
||||
&& !ctx->ATIFragmentShader._Enabled
|
||||
&& !ctx->ShaderObjects._FragmentShaderPresent
|
||||
&& ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
|
||||
|
||||
Reference in New Issue
Block a user