Compare commits
	
		
			53 Commits
		
	
	
		
			mesa-18.1.
			...
			texman_0_1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | b3b325e560 | ||
|  | 382ce985ac | ||
|  | 54b7eca7a0 | ||
|  | f74e06bf11 | ||
|  | 9c02649d18 | ||
|  | 2c34704e41 | ||
|  | 85d0041ff0 | ||
|  | 67ff8b354e | ||
|  | 08e7957571 | ||
|  | 9c1f7089d8 | ||
|  | 5381ac5f11 | ||
|  | a6f78d4eee | ||
|  | ae695e3566 | ||
|  | c82c3335e1 | ||
|  | f8246f504b | ||
|  | 499458bcdb | ||
|  | 37a53fd6a0 | ||
|  | 5ec38fb2ea | ||
|  | 11c0215bf8 | ||
|  | 6a13b6c346 | ||
|  | a103097ee5 | ||
|  | 7efad0d84c | ||
|  | 42c88cd072 | ||
|  | 2541c54e79 | ||
|  | 33529e3d8e | ||
|  | 84c1b82081 | ||
|  | a97a1439ae | ||
|  | 2fd2910010 | ||
|  | fbbda155e0 | ||
|  | a49c3c0fae | ||
|  | baf5998d59 | ||
|  | 4c5acef241 | ||
|  | 9839e272cf | ||
|  | b57e79ff14 | ||
|  | 43824acb4e | ||
|  | d8f509e749 | ||
|  | eb91c93c2e | ||
|  | 79de983b6f | ||
|  | fdb3acf016 | ||
|  | 2807d1f58a | ||
|  | 93f913926e | ||
|  | 33ca04f379 | ||
|  | 398cb30c72 | ||
|  | f67bb30314 | ||
|  | 4578d7b9f0 | ||
|  | dcdfc154c3 | ||
|  | 696ba32779 | ||
|  | dcfe55539f | ||
|  | ff84b1f1b2 | ||
|  | 3bca9c47f4 | ||
|  | d4d7fdb43b | ||
|  | d65dab5777 | ||
|  | 638ca019ef | 
| @@ -9,7 +9,7 @@ CONFIG_NAME = linux-dri | ||||
| CC = gcc | ||||
| CXX = g++ | ||||
|  | ||||
| MKDEP = /usr/X11R6/bin/makedepend | ||||
| #MKDEP = /usr/X11R6/bin/makedepend | ||||
| #MKDEP = gcc -M | ||||
| #MKDEP_OPTIONS = -MF depend | ||||
|  | ||||
| @@ -63,5 +63,7 @@ WINDOW_SYSTEM=dri | ||||
|  | ||||
| # gamma are missing because they have not been converted to use the new | ||||
| # interface. | ||||
| DRI_DIRS = i810 i830 i915 mach64 mga r128 r200 r300 radeon s3v \ | ||||
| DRI_DIRS = i810 i915 mach64 mga r128 r200 r300 radeon s3v \ | ||||
| 	savage sis tdfx trident unichrome ffb | ||||
|  | ||||
| DRI_DIRS = i915  | ||||
|   | ||||
| @@ -25,6 +25,7 @@ PROGS = \ | ||||
| 	fplight \ | ||||
| 	gamma \ | ||||
| 	gears \ | ||||
| 	gearbox \ | ||||
| 	geartrain \ | ||||
| 	glinfo \ | ||||
| 	gloss \ | ||||
| @@ -51,7 +52,7 @@ PROGS = \ | ||||
| 	terrain \ | ||||
| 	tessdemo \ | ||||
| 	texcyl \ | ||||
| 	texdown \ | ||||
| 	texdown-pool \ | ||||
| 	texenv \ | ||||
| 	texobj \ | ||||
| 	trispd \ | ||||
| @@ -73,9 +74,8 @@ PROGS = \ | ||||
|  | ||||
| ##### TARGETS ##### | ||||
|  | ||||
| default: $(PROGS) | ||||
| default: readtex.o $(PROGS) | ||||
|  | ||||
| $(PROGS): readtex.o | ||||
|  | ||||
| readtex.c: $(TOP)/progs/util/readtex.c | ||||
| 	cp $< . | ||||
|   | ||||
							
								
								
									
										486
									
								
								progs/demos/gearbox.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								progs/demos/gearbox.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,486 @@ | ||||
| /* | ||||
|  * Use glCopyTexSubImage2D to draw animated gears on the sides of a box. | ||||
|  * | ||||
|  * Brian Paul | ||||
|  * 27 January 2006 | ||||
|  */ | ||||
|  | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| #ifndef M_PI | ||||
| #define M_PI 3.14159265 | ||||
| #endif | ||||
|  | ||||
| static GLint WinWidth = 800, WinHeight = 500; | ||||
| static GLint TexWidth, TexHeight; | ||||
| static GLuint TexObj = 1; | ||||
| static GLenum IntFormat = GL_RGBA; | ||||
|  | ||||
| static GLboolean WireFrame = GL_FALSE; | ||||
|  | ||||
| static GLint T0 = 0; | ||||
| static GLint Frames = 0; | ||||
| static GLint Win = 0; | ||||
|  | ||||
| static GLfloat ViewRotX = 20.0, ViewRotY = 30.0, ViewRotZ = 0.0; | ||||
| static GLint Gear1, Gear2, Gear3; | ||||
| static GLfloat GearRot = 0.0; | ||||
| static GLfloat CubeRot = 0.0; | ||||
|  | ||||
|  | ||||
| /** | ||||
|   Draw a gear wheel.  You'll probably want to call this function when | ||||
|   building a display list since we do a lot of trig here. | ||||
|   | ||||
|   Input:  inner_radius - radius of hole at center | ||||
|           outer_radius - radius at center of teeth | ||||
|           width - width of gear | ||||
|           teeth - number of teeth | ||||
|           tooth_depth - depth of tooth | ||||
|  **/ | ||||
| static void | ||||
| gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, | ||||
|      GLint teeth, GLfloat tooth_depth) | ||||
| { | ||||
|   GLint i; | ||||
|   GLfloat r0, r1, r2; | ||||
|   GLfloat angle, da; | ||||
|   GLfloat u, v, len; | ||||
|  | ||||
|   r0 = inner_radius; | ||||
|   r1 = outer_radius - tooth_depth / 2.0; | ||||
|   r2 = outer_radius + tooth_depth / 2.0; | ||||
|  | ||||
|   da = 2.0 * M_PI / teeth / 4.0; | ||||
|  | ||||
|   glShadeModel(GL_FLAT); | ||||
|  | ||||
|   glNormal3f(0.0, 0.0, 1.0); | ||||
|  | ||||
|   /* draw front face */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i <= teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); | ||||
|     if (i < teeth) { | ||||
|       glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); | ||||
|       glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); | ||||
|     } | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   /* draw front sides of teeth */ | ||||
|   glBegin(GL_QUADS); | ||||
|   da = 2.0 * M_PI / teeth / 4.0; | ||||
|   for (i = 0; i < teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|  | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   glNormal3f(0.0, 0.0, -1.0); | ||||
|  | ||||
|   /* draw back face */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i <= teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); | ||||
|     if (i < teeth) { | ||||
|       glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); | ||||
|       glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); | ||||
|     } | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   /* draw back sides of teeth */ | ||||
|   glBegin(GL_QUADS); | ||||
|   da = 2.0 * M_PI / teeth / 4.0; | ||||
|   for (i = 0; i < teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|  | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   /* draw outward faces of teeth */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i < teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|  | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); | ||||
|     u = r2 * cos(angle + da) - r1 * cos(angle); | ||||
|     v = r2 * sin(angle + da) - r1 * sin(angle); | ||||
|     len = sqrt(u * u + v * v); | ||||
|     u /= len; | ||||
|     v /= len; | ||||
|     glNormal3f(v, -u, 0.0); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); | ||||
|     glNormal3f(cos(angle), sin(angle), 0.0); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); | ||||
|     u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); | ||||
|     v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); | ||||
|     glNormal3f(v, -u, 0.0); | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); | ||||
|     glNormal3f(cos(angle), sin(angle), 0.0); | ||||
|   } | ||||
|  | ||||
|   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); | ||||
|   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); | ||||
|  | ||||
|   glEnd(); | ||||
|  | ||||
|   glShadeModel(GL_SMOOTH); | ||||
|  | ||||
|   /* draw inside radius cylinder */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i <= teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|     glNormal3f(-cos(angle), -sin(angle), 0.0); | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| cleanup(void) | ||||
| { | ||||
|    glDeleteTextures(1, &TexObj); | ||||
|    glDeleteLists(Gear1, 1); | ||||
|    glDeleteLists(Gear2, 1); | ||||
|    glDeleteLists(Gear3, 1); | ||||
|    glutDestroyWindow(Win); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| DrawGears(void) | ||||
| { | ||||
|    if (WireFrame) { | ||||
|       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
|    } | ||||
|  | ||||
|    glPushMatrix(); | ||||
|       glRotatef(20/*ViewRotX*/, 1.0, 0.0, 0.0); | ||||
|       glRotatef(ViewRotY, 0.0, 1.0, 0.0); | ||||
|       glRotatef(ViewRotZ, 0.0, 0.0, 1.0); | ||||
|  | ||||
|       glPushMatrix(); | ||||
|          glTranslatef(-3.0, -2.0, 0.0); | ||||
|          glRotatef(GearRot, 0.0, 0.0, 1.0); | ||||
|          glCallList(Gear1); | ||||
|       glPopMatrix(); | ||||
|  | ||||
|       glPushMatrix(); | ||||
|          glTranslatef(3.1, -2.0, 0.0); | ||||
|          glRotatef(-2.0 * GearRot - 9.0, 0.0, 0.0, 1.0); | ||||
|          glCallList(Gear2); | ||||
|       glPopMatrix(); | ||||
|  | ||||
|       glPushMatrix(); | ||||
|          glTranslatef(-3.1, 4.2, 0.0); | ||||
|          glRotatef(-2.0 * GearRot - 25.0, 0.0, 0.0, 1.0); | ||||
|          glCallList(Gear3); | ||||
|       glPopMatrix(); | ||||
|  | ||||
|   glPopMatrix(); | ||||
|  | ||||
|   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| DrawCube(void) | ||||
| { | ||||
|    static const GLfloat texcoords[4][2] = { | ||||
|       { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } | ||||
|    }; | ||||
|    static const GLfloat vertices[4][2] = { | ||||
|       { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } | ||||
|    }; | ||||
|    static const GLfloat xforms[6][4] = { | ||||
|       {   0, 0, 1, 0 }, | ||||
|       {  90, 0, 1, 0 }, | ||||
|       { 180, 0, 1, 0 }, | ||||
|       { 270, 0, 1, 0 }, | ||||
|       {  90, 1, 0, 0 }, | ||||
|       { -90, 1, 0, 0 } | ||||
|    }; | ||||
|    static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 }; | ||||
|    GLint i, j; | ||||
|  | ||||
|    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat); | ||||
|    glEnable(GL_TEXTURE_2D); | ||||
|  | ||||
|    glPushMatrix(); | ||||
|       glRotatef(ViewRotX, 1.0, 0.0, 0.0); | ||||
|       glRotatef(15, 1, 0, 0); | ||||
|       glRotatef(CubeRot, 0, 1, 0); | ||||
|       glScalef(4, 4, 4); | ||||
|  | ||||
|       for (i = 0; i < 6; i++) { | ||||
|          glPushMatrix(); | ||||
|             glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]); | ||||
|             glTranslatef(0, 0, 1.1); | ||||
|             glBegin(GL_POLYGON); | ||||
|                glNormal3f(0, 0, 1); | ||||
|                for (j = 0; j < 4; j++) { | ||||
|                   glTexCoord2fv(texcoords[j]); | ||||
|                   glVertex2fv(vertices[j]); | ||||
|                } | ||||
|             glEnd(); | ||||
|          glPopMatrix(); | ||||
|       } | ||||
|    glPopMatrix(); | ||||
|  | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| draw(void) | ||||
| { | ||||
|    float ar; | ||||
|  | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|    glLoadIdentity(); | ||||
|    glTranslatef(0.0, 0.0, -40.0); | ||||
|  | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|    glClear(GL_DEPTH_BUFFER_BIT); | ||||
|    glEnable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    /* draw gears */ | ||||
|    glViewport(0, 0, TexWidth, TexHeight); | ||||
|    glScissor(0, 0, TexWidth, TexHeight); | ||||
|    glClearColor(0.5, 0.5, 0.8, 0.0); | ||||
|    glClearColor(1, 1, 1, 0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT); | ||||
|  | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 60.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|  | ||||
|    DrawGears(); | ||||
|  | ||||
|    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight); | ||||
|     | ||||
|    /* draw textured cube */ | ||||
|    glViewport(TexWidth, 0, WinWidth - TexWidth, WinHeight); | ||||
|    glScissor(TexWidth, 0, WinWidth - TexWidth, WinHeight); | ||||
|    glClearColor(0.5, 0.5, 0.8, 0.0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT); | ||||
|  | ||||
|    ar = (float) (WinWidth - TexWidth) / WinHeight; | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|  | ||||
|    DrawCube(); | ||||
|  | ||||
|    /* finish up */ | ||||
|    glutSwapBuffers(); | ||||
|  | ||||
|    Frames++; | ||||
|    { | ||||
|       GLint t = glutGet(GLUT_ELAPSED_TIME); | ||||
|       if (t - T0 >= 5000) { | ||||
|          GLfloat seconds = (t - T0) / 1000.0; | ||||
|          GLfloat fps = Frames / seconds; | ||||
|          printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); | ||||
|          T0 = t; | ||||
|          Frames = 0; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| idle(void) | ||||
| { | ||||
|   static double t0 = -1.; | ||||
|   double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|   if (t0 < 0.0) | ||||
|     t0 = t; | ||||
|   dt = t - t0; | ||||
|   t0 = t; | ||||
|  | ||||
|   GearRot += 70.0 * dt;  /* 70 degrees per second */ | ||||
|   GearRot = fmod(GearRot, 360.0); /* prevents eventual overflow */ | ||||
|  | ||||
|   CubeRot += 15.0 * dt; | ||||
|  | ||||
|   glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* change view angle, exit upon ESC */ | ||||
| static void | ||||
| key(unsigned char k, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (k) { | ||||
|    case 'w': | ||||
|       WireFrame = !WireFrame; | ||||
|       break; | ||||
|    case 'z': | ||||
|       ViewRotZ += 5.0; | ||||
|       break; | ||||
|    case 'Z': | ||||
|       ViewRotZ -= 5.0; | ||||
|       break; | ||||
|    case 27:  /* Escape */ | ||||
|       cleanup(); | ||||
|       exit(0); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
| /* change view angle */ | ||||
| static void | ||||
| special(int k, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (k) { | ||||
|    case GLUT_KEY_UP: | ||||
|       ViewRotX += 5.0; | ||||
|       break; | ||||
|    case GLUT_KEY_DOWN: | ||||
|       ViewRotX -= 5.0; | ||||
|       break; | ||||
|    case GLUT_KEY_LEFT: | ||||
|       ViewRotY += 5.0; | ||||
|       break; | ||||
|    case GLUT_KEY_RIGHT: | ||||
|       ViewRotY -= 5.0; | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* new window size or exposure */ | ||||
| static void | ||||
| reshape(int width, int height) | ||||
| { | ||||
|   WinWidth = width; | ||||
|   WinHeight = height; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| init(int argc, char *argv[]) | ||||
| { | ||||
|   static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; | ||||
|   static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; | ||||
|   static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; | ||||
|   static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; | ||||
|   GLint i; | ||||
|  | ||||
|   glLightfv(GL_LIGHT0, GL_POSITION, pos); | ||||
| #if 0 | ||||
|   glEnable(GL_CULL_FACE); | ||||
| #endif | ||||
|   glEnable(GL_LIGHTING); | ||||
|   glEnable(GL_LIGHT0); | ||||
|   glEnable(GL_DEPTH_TEST); | ||||
|  | ||||
|   /* make the gears */ | ||||
|   Gear1 = glGenLists(1); | ||||
|   glNewList(Gear1, GL_COMPILE); | ||||
|   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); | ||||
|   gear(1.0, 4.0, 1.0, 20, 0.7); | ||||
|   glEndList(); | ||||
|  | ||||
|   Gear2 = glGenLists(1); | ||||
|   glNewList(Gear2, GL_COMPILE); | ||||
|   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); | ||||
|   gear(0.5, 2.0, 2.0, 10, 0.7); | ||||
|   glEndList(); | ||||
|  | ||||
|   Gear3 = glGenLists(1); | ||||
|   glNewList(Gear3, GL_COMPILE); | ||||
|   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); | ||||
|   gear(1.3, 2.0, 0.5, 10, 0.7); | ||||
|   glEndList(); | ||||
|  | ||||
|   glEnable(GL_NORMALIZE); | ||||
|  | ||||
|   /* xxx make size dynamic */ | ||||
|   TexWidth = 256; | ||||
|   TexHeight = 256; | ||||
|  | ||||
|    glBindTexture(GL_TEXTURE_2D, TexObj); | ||||
|    glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0, | ||||
|                 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||||
|  | ||||
|   for ( i=1; i<argc; i++ ) { | ||||
|     if (strcmp(argv[i], "-info")==0) { | ||||
|       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|       printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION)); | ||||
|       printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR)); | ||||
|       printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void  | ||||
| visible(int vis) | ||||
| { | ||||
|   if (vis == GLUT_VISIBLE) | ||||
|     glutIdleFunc(idle); | ||||
|   else | ||||
|     glutIdleFunc(NULL); | ||||
| } | ||||
|  | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
|    glutInit(&argc, argv); | ||||
|    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); | ||||
|  | ||||
|    glutInitWindowSize(WinWidth, WinHeight); | ||||
|    Win = glutCreateWindow("gearbox"); | ||||
|    init(argc, argv); | ||||
|  | ||||
|    glutDisplayFunc(draw); | ||||
|    glutReshapeFunc(reshape); | ||||
|    glutKeyboardFunc(key); | ||||
|    glutSpecialFunc(special); | ||||
|    glutVisibilityFunc(visible); | ||||
|  | ||||
|    glutMainLoop(); | ||||
|    return 0;             /* ANSI C requires main to return int. */ | ||||
| } | ||||
| @@ -38,8 +38,8 @@ | ||||
| #include <GL/glut.h> | ||||
| 
 | ||||
| 
 | ||||
| static GLsizei MaxSize = 1024; | ||||
| static GLsizei TexWidth = 256, TexHeight = 256, TexBorder = 0; | ||||
| static GLsizei MaxSize = 2048; | ||||
| static GLsizei TexWidth = 1024, TexHeight = 1024, TexBorder = 0; | ||||
| static GLboolean ScaleAndBias = GL_FALSE; | ||||
| static GLboolean SubImage = GL_FALSE; | ||||
| static GLdouble DownloadRate = 0.0;  /* texels/sec */ | ||||
| @@ -47,6 +47,32 @@ static GLdouble DownloadRate = 0.0;  /* texels/sec */ | ||||
| static GLuint Mode = 0; | ||||
| 
 | ||||
| 
 | ||||
| /* Try and avoid L2 cache effects by cycling through a small number of
 | ||||
|  * textures. | ||||
|  *  | ||||
|  * At the initial size of 1024x1024x4 == 4mbyte, say 8 textures will | ||||
|  * keep us out of most caches at 32mb total. | ||||
|  * | ||||
|  * This turns into a fairly interesting question of what exactly you | ||||
|  * expect to be in cache in normal usage, and what you think should be | ||||
|  * outside.  There's no rules for this, no reason to favour one usage | ||||
|  * over another except what the application you care about happens to | ||||
|  * resemble most closely. | ||||
|  * | ||||
|  * - Should the client texture image be in L2 cache?  Has it just been | ||||
|  *   generated or read from disk? | ||||
|  * - Does the application really use >1 texture, or is it constantly  | ||||
|  *   updating one image in-place? | ||||
|  * | ||||
|  * Different answers will favour different texture upload mechanisms. | ||||
|  * To upload an image that is purely outside of cache, a DMA-based | ||||
|  * upload will probably win, whereas for small, in-cache textures, | ||||
|  * copying looks good. | ||||
|  */ | ||||
| #define NR_TEXOBJ 4 | ||||
| static GLuint TexObj[NR_TEXOBJ]; | ||||
| 
 | ||||
| 
 | ||||
| struct FormatRec { | ||||
|    GLenum Format; | ||||
|    GLenum Type; | ||||
| @@ -116,25 +142,57 @@ TypeStr(GLenum type) | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| /* On x86, there is a performance cliff for memcpy to texture memory
 | ||||
|  * for sources below 64 byte alignment.  We do our best with this in | ||||
|  * the driver, but it is better if the images are correctly aligned to | ||||
|  * start with: | ||||
|  */ | ||||
| #define ALIGN (1<<12) | ||||
| 
 | ||||
| static unsigned align(unsigned value, unsigned a) | ||||
| { | ||||
|    return (value + a - 1) & ~(a-1); | ||||
| } | ||||
| 
 | ||||
| static int MIN2(int a, int b) | ||||
| { | ||||
|    return a < b ? a : b; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| MeasureDownloadRate(void) | ||||
| { | ||||
|    const int w = TexWidth + 2 * TexBorder; | ||||
|    const int h = TexHeight + 2 * TexBorder; | ||||
|    const int bytes = w * h * BytesPerTexel(Format); | ||||
|    const int image_bytes = align(w * h * BytesPerTexel(Format), ALIGN); | ||||
|    const int bytes = image_bytes * NR_TEXOBJ; | ||||
|    GLubyte *orig_texImage, *orig_getImage; | ||||
|    GLubyte *texImage, *getImage; | ||||
|    GLdouble t0, t1, time; | ||||
|    int count; | ||||
|    int i; | ||||
|    int offset = 0; | ||||
|    GLdouble total = 0;		/* ints will tend to overflow */ | ||||
| 
 | ||||
|    texImage = (GLubyte *) malloc(bytes); | ||||
|    getImage = (GLubyte *) malloc(bytes); | ||||
|    if (!texImage || !getImage) { | ||||
|    printf("allocating %d bytes for %d %dx%d images\n", | ||||
| 	  bytes, NR_TEXOBJ, w, h); | ||||
| 
 | ||||
|    orig_texImage = (GLubyte *) malloc(bytes + ALIGN); | ||||
|    orig_getImage = (GLubyte *) malloc(image_bytes + ALIGN); | ||||
|    if (!orig_texImage || !orig_getImage) { | ||||
|       DownloadRate = 0.0; | ||||
|       return; | ||||
|    } | ||||
| 
 | ||||
|    printf("alloc %p %p\n", orig_texImage, orig_getImage); | ||||
| 
 | ||||
|    texImage = (GLubyte *)align((unsigned)orig_texImage, ALIGN); | ||||
|    getImage = (GLubyte *)align((unsigned)orig_getImage, ALIGN);    | ||||
| 
 | ||||
|    for (i = 1; !(((unsigned)texImage) & i); i<<=1) | ||||
|       ; | ||||
|    printf("texture image alignment: %d bytes (%p)\n", i, texImage); | ||||
|        | ||||
|    for (i = 0; i < bytes; i++) { | ||||
|       texImage[i] = i & 0xff; | ||||
|    } | ||||
| @@ -166,51 +224,80 @@ MeasureDownloadRate(void) | ||||
|    count = 0; | ||||
|    t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001; | ||||
|    do { | ||||
|       int img = count%NR_TEXOBJ; | ||||
|       GLubyte *img_ptr = texImage + img * image_bytes; | ||||
| 
 | ||||
|       glBindTexture(GL_TEXTURE_2D, TexObj[img]); | ||||
| 
 | ||||
|       if (SubImage && count > 0) { | ||||
|          glTexSubImage2D(GL_TEXTURE_2D, 0, -TexBorder, -TexBorder, w, h, | ||||
| 	 /* Only update a portion of the image each iteration.  This
 | ||||
| 	  * is presumably why you'd want to use texsubimage, otherwise | ||||
| 	  * you may as well just call teximage again. | ||||
| 	  * | ||||
| 	  * A bigger question is whether to use a pointer that moves | ||||
| 	  * with each call, ie does the incoming data come from L2 | ||||
| 	  * cache under normal circumstances, or is it pulled from | ||||
| 	  * uncached memory?   | ||||
| 	  *  | ||||
| 	  * There's a good argument to say L2 cache, ie you'd expect | ||||
| 	  * the data to have been recently generated.  It's possible | ||||
| 	  * that it could have come from a file read, which may or may | ||||
| 	  * not have gone through the cpu. | ||||
| 	  */ | ||||
|          glTexSubImage2D(GL_TEXTURE_2D, 0,  | ||||
| 			 -TexBorder,  | ||||
| 			 -TexBorder + offset * h/8,  | ||||
| 			 w,  | ||||
| 			 h/8, | ||||
|                          FormatTable[Format].Format, | ||||
|                          FormatTable[Format].Type, texImage); | ||||
|                          FormatTable[Format].Type,  | ||||
| #if 1 | ||||
| 			 texImage /* likely in L2$ */ | ||||
| #else | ||||
| 			 img_ptr + offset * bytes/8 /* unlikely in L2$ */ | ||||
| #endif | ||||
| 	    ); | ||||
| 	 offset += 1; | ||||
| 	 offset %= 8; | ||||
| 	 total += w * h / 8; | ||||
|       } | ||||
|       else { | ||||
|          glTexImage2D(GL_TEXTURE_2D, 0, | ||||
|                       FormatTable[Format].IntFormat, w, h, TexBorder, | ||||
|                       FormatTable[Format].Format, | ||||
|                       FormatTable[Format].Type, texImage); | ||||
|                       FormatTable[Format].Type,  | ||||
| 		      img_ptr); | ||||
| 	 total += w*h; | ||||
|       } | ||||
| 
 | ||||
| #if 1 | ||||
|       /* Render a texture, but not necessarily the one just uploaded.  
 | ||||
|        */ | ||||
| /*       glBindTexture(GL_TEXTURE_2D, TexObj[(img + NR_TEXOBJ/2)%NR_TEXOBJ]); */ | ||||
| 
 | ||||
|       /* draw a tiny polygon to force texture into texram */ | ||||
|       glBegin(GL_TRIANGLES); | ||||
|       glTexCoord2f(0, 0);     glVertex2f(1, 1); | ||||
|       glTexCoord2f(1, 0);     glVertex2f(3, 1); | ||||
|       glTexCoord2f(0.5, 1);   glVertex2f(2, 3); | ||||
|       glEnd(); | ||||
| /*       glFinish(); */ | ||||
| #endif | ||||
| 
 | ||||
|       t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001; | ||||
|       time = t1 - t0; | ||||
|       count++; | ||||
| /*       printf("total %f count %d\n", total, count); */ | ||||
|    } while (time < 3.0); | ||||
| 
 | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
| 
 | ||||
|    printf("w*h=%d  count=%d  time=%f\n", w*h, count, time); | ||||
|    DownloadRate = w * h * count / time; | ||||
|    printf("total texels=%f  time=%f\n", total, time); | ||||
|    DownloadRate = total / time; | ||||
| 
 | ||||
| #if 0 | ||||
|    if (!ScaleAndBias) { | ||||
|       /* verify texture readback */ | ||||
|       glGetTexImage(GL_TEXTURE_2D, 0, | ||||
|                     FormatTable[Format].Format, | ||||
|                     FormatTable[Format].Type, getImage); | ||||
|       for (i = 0; i < w * h; i++) { | ||||
|          if (texImage[i] != getImage[i]) { | ||||
|             printf("[%d] %d != %d\n", i, texImage[i], getImage[i]); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| #endif | ||||
| 
 | ||||
|    free(texImage); | ||||
|    free(getImage); | ||||
|    free(orig_texImage);  | ||||
|    free(orig_getImage);  | ||||
| 
 | ||||
|    { | ||||
|       GLint err = glGetError(); | ||||
| @@ -92,7 +92,7 @@ static void idle( void ) | ||||
|    dt = t - t0; | ||||
|    t0 = t; | ||||
|    Angle += 120.0*dt; | ||||
|    glutPostRedisplay(); | ||||
| /*    glutPostRedisplay(); */ | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -47,6 +47,7 @@ SOURCES = antialias.c \ | ||||
| 	sharedtex.c \ | ||||
| 	stencilwrap.c \ | ||||
| 	stencil_wrap.c \ | ||||
| 	subtexrate.c \ | ||||
| 	tex1d.c \ | ||||
| 	texfilt.c \ | ||||
| 	texline.c \ | ||||
|   | ||||
							
								
								
									
										378
									
								
								progs/tests/subtexrate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								progs/tests/subtexrate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,378 @@ | ||||
| /* | ||||
|  * Measure glTexSubImage and glCopyTexSubImage speed | ||||
|  * | ||||
|  * Brian Paul | ||||
|  * 26 Jan 2006 | ||||
|  */ | ||||
|  | ||||
| #define GL_GLEXT_PROTOTYPES | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <math.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| static GLint WinWidth = 1024, WinHeight = 512; | ||||
| static GLint TexWidth = 512, TexHeight = 512; | ||||
|  | ||||
| static GLuint TexObj = 1; | ||||
|  | ||||
| static GLenum IntFormat = GL_RGBA; | ||||
| static GLenum ReadFormat = GL_BGRA; /* for glReadPixels */ | ||||
|  | ||||
| static GLboolean DrawQuad = GL_TRUE; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * draw teapot image, size TexWidth by TexHeight | ||||
|  */ | ||||
| static void | ||||
| DrawTestImage(void) | ||||
| { | ||||
|    GLfloat ar; | ||||
|  | ||||
|    glViewport(0, 0, TexWidth, TexHeight); | ||||
|    glScissor(0, 0, TexWidth, TexHeight); | ||||
|    glEnable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    glClearColor(0.5, 0.5, 0.5, 0.0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
|  | ||||
|    ar = (float) TexWidth / TexHeight; | ||||
|  | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|  | ||||
|    glEnable(GL_LIGHTING); | ||||
|    glEnable(GL_LIGHT0); | ||||
|    glEnable(GL_DEPTH_TEST); | ||||
|    glFrontFace(GL_CW); | ||||
|    glPushMatrix(); | ||||
|    glRotatef(45, 1, 0, 0); | ||||
|    glRotatef(45, 0, 1, 0); | ||||
|    glutSolidTeapot(2.3); | ||||
|    glPopMatrix(); | ||||
|    glFrontFace(GL_CCW); | ||||
|    glDisable(GL_DEPTH_TEST); | ||||
|    glDisable(GL_LIGHTING); | ||||
|  | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    glViewport(0, 0, WinWidth, WinHeight); | ||||
|    glFinish(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Do glCopyTexSubImage2D call (update texture with framebuffer data) | ||||
|  * If doSubRect is true, do the copy in four pieces instead of all at once. | ||||
|  */ | ||||
| static void | ||||
| DoCopyTex(GLboolean doSubRect) | ||||
| { | ||||
|    if (doSubRect) { | ||||
|       /* copy in four parts */ | ||||
|       int w = TexWidth / 2, h = TexHeight / 2; | ||||
|       int x0 = 0, y0 = 0; | ||||
|       int x1 = w, y1 = h; | ||||
| #if 0 | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x0, y0, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x1, y0, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x0, y1, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x1, y1, w, h); | ||||
| #else | ||||
|       /* scramble */ | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x1, y1, w, h);  | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x0, y1, w, h);  | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x1, y0, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x0, y0, w, h); | ||||
| #endif | ||||
|    } | ||||
|    else { | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Do glTexSubImage2D (update texture w/ user data) | ||||
|  * If doSubRect, do update in four pieces, else all at once. | ||||
|  */ | ||||
| static void | ||||
| SubTex(GLboolean doSubRect, const GLubyte *image) | ||||
| { | ||||
|    if (doSubRect) { | ||||
|       /* four pieces */ | ||||
|       int w = TexWidth / 2, h = TexHeight / 2; | ||||
|       int x0 = 0, y0 = 0; | ||||
|       int x1 = w, y1 = h; | ||||
|       glPixelStorei(GL_UNPACK_ROW_LENGTH, TexWidth); | ||||
|       glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|       glPixelStorei( GL_PACK_INVERT_MESA, GL_TRUE ); | ||||
|  | ||||
|        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);  | ||||
|        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|       glPixelStorei( GL_PACK_INVERT_MESA, GL_FALSE ); | ||||
|        | ||||
|    } | ||||
|    else { | ||||
|       /* all at once */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexWidth, TexHeight, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Measure gl[Copy]TexSubImage rate. | ||||
|  * This actually also includes time to render a quad and SwapBuffers. | ||||
|  */ | ||||
| static void | ||||
| RunTest(GLboolean copyTex, GLboolean doSubRect) | ||||
| { | ||||
|    double t0, t1; | ||||
|    int iters = 0; | ||||
|    float copyRate, mbRate; | ||||
|    float rot = 0.0; | ||||
|    int bpp, r, g, b, a; | ||||
|    int w, h; | ||||
|    GLubyte *image = NULL; | ||||
|  | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r); | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g); | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b); | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a); | ||||
|    bpp = (r + g + b + a) / 8; | ||||
|  | ||||
|    if (!copyTex) { | ||||
|       /* read image from frame buffer */ | ||||
|       image = (GLubyte *) malloc(TexWidth * TexHeight * bpp); | ||||
|       glPixelStorei(GL_PACK_ALIGNMENT, 1); | ||||
|       glReadPixels(0, 0, TexWidth, TexHeight, | ||||
|                    ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|    } | ||||
|  | ||||
|    glEnable(GL_TEXTURE_2D); | ||||
|    glViewport(WinWidth / 2, 0, WinWidth / 2, WinHeight); | ||||
|  | ||||
|    t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|  | ||||
|    if (!DrawQuad) | ||||
|       glDrawBuffer(GL_FRONT); | ||||
|  | ||||
|    do { | ||||
|       if (copyTex) | ||||
|          /* Framebuffer -> Texture */ | ||||
|          DoCopyTex(doSubRect); | ||||
|       else { | ||||
|          /* Main Mem -> Texture */ | ||||
|          SubTex(doSubRect, image); | ||||
|       } | ||||
|  | ||||
|       /* draw textured quad */ | ||||
|       if (DrawQuad) { | ||||
|          glPushMatrix(); | ||||
|             glRotatef(rot, 0, 0, 1); | ||||
|             glTranslatef(1, 0, 0); | ||||
|             glBegin(GL_POLYGON); | ||||
|                glTexCoord2f(0, 0);  glVertex2f(-1, -1); | ||||
|                glTexCoord2f(1, 0);  glVertex2f( 1, -1); | ||||
|                glTexCoord2f(1, 1);  glVertex2f( 1,  1); | ||||
|                glTexCoord2f(0, 1);  glVertex2f(-1,  1); | ||||
|             glEnd(); | ||||
|          glPopMatrix(); | ||||
| 	 glutSwapBuffers(); | ||||
|       } | ||||
|       else { | ||||
| 	 /* Draw something tiny to ensure that the texture is really | ||||
| 	  * uploaded: | ||||
| 	  */ | ||||
|          glPushMatrix(); | ||||
|             glRotatef(rot, 0, 0, 1); | ||||
|             glTranslatef(1, 0, 0); | ||||
|             glBegin(GL_POLYGON); | ||||
|                glTexCoord2f(0, 0);  glVertex2f(-.01, -.01); | ||||
|                glTexCoord2f(.01, 0);  glVertex2f( .01, -.01); | ||||
|                glTexCoord2f(.01, .01);  glVertex2f( .01,  .01); | ||||
|                glTexCoord2f(0, .01);  glVertex2f(-.01,  .01); | ||||
|             glEnd(); | ||||
|          glPopMatrix(); | ||||
| 	 glFlush(); | ||||
|       } | ||||
|  | ||||
|       iters++; | ||||
|       rot += 2.0; | ||||
|  | ||||
|       t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|    } while (t1 - t0 < 2.0); | ||||
|  | ||||
|    /*  Make sure everything is done before taking the final timing: | ||||
|     */ | ||||
|    glFinish(); | ||||
|    t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|     | ||||
|  | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
|    if (image) | ||||
|       free(image); | ||||
|  | ||||
|    if (doSubRect) { | ||||
|       w = TexWidth / 2; | ||||
|       h = TexHeight / 2; | ||||
|       iters *= 4; | ||||
|    } | ||||
|    else { | ||||
|       w = TexWidth; | ||||
|       h = TexHeight; | ||||
|    } | ||||
|  | ||||
|    copyRate = iters / (t1 - t0); | ||||
|    mbRate = w * h * bpp * copyRate / (1024 * 1024); | ||||
|  | ||||
|    if (copyTex) | ||||
|       printf("glCopyTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp); | ||||
|    else | ||||
|       printf("glTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp); | ||||
|    printf("   %d calls in %.2f = %.2f calls/sec, %.2f MB/s\n", | ||||
|           iters, t1-t0, copyRate, mbRate); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Draw(void) | ||||
| { | ||||
|    glClearColor(0.2, 0.2, 0.8, 0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
|  | ||||
|    DrawTestImage(); | ||||
|    if (!DrawQuad) { | ||||
|       glutSwapBuffers(); | ||||
|    } | ||||
|  | ||||
|    RunTest(GL_FALSE, GL_FALSE);  | ||||
|    RunTest(GL_FALSE, GL_TRUE);  | ||||
|    RunTest(GL_TRUE, GL_FALSE);  | ||||
|    RunTest(GL_TRUE, GL_TRUE); | ||||
|  | ||||
|    glutSwapBuffers();  | ||||
|  | ||||
| /*    printf("exiting\n"); */ | ||||
| /*    exit(0); */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Reshape(int width, int height) | ||||
| { | ||||
|    glViewport(0, 0, width, height); | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|    glLoadIdentity(); | ||||
|    glTranslatef(0.0, 0.0, -15.0); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Key(unsigned char key, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case 27: | ||||
|          exit(0); | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| SpecialKey(int key, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case GLUT_KEY_UP: | ||||
|          break; | ||||
|       case GLUT_KEY_DOWN: | ||||
|          break; | ||||
|       case GLUT_KEY_LEFT: | ||||
|          break; | ||||
|       case GLUT_KEY_RIGHT: | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Init(void) | ||||
| { | ||||
|    /* create initial, empty teximage */ | ||||
|    glBindTexture(GL_TEXTURE_2D, TexObj); | ||||
|    glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0, | ||||
|                 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| ParseArgs(int argc, char *argv[]) | ||||
| { | ||||
|    int i; | ||||
|    for (i = 1; i < argc; i++) { | ||||
|       if (strcmp(argv[i], "-nodraw") == 0) | ||||
|          DrawQuad = GL_FALSE; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
|    GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH; | ||||
|    glutInit(&argc, argv); | ||||
|  | ||||
|    ParseArgs(argc, argv); | ||||
|  | ||||
|    glutInitWindowPosition(0, 0); | ||||
|    glutInitWindowSize(WinWidth, WinHeight); | ||||
|    glutInitDisplayMode(mode); | ||||
|    glutCreateWindow(argv[0]); | ||||
|    glutReshapeFunc(Reshape); | ||||
|    glutKeyboardFunc(Key); | ||||
|    glutSpecialFunc(SpecialKey); | ||||
|    glutDisplayFunc(Draw); | ||||
|  | ||||
|    printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|    Init(); | ||||
|  | ||||
|    glutMainLoop(); | ||||
|    return 0; | ||||
| } | ||||
| @@ -89,7 +89,7 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME) | ||||
| depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) | ||||
| 	touch depend | ||||
| 	$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \ | ||||
| 		> /dev/null  | ||||
| 		>& /dev/null  | ||||
|  | ||||
|  | ||||
| # Emacs tags | ||||
|   | ||||
| @@ -5,33 +5,50 @@ include $(TOP)/configs/current | ||||
| LIBNAME = i915_dri.so | ||||
|  | ||||
| DRIVER_SOURCES = \ | ||||
| 	bufmgr_fake.c \ | ||||
| 	intel_regions.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_tex.c \ | ||||
| 	i915_texprog.c \ | ||||
| 	i915_texstate.c \ | ||||
| 	i915_vtbl.c \ | ||||
| 	intel_context.c \ | ||||
| 	intel_ioctl.c \ | ||||
| 	intel_screen.c \ | ||||
| 	intel_span.c \ | ||||
| 	intel_state.c \ | ||||
| 	intel_tris.c  | ||||
|  | ||||
|  | ||||
| DISABLED = \ | ||||
| 	intel_render.c \ | ||||
| 	i830_context.c \ | ||||
| 	i830_metaops.c \ | ||||
| 	i830_state.c \ | ||||
| 	i830_texblend.c \ | ||||
| 	i830_tex.c \ | ||||
| 	i830_texstate.c \ | ||||
| 	i830_vtbl.c \ | ||||
| 	intel_batchbuffer.c \ | ||||
| 	intel_context.c \ | ||||
| 	intel_ioctl.c \ | ||||
| 	intel_pixel.c \ | ||||
| 	intel_render.c \ | ||||
| 	intel_screen.c \ | ||||
| 	intel_span.c \ | ||||
| 	intel_state.c \ | ||||
| 	intel_tex.c \ | ||||
| 	intel_tris.c  | ||||
| 	i830_vtbl.c  | ||||
|  | ||||
| C_SOURCES = \ | ||||
| 	$(COMMON_SOURCES) \ | ||||
|   | ||||
							
								
								
									
										181
									
								
								src/mesa/drivers/dri/i915/bufmgr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								src/mesa/drivers/dri/i915/bufmgr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,181 @@ | ||||
| #ifndef BUFMGR_H | ||||
| #define BUFMGR_H | ||||
|  | ||||
| #include "intel_context.h" | ||||
|  | ||||
| /* Note that this is destined to be external to Mesa, so don't use GL | ||||
|  * types like GLuint, etc. | ||||
|  */ | ||||
|  | ||||
| /* The buffer manager context.  Opaque. | ||||
|  */ | ||||
| struct bufmgr; | ||||
|  | ||||
| #define BM_LIST_MAX 32 | ||||
|  | ||||
| /* List of buffers to validate.  Probably better managed by the client: | ||||
|  */ | ||||
| struct bm_buffer_list { | ||||
|    struct { | ||||
|       unsigned buffer; | ||||
|       unsigned *offset_return; | ||||
|       unsigned *memtype_return; | ||||
|    } elem[BM_LIST_MAX]; | ||||
|  | ||||
|    unsigned nr; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct bufmgr *bm_fake_intel_Attach( struct intel_context *intel );  | ||||
|  | ||||
| /* struct bufmgr *bmCreate( ... ); */ | ||||
| /* struct bufmgr *bmAttach( ... ); */ | ||||
|  | ||||
| /* Define an address space.  Doesn't really do anything, but the | ||||
|  * information could be used to validate the bmInitPool() requests. | ||||
|  */ | ||||
| void bmInitMemType( struct bufmgr *, | ||||
| 		    unsigned mem_type, | ||||
| 		    unsigned long size ); | ||||
|  | ||||
|  | ||||
| /* Create a pool of a given memory type, from a certain offset and a | ||||
|  * certain size.   | ||||
|  * | ||||
|  * Also passed in is a virtual pointer to the start of the pool.  This | ||||
|  * is useful in the faked-out version in i915 so that MapBuffer can | ||||
|  * return a pointer to a buffer residing in AGP space.   | ||||
|  * | ||||
|  * Flags passed into a pool are inherited by all buffers allocated in | ||||
|  * that pool.  So pools representing the static front,back,depth | ||||
|  * buffer allocations should have MEM_AGP|NO_UPLOAD|NO_EVICT|NO_MOVE to match | ||||
|  * the behaviour of the legacy allocations. | ||||
|  * | ||||
|  * Returns -1 for failure, pool number for success. | ||||
|  */ | ||||
| int bmInitPool( struct bufmgr *,  | ||||
| 		unsigned long low_offset, | ||||
| 		void *low_virtual, | ||||
| 		unsigned long size, | ||||
| 		unsigned flags); | ||||
|  | ||||
|  | ||||
| /* Flags for validate and other calls.  If both NO_UPLOAD and NO_EVICT | ||||
|  * are specified, ValidateBuffers is essentially a query. | ||||
|  */ | ||||
| #define BM_MEM_LOCAL   0x1 | ||||
| #define BM_MEM_AGP     0x2 | ||||
| #define BM_MEM_VRAM    0x4	/* not yet used */ | ||||
| #define BM_WRITE       0x8	/* not yet used */ | ||||
| #define BM_READ        0x10	/* not yet used */ | ||||
| #define BM_NO_UPLOAD   0x20 | ||||
| #define BM_NO_EVICT    0x40 | ||||
| #define BM_NO_MOVE     0x80	/* not yet used */ | ||||
| #define BM_NO_ALLOC    0x100	/* legacy "fixed" buffers only */ | ||||
| #define BM_CLIENT      0x200	/* for map - pointer will be accessed | ||||
| 				 * without dri lock */ | ||||
|  | ||||
| #define BM_MEM_MASK (BM_MEM_LOCAL|BM_MEM_AGP|BM_MEM_VRAM) | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Stick closely to ARB_vbo semantics - they're well defined and | ||||
|  * understood, and drivers can just pass the calls through without too | ||||
|  * much thunking. | ||||
|  */ | ||||
| void bmGenBuffers(struct bufmgr *, unsigned n, unsigned *buffers); | ||||
| void bmDeleteBuffers(struct bufmgr *, unsigned n, unsigned *buffers); | ||||
|  | ||||
|  | ||||
| /* Hook to inform faked buffer manager about fixed-position | ||||
|  * front,depth,back buffers.  These may move to a fully memory-managed | ||||
|  * scheme, or they may continue to be managed as is. | ||||
|  */ | ||||
| unsigned bmBufferStatic(struct bufmgr *, | ||||
| 			unsigned buffer, | ||||
| 			unsigned size, | ||||
| 			unsigned pool); | ||||
|  | ||||
|  | ||||
|  | ||||
| /* The driver has more intimate knowledge of the hardare than a GL | ||||
|  * client would, so flags here is more proscriptive than the usage | ||||
|  * values in the ARB_vbo interface: | ||||
|  */ | ||||
| void bmBufferData(struct bufmgr *,  | ||||
| 		  unsigned buffer,  | ||||
| 		  unsigned size,  | ||||
| 		  const void *data,  | ||||
| 		  unsigned flags ); | ||||
|  | ||||
| void bmBufferSubData(struct bufmgr *,  | ||||
| 		     unsigned buffer,  | ||||
| 		     unsigned offset,  | ||||
| 		     unsigned size,  | ||||
| 		     const void *data ); | ||||
|  | ||||
| void *bmMapBuffer( struct bufmgr *, | ||||
| 		   unsigned buffer,  | ||||
| 		   unsigned access ); | ||||
|  | ||||
| void bmUnmapBuffer( struct bufmgr *, | ||||
| 		    unsigned buffer ); | ||||
|  | ||||
| /* To be called prior to emitting commands to hardware which reference | ||||
|  * these buffers.   | ||||
|  * | ||||
|  * NewBufferList() and AddBuffer() build up a list of buffers to be | ||||
|  * validated.  The buffer list provides information on where the | ||||
|  * buffers should be placed and whether their contents need to be | ||||
|  * preserved on copying.  The offset data elements are return values | ||||
|  * from this function telling the driver exactly where the buffers are | ||||
|  * currently located. | ||||
|  * | ||||
|  * ValidateBufferList() performs the actual validation and returns the | ||||
|  * buffer pools and offsets within the pools. | ||||
|  * | ||||
|  * FenceBufferList() must be called to set fences and other | ||||
|  * housekeeping before unlocking after a successful call to | ||||
|  * ValidateBufferList(). The buffer manager knows how to emit and test | ||||
|  * fences directly through the drm and without callbacks to the | ||||
|  * driver. | ||||
|  */ | ||||
| struct bm_buffer_list *bmNewBufferList( void ); | ||||
|  | ||||
| void bmAddBuffer( struct bm_buffer_list *list, | ||||
| 		  unsigned buffer, | ||||
| 		  unsigned flags, | ||||
| 		  unsigned *pool_return, | ||||
| 		  unsigned *offset_return ); | ||||
|  | ||||
| int bmValidateBufferList( struct bufmgr *,  | ||||
| 			  struct bm_buffer_list *, | ||||
| 			  unsigned flags ); | ||||
|  | ||||
| unsigned bmFenceBufferList( struct bufmgr *, | ||||
| 			struct bm_buffer_list * ); | ||||
|  | ||||
| void bmFreeBufferList( struct bm_buffer_list * ); | ||||
|  | ||||
|  | ||||
| /* This functionality is used by the buffer manager, not really sure | ||||
|  * if we need to be exposing it in this way, probably libdrm will | ||||
|  * offer equivalent calls. | ||||
|  * | ||||
|  * For now they can stay, but will likely change/move before final: | ||||
|  */ | ||||
| unsigned bmSetFence( struct bufmgr * ); | ||||
| int bmTestFence( struct bufmgr *, unsigned fence ); | ||||
| void bmFinishFence( struct bufmgr *, unsigned fence ); | ||||
|  | ||||
| void bmFlushReadCaches( struct bufmgr *bm ); | ||||
| void bmFlushDrawCache( struct bufmgr *bm ); | ||||
|  | ||||
| void bm_fake_NotifyContendedLockTake( struct bufmgr * ); | ||||
|  | ||||
| extern int INTEL_DEBUG; | ||||
| #define DEBUG_BUFMGR 0x2000 | ||||
|  | ||||
| #define DBG(...)  do { if (INTEL_DEBUG & DEBUG_BUFMGR) _mesa_printf(__VA_ARGS__); } while(0) | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										858
									
								
								src/mesa/drivers/dri/i915/bufmgr_fake.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										858
									
								
								src/mesa/drivers/dri/i915/bufmgr_fake.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,858 @@ | ||||
| /* Fake version of the buffer manager so that we can prototype the | ||||
|  * changes in a driver fairly quickly.  Basically wraps the old style | ||||
|  * memory management in the new programming interface. | ||||
|  * | ||||
|  * This version imports code from the via memory manager to closer | ||||
|  * approximate the behaviour of a true memory manager.  In particular, | ||||
|  * in this version we do not expect to lose texture memory contents on | ||||
|  * context switches. | ||||
|  */ | ||||
| #include "bufmgr.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
| #include "hash.h" | ||||
| #include "simple_list.h" | ||||
| #include "mm.h" | ||||
| #include "imports.h" | ||||
|  | ||||
| struct _mesa_HashTable; | ||||
|  | ||||
| static int delayed_free( struct bufmgr *bm ); | ||||
|  | ||||
| #define BM_POOL_MAX 8 | ||||
|  | ||||
|  | ||||
| /* Wrapper around mm.c's mem_block, which understands that you must | ||||
|  * wait for fences to expire before memory can be freed.  This is | ||||
|  * specific to our use of memcpy for uploads - an upload that was | ||||
|  * processed through the command queue wouldn't need to care about | ||||
|  * fences. | ||||
|  */ | ||||
| struct block { | ||||
|    struct block *next, *prev; | ||||
|    int mem_type; | ||||
|    struct pool *pool;		/* BM_MEM_AGP */ | ||||
|    struct mem_block *mem;	/* BM_MEM_AGP */ | ||||
|    unsigned fence;		/* BM_MEM_AGP, Split to read_fence, write_fence */ | ||||
|    void *virtual;                | ||||
|    struct buffer *buf; | ||||
| }; | ||||
|  | ||||
|  | ||||
| struct buffer { | ||||
|    unsigned id;			/* debug only */ | ||||
|    unsigned size; | ||||
|    unsigned alignment; | ||||
|    unsigned mapped; | ||||
|    unsigned flags; | ||||
|    struct block *block; | ||||
| }; | ||||
|  | ||||
| struct pool { | ||||
|    unsigned flags; | ||||
|    struct mem_block *heap; | ||||
|    void *virtual; | ||||
|    struct block lru; | ||||
|    struct block freed; | ||||
| }; | ||||
|  | ||||
| struct bufmgr { | ||||
|    struct intel_context *intel; | ||||
|    struct pool pool[BM_POOL_MAX]; | ||||
|    unsigned nr_pools; | ||||
|  | ||||
|    struct _mesa_HashTable *hash; | ||||
|  | ||||
|    unsigned buf_nr;		/* for generating ids */ | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static struct block *alloc_from_pool( struct bufmgr *bm,				 | ||||
| 				      unsigned pool_nr, | ||||
| 				      unsigned size,  | ||||
| 				      unsigned align ) | ||||
| { | ||||
|    struct pool *pool = &bm->pool[pool_nr]; | ||||
|    struct block *block = (struct block *)calloc(sizeof *block, 1); | ||||
|    if (!block) | ||||
|       return NULL; | ||||
|  | ||||
|    DBG("alloc_from_pool %d sz 0x%x\n", pool_nr, size); | ||||
|    assert(align >= 7); | ||||
|  | ||||
|    block->mem = mmAllocMem(pool->heap, size, align, 0); | ||||
|    if (!block->mem) { | ||||
|       DBG("\t- failed\n"); | ||||
|       free(block); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    make_empty_list(block); | ||||
|    block->pool = pool; | ||||
|    block->mem_type = pool->flags & BM_MEM_MASK; | ||||
|    block->virtual = pool->virtual + block->mem->ofs; | ||||
|  | ||||
|    DBG("\t- offset 0x%x\n", block->mem->ofs); | ||||
|    return block; | ||||
| } | ||||
|  | ||||
|  | ||||
| static struct block *alloc_local( unsigned size ) | ||||
| { | ||||
|    struct block *block = (struct block *)calloc(sizeof *block, 1); | ||||
|    if (!block) | ||||
|       return NULL; | ||||
|  | ||||
|    DBG("alloc_local 0x%x\n", size); | ||||
|  | ||||
|    block->mem_type = BM_MEM_LOCAL; | ||||
|    block->virtual = ALIGN_MALLOC(size, 1<<7); | ||||
|    if (!block->virtual) { | ||||
|       free(block); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return block; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static struct block *alloc_block( struct bufmgr *bm, | ||||
| 				  unsigned size, | ||||
| 				  unsigned align, | ||||
| 				  int flags ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    if (!(flags & BM_CLIENT)) { | ||||
|       for (i = 0; i < bm->nr_pools; i++) { | ||||
| 	 struct block *block; | ||||
| 	  | ||||
| 	 if (bm->pool[i].flags & BM_NO_ALLOC) | ||||
| 	    continue; | ||||
| 	  | ||||
| 	 if ((bm->pool[i].flags & flags & BM_MEM_MASK) == 0) | ||||
| 	    continue; | ||||
| 	  | ||||
| 	 block = alloc_from_pool(bm, i, size, align); | ||||
| 	 if (block) | ||||
| 	    return block; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (flags & BM_MEM_LOCAL) | ||||
|       return alloc_local(size); | ||||
|  | ||||
|    return NULL; | ||||
| } | ||||
|  | ||||
| static int bmAllocMem( struct bufmgr *bm, | ||||
| 		       struct buffer *buf, | ||||
| 		       GLuint flags )	 | ||||
| { | ||||
|    delayed_free(bm); | ||||
|  | ||||
|    buf->block = alloc_block(bm,  | ||||
| 			    buf->size, | ||||
| 			    buf->alignment,  | ||||
| 			    buf->flags | flags); | ||||
|  | ||||
|    if (buf->block) | ||||
|       buf->block->buf = buf; | ||||
|    else | ||||
|       _mesa_printf("bmAllocMem failed memflags %x\n", buf->flags & BM_MEM_MASK); | ||||
|  | ||||
|    /* Sleep here or fail???  | ||||
|     */ | ||||
| /*    assert(buf->block); */ | ||||
|    return buf->block != NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Release the card storage associated with buf: | ||||
|  */ | ||||
| static void free_block( struct bufmgr *bm, struct block *block ) | ||||
| { | ||||
|    DBG("free block %p\n", block); | ||||
|  | ||||
|    if (!block)  | ||||
|       return; | ||||
|  | ||||
|    DBG("free block (mem: %d, sz %d) from buf %d\n", | ||||
|        block->mem_type, | ||||
|        block->buf->size, | ||||
|        block->buf->id); | ||||
|  | ||||
|    switch (block->mem_type) { | ||||
|    case BM_MEM_AGP: | ||||
|    case BM_MEM_VRAM: | ||||
|       remove_from_list(block); | ||||
|  | ||||
|       DBG("    - offset %x\n", block->mem->ofs); | ||||
|  | ||||
|       if (bmTestFence(bm, block->fence)) { | ||||
| 	 DBG("    - free immediately\n"); | ||||
|          mmFreeMem(block->mem); | ||||
|          free(block); | ||||
|       } | ||||
|       else { | ||||
| 	 DBG("    - place on delayed_free list\n"); | ||||
| 	 block->buf = NULL; | ||||
|          insert_at_tail(&block->pool->freed, block); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|    case BM_MEM_LOCAL: | ||||
|       DBG("    - free local memory\n"); | ||||
|       ALIGN_FREE(block->virtual); | ||||
|       free(block); | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       DBG("    - unknown memory type\n"); | ||||
|       free(block); | ||||
|       break; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static int delayed_free( struct bufmgr *bm ) | ||||
| { | ||||
|    struct block *block, *tmp; | ||||
|    int ret = 0; | ||||
|    int i; | ||||
|  | ||||
|    for (i = 0; i < bm->nr_pools; i++) { | ||||
|       foreach_s(block, tmp, &bm->pool[i].freed ) { | ||||
| 	 if (bmTestFence(bm, block->fence)) { | ||||
| 	    ret += block->mem->size; | ||||
| 	    remove_from_list(block); | ||||
| 	    mmFreeMem(block->mem); | ||||
| 	    free(block); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
|     | ||||
|    DBG("%s: %d\n", __FUNCTION__, ret); | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int move_buffers( struct bufmgr *bm,  | ||||
| 			 struct buffer *buffers[], | ||||
| 			 int nr, | ||||
| 			 int flags ) | ||||
| { | ||||
|    struct block *newMem[BM_LIST_MAX]; | ||||
|    GLint i; | ||||
|    GLuint nr_uploads = 0; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    memset(newMem, 0, sizeof(newMem)); | ||||
|  | ||||
|    /* First do all the allocations (or fail): | ||||
|     */  | ||||
|    for (i = 0; i < nr; i++) {     | ||||
|       if (!buffers[i]->block) { | ||||
|  	 if (flags & BM_NO_ALLOC) | ||||
|  	    goto cleanup; | ||||
|  | ||||
| 	 newMem[i] = alloc_block(bm,  | ||||
| 				 buffers[i]->size, | ||||
| 				 buffers[i]->alignment, | ||||
| 				 flags & BM_MEM_MASK); | ||||
|  | ||||
| 	 if (!newMem[i])  | ||||
| 	    goto cleanup; | ||||
| 	 | ||||
|       }  | ||||
|       else if (!(buffers[i]->block->mem_type & flags)) {  | ||||
| 	 if (flags & BM_NO_UPLOAD) | ||||
| 	    goto cleanup; | ||||
|  | ||||
| 	 /* Known issue: this assert will get hit on texture swapping. | ||||
| 	  * There's not much to do about that at this stage - it's a | ||||
| 	  * todo item. | ||||
| 	  */ | ||||
|  	 assert(!buffers[i]->mapped); | ||||
|  | ||||
| 	 DBG("try to move buffer %d size 0x%x to pools 0x%x\n",  | ||||
| 		      buffers[i]->id, buffers[i]->size, flags & BM_MEM_MASK); | ||||
|  | ||||
| 	 newMem[i] = alloc_block(bm,  | ||||
| 				 buffers[i]->size, | ||||
| 				 buffers[i]->alignment, | ||||
| 				 flags & BM_MEM_MASK); | ||||
|  | ||||
| 	 if (!newMem[i])  | ||||
| 	    goto cleanup; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* Now copy all the image data and free the old texture memory. | ||||
|     */ | ||||
|    for (i = 0; i < nr; i++) {     | ||||
|       if (newMem[i]) { | ||||
| 	 if (buffers[i]->block) { | ||||
| 	    /* XXX: To be replaced with DMA, GTT bind, and other | ||||
| 	     * mechanisms in final version.  Memcpy (or sse_memcpy) is | ||||
| 	     * probably pretty good for local->agp uploads. | ||||
| 	     */ | ||||
| 	    DBG("memcpy %d bytes\n", buffers[i]->size); | ||||
| 	    memcpy(newMem[i]->virtual, | ||||
| 		   buffers[i]->block->virtual,  | ||||
| 		   buffers[i]->size); | ||||
| 	     | ||||
| 	    free_block(bm, buffers[i]->block); | ||||
| 	    nr_uploads++; | ||||
| 	 } | ||||
|  | ||||
| 	 buffers[i]->block = newMem[i]; | ||||
| 	 buffers[i]->block->buf = buffers[i]; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Tell hardware that its texture and other caches may be invalid:  | ||||
|     */ | ||||
|    if (nr_uploads && (flags & (BM_MEM_AGP|BM_MEM_VRAM))) | ||||
|       bmFlushReadCaches(bm);    | ||||
|  | ||||
|    DBG("%s - success\n", __FUNCTION__); | ||||
|    return 1; | ||||
|  | ||||
|  cleanup: | ||||
|    /* Release any allocations made prior to failure: | ||||
|     */ | ||||
|    for (i = 0; i < nr; i++) {     | ||||
|       if (newMem[i])  | ||||
| 	 free_block(bm, newMem[i]); | ||||
|    } | ||||
|     | ||||
|    _mesa_printf("%s - fail\n", __FUNCTION__); | ||||
|    return 0;    | ||||
| } | ||||
|  | ||||
|  | ||||
| static unsigned evict_lru( struct bufmgr *bm, | ||||
| 			   unsigned flags) | ||||
| { | ||||
|    int i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (flags & BM_NO_EVICT) | ||||
|       return 0; | ||||
|  | ||||
|    /* XXX: this is broken with >1 active pool - all the first pool | ||||
|     * will be evicted before starting on the second.  Actually, maybe | ||||
|     * you want that in some situations... | ||||
|     */ | ||||
|    for (i = 0; i < bm->nr_pools; i++) { | ||||
|       if ((bm->pool[i].flags & flags & BM_MEM_MASK) &&  | ||||
| 	  !(bm->pool[i].flags & BM_NO_EVICT)) { | ||||
| 	 struct block *block = bm->pool[i].lru.next; | ||||
| 	 unsigned size = block->buf->size; | ||||
|  | ||||
| 	 if (block == &bm->pool[i].lru || | ||||
| 	     !bmTestFence(bm, block->fence))  | ||||
| 	    return 0; | ||||
|     | ||||
| 	 move_buffers(bm, &block->buf, 1, BM_MEM_LOCAL); | ||||
| 	 return size; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| /* Speculatively move texture images which haven't been used in a | ||||
|  * while back to local memory. | ||||
|  */ | ||||
| static void viaSwapOutWork( struct bufmgr *bm ) | ||||
| { | ||||
|    unsigned total = 0; | ||||
|    unsigned target; | ||||
|  | ||||
|    if (bm->thrashing) { | ||||
|       target = 1*1024*1024; | ||||
|    } | ||||
|    else if (bmIsTexMemLow(bm)) { | ||||
|       target = 64*1024; | ||||
|    } | ||||
|    else { | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    while (1) { | ||||
|       unsigned size = evict_lru(bm); | ||||
|       if (!size) | ||||
|          return; | ||||
|  | ||||
|       total += size; | ||||
|       if (total >= target) | ||||
|          return; | ||||
|    } | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /*********************************************************************** | ||||
|  * Public functions | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /* The initialization functions are skewed in the fake implementation. | ||||
|  * This call would be to attach to an existing manager, rather than to | ||||
|  * create a local one. | ||||
|  */ | ||||
| struct bufmgr *bm_fake_intel_Attach( struct intel_context *intel ) | ||||
| { | ||||
|    struct bufmgr *bm = (struct bufmgr *)calloc(sizeof(*bm), 1); | ||||
|     | ||||
|    bm->intel = intel; | ||||
|    bm->hash = _mesa_NewHashTable(); | ||||
|  | ||||
|    return bm; | ||||
| } | ||||
|  | ||||
|  | ||||
| void bmInitMemType( struct bufmgr *bm, | ||||
| 		    unsigned mem_type, | ||||
| 		    unsigned long size ) | ||||
| { | ||||
|    /* Nothing really to do.  Could store and use to validate | ||||
|     * bmInitPool requests. | ||||
|     */ | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* The virtual pointer would go away in a true implementation. | ||||
|  */ | ||||
| int bmInitPool( struct bufmgr *bm,  | ||||
| 		unsigned long low_offset, | ||||
| 		void *low_virtual, | ||||
| 		unsigned long size, | ||||
| 		unsigned flags) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    if (bm->nr_pools >= BM_POOL_MAX) | ||||
|       return -1; | ||||
|  | ||||
|    i = bm->nr_pools++; | ||||
|     | ||||
|    DBG("bmInitPool %d low_offset %x sz %x\n", | ||||
| 		i, low_offset, size); | ||||
|     | ||||
|    bm->pool[i].heap = mmInit( low_offset, size ); | ||||
|    bm->pool[i].virtual = low_virtual - low_offset; | ||||
|    bm->pool[i].flags = flags; | ||||
|     | ||||
|    make_empty_list(&bm->pool[i].lru); | ||||
|    make_empty_list(&bm->pool[i].freed); | ||||
|  | ||||
|    return i; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void bmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers) | ||||
| { | ||||
|    unsigned i; | ||||
|  | ||||
|    for (i = 0; i < n; i++) { | ||||
|       struct buffer *buf = calloc(sizeof(*buf), 1); | ||||
|       buf->id = ++bm->buf_nr; | ||||
|       buf->alignment = 12;	/* page-alignment to fit in with AGP swapping */ | ||||
|       buf->flags = BM_MEM_AGP|BM_MEM_VRAM|BM_MEM_LOCAL; | ||||
|       buffers[i] = buf->id; | ||||
|       _mesa_HashInsert(bm->hash, buffers[i], buf); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void bmDeleteBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers) | ||||
| { | ||||
|    unsigned i; | ||||
|     | ||||
|    for (i = 0; i < n; i++) { | ||||
|       struct buffer *buf = _mesa_HashLookup(bm->hash, buffers[i]); | ||||
|       if (buf) { | ||||
|          free_block(bm, buf->block);	 | ||||
|          free(buf); | ||||
| 	 _mesa_HashRemove(bm->hash, buffers[i]); | ||||
|       } | ||||
|       assert(_mesa_HashLookup(bm->hash, buffers[i]) == NULL); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Hook to inform faked buffer manager about fixed-position | ||||
|  * front,depth,back buffers.  These may move to a fully memory-managed | ||||
|  * scheme, or they may continue to be managed as is.  It will probably | ||||
|  * be useful to pass a fixed offset here one day. | ||||
|  */ | ||||
| unsigned bmBufferStatic(struct bufmgr *bm, | ||||
| 			unsigned buffer, | ||||
| 			unsigned size, | ||||
| 			unsigned pool ) | ||||
| { | ||||
|    struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer ); | ||||
|     | ||||
|    assert(!buf->block); | ||||
|    assert(bm->pool[pool].flags & BM_NO_EVICT); | ||||
|    assert(bm->pool[pool].flags & BM_NO_MOVE); | ||||
|  | ||||
|    buf->size = size; | ||||
|    buf->flags = bm->pool[pool].flags; | ||||
|    buf->alignment = 12; | ||||
|    buf->block = alloc_from_pool(bm, pool, buf->size, buf->alignment); | ||||
|    if (!buf->block) | ||||
|       return 0; | ||||
|  | ||||
|    buf->block->buf = buf; | ||||
|    return buf->block->mem->ofs; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* If buffer size changes, free and reallocate.  Otherwise update in | ||||
|  * place. | ||||
|  */ | ||||
| void bmBufferData(struct bufmgr *bm,  | ||||
| 		  unsigned buffer,  | ||||
| 		  unsigned size,  | ||||
| 		  const void *data,  | ||||
| 		  unsigned flags ) | ||||
| { | ||||
|    struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer ); | ||||
|  | ||||
|    DBG("bmBufferData %d sz 0x%x data: %p\n", buffer, size, data); | ||||
|  | ||||
|    assert(!buf->mapped); | ||||
|  | ||||
|    if (buf->block) { | ||||
|       if ((buf->block->mem_type != BM_MEM_LOCAL && !bmTestFence(bm, buf->block->fence)) || | ||||
| 	  (buf->size && buf->size != size) || | ||||
| 	  (data == NULL)) { | ||||
| 	 free_block(bm, buf->block); | ||||
| 	 buf->block = NULL; | ||||
|       } | ||||
|    } | ||||
|     | ||||
|    buf->size = size; | ||||
|  | ||||
|    if (data != NULL) {       | ||||
|       bmAllocMem(bm, buf, buf->flags | flags); | ||||
|       memcpy(buf->block->virtual, data, size); | ||||
|    } | ||||
| } | ||||
|  | ||||
| /* Update the buffer in place, in whatever space it is currently resident: | ||||
|  */ | ||||
| void bmBufferSubData(struct bufmgr *bm,  | ||||
| 		     unsigned buffer,  | ||||
| 		     unsigned offset,  | ||||
| 		     unsigned size,  | ||||
| 		     const void *data ) | ||||
| { | ||||
|    struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer ); | ||||
|  | ||||
|    DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size); | ||||
|  | ||||
|    if (buf->block == 0) | ||||
|       bmAllocMem(bm, buf, buf->flags); | ||||
|  | ||||
|    if (buf->block->mem_type != BM_MEM_LOCAL) | ||||
|       bmFinishFence(bm, buf->block->fence); | ||||
|  | ||||
|    if (size)  | ||||
|       memcpy(buf->block->virtual + offset, data, size);  | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Return a pointer to whatever space the buffer is currently resident in: | ||||
|  */ | ||||
| void *bmMapBuffer( struct bufmgr *bm, | ||||
| 		   unsigned buffer,  | ||||
| 		   unsigned flags ) | ||||
| { | ||||
|    struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer ); | ||||
|  | ||||
|    DBG("bmMapBuffer %d\n", buffer); | ||||
|  | ||||
|    if (buf->mapped) | ||||
|       return NULL; | ||||
|  | ||||
|    if (buf->block == 0) | ||||
|       bmAllocMem(bm, buf, flags); | ||||
|  | ||||
|    if (buf->block == 0) | ||||
|       return NULL; | ||||
|  | ||||
|    buf->mapped = 1; | ||||
|  | ||||
|    /* Finish any outstanding operations to/from this memory: | ||||
|     */ | ||||
|    if (buf->block->mem_type != BM_MEM_LOCAL)  | ||||
|       bmFinishFence(bm, buf->block->fence); | ||||
|  | ||||
|    return buf->block->virtual; | ||||
| } | ||||
|  | ||||
| void bmUnmapBuffer( struct bufmgr *bm, unsigned buffer ) | ||||
| { | ||||
|    struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer ); | ||||
|  | ||||
|    DBG("bmUnmapBuffer %d\n", buffer); | ||||
|    buf->mapped = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Add a mechanism to tell the manager about some fixed buffers such | ||||
|  * as the (fixed) front, back and depth buffers.  Something like this | ||||
|  * may be needed even in a finalized version if we keep the static | ||||
|  * management of these buffers. | ||||
|  *  | ||||
|  * These are excluded from the buffer memory management in this file, | ||||
|  * but are presented to the driver by the same interface.  In the | ||||
|  * future they may become managed. | ||||
|  */ | ||||
| #if 0 | ||||
| void bm_fake_SetFixedBufferParams( struct bufmgr *bm | ||||
|                                    unsigned buffer, | ||||
|                                    unsigned offset, | ||||
|                                    unsigned size ) | ||||
| { | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* Build the list of buffers to validate: | ||||
|  */ | ||||
| struct bm_buffer_list *bmNewBufferList( void ) | ||||
| { | ||||
|    struct bm_buffer_list *list = calloc(sizeof(*list), 1); | ||||
|    DBG("bmNewBufferList\n"); | ||||
|    return list; | ||||
| } | ||||
|  | ||||
| void bmAddBuffer( struct bm_buffer_list *list, | ||||
| 		  unsigned buffer, | ||||
| 		  unsigned flags, | ||||
| 		  unsigned *memtype_return, | ||||
| 		  unsigned *offset_return ) | ||||
| { | ||||
|    assert(list->nr < BM_LIST_MAX); | ||||
|  | ||||
|  | ||||
|    list->elem[list->nr].buffer = buffer; | ||||
|    list->elem[list->nr].memtype_return = memtype_return; | ||||
|    list->elem[list->nr].offset_return = offset_return; | ||||
|  | ||||
|    DBG("bmAddBuffer nr %d buf %d\n",  | ||||
| 		list->nr, buffer); | ||||
|  | ||||
|    list->nr++; | ||||
| } | ||||
| 		 | ||||
| void bmFreeBufferList( struct bm_buffer_list *list ) | ||||
| { | ||||
|    free(list); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* To be called prior to emitting commands to hardware which reference | ||||
|  * these buffers.  The buffer_usage list provides information on where | ||||
|  * the buffers should be placed and whether their contents need to be | ||||
|  * preserved on copying.  The offset and pool data elements are return | ||||
|  * values from this function telling the driver exactly where the | ||||
|  * buffers are currently located. | ||||
|  */ | ||||
| int bmValidateBufferList( struct bufmgr *bm, | ||||
| 			  struct bm_buffer_list *list, | ||||
| 			  unsigned flags ) | ||||
| { | ||||
|    struct buffer *bufs[BM_LIST_MAX]; | ||||
|    unsigned i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (list->nr > BM_LIST_MAX) | ||||
|       return 0; | ||||
|  | ||||
|    for (i = 0; i < list->nr; i++) | ||||
|       bufs[i] = _mesa_HashLookup(bm->hash, list->elem[i].buffer); | ||||
|  | ||||
|     | ||||
|    /* The old story: evict one texture after another until allocation | ||||
|     * succeeds.  This is a pretty poor strategy but really hard to do | ||||
|     * better without more infrastucture...  Which is coming - hooray! | ||||
|     */ | ||||
|    while (!move_buffers(bm, bufs, list->nr, flags)) { | ||||
|       if (!delayed_free(bm) && | ||||
| 	  !evict_lru(bm, flags)) | ||||
| 	 return 0; | ||||
|       _mesa_printf("couldn't allocate sufficient texture memory\n"); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    for (i = 0; i < list->nr; i++) { | ||||
|       DBG("%d: buf %d ofs 0x%x\n", | ||||
| 		   i, bufs[i]->id, bufs[i]->block->mem->ofs); | ||||
|  | ||||
|       assert(!bufs[i]->mapped); | ||||
|  | ||||
|       if (list->elem[i].offset_return) | ||||
| 	 list->elem[i].offset_return[0] = bufs[i]->block->mem->ofs; | ||||
|        | ||||
|       if (list->elem[i].memtype_return) | ||||
| 	 list->elem[i].memtype_return[0] = bufs[i]->block->mem_type; | ||||
|    } | ||||
|     | ||||
|    return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* After commands are emitted but before unlocking, this must be | ||||
|  * called so that the buffer manager can correctly age the buffers. | ||||
|  * The buffer manager keeps track of the list of validated buffers, so | ||||
|  * already knows what to apply the fence to. | ||||
|  * | ||||
|  * The buffer manager knows how to emit and test fences directly | ||||
|  * through the drm and without callbacks or whatever into the driver. | ||||
|  */ | ||||
| unsigned bmFenceBufferList( struct bufmgr *bm, struct bm_buffer_list *list ) | ||||
| { | ||||
|  | ||||
|    DBG("%s (%d bufs)\n", __FUNCTION__, list->nr); | ||||
|  | ||||
|    if (list->nr) { | ||||
|       unsigned i; | ||||
|       unsigned fence = bmSetFence( bm ); | ||||
|  | ||||
|       /* Move all buffers to head of resident list and set their fences | ||||
|        */ | ||||
|       for (i = 0; i < list->nr; i++) { | ||||
| 	 struct buffer *buf = _mesa_HashLookup(bm->hash, list->elem[i].buffer); | ||||
|  | ||||
| 	 move_to_head(&buf->block->pool->lru, buf->block); | ||||
| 	 buf->block->fence = fence; | ||||
|       } | ||||
|  | ||||
|       return fence; | ||||
|    } | ||||
|    else | ||||
|       return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* This functionality is used by the buffer manager, not really sure | ||||
|  * if we need to be exposing it in this way, probably libdrm will | ||||
|  * offer equivalent calls. | ||||
|  * | ||||
|  * For now they can stay, but will likely change/move before final: | ||||
|  */ | ||||
| unsigned bmSetFence( struct bufmgr *bm ) | ||||
| { | ||||
|    assert(bm->intel->locked); | ||||
|  | ||||
|    return intelEmitIrqLocked( bm->intel ); | ||||
| } | ||||
|  | ||||
| int bmTestFence( struct bufmgr *bm, unsigned fence ) | ||||
| { | ||||
| /*    if (fence % 1024 == 0) */ | ||||
| /*       _mesa_printf("%d %d\n", fence, bm->intel->sarea->last_dispatch); */ | ||||
|  | ||||
|    return fence <= bm->intel->sarea->last_dispatch; | ||||
| } | ||||
|  | ||||
| void bmFinishFence( struct bufmgr *bm, unsigned fence ) | ||||
| { | ||||
|    if (!bmTestFence(bm, fence)) | ||||
|       intelWaitIrq( bm->intel, fence ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* There is a need to tell the hardware to flush various caches | ||||
|  * before we can start reading and writing video memory. | ||||
|  * | ||||
|  * TODO: Need a flag value to tell hardware which caches have changed? | ||||
|  * Who would we rely on to populate the flag? | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /* If new data is uploaded/mapped to video or agp memory, need to | ||||
|  * flush the texture and other read caches to ensure the new version | ||||
|  * is picked up.  Can be done immediately after the upload (ie. within | ||||
|  * ValidateBuffers). | ||||
|  */ | ||||
| void bmFlushReadCaches( struct bufmgr *bm ) | ||||
| { | ||||
| } | ||||
|  | ||||
| /* If a buffer which has been written to is going to be evicted, read | ||||
|  * by bmGetBufferData or mappped with bmMapBuffer, need to flush the | ||||
|  * write cache first.  Probably want to make sure this happens | ||||
|  * immediately after the last write and before the fence (how to | ||||
|  * tell?).  If we wait until just prior the evict/read/map, would then | ||||
|  * have to emit another fence and wait for the hw queue to drain to be | ||||
|  * sure the caches had flushed. | ||||
|  * | ||||
|  * A possible strategy: | ||||
|  * - every once in a while, when there is no last_draw_flush_fence outstanding, | ||||
|  *     emit a draw-cache flush just prior to the fence. | ||||
|  * - note the fence (last_draw_flush_fence) | ||||
|  * - note the most recently retired value of last_draw_flush_fence in | ||||
|  *      last_retired_draw_flush_fence | ||||
|  * - keep track of which fence each buffer is last written to in | ||||
|  *      buffer.last_write_fence | ||||
|  * - on evict/read/map, check: | ||||
|  *      - if buffer.last_write_fence > last_draw_flush_fence { | ||||
|  *            emit_flush | ||||
|  *            last_draw_flush_fence = emit fence  | ||||
|  *        } | ||||
|  *        if last_write_fence > last_retired_draw_flush_fence { | ||||
|  *            finish_fence(last_draw_flush_fence) | ||||
|  *            last_retired_draw_flush_fence = last_draw_fence | ||||
|  *        } | ||||
|  *    | ||||
|  */ | ||||
| void bmFlushDrawCache( struct bufmgr *bm ) | ||||
| { | ||||
| } | ||||
|  | ||||
| /* Specifically ignore texture memory sharing. | ||||
|  */ | ||||
| void bm_fake_NotifyContendedLockTake( struct bufmgr *bm ) | ||||
| { | ||||
|    fprintf(stderr, "did we just lose texture memory? oh well, never mind\n"); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -59,7 +59,7 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis, | ||||
| { | ||||
|    struct dd_function_table functions; | ||||
|    i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context); | ||||
|    intelContextPtr intel = &i830->intel; | ||||
|    struct intel_context *intel = &i830->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    if (!i830) return GL_FALSE; | ||||
|  | ||||
|   | ||||
| @@ -48,10 +48,8 @@ | ||||
|  */ | ||||
| #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 | ||||
| @@ -160,7 +158,7 @@ i830CreateContext( const __GLcontextModes *mesaVis, | ||||
| /* i830_tex.c, i830_texstate.c | ||||
|  */ | ||||
| extern void  | ||||
| i830UpdateTextureState( intelContextPtr intel ); | ||||
| i830UpdateTextureState( struct intel_context *intel ); | ||||
|  | ||||
| extern void  | ||||
| i830InitTextureFuncs( struct dd_function_table *functions ); | ||||
| @@ -206,7 +204,7 @@ i830TryTextureDrawPixels( GLcontext *ctx, | ||||
| 			  const GLvoid *pixels ); | ||||
|  | ||||
| extern void  | ||||
| i830ClearWithTris( intelContextPtr intel, GLbitfield mask, | ||||
| i830ClearWithTris( struct intel_context *intel, GLbitfield mask, | ||||
| 		   GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -58,7 +58,7 @@ do {						\ | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void set_initial_state( i830ContextPtr i830 ) | ||||
| static void set_initial_state( struct intel_context *intel ) | ||||
| { | ||||
|    memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) ); | ||||
|    i830->meta.active = ACTIVE; | ||||
| @@ -66,7 +66,7 @@ static void set_initial_state( i830ContextPtr i830 ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_no_depth_stencil_write( i830ContextPtr i830 ) | ||||
| static void set_no_depth_stencil_write( struct intel_context *intel ) | ||||
| { | ||||
|    /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE ) | ||||
|     */ | ||||
| @@ -88,7 +88,7 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 ) | ||||
|  | ||||
| /* Set stencil unit to replace always with the reference value. | ||||
|  */ | ||||
| static void set_stencil_replace( i830ContextPtr i830, | ||||
| static void set_stencil_replace( struct intel_context *intel, | ||||
| 				 GLuint s_mask, | ||||
| 				 GLuint s_clear) | ||||
| { | ||||
| @@ -140,7 +140,7 @@ static void set_stencil_replace( i830ContextPtr i830, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_color_mask( i830ContextPtr i830, GLboolean state ) | ||||
| static void set_color_mask( struct intel_context *intel, GLboolean state ) | ||||
| { | ||||
|    const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) | | ||||
| 			(1 << WRITEMASK_GREEN_SHIFT) | | ||||
| @@ -161,7 +161,7 @@ static void set_color_mask( i830ContextPtr i830, GLboolean state ) | ||||
| /* Installs a one-stage passthrough texture blend pipeline.  Is there | ||||
|  * more that can be done to turn off texturing? | ||||
|  */ | ||||
| static void set_no_texture( i830ContextPtr i830 ) | ||||
| static void set_no_texture( struct intel_context *intel ) | ||||
| { | ||||
|    static const struct gl_tex_env_combine_state comb = { | ||||
|       GL_NONE, GL_NONE, | ||||
| @@ -181,7 +181,7 @@ static void set_no_texture( i830ContextPtr i830 ) | ||||
| /* Set up a single element blend stage for 'replace' texturing with no | ||||
|  * funny ops. | ||||
|  */ | ||||
| static void enable_texture_blend_replace( i830ContextPtr i830, | ||||
| static void enable_texture_blend_replace( struct intel_context *intel, | ||||
| 					  GLenum format ) | ||||
| { | ||||
|    static const struct gl_tex_env_combine_state comb = { | ||||
| @@ -207,7 +207,7 @@ static void enable_texture_blend_replace( i830ContextPtr i830, | ||||
| /* Set up an arbitary piece of memory as a rectangular texture | ||||
|  * (including the front or back buffer). | ||||
|  */ | ||||
| static void set_tex_rect_source( i830ContextPtr i830, | ||||
| static void set_tex_rect_source( struct intel_context *intel, | ||||
| 				 GLuint offset, | ||||
| 				 GLuint width,  | ||||
| 				 GLuint height, | ||||
| @@ -249,17 +249,17 @@ static void set_tex_rect_source( i830ContextPtr i830, | ||||
|  | ||||
| /* Select between front and back draw buffers. | ||||
|  */ | ||||
| static void set_draw_offset( i830ContextPtr i830, | ||||
| static void set_draw_offset( struct intel_context *intel, | ||||
| 			     GLuint offset ) | ||||
| { | ||||
|    i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset; | ||||
| /*    i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset; */ | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_BUFFERS; | ||||
| } | ||||
|  | ||||
| /* Setup an arbitary draw format, useful for targeting | ||||
|  * texture or agp memory. | ||||
|  */ | ||||
| static void set_draw_format( i830ContextPtr i830, | ||||
| static void set_draw_format( struct intel_context *intel, | ||||
| 			     GLuint format, | ||||
| 			     GLuint depth_format) | ||||
| { | ||||
| @@ -271,7 +271,7 @@ static void set_draw_format( i830ContextPtr i830, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_vertex_format( i830ContextPtr i830 ) | ||||
| static void set_vertex_format( struct intel_context *intel ) | ||||
| { | ||||
|    i830->meta.Ctx[I830_CTXREG_VF] =  (_3DSTATE_VFT0_CMD | | ||||
| 				      VFT0_TEX_COUNT(1) | | ||||
| @@ -287,446 +287,6 @@ static void set_vertex_format( i830ContextPtr i830 ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void draw_quad(i830ContextPtr i830,  | ||||
| 		      GLfloat x0, GLfloat x1, | ||||
| 		      GLfloat y0, GLfloat y1,  | ||||
| 		      GLubyte red, GLubyte green, | ||||
| 		      GLubyte blue, GLubyte alpha, | ||||
| 		      GLfloat s0, GLfloat s1, | ||||
| 		      GLfloat t0, GLfloat t1 ) | ||||
| { | ||||
|    GLuint vertex_size = 8; | ||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,  | ||||
| 						PRIM3D_TRIFAN,  | ||||
| 						4*vertex_size, | ||||
| 						vertex_size ); | ||||
|    intelVertex tmp; | ||||
|    int i; | ||||
|  | ||||
|  | ||||
| /*    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 < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right bottom */ | ||||
|    vb += 8; | ||||
|    tmp.v.x = x1; | ||||
|    tmp.v.u0 = s1; | ||||
|    for (i = 0 ; i < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right top */ | ||||
|    vb += 8; | ||||
|    tmp.v.y = y1; | ||||
|    tmp.v.v0 = t1; | ||||
|    for (i = 0 ; i < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* left top */ | ||||
|    vb += 8; | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.u0 = s0; | ||||
|    for (i = 0 ; i < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
| /*    fprintf(stderr, "%s: DV1: %x\n",  */ | ||||
| /* 	   __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */ | ||||
| } | ||||
|  | ||||
| void  | ||||
| i830ClearWithTris(intelContextPtr intel, GLbitfield mask, | ||||
| 		  GLboolean all, | ||||
| 		  GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( intel ); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    int x0, y0, x1, y1; | ||||
|  | ||||
|  | ||||
|    SET_STATE( i830, meta ); | ||||
|    set_initial_state( i830 ); | ||||
|    set_no_texture( i830 ); | ||||
|    set_vertex_format( i830 );  | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if(!all) { | ||||
|       x0 = cx; | ||||
|       y0 = cy; | ||||
|       x1 = x0 + cw; | ||||
|       y1 = y0 + ch; | ||||
|    } else { | ||||
|       x0 = 0; | ||||
|       y0 = 0; | ||||
|       x1 = x0 + dPriv->w; | ||||
|       y1 = y0 + dPriv->h; | ||||
|    } | ||||
|  | ||||
|    /* Don't do any clipping to screen - these are window coordinates. | ||||
|     * The active cliprects will be applied as for any other geometry. | ||||
|     */ | ||||
|  | ||||
|    if(mask & BUFFER_BIT_FRONT_LEFT) { | ||||
|       set_no_depth_stencil_write( i830 ); | ||||
|       set_color_mask( i830, GL_TRUE ); | ||||
|       set_draw_offset( i830, screen->front.offset ); | ||||
|       draw_quad(i830, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green, | ||||
| 		intel->clear_blue, intel->clear_alpha, | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if(mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       set_no_depth_stencil_write( i830 ); | ||||
|       set_color_mask( i830, GL_TRUE ); | ||||
|       set_draw_offset( i830, screen->back.offset ); | ||||
|  | ||||
|       draw_quad(i830, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green, | ||||
| 		intel->clear_blue, intel->clear_alpha, | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if(mask & BUFFER_BIT_STENCIL) { | ||||
|       set_stencil_replace( i830,  | ||||
| 			   intel->ctx.Stencil.WriteMask[0],  | ||||
| 			   intel->ctx.Stencil.Clear); | ||||
|  | ||||
|       set_color_mask( i830, GL_FALSE ); | ||||
|       set_draw_offset( i830, screen->front.offset ); | ||||
|       draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 ); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    SET_STATE( i830, state ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| GLboolean | ||||
| i830TryTextureReadPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *pack, | ||||
| 			  GLvoid *pixels ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = i830->intel.intelScreen; | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|    __DRIdrawablePrivate *dPriv = i830->intel.driDrawable; | ||||
|    int textureFormat; | ||||
|    GLenum glTextureFormat; | ||||
|    int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; | ||||
|    int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels); | ||||
|    int destFormat, depthFormat, destPitch; | ||||
|    drm_clip_rect_t tmp; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|  | ||||
|    if (	ctx->_ImageTransferState || | ||||
| 	pack->SwapBytes || | ||||
| 	pack->LsbFirst || | ||||
| 	!pack->Invert) { | ||||
|       fprintf(stderr, "%s: check_color failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    switch (screen->fbFormat) { | ||||
|    case DV_PF_565: | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|       glTextureFormat = GL_RGB; | ||||
|       break; | ||||
|    case DV_PF_555: | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    case DV_PF_8888: | ||||
|       textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__, | ||||
| 	      screen->fbFormat); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    switch (type) { | ||||
|    case GL_UNSIGNED_SHORT_5_6_5:  | ||||
|       if (format != GL_RGB) return GL_FALSE; | ||||
|       destFormat = COLR_BUF_RGB565;  | ||||
|       depthFormat = DEPTH_FRMT_16_FIXED; | ||||
|       destPitch = pitch * 2; | ||||
|       break; | ||||
|    case GL_UNSIGNED_INT_8_8_8_8_REV:  | ||||
|       if (format != GL_BGRA) return GL_FALSE; | ||||
|       destFormat = COLR_BUF_ARGB8888;  | ||||
|       depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER; | ||||
|       destPitch = pitch * 4; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__, | ||||
| 	      _mesa_lookup_enum_by_nr(type)); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    destFormat |= (0x02<<24); | ||||
|  | ||||
| /*    fprintf(stderr, "type: %s destFormat: %x\n", */ | ||||
| /* 	   _mesa_lookup_enum_by_nr(type), */ | ||||
| /* 	   destFormat); */ | ||||
|  | ||||
|    intelFlush( ctx ); | ||||
|  | ||||
|    SET_STATE( i830, meta ); | ||||
|    set_initial_state( i830 ); | ||||
|    set_no_depth_stencil_write( i830 ); | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       intelWaitForIdle( intel ); /* required by GL */ | ||||
|  | ||||
|       if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 SET_STATE(i830, state); | ||||
| 	 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
| #if 0 | ||||
|       /* FIXME -- Just emit the correct state | ||||
|        */ | ||||
|       if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,  | ||||
| 		      destPitch) != 0) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 SET_STATE(i830, state); | ||||
| 	 fprintf(stderr, "%s: setparam failed\n", __FUNCTION__); | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       /* Set the frontbuffer up as a large rectangular texture. | ||||
|        */ | ||||
|       set_tex_rect_source( i830,  | ||||
| 			   src_offset,  | ||||
| 			   screen->width,  | ||||
| 			   screen->height,  | ||||
| 			   screen->front.pitch,  | ||||
| 			   textureFormat );  | ||||
|     | ||||
|     | ||||
|       enable_texture_blend_replace( i830, glTextureFormat );  | ||||
|  | ||||
|  | ||||
|       /* Set the 3d engine to draw into the agp memory | ||||
|        */ | ||||
|  | ||||
|       set_draw_offset( i830, destOffset );  | ||||
|       set_draw_format( i830, destFormat, depthFormat );   | ||||
|  | ||||
|  | ||||
|       /* Draw a single quad, no cliprects: | ||||
|        */ | ||||
|       i830->intel.numClipRects = 1; | ||||
|       i830->intel.pClipRects = &tmp; | ||||
|       i830->intel.pClipRects[0].x1 = 0; | ||||
|       i830->intel.pClipRects[0].y1 = 0; | ||||
|       i830->intel.pClipRects[0].x2 = width; | ||||
|       i830->intel.pClipRects[0].y2 = height; | ||||
|  | ||||
|       draw_quad( i830,  | ||||
| 		 0, width, 0, height,  | ||||
| 		 0, 255, 0, 0,  | ||||
| 		 x, x+width, y, y+height ); | ||||
|  | ||||
|       intelWindowMoved( intel ); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( ctx ); /* required by GL */ | ||||
|  | ||||
|    SET_STATE( i830, state ); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| 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 ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    GLint pitch = unpack->RowLength ? unpack->RowLength : width; | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    int textureFormat; | ||||
|    GLenum glTextureFormat; | ||||
|    int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; | ||||
|    int src_offset = intelAgpOffsetFromVirtual( intel, pixels ); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Todo -- upload images that aren't in agp space, then texture | ||||
|     * from them.   | ||||
|     */ | ||||
|  | ||||
|    if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) { | ||||
|       fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Todo -- don't want to clobber all the drawing state like we do | ||||
|     * for readpixels -- most of this state can be handled just fine. | ||||
|     */ | ||||
|    if (	ctx->_ImageTransferState || | ||||
| 	unpack->SwapBytes || | ||||
| 	unpack->LsbFirst || | ||||
| 	ctx->Color.AlphaEnabled ||  | ||||
| 	ctx->Depth.Test || | ||||
| 	ctx->Fog.Enabled || | ||||
| 	ctx->Scissor.Enabled || | ||||
| 	ctx->Stencil.Enabled || | ||||
| 	!ctx->Color.ColorMask[0] || | ||||
| 	!ctx->Color.ColorMask[1] || | ||||
| 	!ctx->Color.ColorMask[2] || | ||||
| 	!ctx->Color.ColorMask[3] || | ||||
| 	ctx->Color.ColorLogicOpEnabled || | ||||
| 	ctx->Texture._EnabledUnits) { | ||||
|       fprintf(stderr, "%s: other tests failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Todo -- remove these restrictions: | ||||
|     */ | ||||
|    if (ctx->Pixel.ZoomX != 1.0F || | ||||
|        ctx->Pixel.ZoomY != -1.0F) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|  | ||||
|    switch (type) { | ||||
|    case GL_UNSIGNED_SHORT_1_5_5_5_REV: | ||||
|       if (format != GL_BGRA) return GL_FALSE; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    case GL_UNSIGNED_SHORT_5_6_5:  | ||||
|       if (format != GL_RGB) return GL_FALSE; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|       glTextureFormat = GL_RGB; | ||||
|       break; | ||||
|    case GL_UNSIGNED_SHORT_8_8_MESA:  | ||||
|       if (format != GL_YCBCR_MESA) return GL_FALSE; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY  | ||||
| /*  		       | TM0S1_COLORSPACE_CONVERSION */ | ||||
| 	 ); | ||||
|       glTextureFormat = GL_YCBCR_MESA; | ||||
|       break; | ||||
|    case GL_UNSIGNED_SHORT_8_8_REV_MESA:  | ||||
|       if (format != GL_YCBCR_MESA) return GL_FALSE; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL  | ||||
| /* 		       | TM0S1_COLORSPACE_CONVERSION */ | ||||
| 	 ); | ||||
|       glTextureFormat = GL_YCBCR_MESA; | ||||
|       break; | ||||
|    case GL_UNSIGNED_INT_8_8_8_8_REV:  | ||||
|       if (format != GL_BGRA) return GL_FALSE; | ||||
|       textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intelFlush( ctx ); | ||||
|  | ||||
|    SET_STATE( i830, meta ); | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       intelWaitForIdle( intel ); /* required by GL */ | ||||
|  | ||||
|       y -= height;			/* cope with pixel zoom */ | ||||
|  | ||||
|       if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 SET_STATE(i830, state); | ||||
| 	 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|  | ||||
|       set_initial_state( i830 ); | ||||
|  | ||||
|       /* Set the pixel image up as a rectangular texture. | ||||
|        */ | ||||
|       set_tex_rect_source( i830,  | ||||
| 			   src_offset,  | ||||
| 			   width,  | ||||
| 			   height,  | ||||
| 			   pitch, /* XXXX!!!! -- /2 sometimes */ | ||||
| 			   textureFormat );  | ||||
|     | ||||
|     | ||||
|       enable_texture_blend_replace( i830, glTextureFormat );  | ||||
|  | ||||
|     | ||||
|       /* Draw to the current draw buffer: | ||||
|        */ | ||||
|       set_draw_offset( i830, dst_offset ); | ||||
|  | ||||
|       /* Draw a quad, use regular cliprects | ||||
|        */ | ||||
| /*       fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */ | ||||
|  | ||||
|       draw_quad( i830,  | ||||
| 		 x, x+width, y, y+height, | ||||
| 		 0, 255, 0, 0,  | ||||
| 		 0, width, 0, height ); | ||||
|  | ||||
|       intelWindowMoved( intel ); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( ctx ); /* required by GL */ | ||||
|     | ||||
|    SET_STATE(i830, state); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -407,10 +407,10 @@ | ||||
| #define LOGICOP_SET			0xf | ||||
| #define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00)) | ||||
| #define ENABLE_STENCIL_TEST_MASK	(1<<17) | ||||
| #define STENCIL_TEST_MASK(x)		((x)<<8) | ||||
| #define STENCIL_TEST_MASK(x)		(((x)&0xff)<<8) | ||||
| #define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff)) | ||||
| #define ENABLE_STENCIL_WRITE_MASK	(1<<16) | ||||
| #define STENCIL_WRITE_MASK(x)		(x) | ||||
| #define STENCIL_WRITE_MASK(x)		((x)&0xff) | ||||
|  | ||||
| /* _3DSTATE_MODES_5, p196 */ | ||||
| #define _3DSTATE_MODES_5_CMD		(CMD_3D|(0x0c<<24)) | ||||
|   | ||||
| @@ -1012,13 +1012,12 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|       (BUF_3D_ID_DEPTH | | ||||
|        BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | | ||||
|        BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; | ||||
| /*    i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; */ | ||||
|  | ||||
|  | ||||
|    i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; | ||||
|  | ||||
|    switch (screen->fbFormat) { | ||||
|    case DV_PF_555: | ||||
|    case DV_PF_565: | ||||
|       i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
| 					      DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
|   | ||||
| @@ -200,7 +200,7 @@ intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj ) | ||||
|  | ||||
|    texObj->DriverData = t; | ||||
|    t->intel.base.tObj = texObj; | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
|    t->intel.dirty = ~0; | ||||
|    make_empty_list( &t->intel.base ); | ||||
|  | ||||
|    t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */ | ||||
| @@ -268,7 +268,7 @@ static void i830TexParameter( GLcontext *ctx, GLenum target, | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
|    t->intel.dirty = ~0; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -101,7 +101,7 @@ static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ GLuint GetTexelOp(GLint unit) | ||||
| static inline GLuint GetTexelOp(GLint unit) | ||||
| { | ||||
|    switch(unit) { | ||||
|    case 0: return TEXBLENDARG_TEXEL0; | ||||
|   | ||||
| @@ -246,7 +246,7 @@ static GLboolean i830SetTexImages( i830ContextPtr i830, | ||||
|    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; | ||||
|    t->intel.dirty = ~0; | ||||
|  | ||||
|    return intelUploadTexImages( &i830->intel, &t->intel, 0 ); | ||||
| } | ||||
| @@ -259,11 +259,7 @@ static void i830_import_tex_unit( i830ContextPtr i830, | ||||
|    if(INTEL_DEBUG&DEBUG_TEXTURE) | ||||
|       fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); | ||||
|     | ||||
|    if (i830->intel.CurrentTexObj[unit])  | ||||
|       i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit); | ||||
|  | ||||
|    i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t; | ||||
|    t->intel.base.bound |= (1 << unit); | ||||
|  | ||||
|    I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) ); | ||||
|  | ||||
| @@ -285,7 +281,7 @@ static void i830_import_tex_unit( i830ContextPtr i830, | ||||
|    i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE]; | ||||
|    i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit); | ||||
|  | ||||
|    t->intel.dirty &= ~I830_UPLOAD_TEX(unit); | ||||
|    t->intel.dirty &= ~(1<<unit); /* This is broken! */ | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -317,7 +313,7 @@ static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) | ||||
|     * time. | ||||
|     */ | ||||
|    if (i830->intel.CurrentTexObj[unit] != &t->intel ||  | ||||
|        (t->intel.dirty & I830_UPLOAD_TEX(unit))) { | ||||
|        (t->intel.dirty & (1<<unit))) { | ||||
|       i830_import_tex_unit( i830, t, unit); | ||||
|    } | ||||
|  | ||||
| @@ -419,14 +415,10 @@ static GLboolean disable_tex( GLcontext *ctx, GLuint 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; | ||||
|    } | ||||
|    /* The old texture is no longer bound to this texture unit. | ||||
|     * Mark it as such. | ||||
|     */ | ||||
|    i830->intel.CurrentTexObj[unit] = NULL; | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
| @@ -436,7 +428,7 @@ 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) | ||||
|        intel_context(ctx)->intelScreen->tex.size < 2048 * 1024) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    switch(texUnit->_ReallyEnabled) { | ||||
| @@ -458,7 +450,7 @@ static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i830UpdateTextureState( intelContextPtr intel ) | ||||
| void i830UpdateTextureState( struct intel_context *intel ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|   | ||||
| @@ -34,7 +34,7 @@ | ||||
| #include "tnl/t_context.h" | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
| static GLboolean i830_check_vertex_size( struct intel_context *intel, | ||||
| 					 GLuint expected ); | ||||
|  | ||||
| #define SZ_TO_HW(sz)  ((sz-2)&0x3) | ||||
| @@ -59,7 +59,7 @@ 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); | ||||
| @@ -186,7 +186,7 @@ static void i830_render_start( intelContextPtr intel ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i830_reduced_primitive_state( intelContextPtr intel, | ||||
| static void i830_reduced_primitive_state( struct intel_context *intel, | ||||
| 					  GLenum rprim ) | ||||
| { | ||||
|     i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
| @@ -217,7 +217,7 @@ static void i830_reduced_primitive_state( intelContextPtr intel, | ||||
| /* Pull apart the vertex format registers and figure out how large a | ||||
|  * vertex is supposed to be.  | ||||
|  */ | ||||
| static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
| static GLboolean i830_check_vertex_size( struct intel_context *intel, | ||||
| 					 GLuint expected ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
| @@ -257,11 +257,11 @@ static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
|    return sz == expected; | ||||
| } | ||||
|  | ||||
| static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
| static void i830_emit_invarient_state( struct intel_context *intel ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH( 200 ); | ||||
|    BEGIN_BATCH(200, 0); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0)); | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1)); | ||||
| @@ -355,7 +355,7 @@ static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
| #define emit( intel, state, size )			\ | ||||
| do {							\ | ||||
|    int k;						\ | ||||
|    BEGIN_BATCH( size / sizeof(GLuint));			\ | ||||
|    BEGIN_BATCH(size / sizeof(GLuint), 0);			\ | ||||
|    for (k = 0 ; k < size / sizeof(GLuint) ; k++)	\ | ||||
|       OUT_BATCH(state[k]);				\ | ||||
|    ADVANCE_BATCH();					\ | ||||
| @@ -364,7 +364,7 @@ do {							\ | ||||
|  | ||||
| /* 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_hw_state *state = i830->current; | ||||
| @@ -405,32 +405,32 @@ static void i830_emit_state( intelContextPtr intel ) | ||||
|    state->emitted |= dirty; | ||||
| } | ||||
|  | ||||
| static void i830_destroy_context( intelContextPtr intel ) | ||||
| static void i830_destroy_context( struct intel_context *intel ) | ||||
| { | ||||
|    _tnl_free_vertices(&intel->ctx); | ||||
| } | ||||
|  | ||||
| static void i830_set_draw_offset( intelContextPtr intel, int offset ) | ||||
| static void i830_set_draw_offset( struct intel_context *intel, int offset ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS ); | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset; | ||||
| /*    i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset; */ | ||||
| } | ||||
|  | ||||
| /* This isn't really handled at the moment. | ||||
|  */ | ||||
| static void i830_lost_hardware( intelContextPtr intel ) | ||||
| static void i830_lost_hardware( struct intel_context *intel ) | ||||
| { | ||||
|    I830_CONTEXT(intel)->state.emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void i830_emit_flush( intelContextPtr intel ) | ||||
| static void i830_emit_flush( struct intel_context *intel ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH(2); | ||||
|    BEGIN_BATCH(2, 0); | ||||
|    OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
| @@ -441,7 +441,6 @@ static void i830_emit_flush( intelContextPtr intel ) | ||||
|  | ||||
| void i830InitVtbl( i830ContextPtr i830 ) | ||||
| { | ||||
|    i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj; | ||||
|    i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; | ||||
|    i830->intel.vtbl.clear_with_tris = i830ClearWithTris; | ||||
|    i830->intel.vtbl.destroy = i830_destroy_context; | ||||
|   | ||||
| @@ -41,6 +41,10 @@ | ||||
| #include "utils.h" | ||||
| #include "i915_reg.h" | ||||
|  | ||||
| #include "bufmgr.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| /*************************************** | ||||
|  * Mesa's Driver Functions | ||||
|  ***************************************/ | ||||
| @@ -65,7 +69,7 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state ) | ||||
|    _ac_InvalidateState( ctx, new_state ); | ||||
|    _tnl_InvalidateState( ctx, new_state ); | ||||
|    _tnl_invalidate_vertex_state( ctx, new_state ); | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= new_state; | ||||
|    intel_context(ctx)->NewGLState |= new_state; | ||||
|  | ||||
|    /* Todo: gather state values under which tracked parameters become | ||||
|     * invalidated, add callbacks for things like | ||||
| @@ -99,13 +103,16 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
| 			    void *sharedContextPrivate) | ||||
| { | ||||
|    struct dd_function_table functions; | ||||
|    i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context); | ||||
|    intelContextPtr intel = &i915->intel; | ||||
|    struct i915_context *i915 = (struct i915_context *) CALLOC_STRUCT(i915_context); | ||||
|    struct intel_context *intel = &i915->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|    if (!i915) return GL_FALSE; | ||||
|  | ||||
|    _mesa_printf( "\ntexmem branch (i915, drop2)\n\n"); | ||||
|     | ||||
|    i915InitVtbl( i915 ); | ||||
|    i915InitMetaFuncs( i915 ); | ||||
|  | ||||
|    i915InitDriverFunctions( &functions ); | ||||
|  | ||||
| @@ -119,33 +126,14 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
|    ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS; | ||||
|    ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS; | ||||
|  | ||||
|    intel->nr_heaps = 1; | ||||
|    intel->texture_heaps[0] =  | ||||
|       driCreateTextureHeap( 0, intel, | ||||
| 			    intel->intelScreen->tex.size, | ||||
| 			    12, | ||||
| 			    I830_NR_TEX_REGIONS, | ||||
| 			    intel->sarea->texList, | ||||
| 			    & intel->sarea->texAge, | ||||
| 			    & intel->swapped, | ||||
| 			    sizeof( struct i915_texture_object ), | ||||
| 			    (destroy_texture_object_t *)intelDestroyTexObj ); | ||||
|  | ||||
|    /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are | ||||
|     * tightly packed, but they're not in Intel graphics | ||||
|     * hardware. | ||||
|    /* Advertise the full hardware capabilities.  The new memory | ||||
|     * manager should cope much better with overload situations: | ||||
|     */ | ||||
|    ctx->Const.MaxTextureUnits = 1; | ||||
|    driCalculateMaxTextureLevels( intel->texture_heaps, | ||||
| 				 intel->nr_heaps, | ||||
| 				 &intel->ctx.Const, | ||||
| 				 4, | ||||
| 				 11, /* max 2D texture size is 2048x2048 */ | ||||
| 				 8,  /* 3D texture */ | ||||
| 				 11, /* cube texture. */ | ||||
| 				 11, /* rect texture */ | ||||
| 				 12, | ||||
| 				 GL_FALSE ); | ||||
|    ctx->Const.MaxTextureLevels = 12; | ||||
|    ctx->Const.Max3DTextureLevels = 9; | ||||
|    ctx->Const.MaxCubeTextureLevels = 12; | ||||
|    ctx->Const.MaxTextureRectSize = (1<<11); | ||||
|    ctx->Const.MaxTextureUnits = I915_TEX_UNITS; | ||||
|  | ||||
|    /* GL_ARB_fragment_program limits - don't think Mesa actually | ||||
| @@ -153,14 +141,13 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
|     * instruction can translate to more than one HW instruction, so | ||||
|     * we'll still have to check and fallback each time. | ||||
|     */    | ||||
|     | ||||
|    ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */ | ||||
|    ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN; | ||||
|    ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN; | ||||
|    ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +  | ||||
| 						I915_MAX_TEX_INSN); | ||||
| 						       I915_MAX_TEX_INSN); | ||||
|    ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */ | ||||
|  | ||||
|   | ||||
| @@ -43,6 +43,7 @@ | ||||
| #define I915_UPLOAD_PROGRAM          0x8 | ||||
| #define I915_UPLOAD_CONSTANTS        0x10 | ||||
| #define I915_UPLOAD_FOG              0x20 | ||||
| #define I915_UPLOAD_INVARIENT        0x40 | ||||
| #define I915_UPLOAD_TEX(i)           (0x00010000<<(i)) | ||||
| #define I915_UPLOAD_TEX_ALL          (0x00ff0000) | ||||
| #define I915_UPLOAD_TEX_0_SHIFT      16 | ||||
| @@ -52,10 +53,8 @@ | ||||
|  */ | ||||
| #define I915_DESTREG_CBUFADDR0 0 | ||||
| #define I915_DESTREG_CBUFADDR1 1 | ||||
| #define I915_DESTREG_CBUFADDR2 2 | ||||
| #define I915_DESTREG_DBUFADDR0 3 | ||||
| #define I915_DESTREG_DBUFADDR1 4 | ||||
| #define I915_DESTREG_DBUFADDR2 5 | ||||
| #define I915_DESTREG_DV0 6 | ||||
| #define I915_DESTREG_DV1 7 | ||||
| #define I915_DESTREG_SENABLE 8 | ||||
| @@ -86,7 +85,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 | ||||
| @@ -163,8 +161,6 @@ struct i915_fragment_program { | ||||
|    GLuint nr_params; | ||||
|        | ||||
|  | ||||
|  | ||||
|  | ||||
|    /* Helpers for i915_texprog.c: | ||||
|     */ | ||||
|    GLuint src_texture;		/* Reg containing sampled texture color, | ||||
| @@ -185,13 +181,6 @@ struct i915_fragment_program { | ||||
|  | ||||
|  | ||||
|  | ||||
| struct i915_texture_object | ||||
| { | ||||
|    struct intel_texture_object intel; | ||||
|    GLenum lastTarget; | ||||
|    GLboolean refs_border_color; | ||||
|    GLuint Setup[I915_TEX_SETUP_SIZE]; | ||||
| }; | ||||
|  | ||||
| #define I915_TEX_UNITS 8 | ||||
|  | ||||
| @@ -206,6 +195,15 @@ struct i915_hw_state { | ||||
|    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]; | ||||
|    GLuint tex_offset[I915_TEX_UNITS]; | ||||
|     | ||||
|  | ||||
|    GLuint active;		/* I915_UPLOAD_* */ | ||||
|    GLuint emitted;		/* I915_UPLOAD_* */ | ||||
| }; | ||||
| @@ -220,6 +218,8 @@ struct i915_context | ||||
|  | ||||
|    GLuint last_ReallyEnabled; | ||||
|    GLuint vertex_fog; | ||||
|    GLuint lodbias_ss2[MAX_TEXTURE_UNITS]; | ||||
|  | ||||
|  | ||||
|    struct i915_fragment_program tex_program; | ||||
|    struct i915_fragment_program *current_program; | ||||
| @@ -228,24 +228,14 @@ struct i915_context | ||||
| }; | ||||
|  | ||||
|  | ||||
| typedef struct i915_context *i915ContextPtr; | ||||
| typedef struct i915_texture_object *i915TextureObjectPtr; | ||||
|  | ||||
| #define I915_CONTEXT(ctx)	((i915ContextPtr)(ctx)) | ||||
|  | ||||
|  | ||||
|  | ||||
| #define I915_STATECHANGE(i915, flag)					\ | ||||
| do {									\ | ||||
|    if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__);	\ | ||||
|    INTEL_FIREVERTICES( &(i915)->intel );					\ | ||||
|    (i915)->state.emitted &= ~(flag);					\ | ||||
| } while (0) | ||||
|  | ||||
| #define I915_ACTIVESTATE(i915, flag, mode)			\ | ||||
| do {								\ | ||||
|    if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n",	\ | ||||
| 		  flag, mode, __FUNCTION__);			\ | ||||
|    INTEL_FIREVERTICES( &(i915)->intel );				\ | ||||
|    if (mode)							\ | ||||
|       (i915)->state.active |= (flag);				\ | ||||
| @@ -257,7 +247,7 @@ do {								\ | ||||
| /*====================================================================== | ||||
|  * i915_vtbl.c | ||||
|  */ | ||||
| extern void i915InitVtbl( i915ContextPtr i915 ); | ||||
| extern void i915InitVtbl( struct i915_context *i915 ); | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -294,7 +284,7 @@ extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
| /*====================================================================== | ||||
|  * i915_texprog.c | ||||
|  */ | ||||
| extern void i915ValidateTextureProgram( i915ContextPtr i915 ); | ||||
| extern void i915ValidateTextureProgram( struct i915_context *i915 ); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
| @@ -308,44 +298,43 @@ extern void i915_print_ureg( const char *msg, GLuint ureg ); | ||||
|  * i915_state.c | ||||
|  */ | ||||
| extern void i915InitStateFunctions( struct dd_function_table *functions ); | ||||
| extern void i915InitState( i915ContextPtr i915 ); | ||||
| extern void i915InitState( struct i915_context *i915 ); | ||||
| extern void i915_update_fog( GLcontext *ctx ); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_tex.c | ||||
|  */ | ||||
| extern void i915UpdateTextureState( intelContextPtr intel ); | ||||
| extern void i915UpdateTextureState( struct intel_context *intel ); | ||||
| extern void i915InitTextureFuncs( struct dd_function_table *functions ); | ||||
| extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ); | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_metaops.c | ||||
|  */ | ||||
| extern GLboolean | ||||
| i915TryTextureReadPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *pack, | ||||
| 			  GLvoid *pixels ); | ||||
|  | ||||
| extern GLboolean | ||||
| i915TryTextureDrawPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  const GLvoid *pixels ); | ||||
|  | ||||
| extern void  | ||||
| i915ClearWithTris( intelContextPtr intel, GLbitfield mask, | ||||
| 		   GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); | ||||
| void i915InitMetaFuncs( struct i915_context *i915 ); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_fragprog.c | ||||
|  */ | ||||
| extern void i915ValidateFragmentProgram( i915ContextPtr i915 ); | ||||
| extern void i915ValidateFragmentProgram( struct i915_context *i915 ); | ||||
| extern void i915InitFragProgFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.  These are better-typed than the | ||||
|  * macros used previously: | ||||
|  */ | ||||
| static inline struct i915_context * | ||||
| i915_context( GLcontext *ctx ) | ||||
| { | ||||
|    return (struct i915_context *)ctx; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #define I915_CONTEXT(ctx)	i915_context(ctx) | ||||
|  | ||||
|  | ||||
| 	 | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -806,7 +806,7 @@ static void check_wpos( struct i915_fragment_program *p ) | ||||
|  | ||||
| static void translate_program( struct i915_fragment_program *p ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(p->ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(p->ctx); | ||||
|     | ||||
|    i915_init_program( i915, p ); | ||||
|    check_wpos( p );  | ||||
| @@ -840,7 +840,7 @@ static void i915BindProgram( GLcontext *ctx, | ||||
| 			    struct program *prog ) | ||||
| { | ||||
|    if (target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *)prog; | ||||
|  | ||||
|       if (i915->current_program == p)  | ||||
| @@ -896,7 +896,7 @@ static void i915DeleteProgram( GLcontext *ctx, | ||||
| 			      struct program *prog ) | ||||
| { | ||||
|    if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *)prog; | ||||
|        | ||||
|       if (i915->current_program == p)  | ||||
| @@ -940,10 +940,10 @@ static void i915ProgramStringNotify( GLcontext *ctx, | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
| void i915ValidateFragmentProgram( struct i915_context *i915 ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|  | ||||
|   | ||||
| @@ -34,39 +34,32 @@ | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i915_context.h" | ||||
| #include "i915_reg.h" | ||||
|  | ||||
| /* A large amount of state doesn't need to be uploaded. | ||||
|  */ | ||||
| #define ACTIVE (I915_UPLOAD_PROGRAM | 		\ | ||||
| #define ACTIVE (I915_UPLOAD_INVARIENT | 	\ | ||||
|                 I915_UPLOAD_PROGRAM | 		\ | ||||
| 		I915_UPLOAD_STIPPLE |		\ | ||||
| 		I915_UPLOAD_CTX |		\ | ||||
| 		I915_UPLOAD_BUFFERS |		\ | ||||
| 		I915_UPLOAD_TEX(0))		 | ||||
|  | ||||
| #define SET_STATE( i915, STATE )			\ | ||||
| #define SET_STATE( i915, STATE )		\ | ||||
| do {						\ | ||||
|    i915->current->emitted &= ~ACTIVE;		\ | ||||
|    i915->current = &i915->STATE;			\ | ||||
|    i915->current = &i915->STATE;		\ | ||||
|    i915->current->emitted &= ~ACTIVE;		\ | ||||
| } while (0) | ||||
|  | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void set_initial_state( i915ContextPtr i915 ) | ||||
| { | ||||
|    memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) ); | ||||
|    i915->meta.active = ACTIVE; | ||||
|    i915->meta.emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_no_depth_stencil_write( i915ContextPtr i915 ) | ||||
| static void meta_no_depth_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 |  | ||||
| @@ -82,10 +75,11 @@ static void set_no_depth_stencil_write( i915ContextPtr i915 ) | ||||
|  | ||||
| /* Set stencil unit to replace always with the reference value. | ||||
|  */ | ||||
| static void set_stencil_replace( i915ContextPtr i915, | ||||
| static void meta_stencil_replace( struct intel_context *intel, | ||||
| 				 GLuint s_mask, | ||||
| 				 GLuint s_clear) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint op = STENCILOP_REPLACE; | ||||
|    GLuint func = COMPAREFUNC_ALWAYS; | ||||
|  | ||||
| @@ -100,7 +94,6 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE | | ||||
| 				       S6_DEPTH_WRITE_ENABLE); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.StencilMask( ctx, s_mask ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; | ||||
| @@ -108,7 +101,6 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | | ||||
| 					STENCIL_WRITE_MASK(s_mask)); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK | | ||||
| @@ -137,8 +129,9 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
| static void meta_color_mask( struct intel_context *intel, GLboolean state ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    const GLuint mask = (S5_WRITEDISABLE_RED | | ||||
| 			S5_WRITEDISABLE_GREEN | | ||||
| 			S5_WRITEDISABLE_BLUE | | ||||
| @@ -210,8 +203,10 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void set_no_texture( i915ContextPtr i915 ) | ||||
| static void meta_no_texture( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    static const GLuint prog[] = { | ||||
|       _3DSTATE_PIXEL_SHADER_PROGRAM, | ||||
|  | ||||
| @@ -240,9 +235,10 @@ static void set_no_texture( i915ContextPtr i915 ) | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_PROGRAM; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static void enable_texture_blend_replace( i915ContextPtr i915 ) | ||||
| static void meta_texture_blend_replace( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    static const GLuint prog[] = { | ||||
|       _3DSTATE_PIXEL_SHADER_PROGRAM, | ||||
|  | ||||
| @@ -285,78 +281,86 @@ static void enable_texture_blend_replace( i915ContextPtr i915 ) | ||||
| /* Set up an arbitary piece of memory as a rectangular texture | ||||
|  * (including the front or back buffer). | ||||
|  */ | ||||
| static void set_tex_rect_source( i915ContextPtr i915, | ||||
| 				 GLuint offset, | ||||
| 				 GLuint width,  | ||||
| 				 GLuint height, | ||||
| 				 GLuint pitch, | ||||
| static void meta_tex_rect_source( struct intel_context *intel, | ||||
| 				 struct intel_region *region, | ||||
| 				 GLuint textureFormat ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint unit = 0; | ||||
|    GLint numLevels = 1; | ||||
|    GLuint *state = i915->meta.Tex[0]; | ||||
|  | ||||
|    pitch *= i915->intel.intelScreen->cpp; | ||||
|    GLuint pitch = region->pitch * region->cpp; | ||||
|  | ||||
| /*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */ | ||||
| /* 	   __FUNCTION__, offset, width, height, pitch, textureFormat ); */ | ||||
|  | ||||
|    state[I915_TEXREG_MS2] = offset; | ||||
|    state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) | | ||||
| 			    ((width - 1) << MS3_WIDTH_SHIFT) | | ||||
| 			    textureFormat | | ||||
| 			    MS3_USE_FENCE_REGS); | ||||
|    intel_region_release(intel, &i915->meta.tex_region[0]); | ||||
|    intel_region_reference(&i915->meta.tex_region[0], region); | ||||
|    i915->meta.tex_offset[0] = 0; | ||||
|  | ||||
|    state[I915_TEXREG_MS3] = (((region->height - 1) << MS3_HEIGHT_SHIFT) | | ||||
| 			     ((region->pitch - 1) << MS3_WIDTH_SHIFT) | | ||||
| 			     textureFormat | | ||||
| 			     MS3_USE_FENCE_REGS); | ||||
|  | ||||
|    state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |  | ||||
| 			    MS4_CUBE_FACE_ENA_MASK | | ||||
| 			    ((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT)); | ||||
| 			     MS4_CUBE_FACE_ENA_MASK | | ||||
| 			     ((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) | | ||||
| 			    (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | | ||||
| 			    (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT)); | ||||
| 			     (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | | ||||
| 			     (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) | | ||||
| 			    (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) | | ||||
| 			    (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) | | ||||
| 			    (unit<<SS3_TEXTUREMAP_INDEX_SHIFT)); | ||||
| 			     (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) | | ||||
| 			     (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) | | ||||
| 			     (unit<<SS3_TEXTUREMAP_INDEX_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS4] = 0; | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_TEX(0); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* Select between front and back draw buffers. | ||||
|  */ | ||||
| static void set_draw_offset( i915ContextPtr i915, | ||||
| 			     GLuint offset ) | ||||
| static void meta_draw_region( struct intel_context *intel, | ||||
| 			     struct intel_region *draw_region, | ||||
| 			     struct intel_region *depth_region ) | ||||
| { | ||||
|    i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    intel_region_release(intel, &i915->meta.draw_region); | ||||
|    intel_region_release(intel, &i915->meta.depth_region); | ||||
|    intel_region_reference(&i915->meta.draw_region, draw_region); | ||||
|    intel_region_reference(&i915->meta.depth_region, depth_region); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| /* Setup an arbitary draw format, useful for targeting texture or agp | ||||
|  * memory. | ||||
|  */ | ||||
| static void set_draw_format( i915ContextPtr i915, | ||||
| static void set_draw_format( struct intel_context *intel, | ||||
| 			     GLuint format, | ||||
| 			     GLuint depth_format) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    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); | ||||
| 					  DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
| 					  format | | ||||
| 					  LOD_PRECLAMP_OGL | | ||||
| 					  TEX_DEFAULT_COLOR_OGL | | ||||
| 					  depth_format); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
| /*    fprintf(stderr, "%s: DV1: %x\n",  */ | ||||
| /* 	   __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void set_vertex_format( i915ContextPtr i915 ) | ||||
| static void set_vertex_format( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS2] =  | ||||
|       (S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) | | ||||
|        S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |  | ||||
| @@ -371,146 +375,50 @@ static void set_vertex_format( i915ContextPtr i915 ) | ||||
|  | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS4] |=  | ||||
|       (S4_VFMT_COLOR | | ||||
|        S4_VFMT_SPEC_FOG | | ||||
|        S4_VFMT_XYZW); | ||||
|        S4_VFMT_XYZ); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| static void draw_quad(i915ContextPtr i915,  | ||||
| 		      GLfloat x0, GLfloat x1, | ||||
| 		      GLfloat y0, GLfloat y1,  | ||||
| 		      GLubyte red, GLubyte green, | ||||
| 		      GLubyte blue, GLubyte alpha, | ||||
| 		      GLfloat s0, GLfloat s1, | ||||
| 		      GLfloat t0, GLfloat t1 ) | ||||
|  | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void install_meta_state( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint vertex_size = 8; | ||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,  | ||||
| 						PRIM3D_TRIFAN,  | ||||
| 						4 * vertex_size, | ||||
| 						vertex_size ); | ||||
|    intelVertex tmp; | ||||
|    int i; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) ); | ||||
|    i915->meta.active = ACTIVE; | ||||
|    i915->meta.emitted = 0; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", | ||||
| 	      __FUNCTION__, | ||||
| 	      x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); | ||||
|  | ||||
|  | ||||
|    /* initial vertex, left bottom */ | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.y = y0; | ||||
|    tmp.v.z = 1.0; | ||||
|    tmp.v.w = 1.0;  | ||||
|    tmp.v.color.red = red; | ||||
|    tmp.v.color.green = green; | ||||
|    tmp.v.color.blue = blue; | ||||
|    tmp.v.color.alpha = alpha; | ||||
|    tmp.v.specular.red = 0; | ||||
|    tmp.v.specular.green = 0; | ||||
|    tmp.v.specular.blue = 0; | ||||
|    tmp.v.specular.alpha = 0; | ||||
|    tmp.v.u0 = s0; | ||||
|    tmp.v.v0 = t0; | ||||
|  | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right bottom */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.x = x1; | ||||
|    tmp.v.u0 = s1; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right top */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.y = y1; | ||||
|    tmp.v.v0 = t1; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* left top */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.u0 = s0; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|    SET_STATE(i915, meta); | ||||
|    set_vertex_format(intel); | ||||
|    meta_no_texture(intel); | ||||
| } | ||||
|  | ||||
| void  | ||||
| i915ClearWithTris(intelContextPtr intel, GLbitfield mask, | ||||
| 		  GLboolean all, | ||||
| 		  GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| static void leave_meta_state( struct intel_context *intel ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( intel ); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    int x0, y0, x1, y1; | ||||
|  | ||||
|    SET_STATE( i915, meta );  | ||||
|    set_initial_state( i915 );  | ||||
|    set_no_texture( i915 );  | ||||
|    set_vertex_format( i915 );  | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if(!all) { | ||||
|       x0 = cx; | ||||
|       y0 = cy; | ||||
|       x1 = x0 + cw; | ||||
|       y1 = y0 + ch; | ||||
|    } else { | ||||
|       x0 = 0; | ||||
|       y0 = 0; | ||||
|       x1 = x0 + dPriv->w; | ||||
|       y1 = y0 + dPriv->h; | ||||
|    } | ||||
|  | ||||
|    /* Don't do any clipping to screen - these are window coordinates. | ||||
|     * The active cliprects will be applied as for any other geometry. | ||||
|     */ | ||||
|  | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) {  | ||||
|       set_no_depth_stencil_write( i915 ); | ||||
|       set_color_mask( i915, GL_TRUE ); | ||||
|       set_draw_offset( i915, screen->front.offset ); | ||||
|  | ||||
|       draw_quad(i915, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green,  | ||||
|  		intel->clear_blue, intel->clear_alpha,  | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       set_no_depth_stencil_write( i915 ); | ||||
|       set_color_mask( i915, GL_TRUE ); | ||||
|       set_draw_offset( i915, screen->back.offset ); | ||||
|  | ||||
|       draw_quad(i915, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green, | ||||
| 		intel->clear_blue, intel->clear_alpha, | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       set_stencil_replace( i915,  | ||||
| 			   intel->ctx.Stencil.WriteMask[0],  | ||||
| 			   intel->ctx.Stencil.Clear); | ||||
|        | ||||
|       set_color_mask( i915, GL_FALSE ); | ||||
|       set_draw_offset( i915, screen->front.offset ); /* could be either? */ | ||||
|  | ||||
|       draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 ); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    SET_STATE( i915, state ); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    intel_region_release(intel, &i915->meta.draw_region); | ||||
|    intel_region_release(intel, &i915->meta.depth_region); | ||||
|    intel_region_release(intel, &i915->meta.tex_region[0]); | ||||
|    SET_STATE(i915, state); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void i915InitMetaFuncs( struct i915_context *i915 ) | ||||
| { | ||||
|    i915->intel.vtbl.install_meta_state = install_meta_state; | ||||
|    i915->intel.vtbl.leave_meta_state = leave_meta_state; | ||||
|    i915->intel.vtbl.meta_no_depth_stencil_write = meta_no_depth_stencil_write; | ||||
|    i915->intel.vtbl.meta_stencil_replace = meta_stencil_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_draw_format = set_draw_format; | ||||
| } | ||||
|   | ||||
| @@ -358,7 +358,7 @@ void i915_program_error( struct i915_fragment_program *p, const char *msg ) | ||||
|    p->error = 1; | ||||
| } | ||||
|  | ||||
| void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
| void i915_init_program( struct i915_context *i915, struct i915_fragment_program *p ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT( ctx ); | ||||
| @@ -431,7 +431,7 @@ void i915_fini_program( struct i915_fragment_program *p ) | ||||
|    p->declarations[0] |= program_size + decl_size - 2; | ||||
| } | ||||
|  | ||||
| void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
| void i915_upload_program( struct i915_context *i915, struct i915_fragment_program *p ) | ||||
| { | ||||
|    GLuint program_size = p->csr - p->program; | ||||
|    GLuint decl_size = p->decl - p->declarations; | ||||
|   | ||||
| @@ -84,7 +84,7 @@ | ||||
|  | ||||
| /* One neat thing about the UREG representation:   | ||||
|  */ | ||||
| static __inline int swizzle( int reg, int x, int y, int z, int w ) | ||||
| static inline int swizzle( int reg, int x, int y, int z, int w ) | ||||
| { | ||||
|    return ((reg & ~UREG_XYZW_CHANNEL_MASK) | | ||||
| 	   CHANNEL_SRC( GET_CHANNEL_SRC( reg, x ), 0 ) | | ||||
| @@ -95,7 +95,7 @@ static __inline int swizzle( int reg, int x, int y, int z, int w ) | ||||
|  | ||||
| /* Another neat thing about the UREG representation:   | ||||
|  */ | ||||
| static __inline int negate( int reg, int x, int y, int z, int w ) | ||||
| static inline int negate( int reg, int x, int y, int z, int w ) | ||||
| { | ||||
|    return reg ^ (((x&1)<<UREG_CHANNEL_X_NEGATE_SHIFT)| | ||||
| 		 ((y&1)<<UREG_CHANNEL_Y_NEGATE_SHIFT)| | ||||
| @@ -149,10 +149,10 @@ extern GLuint i915_emit_param4fv( struct i915_fragment_program *p, | ||||
| extern void i915_program_error( struct i915_fragment_program *p, | ||||
|                                 const char *msg ); | ||||
|  | ||||
| extern void i915_init_program( i915ContextPtr i915, | ||||
| extern void i915_init_program( struct i915_context *i915, | ||||
| 			      struct i915_fragment_program *p ); | ||||
|  | ||||
| extern void i915_upload_program( i915ContextPtr i915,  | ||||
| extern void i915_upload_program( struct i915_context *i915,  | ||||
| 				struct i915_fragment_program *p ); | ||||
|  | ||||
| extern void i915_fini_program( struct i915_fragment_program *p ); | ||||
|   | ||||
| @@ -435,10 +435,10 @@ | ||||
| #define LOGICOP_MASK			(0xf<<18) | ||||
| #define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00)) | ||||
| #define ENABLE_STENCIL_TEST_MASK	(1<<17) | ||||
| #define STENCIL_TEST_MASK(x)		((x)<<8) | ||||
| #define STENCIL_TEST_MASK(x)		(((x)&0xff)<<8) | ||||
| #define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff)) | ||||
| #define ENABLE_STENCIL_WRITE_MASK	(1<<16) | ||||
| #define STENCIL_WRITE_MASK(x)		(x) | ||||
| #define STENCIL_WRITE_MASK(x)		((x)&0xff) | ||||
|  | ||||
| /* _3DSTATE_MODES_5, p220 */ | ||||
| #define _3DSTATE_MODES_5_CMD		(CMD_3D|(0x0c<<24)) | ||||
|   | ||||
| @@ -48,7 +48,7 @@ static void | ||||
| i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
|                         GLuint mask) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func( func ); | ||||
|  | ||||
|    mask = mask & 0xff; | ||||
| @@ -73,7 +73,7 @@ i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
| static void | ||||
| i915StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask); | ||||
| @@ -91,7 +91,7 @@ static void | ||||
| i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|                       GLenum zpass) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int fop = intel_translate_stencil_op(fail);  | ||||
|    int dfop = intel_translate_stencil_op(zfail);  | ||||
|    int dpop = intel_translate_stencil_op(zpass); | ||||
| @@ -116,7 +116,7 @@ i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|  | ||||
| static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func( func ); | ||||
|    GLubyte refByte; | ||||
|  | ||||
| @@ -137,7 +137,7 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
|  */ | ||||
| static void i915EvalLogicOpBlendState(GLcontext *ctx) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
| @@ -157,7 +157,7 @@ static void i915EvalLogicOpBlendState(GLcontext *ctx) | ||||
|  | ||||
| static void i915BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLubyte r, g, b, a; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -194,7 +194,7 @@ static GLuint translate_blend_equation( GLenum mode ) | ||||
|  | ||||
| static void i915UpdateBlendState( GLcontext *ctx ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &  | ||||
| 		 ~(IAB_SRC_FACTOR_MASK | | ||||
| 		   IAB_DST_FACTOR_MASK | | ||||
| @@ -261,7 +261,7 @@ static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB, | ||||
|  | ||||
| static void i915DepthFunc(GLcontext *ctx, GLenum func) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func( func ); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -274,7 +274,7 @@ static void i915DepthFunc(GLcontext *ctx, GLenum func) | ||||
|  | ||||
| static void i915DepthMask(GLcontext *ctx, GLboolean flag) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag); | ||||
| @@ -295,7 +295,7 @@ static void i915DepthMask(GLcontext *ctx, GLboolean flag) | ||||
|  */ | ||||
| static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    const GLubyte *m = mask; | ||||
|    GLubyte p[4]; | ||||
|    int i,j,k; | ||||
| @@ -348,7 +348,7 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| static void i915Scissor(GLcontext *ctx, GLint x, GLint y,  | ||||
| 			GLsizei w, GLsizei h) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = i915->intel.intelScreen; | ||||
|    int x1, y1, x2, y2; | ||||
|  | ||||
| @@ -382,7 +382,7 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y, | ||||
|  | ||||
| static void i915LogicOp(GLcontext *ctx, GLenum opcode) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int tmp = intel_translate_logic_op(opcode); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -397,7 +397,7 @@ static void i915LogicOp(GLcontext *ctx, GLenum opcode) | ||||
|  | ||||
| static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLuint mode; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -425,7 +425,7 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
|  | ||||
| static void i915LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    struct i915_context *i915 = I915_CONTEXT( ctx ); | ||||
|    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK; | ||||
|    int width; | ||||
|  | ||||
| @@ -444,7 +444,7 @@ static void i915LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
|  | ||||
| static void i915PointSize(GLcontext *ctx, GLfloat size) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK; | ||||
|    GLint point_size = (int)size; | ||||
|  | ||||
| @@ -469,7 +469,7 @@ static void i915ColorMask(GLcontext *ctx, | ||||
| 			 GLboolean r, GLboolean g, | ||||
| 			 GLboolean b, GLboolean a) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    struct i915_context *i915 = I915_CONTEXT( ctx ); | ||||
|    GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -490,7 +490,7 @@ static void update_specular( GLcontext *ctx ) | ||||
| { | ||||
|    /* A hack to trigger the rebuild of the fragment program. | ||||
|     */ | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= _NEW_TEXTURE; | ||||
|    intel_context(ctx)->NewGLState |= _NEW_TEXTURE; | ||||
|    I915_CONTEXT(ctx)->tex_program.translated = 0;  | ||||
| } | ||||
|  | ||||
| @@ -507,7 +507,7 @@ static void i915LightModelfv(GLcontext *ctx, GLenum pname, | ||||
|  | ||||
| static void i915ShadeModel(GLcontext *ctx, GLenum mode) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
|    if (mode == GL_SMOOTH) { | ||||
| @@ -526,7 +526,7 @@ static void i915ShadeModel(GLcontext *ctx, GLenum mode) | ||||
|  */ | ||||
| void i915_update_fog( GLcontext *ctx ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLenum mode; | ||||
|    GLboolean enabled; | ||||
|    GLboolean try_pixel_fog; | ||||
| @@ -619,7 +619,7 @@ void i915_update_fog( GLcontext *ctx ) | ||||
|  | ||||
| static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_FOG_COORDINATE_SOURCE_EXT:  | ||||
| @@ -671,7 +671,7 @@ static void i915Hint(GLcontext *ctx, GLenum target, GLenum state) | ||||
|  | ||||
| static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    switch(cap) { | ||||
|    case GL_TEXTURE_2D: | ||||
| @@ -785,7 +785,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_init_packets( i915ContextPtr i915 ) | ||||
| static void i915_init_packets( struct i915_context *i915 ) | ||||
| { | ||||
|    intelScreenPrivate *screen = i915->intel.intelScreen; | ||||
|  | ||||
| @@ -823,7 +823,6 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
| 					   ENABLE_STENCIL_WRITE_MASK | | ||||
| 					   STENCIL_WRITE_MASK(0xff)); | ||||
|  | ||||
|  | ||||
|       i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | | ||||
| 					IAB_MODIFY_ENABLE | | ||||
| 					IAB_MODIFY_FUNC | | ||||
| @@ -862,19 +861,15 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
| 	  BUF_3D_PITCH(screen->front.pitch * screen->cpp) | | ||||
| 	  BUF_3D_USE_FENCE); | ||||
|  | ||||
|  | ||||
|       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 * screen->cpp) | | ||||
| 	  BUF_3D_USE_FENCE); | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset; | ||||
|  | ||||
|  | ||||
|       i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; | ||||
|  | ||||
|       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,9 +900,10 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|     * we get hardware contexts working. | ||||
|     */ | ||||
|    i915->state.active = (I915_UPLOAD_PROGRAM |  | ||||
| 			I915_UPLOAD_STIPPLE |  | ||||
| 			I915_UPLOAD_CTX |  | ||||
| 			I915_UPLOAD_BUFFERS); | ||||
| 			 I915_UPLOAD_STIPPLE |  | ||||
| 			 I915_UPLOAD_CTX |  | ||||
| 			 I915_UPLOAD_BUFFERS | | ||||
| 			 I915_UPLOAD_INVARIENT); | ||||
| } | ||||
|  | ||||
| void i915InitStateFunctions( struct dd_function_table *functions ) | ||||
| @@ -937,7 +933,7 @@ void i915InitStateFunctions( struct dd_function_table *functions ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915InitState( i915ContextPtr i915 ) | ||||
| void i915InitState( struct i915_context *i915 ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|  | ||||
|   | ||||
| @@ -45,76 +45,10 @@ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Allocate space for and load the mesa images into the texture memory block. | ||||
|  * This will happen before drawing with a new texture, or drawing with a | ||||
|  * texture after it was swapped out or teximaged again. | ||||
|  */ | ||||
|  | ||||
| intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ) | ||||
| { | ||||
|    i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object ); | ||||
|    if ( !t )  | ||||
|       return NULL; | ||||
|  | ||||
|    texObj->DriverData = t; | ||||
|    t->intel.base.tObj = texObj; | ||||
|    t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|    make_empty_list( &t->intel.base ); | ||||
|    return &t->intel; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915TexParameter( GLcontext *ctx, GLenum target, | ||||
| 			     struct gl_texture_object *tObj, | ||||
| 			     GLenum pname, const GLfloat *params ) | ||||
| { | ||||
|    i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; | ||||
|   | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_MIN_FILTER: | ||||
|    case GL_TEXTURE_MAG_FILTER: | ||||
|    case GL_TEXTURE_MAX_ANISOTROPY_EXT: | ||||
|    case GL_TEXTURE_WRAP_S: | ||||
|    case GL_TEXTURE_WRAP_T: | ||||
|    case GL_TEXTURE_WRAP_R: | ||||
|    case GL_TEXTURE_BORDER_COLOR: | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_COMPARE_MODE: | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|    case GL_TEXTURE_COMPARE_FUNC: | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_BASE_LEVEL: | ||||
|    case GL_TEXTURE_MAX_LEVEL: | ||||
|    case GL_TEXTURE_MIN_LOD: | ||||
|    case GL_TEXTURE_MAX_LOD: | ||||
|       /* The i915 and its successors can do a lot of this without | ||||
|        * reloading the textures.  A project for someone? | ||||
|        */ | ||||
|       intelFlush( ctx ); | ||||
|       driSwapOutTextureObject( (driTextureObject *) t ); | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915TexEnv( GLcontext *ctx, GLenum target,  | ||||
| 			GLenum pname, const GLfloat *param ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    GLuint unit = ctx->Texture.CurrentUnit; | ||||
|    struct i915_context *i915 = I915_CONTEXT( ctx ); | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_ENV_COLOR: 	/* Should be a tracked param */ | ||||
| @@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_LOD_BIAS: { | ||||
|       int b = (int) ((*param) * 16.0); | ||||
|       GLuint unit = ctx->Texture.CurrentUnit; | ||||
|       GLint b = (int) ((*param) * 16.0); | ||||
|       if (b > 255) b = 255; | ||||
|       if (b < -256) b = -256; | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); | ||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK; | ||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] |=  | ||||
| 	 ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); | ||||
|       i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
| @@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | ||||
|  | ||||
|  | ||||
| static void i915BindTexture( GLcontext *ctx, GLenum target, | ||||
| 			    struct gl_texture_object *texObj ) | ||||
|                              struct gl_texture_object *texobj ) | ||||
| { | ||||
|    i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData; | ||||
|  | ||||
|    if (tex->lastTarget != texObj->Target) { | ||||
|       tex->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       tex->lastTarget = texObj->Target; | ||||
|    } | ||||
|  | ||||
|    /* Need this if image format changes between bound textures. | ||||
|     * Could try and shortcircuit by checking for differences in | ||||
|     * state between incoming and outgoing textures: | ||||
| @@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->BindTexture = i915BindTexture; | ||||
|    functions->TexEnv = i915TexEnv; | ||||
|    functions->TexParameter = i915TexParameter; | ||||
| } | ||||
|   | ||||
							
								
								
									
										333
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,333 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| /* Code to layout images in a mipmap tree for i915 and i945 | ||||
|  * respectively. | ||||
|  */ | ||||
|  | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "macros.h" | ||||
|  | ||||
| static GLint initial_offsets[6][2] = { {0,0}, | ||||
| 				       {0,2}, | ||||
| 				       {1,0}, | ||||
| 				       {1,2}, | ||||
| 				       {1,1}, | ||||
| 				       {1,3} }; | ||||
|  | ||||
|  | ||||
| static GLint step_offsets[6][2] = { {0,2}, | ||||
| 				    {0,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,1}, | ||||
| 				    {-1,1} }; | ||||
|  | ||||
| static GLuint minify( GLuint d ) | ||||
| { | ||||
|    return MAX2(1, d>>1); | ||||
| } | ||||
|  | ||||
| GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt ) | ||||
| { | ||||
|    GLint i; | ||||
|  | ||||
|    switch (mt->target) { | ||||
|    case GL_TEXTURE_CUBE_MAP: { | ||||
|       const GLuint dim = mt->width0; | ||||
|       GLuint face; | ||||
|  | ||||
|       /* double pitch for cube layouts */ | ||||
|       mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = dim * 4; | ||||
|        | ||||
|       for ( face = 0 ; face < 6 ; face++) { | ||||
| 	 GLuint x = initial_offsets[face][0] * dim; | ||||
| 	 GLuint y = initial_offsets[face][1] * dim; | ||||
| 	 GLuint d = dim; | ||||
| 	  | ||||
| 	 for (i = mt->first_level; i <= mt->last_level; i++) { | ||||
| 	    intel_miptree_set_image_offset(mt, face, i, | ||||
| 					   x, y, | ||||
| 					   d, d, 1); | ||||
|  | ||||
| 	    if (d == 0) | ||||
| 	       _mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n", | ||||
| 			    face, i, mt->first_level, mt->last_level); | ||||
|  | ||||
| 	    d >>= 1; | ||||
| 	    x += step_offsets[face][0] * d; | ||||
| 	    y += step_offsets[face][1] * d; | ||||
| 	 } | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    case GL_TEXTURE_3D: { | ||||
|       GLuint width  = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|       GLuint depth  = mt->depth0; | ||||
|  | ||||
|       /* Calculate the size of a single slice.  | ||||
|        */ | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       /* XXX: hardware expects/requires 9 levels at minimum. | ||||
|        */ | ||||
|       for ( i = mt->first_level ; i <= MAX2(8, mt->last_level) ; i++ ) { | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					0, mt->total_height, | ||||
| 					width, height, depth); | ||||
|  | ||||
| 	 mt->total_height += MAX2(2, height); | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
| 	 depth  = minify(depth); | ||||
|       } | ||||
|  | ||||
|       /* Fixup depth_image_stride:  | ||||
|        */ | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	 mt->offset[0][i].depth_image_stride = mt->total_height * mt->pitch * mt->cpp; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* Multiply slice size by texture depth for total size.  It's | ||||
|        * remarkable how wasteful of memory the i915 texture layouts | ||||
|        * are.  They are largely fixed in the i945. | ||||
|        */ | ||||
|       mt->total_height *= mt->depth0; | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    default: { | ||||
|       GLuint width  = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|  | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					0, mt->total_height, | ||||
| 					width, height, 1); | ||||
|  | ||||
| 	 if (mt->compressed) | ||||
| 	    mt->total_height += MAX2(1, height/4); | ||||
| 	 else | ||||
| 	    mt->total_height += MAX2(2, height); | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    } | ||||
|    DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,  | ||||
| 		mt->pitch,  | ||||
| 		mt->total_height, | ||||
| 		mt->cpp, | ||||
| 		mt->pitch * mt->total_height * mt->cpp ); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt ) | ||||
| { | ||||
|    GLint i; | ||||
|  | ||||
|    switch (mt->target) { | ||||
|    case GL_TEXTURE_CUBE_MAP: { | ||||
|       const GLuint dim = mt->width0; | ||||
|       GLuint face; | ||||
|  | ||||
|       /* Depending on the size of the largest images, pitch can be | ||||
|        * determined either by the old-style packing of cubemap faces, | ||||
|        * or the final row of 4x4, 2x2 and 1x1 faces below this.  | ||||
|        */ | ||||
|       if (dim > 32)  | ||||
| 	 mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp; | ||||
|       else  | ||||
| 	 mt->pitch = 14 * 8;  | ||||
|  | ||||
|       mt->total_height = dim * 4 + 4; | ||||
|  | ||||
|        | ||||
|       for ( face = 0 ; face < 6 ; face++) { | ||||
| 	 GLuint x = initial_offsets[face][0] * dim; | ||||
| 	 GLuint y = initial_offsets[face][1] * dim; | ||||
| 	 GLuint d = dim; | ||||
| 	  | ||||
| 	 if (dim == 4 && face >= 4) { | ||||
| 	    y = mt->total_height - 4; | ||||
| 	    x = (face - 4) * 8; | ||||
| 	 } | ||||
| 	 else if (dim < 4) { | ||||
| 	    y = mt->total_height - 4; | ||||
| 	    x = face * 8; | ||||
| 	 } | ||||
|  | ||||
| 	 for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	    intel_miptree_set_image_offset(mt, face, i, | ||||
| 					   x, y, | ||||
| 					   d, d, 1); | ||||
|  | ||||
| 	    d >>= 1; | ||||
| 	     | ||||
| 	    switch (d) { | ||||
| 	    case 4: | ||||
| 	       switch (face) { | ||||
| 	       case FACE_POS_X: | ||||
| 	       case FACE_NEG_X: | ||||
| 		  x += step_offsets[face][0] * d; | ||||
| 		  y += step_offsets[face][1] * d; | ||||
| 		  break; | ||||
| 	       case FACE_POS_Y: | ||||
| 	       case FACE_NEG_Y: | ||||
| 		  y += 12; | ||||
| 		  x -= 8; | ||||
| 		  break; | ||||
| 	       case FACE_POS_Z: | ||||
| 	       case FACE_NEG_Z: | ||||
| 		  y = mt->total_height - 4; | ||||
| 		  x = (face - 4) * 8; | ||||
| 		  break; | ||||
| 	       } | ||||
|  | ||||
| 	    case 2: | ||||
| 	       y = mt->total_height - 4; | ||||
| 	       x = 16 + face * 8; | ||||
| 	       break; | ||||
|  | ||||
| 	    case 1: | ||||
| 	       x += 48; | ||||
| 	       break; | ||||
| 	        | ||||
| 	    default: | ||||
| 	       x += step_offsets[face][0] * d; | ||||
| 	       y += step_offsets[face][1] * d; | ||||
| 	       break; | ||||
| 	    } | ||||
| 	 } | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    case GL_TEXTURE_3D: { | ||||
|       GLuint width  = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|       GLuint depth = mt->depth0; | ||||
|       GLuint depth_pack_pitch; | ||||
|       GLuint depth_packing = 0; | ||||
|  | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       depth_pack_pitch = mt->pitch * mt->cpp; | ||||
|  | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
|  | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					0, mt->total_height, | ||||
| 					width, height, depth); | ||||
|  | ||||
|  | ||||
|  | ||||
| 	 mt->total_height += MAX2(2, height) * MAX2((depth >> depth_packing), 1); | ||||
|  | ||||
| 	 /* When alignment dominates, can't increase depth packing? | ||||
| 	  * Or does pitch grow???  What are the alignment constraints, | ||||
| 	  * anyway? | ||||
| 	  */ | ||||
| 	 if (depth_pack_pitch > 4) { | ||||
| 	    depth_packing++; | ||||
| 	    depth_pack_pitch >>= 2; /* KW: is this right?? */ | ||||
| 	 } | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
| 	 depth  = minify(depth); | ||||
|  | ||||
| 	 /* XXX: Not sure how 3d textures work on i945 - where did | ||||
| 	  * t->depth_pitch get set in the old code.  Did it ever work? | ||||
| 	  * Fix up later. | ||||
| 	  */ | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    default: { | ||||
|       GLuint x = 0; | ||||
|       GLuint y = 0; | ||||
|       GLuint width = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|  | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					x, y, | ||||
| 					width, height, 1); | ||||
|  | ||||
| 	  | ||||
| 	 /* LPT change: step right after second mipmap. | ||||
| 	  */ | ||||
| 	 if (i == 1)  | ||||
| 	    x += mt->pitch / 2; | ||||
| 	 else { | ||||
| 	    GLuint img_height; | ||||
| 	  | ||||
| 	    if (mt->compressed) | ||||
| 	       img_height = MAX2(1, height/4); | ||||
| 	    else | ||||
| 	       img_height = MAX2(2, height); | ||||
|  | ||||
| 	    y += img_height; | ||||
| 	 } | ||||
|  | ||||
| 	 /* Because the images are packed better, the final offset | ||||
| 	  * might not be the maximal one: | ||||
| 	  */ | ||||
| 	 mt->total_height = MAX2(mt->total_height, y); | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    } | ||||
|    DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,  | ||||
| 		mt->pitch,  | ||||
| 		mt->total_height, | ||||
| 		mt->cpp, | ||||
| 		mt->pitch * mt->total_height * mt->cpp ); | ||||
| 		 | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| @@ -536,7 +536,7 @@ static void emit_program_fini( struct i915_fragment_program *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915EmitTextureProgram( i915ContextPtr i915 ) | ||||
| static void i915EmitTextureProgram( struct i915_context *i915 ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    struct i915_fragment_program *p = &i915->tex_program; | ||||
| @@ -570,9 +570,9 @@ static void i915EmitTextureProgram( i915ContextPtr i915 ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915ValidateTextureProgram( i915ContextPtr i915 ) | ||||
| void i915ValidateTextureProgram( struct i915_context *i915 ) | ||||
| { | ||||
|    intelContextPtr intel = &i915->intel; | ||||
|    struct intel_context *intel = &i915->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -37,14 +37,16 @@ | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i915_reg.h" | ||||
| #include "i915_context.h" | ||||
|  | ||||
| static void i915_render_start( intelContextPtr intel ) | ||||
| static void i915_render_start( struct intel_context *intel ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    if (ctx->FragmentProgram._Active)  | ||||
|       i915ValidateFragmentProgram( i915 ); | ||||
| @@ -53,42 +55,42 @@ static void i915_render_start( intelContextPtr intel ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_reduced_primitive_state( intelContextPtr intel, | ||||
| static void i915_reduced_primitive_state( struct intel_context *intel, | ||||
| 					  GLenum rprim ) | ||||
| { | ||||
|     i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|     GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; | ||||
|  | ||||
|     st1 &= ~ST1_ENABLE; | ||||
|    st1 &= ~ST1_ENABLE; | ||||
|  | ||||
|     switch (rprim) { | ||||
|     case GL_TRIANGLES: | ||||
|        if (intel->ctx.Polygon.StippleFlag && | ||||
| 	   intel->hw_stipple) | ||||
| 	  st1 |= ST1_ENABLE; | ||||
|        break; | ||||
|     case GL_LINES: | ||||
|     case GL_POINTS: | ||||
|     default: | ||||
|        break; | ||||
|     } | ||||
|    switch (rprim) { | ||||
|    case GL_TRIANGLES: | ||||
|       if (intel->ctx.Polygon.StippleFlag && | ||||
| 	  intel->hw_stipple) | ||||
| 	 st1 |= ST1_ENABLE; | ||||
|       break; | ||||
|    case GL_LINES: | ||||
|    case GL_POINTS: | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|     i915->intel.reduced_primitive = rprim; | ||||
|    i915->intel.reduced_primitive = rprim; | ||||
|  | ||||
|     if (st1 != i915->state.Stipple[I915_STPREG_ST1]) { | ||||
|        I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); | ||||
|        i915->state.Stipple[I915_STPREG_ST1] = st1; | ||||
|     } | ||||
|    if (st1 != i915->state.Stipple[I915_STPREG_ST1]) { | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); | ||||
|       i915->state.Stipple[I915_STPREG_ST1] = st1; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Pull apart the vertex format registers and figure out how large a | ||||
|  * vertex is supposed to be.  | ||||
|  */ | ||||
| static GLboolean i915_check_vertex_size( intelContextPtr intel, | ||||
| static GLboolean i915_check_vertex_size( struct intel_context *intel, | ||||
| 					 GLuint expected ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    int lis2 = i915->current->Ctx[I915_CTXREG_LIS2]; | ||||
|    int lis4 = i915->current->Ctx[I915_CTXREG_LIS4]; | ||||
|    int i, sz = 0; | ||||
| @@ -132,11 +134,11 @@ static GLboolean i915_check_vertex_size( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
| static void i915_emit_invarient_state( struct intel_context *intel ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH( 200 ); | ||||
|    BEGIN_BATCH( 200, 0 ); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_AA_CMD | | ||||
| 	     AA_LINE_ECAAR_WIDTH_ENABLE | | ||||
| @@ -204,21 +206,15 @@ static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
| } | ||||
|  | ||||
|  | ||||
| #define emit( intel, state, size )			\ | ||||
| do {							\ | ||||
|    int k;						\ | ||||
|    BEGIN_BATCH( (size) / sizeof(GLuint));		\ | ||||
|    for (k = 0 ; k < (size) / sizeof(GLuint) ; k++)	\ | ||||
|       OUT_BATCH((state)[k]);				\ | ||||
|    ADVANCE_BATCH();					\ | ||||
| } while (0); | ||||
| #define emit(intel, state, size )		     \ | ||||
|    intel_batchbuffer_data(intel->batch, state, size, 0 ) | ||||
|  | ||||
|  | ||||
| /* Push the state into the sarea and/or texture memory. | ||||
|  */ | ||||
| static void i915_emit_state( intelContextPtr intel ) | ||||
| static void i915_emit_state( struct intel_context *intel ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    struct i915_hw_state *state = i915->current; | ||||
|    int i; | ||||
|    GLuint dirty; | ||||
| @@ -233,27 +229,48 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
|    dirty = state->active & ~state->emitted; | ||||
|  | ||||
|  | ||||
|    if (VERBOSE)  | ||||
|    if (INTEL_DEBUG & DEBUG_STATE)  | ||||
|       fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_INVARIENT) { | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n");  | ||||
|       i915_emit_invarient_state( intel ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_CTX) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");  | ||||
|       emit( i915, state->Ctx, sizeof(state->Ctx) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n");  | ||||
|       emit(intel, state->Ctx, sizeof(state->Ctx) ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_BUFFERS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");  | ||||
|       emit( i915, state->Buffer, sizeof(state->Buffer) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");  | ||||
|  | ||||
|       BEGIN_BATCH(I915_DEST_SETUP_SIZE, 0); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); | ||||
|       OUT_RELOC(state->draw_region->buffer, BM_MEM_AGP|BM_WRITE, 0); | ||||
|  | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); | ||||
|       OUT_RELOC(state->depth_region->buffer, BM_MEM_AGP|BM_WRITE, 0); | ||||
|  | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_STIPPLE) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");  | ||||
|       emit( i915, state->Stipple, sizeof(state->Stipple) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");  | ||||
|       emit(intel, state->Stipple, sizeof(state->Stipple) ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_FOG) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n");  | ||||
|       emit( i915, state->Fog, sizeof(state->Fog) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_FOG:\n");  | ||||
|       emit(intel, state->Fog, sizeof(state->Fog) ); | ||||
|    } | ||||
|  | ||||
|    /* Combine all the dirty texture state into a single command to | ||||
| @@ -266,18 +283,29 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
| 	 if (dirty & I915_UPLOAD_TEX(i))  | ||||
| 	    nr++; | ||||
|  | ||||
|       BEGIN_BATCH(2+nr*3); | ||||
|       BEGIN_BATCH(2+nr*3, 0); | ||||
|       OUT_BATCH(_3DSTATE_MAP_STATE | (3*nr)); | ||||
|       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); | ||||
|       for (i = 0 ; i < I915_TEX_UNITS ; i++) | ||||
| 	 if (dirty & I915_UPLOAD_TEX(i)) { | ||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]); | ||||
|  | ||||
| 	    if (state->tex_region[i]) { | ||||
| 	       OUT_RELOC(state->tex_region[i]->buffer, | ||||
| 			 BM_MEM_AGP|BM_READ, | ||||
| 			 state->tex_offset[i]); | ||||
| 	    } | ||||
| 	    else { | ||||
| 	       assert(i == 0); | ||||
| 	       assert(state == &i915->meta); | ||||
| 	       OUT_BATCH(0); | ||||
| 	    } | ||||
|  | ||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); | ||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); | ||||
| 	 } | ||||
|       ADVANCE_BATCH(); | ||||
|  | ||||
|       BEGIN_BATCH(2+nr*3); | ||||
|       BEGIN_BATCH(2+nr*3, 0); | ||||
|       OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3*nr)); | ||||
|       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); | ||||
|       for (i = 0 ; i < I915_TEX_UNITS ; i++) | ||||
| @@ -290,64 +318,65 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_CONSTANTS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");  | ||||
|       emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");  | ||||
|       emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint) ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_PROGRAM) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");  | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");  | ||||
|  | ||||
|       assert((state->Program[0] & 0x1ff)+2 == state->ProgramSize); | ||||
|        | ||||
|       emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) ); | ||||
|       if (VERBOSE) | ||||
|       emit(intel, state->Program, state->ProgramSize * sizeof(GLuint) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
| 	 i915_disassemble_program( state->Program, state->ProgramSize ); | ||||
|    } | ||||
|  | ||||
|    state->emitted |= dirty; | ||||
| } | ||||
|  | ||||
| static void i915_destroy_context( intelContextPtr intel ) | ||||
| static void i915_destroy_context( struct intel_context *intel ) | ||||
| { | ||||
|    _tnl_free_vertices(&intel->ctx); | ||||
| } | ||||
|  | ||||
| static void i915_set_draw_offset( intelContextPtr intel, int offset ) | ||||
| static void i915_set_draw_region( struct intel_context *intel,  | ||||
| 				  struct intel_region *draw_region, | ||||
| 				  struct intel_region *depth_region) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    intel_region_release(intel, &i915->state.draw_region); | ||||
|    intel_region_release(intel, &i915->state.depth_region); | ||||
|    intel_region_reference(&i915->state.draw_region, draw_region); | ||||
|    intel_region_reference(&i915->state.depth_region, depth_region); | ||||
|  | ||||
|    I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); | ||||
|    i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset; | ||||
| } | ||||
|  | ||||
| static void i915_lost_hardware( intelContextPtr intel ) | ||||
| static void i915_lost_hardware( struct intel_context *intel ) | ||||
| { | ||||
|    I915_CONTEXT(intel)->state.emitted = 0; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    i915->state.emitted = 0; | ||||
| } | ||||
|  | ||||
| static void i915_emit_flush( intelContextPtr intel ) | ||||
| static GLuint i915_flush_cmd( void ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH(2); | ||||
|    OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE );  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
|    return MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE; | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915InitVtbl( i915ContextPtr i915 ) | ||||
| void i915InitVtbl( struct i915_context *i915 ) | ||||
| { | ||||
|    i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj; | ||||
|    i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; | ||||
|    i915->intel.vtbl.clear_with_tris = i915ClearWithTris; | ||||
|    i915->intel.vtbl.destroy = i915_destroy_context; | ||||
|    i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state; | ||||
|    i915->intel.vtbl.emit_state = i915_emit_state; | ||||
|    i915->intel.vtbl.lost_hardware = i915_lost_hardware; | ||||
|    i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state; | ||||
|    i915->intel.vtbl.render_start = i915_render_start; | ||||
|    i915->intel.vtbl.set_draw_offset = i915_set_draw_offset; | ||||
|    i915->intel.vtbl.set_draw_region = i915_set_draw_region; | ||||
|    i915->intel.vtbl.update_texture_state = i915UpdateTextureState; | ||||
|    i915->intel.vtbl.emit_flush = i915_emit_flush; | ||||
|    i915->intel.vtbl.flush_cmd = i915_flush_cmd; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
| @@ -25,664 +25,266 @@ | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "context.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "intel_reg.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * Performance monitoring functions | ||||
| /* Relocations in kernel space: | ||||
|  *    - pass dma buffer seperately | ||||
|  *    - memory manager knows how to patch | ||||
|  *    - pass list of dependent buffers | ||||
|  *    - pass relocation list | ||||
|  * | ||||
|  * Either: | ||||
|  *    - get back an offset for buffer to fire | ||||
|  *    - memory manager knows how to fire buffer | ||||
|  * | ||||
|  * Really want the buffer to be AGP and pinned. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| static void intel_fill_box( intelContextPtr intel, | ||||
| 			    GLshort x, GLshort y, | ||||
| 			    GLshort w, GLshort h, | ||||
| 			    GLubyte r, GLubyte g, GLubyte b ) | ||||
| { | ||||
|    intelEmitFillBlitLocked( intel,  | ||||
| 			    intel->intelScreen->cpp, | ||||
| 			    intel->intelScreen->back.pitch, | ||||
| 			    intel->intelScreen->front.offset, | ||||
| 			    x, y, w, h, | ||||
| 			    INTEL_PACKCOLOR(intel->intelScreen->fbFormat, | ||||
| 					    r,g,b,0xff)); | ||||
| } | ||||
|  | ||||
| static void intel_draw_performance_boxes( intelContextPtr intel ) | ||||
| { | ||||
|    /* Purple box for page flipping | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_FLIP )  | ||||
|       intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 ); | ||||
|  | ||||
|    /* Red box if we have to wait for idle at any point | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_WAIT )  | ||||
|       intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 ); | ||||
|  | ||||
|    /* Blue box: lost context? | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )  | ||||
|       intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 ); | ||||
|  | ||||
|    /* Yellow box for texture swaps | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )  | ||||
|       intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 ); | ||||
|  | ||||
|    /* Green box if hardware never idles (as far as we can tell) | ||||
|     */ | ||||
|    if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )  | ||||
|       intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 ); | ||||
|  | ||||
|  | ||||
|    /* Draw bars indicating number of buffers allocated  | ||||
|     * (not a great measure, easily confused) | ||||
|     */ | ||||
| #if 0 | ||||
|    if (intel->dma_used) { | ||||
|       int bar = intel->dma_used / 10240; | ||||
|       if (bar > 100) bar = 100; | ||||
|       if (bar < 1) bar = 1; | ||||
|       intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 ); | ||||
|       intel->dma_used = 0; | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    intel->perf_boxes = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static int bad_prim_vertex_nr( int primitive, int nr ) | ||||
| { | ||||
|    switch (primitive & PRIM3D_MASK) { | ||||
|    case PRIM3D_POINTLIST: | ||||
|       return nr < 1; | ||||
|    case PRIM3D_LINELIST: | ||||
|       return (nr & 1) || nr == 0; | ||||
|    case PRIM3D_LINESTRIP: | ||||
|       return nr < 2; | ||||
|    case PRIM3D_TRILIST: | ||||
|    case PRIM3D_RECTLIST: | ||||
|       return nr % 3 || nr == 0; | ||||
|    case PRIM3D_POLY: | ||||
|    case PRIM3D_TRIFAN: | ||||
|    case PRIM3D_TRISTRIP: | ||||
|    case PRIM3D_TRISTRIP_RVRSE: | ||||
|       return nr < 3; | ||||
|    default: | ||||
|       return 1; | ||||
|    }	 | ||||
| } | ||||
|  | ||||
| static void intel_flush_inline_primitive( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    GLuint used = intel->batch.ptr - intel->prim.start_ptr; | ||||
|    GLuint vertcount; | ||||
|  | ||||
|    assert(intel->prim.primitive != ~0); | ||||
|  | ||||
|    if (1) { | ||||
|       /* Check vertex size against the vertex we're specifying to | ||||
|        * hardware.  If it's wrong, ditch the primitive. | ||||
|        */  | ||||
|       if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))  | ||||
| 	 goto do_discard; | ||||
|  | ||||
|       vertcount = (used - 4)/ (intel->vertex_size * 4); | ||||
|  | ||||
|       if (!vertcount) | ||||
| 	 goto do_discard; | ||||
|        | ||||
|       if (vertcount * intel->vertex_size * 4 != used - 4) { | ||||
| 	 fprintf(stderr, "vertex size confusion %d %d\n", used,  | ||||
| 		 intel->vertex_size * vertcount * 4); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|  | ||||
|       if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) { | ||||
| 	 fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive, | ||||
| 		 vertcount); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    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; | ||||
|    intel->batch.space += used; | ||||
|    assert(intel->batch.space >= 0); | ||||
|  | ||||
|  finished: | ||||
|    intel->prim.primitive = ~0; | ||||
|    intel->prim.start_ptr = 0; | ||||
|    intel->prim.flush = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Emit a primitive referencing vertices in a vertex buffer. | ||||
| /* Cliprect fence: The highest fence protecting a dma buffer | ||||
|  * containing explicit cliprect information.  Like the old drawable | ||||
|  * lock but irq-driven.  X server must wait for this fence to expire | ||||
|  * before changing cliprects [and then doing sw rendering?].  For | ||||
|  * other dma buffers, the scheduler will grab current cliprect info | ||||
|  * and mix into buffer.  X server must hold the lock while changing | ||||
|  * cliprects???  Make per-drawable.  Need cliprects in shared memory | ||||
|  * -- beats storing them with every cmd buffer in the queue. | ||||
|  * | ||||
|  * ==> X server must wait for this fence to expire before touching the | ||||
|  * framebuffer with new cliprects. | ||||
|  * | ||||
|  * ==> Cliprect-dependent buffers associated with a | ||||
|  * cliprect-timestamp.  All of the buffers associated with a timestamp | ||||
|  * must go to hardware before any buffer with a newer timestamp. | ||||
|  * | ||||
|  * ==> Dma should be queued per-drawable for correct X/GL | ||||
|  * synchronization.  Or can fences be used for this? | ||||
|  * | ||||
|  * Applies to: Blit operations, metaops, X server operations -- X | ||||
|  * server automatically waits on its own dma to complete before | ||||
|  * modifying cliprects ??? | ||||
|  */				 | ||||
| void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ) | ||||
|  | ||||
| static void intel_dump_batchbuffer( unsigned offset, | ||||
| 				    int *ptr, | ||||
| 				    int count ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %x\n", __FUNCTION__, prim); | ||||
|  | ||||
|  | ||||
|    /* Finish any in-progress primitive: | ||||
|     */ | ||||
|    INTEL_FIREVERTICES( intel ); | ||||
|     | ||||
|    /* Emit outstanding state: | ||||
|     */ | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|     | ||||
|    /* Make sure there is some space in this buffer: | ||||
|     */ | ||||
|    if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) | ||||
|       intelFlushBatch(intel, GL_TRUE);  | ||||
|  | ||||
|  | ||||
| #if 1 | ||||
|    if (((int)intel->batch.ptr) & 0x4) { | ||||
|       BEGIN_BATCH(1); | ||||
|       OUT_BATCH(0); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    /* Emit a slot which will be filled with the inline primitive | ||||
|     * command later. | ||||
|     */ | ||||
|    BEGIN_BATCH(2); | ||||
|    OUT_BATCH( 0 ); | ||||
|  | ||||
|    intel->prim.start_ptr = batch_ptr; | ||||
|    intel->prim.primitive = prim; | ||||
|    intel->prim.flush = intel_flush_inline_primitive; | ||||
|  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
|    int i; | ||||
|    fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count/4); | ||||
|    for (i = 0; i < count/4; i += 4)  | ||||
|       fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",  | ||||
| 	      offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); | ||||
|    fprintf(stderr, "END BATCH\n\n\n"); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelRestartInlinePrimitive( intelContextPtr intel ) | ||||
| static void intel_batchbuffer_reset( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    GLuint prim = intel->prim.primitive; | ||||
|    bmBufferData(batch->bm, | ||||
| 		batch->buffer, | ||||
| 		BATCH_SZ, | ||||
| 		NULL, | ||||
| 		0); | ||||
| 		 | ||||
|    intel_flush_inline_primitive( &intel->ctx ); | ||||
|    if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */ | ||||
|    intelStartInlinePrimitive( intel, prim ); | ||||
|    if (!batch->list)  | ||||
|       batch->list = bmNewBufferList(); | ||||
|  | ||||
|    batch->list->nr = 0; | ||||
|    batch->nr_relocs = 0; | ||||
|    batch->flags = 0; | ||||
|  | ||||
|    bmAddBuffer( batch->list, | ||||
| 		batch->buffer, | ||||
| 		0, | ||||
| 		NULL, | ||||
| 		&batch->offset[batch->list->nr]); | ||||
|  | ||||
|    batch->map = bmMapBuffer(batch->bm, batch->buffer,  | ||||
| 			    BM_MEM_AGP|BM_MEM_LOCAL|BM_CLIENT|BM_WRITE); | ||||
|    batch->ptr = batch->map; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelWrapInlinePrimitive( intelContextPtr intel ) | ||||
| { | ||||
|    GLuint prim = intel->prim.primitive; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    intel_flush_inline_primitive( &intel->ctx ); | ||||
|    intelFlushBatch(intel, GL_TRUE); | ||||
|    intelStartInlinePrimitive( intel, prim ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Emit a primitive with space for inline vertices. | ||||
| /*====================================================================== | ||||
|  * Public functions | ||||
|  */ | ||||
| GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  | ||||
| 				       int primitive, | ||||
| 				       int dwords, | ||||
| 				       int vertex_size ) | ||||
| struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint *tmp = 0; | ||||
|    BATCH_LOCALS; | ||||
|    struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords); | ||||
|    batch->intel = intel; | ||||
|    batch->bm = intel->bm; | ||||
|  | ||||
|    /* Emit outstanding state: | ||||
|     */ | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|  | ||||
|  | ||||
|    if (1) { | ||||
|       int used = dwords * 4; | ||||
|       int vertcount; | ||||
|  | ||||
|       /* Check vertex size against the vertex we're specifying to | ||||
|        * hardware.  If it's wrong, ditch the primitive. | ||||
|        */  | ||||
|       if (!intel->vtbl.check_vertex_size( intel, vertex_size ))  | ||||
| 	 goto do_discard; | ||||
|  | ||||
|       vertcount = dwords / vertex_size; | ||||
|        | ||||
|       if (dwords % vertex_size) { | ||||
| 	 fprintf(stderr, "did not request a whole number of vertices\n"); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|  | ||||
|       if (bad_prim_vertex_nr( primitive, vertcount )) { | ||||
| 	 fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|  | ||||
|       if (used < 8) | ||||
| 	 goto do_discard; | ||||
|    } | ||||
|  | ||||
|    /* Emit 3D_PRIMITIVE commands: | ||||
|     */ | ||||
|    BEGIN_BATCH(1 + dwords); | ||||
|    OUT_BATCH( _3DPRIMITIVE |  | ||||
| 	      primitive | | ||||
| 	      (dwords-1) ); | ||||
|  | ||||
|    tmp = (GLuint *)batch_ptr; | ||||
|    batch_ptr += dwords * 4; | ||||
|  | ||||
|    ADVANCE_BATCH(); | ||||
|  | ||||
|  do_discard: | ||||
|    return tmp; | ||||
|    bmGenBuffers(intel->bm, 1, &batch->buffer); | ||||
|    intel_batchbuffer_reset( batch ); | ||||
|    return batch; | ||||
| } | ||||
|  | ||||
| void intel_batchbuffer_free( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    if (batch->map) | ||||
|       bmUnmapBuffer(batch->bm, batch->buffer); | ||||
|     | ||||
|    free(batch); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Copy the back buffer to the front buffer.  | ||||
| /* TODO: Push this whole function into bufmgr. | ||||
|  */ | ||||
| void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )  | ||||
| static void do_flush_locked( struct intel_batchbuffer *batch, | ||||
| 			     GLuint used, | ||||
| 			     GLboolean ignore_cliprects) | ||||
| { | ||||
|    intelContextPtr intel; | ||||
|    GLuint *ptr; | ||||
|    GLuint i; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    bmValidateBufferList( batch->bm,  | ||||
| 			 batch->list, | ||||
| 			 BM_MEM_AGP ); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|    /* Apply the relocations.  This nasty map indicates to me that the | ||||
|     * whole task should be done internally by the memory manager, and | ||||
|     * that dma buffers probably need to be pinned within agp space. | ||||
|     */ | ||||
|    ptr = (GLuint *)bmMapBuffer(batch->bm, batch->buffer,  | ||||
| 			       BM_NO_MOVE|BM_NO_UPLOAD| | ||||
| 			       BM_NO_EVICT|BM_MEM_AGP| | ||||
| 			       BM_WRITE); | ||||
|  | ||||
|    intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|    for (i = 0; i < batch->nr_relocs; i++) { | ||||
|       struct buffer_reloc *r = &batch->reloc[i]; | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *pbox = dPriv->pClipRects; | ||||
|       int pitch = intelScreen->front.pitch; | ||||
|       int cpp = intelScreen->cpp; | ||||
|       int i; | ||||
|       GLuint CMD, BR13; | ||||
|       BATCH_LOCALS; | ||||
|       DBG("apply fixup at offset 0x%x, elem %d (buf %d, offset 0x%x), delta 0x%x\n", | ||||
| 	  r->offset, r->elem, batch->list->elem[r->elem].buffer, | ||||
| 	  batch->offset[r->elem], r->delta); | ||||
|  | ||||
|       switch(cpp) { | ||||
|       case 2:  | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); | ||||
| 	 CMD = XY_SRC_COPY_BLT_CMD; | ||||
| 	 break; | ||||
|       case 4: | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25); | ||||
| 	 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 		XY_SRC_COPY_BLT_WRITE_RGB); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); | ||||
| 	 CMD = XY_SRC_COPY_BLT_CMD; | ||||
| 	 break; | ||||
|       } | ||||
|  | ||||
|       if (0) | ||||
| 	 intel_draw_performance_boxes( intel ); | ||||
|  | ||||
|       for (i = 0 ; i < nbox; i++, pbox++)  | ||||
|       { | ||||
| 	 if (pbox->x1 > pbox->x2 || | ||||
| 	     pbox->y1 > pbox->y2 || | ||||
| 	     pbox->x2 > intelScreen->width || | ||||
| 	     pbox->y2 > intelScreen->height) | ||||
| 	    continue; | ||||
|   | ||||
| 	 BEGIN_BATCH( 8); | ||||
| 	 OUT_BATCH( CMD ); | ||||
| 	 OUT_BATCH( BR13 ); | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( (pbox->y2 << 16) | pbox->x2 ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_BATCH( intelScreen->front.offset ); | ||||
| 	 else | ||||
| 	    OUT_BATCH( intelScreen->back.offset );			 | ||||
|  | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( BR13 & 0xffff ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_BATCH( intelScreen->back.offset );			 | ||||
| 	 else | ||||
| 	    OUT_BATCH( intelScreen->front.offset ); | ||||
|  | ||||
| 	 ADVANCE_BATCH(); | ||||
|       } | ||||
|       ptr[r->offset/4] = batch->offset[r->elem] + r->delta; | ||||
|    } | ||||
|    intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_DMA) | ||||
|       intel_dump_batchbuffer( 0, ptr, used ); | ||||
|  | ||||
|  | ||||
|  | ||||
|    bmUnmapBuffer(batch->bm, batch->buffer); | ||||
|  | ||||
|  | ||||
|    /* Fire the batch buffer, which was uploaded above: | ||||
|     */ | ||||
|    intel_batch_ioctl(batch->intel,  | ||||
| 		     batch->offset[0], | ||||
| 		     used, | ||||
| 		     ignore_cliprects); | ||||
|     | ||||
|    batch->last_fence = bmFenceBufferList(batch->bm, batch->list); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelEmitFillBlitLocked( intelContextPtr intel, | ||||
| 			      GLuint cpp, | ||||
| 			      GLshort dst_pitch, | ||||
| 			      GLuint dst_offset, | ||||
| 			      GLshort x, GLshort y,  | ||||
| 			      GLshort w, GLshort h, | ||||
| 			      GLuint color ) | ||||
| GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    GLuint BR13, CMD; | ||||
|    BATCH_LOCALS; | ||||
|    struct intel_context *intel = batch->intel; | ||||
|    GLuint used = batch->ptr - batch->map; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|    if (used == 0)  | ||||
|       return batch->last_fence; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24); | ||||
|       CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | | ||||
| 	     XY_COLOR_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    BEGIN_BATCH( 6); | ||||
|    OUT_BATCH( CMD ); | ||||
|    OUT_BATCH( BR13 ); | ||||
|    OUT_BATCH( (y << 16) | x ); | ||||
|    OUT_BATCH( ((y+h) << 16) | (x+w) ); | ||||
|    OUT_BATCH( dst_offset ); | ||||
|    OUT_BATCH( color ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Copy BitBlt | ||||
|  */ | ||||
| void intelEmitCopyBlitLocked( intelContextPtr intel, | ||||
| 			      GLuint cpp, | ||||
| 			      GLshort src_pitch, | ||||
| 			      GLuint  src_offset, | ||||
| 			      GLshort dst_pitch, | ||||
| 			      GLuint  dst_offset, | ||||
| 			      GLshort src_x, GLshort src_y, | ||||
| 			      GLshort dst_x, GLshort dst_y, | ||||
| 			      GLshort w, GLshort h ) | ||||
| { | ||||
|    GLuint CMD, BR13; | ||||
|    int dst_y2 = dst_y + h; | ||||
|    int dst_x2 = dst_x + w; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    src_pitch *= cpp; | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = dst_pitch | (0xCC << 16) | (1<<24); | ||||
|       CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 	     XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (dst_y2 < dst_y || | ||||
|        dst_x2 < dst_x) { | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    BEGIN_BATCH( 12); | ||||
|    OUT_BATCH( CMD ); | ||||
|    OUT_BATCH( BR13 ); | ||||
|    OUT_BATCH( (dst_y << 16) | dst_x ); | ||||
|    OUT_BATCH( (dst_y2 << 16) | dst_x2 ); | ||||
|    OUT_BATCH( dst_offset );	 | ||||
|    OUT_BATCH( (src_y << 16) | src_x ); | ||||
|    OUT_BATCH( src_pitch ); | ||||
|    OUT_BATCH( src_offset );  | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, | ||||
| 		      GLint cx1, GLint cy1, GLint cw, GLint ch) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|    GLuint clear_depth, clear_color; | ||||
|    GLint cx, cy; | ||||
|    GLint pitch = intelScreen->front.pitch; | ||||
|    GLint cpp = intelScreen->cpp; | ||||
|    GLint i; | ||||
|    GLuint BR13, CMD, D_CMD; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|     | ||||
|    clear_color = intel->ClearColor; | ||||
|    clear_depth = 0; | ||||
|  | ||||
|    if (flags & BUFFER_BIT_DEPTH) { | ||||
|       clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth); | ||||
|    } | ||||
|  | ||||
|    if (flags & BUFFER_BIT_STENCIL) { | ||||
|       clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; | ||||
|    } | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 2:  | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); | ||||
|       D_CMD = CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | | ||||
| 	     XY_COLOR_BLT_WRITE_ALPHA |  | ||||
| 	     XY_COLOR_BLT_WRITE_RGB); | ||||
|       D_CMD = XY_COLOR_BLT_CMD; | ||||
|       if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB; | ||||
|       if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA; | ||||
|       break; | ||||
|    default: | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); | ||||
|       D_CMD = CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       /* flip top to bottom */ | ||||
|       cy = intel->driDrawable->h-cy1-ch; | ||||
|       cx = cx1 + intel->drawX; | ||||
|       cy += intel->drawY; | ||||
|  | ||||
|       /* adjust for page flipping */ | ||||
|       if ( intel->sarea->pf_current_page == 1 ) { | ||||
| 	 GLuint tmp = flags; | ||||
|  | ||||
| 	 flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); | ||||
| 	 if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT; | ||||
| 	 if ( tmp & BUFFER_BIT_BACK_LEFT )  flags |= BUFFER_BIT_FRONT_LEFT; | ||||
|       } | ||||
|  | ||||
|       for (i = 0 ; i < intel->numClipRects ; i++)  | ||||
|       { 	  | ||||
| 	 drm_clip_rect_t *box = &intel->pClipRects[i];	  | ||||
| 	 drm_clip_rect_t b; | ||||
|  | ||||
| 	 if (!all) { | ||||
| 	    GLint x = box[i].x1; | ||||
| 	    GLint y = box[i].y1; | ||||
| 	    GLint w = box[i].x2 - x; | ||||
| 	    GLint h = box[i].y2 - y; | ||||
|  | ||||
| 	    if (x < cx) w -= cx - x, x = cx;  | ||||
| 	    if (y < cy) h -= cy - y, y = cy; | ||||
| 	    if (x + w > cx + cw) w = cx + cw - x; | ||||
| 	    if (y + h > cy + ch) h = cy + ch - y; | ||||
| 	    if (w <= 0) continue; | ||||
| 	    if (h <= 0) continue; | ||||
|  | ||||
| 	    b.x1 = x; | ||||
| 	    b.y1 = y; | ||||
| 	    b.x2 = x + w; | ||||
| 	    b.y2 = y + h;       | ||||
| 	 } else { | ||||
| 	    b = *box; | ||||
| 	 } | ||||
|  | ||||
|  | ||||
| 	 if (b.x1 > b.x2 || | ||||
| 	     b.y1 > b.y2 || | ||||
| 	     b.x2 > intelScreen->width || | ||||
| 	     b.y2 > intelScreen->height) | ||||
| 	    continue; | ||||
|  | ||||
| 	 if ( flags & BUFFER_BIT_FRONT_LEFT ) {	     | ||||
| 	    BEGIN_BATCH( 6);	     | ||||
| 	    OUT_BATCH( CMD ); | ||||
| 	    OUT_BATCH( BR13 ); | ||||
| 	    OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
| 	    OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
| 	    OUT_BATCH( intelScreen->front.offset ); | ||||
| 	    OUT_BATCH( clear_color ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 } | ||||
|  | ||||
| 	 if ( flags & BUFFER_BIT_BACK_LEFT ) { | ||||
| 	    BEGIN_BATCH( 6);  | ||||
| 	    OUT_BATCH( CMD ); | ||||
| 	    OUT_BATCH( BR13 ); | ||||
| 	    OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
| 	    OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
| 	    OUT_BATCH( intelScreen->back.offset ); | ||||
| 	    OUT_BATCH( clear_color ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 } | ||||
|  | ||||
| 	 if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) { | ||||
| 	    BEGIN_BATCH( 6); | ||||
| 	    OUT_BATCH( D_CMD ); | ||||
| 	    OUT_BATCH( BR13 ); | ||||
| 	    OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
| 	    OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
| 	    OUT_BATCH( intelScreen->depth.offset ); | ||||
| 	    OUT_BATCH( clear_depth ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 }       | ||||
|       } | ||||
|    } | ||||
|    intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelDestroyBatchBuffer( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    if (intel->alloc.ptr) { | ||||
|       intelFreeAGP( intel, intel->alloc.ptr ); | ||||
|       intel->alloc.ptr = 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitBatchBuffer( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) { | ||||
|       intel->alloc.size = 8 * 1024; | ||||
|       intel->alloc.ptr = malloc( intel->alloc.size ); | ||||
|       intel->alloc.offset = 0; | ||||
|    /* Add the MI_BATCH_BUFFER_END.  Always add an MI_FLUSH - this is a | ||||
|     * performance drain that we would like to avoid. | ||||
|     */ | ||||
|    if (used & 4) { | ||||
|       ((int *)batch->ptr)[0] = intel->vtbl.flush_cmd(); | ||||
|       ((int *)batch->ptr)[1] = 0; | ||||
|       ((int *)batch->ptr)[2] = MI_BATCH_BUFFER_END; | ||||
|       used += 12; | ||||
|    } | ||||
|    else { | ||||
|       switch (intel->intelScreen->deviceID) { | ||||
|       case PCI_CHIP_I865_G: | ||||
| 	 /* HW bug?  Seems to crash if batchbuffer crosses 4k boundary. | ||||
| 	  */ | ||||
| 	 intel->alloc.size = 8 * 1024;  | ||||
| 	 break; | ||||
|       default: | ||||
| 	 /* This is the smallest amount of memory the kernel deals with. | ||||
| 	  * We'd ideally like to make this smaller. | ||||
| 	  */ | ||||
| 	 intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity; | ||||
| 	 break; | ||||
|       } | ||||
|  | ||||
|       intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size ); | ||||
|       if (intel->alloc.ptr) | ||||
| 	 intel->alloc.offset =  | ||||
| 	    intelAgpOffsetFromVirtual( intel, intel->alloc.ptr ); | ||||
|       ((int *)batch->ptr)[0] = intel->vtbl.flush_cmd(); | ||||
|       ((int *)batch->ptr)[1] = MI_BATCH_BUFFER_END; | ||||
|       used += 8; | ||||
|    } | ||||
|  | ||||
|    if (!intel->alloc.ptr) { | ||||
|       FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1); | ||||
|    bmUnmapBuffer(batch->bm, batch->buffer); | ||||
|    batch->ptr = NULL; | ||||
|    batch->map = NULL; | ||||
|  | ||||
|    /* TODO: Just pass the relocation list and dma buffer up to the | ||||
|     * kernel. | ||||
|     */ | ||||
|    if (!intel->locked) | ||||
|    { | ||||
|       assert(!(batch->flags & INTEL_BATCH_NO_CLIPRECTS)); | ||||
|  | ||||
|       LOCK_HARDWARE(intel); | ||||
|       do_flush_locked(batch, used, GL_FALSE); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|    } | ||||
|    else { | ||||
|       intel->prim.flush = 0; | ||||
|       intel->vtbl.emit_invarient_state( intel ); | ||||
|       assert(!(batch->flags & INTEL_BATCH_CLIPRECTS)); | ||||
|  | ||||
|       /* Make sure this gets to the hardware, even if we have no cliprects: | ||||
|        */ | ||||
|       LOCK_HARDWARE( intel ); | ||||
|       intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE ); | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       do_flush_locked(batch, used, GL_TRUE); | ||||
|    } | ||||
|  | ||||
|    /* Reset the buffer: | ||||
|     */ | ||||
|    intel_batchbuffer_reset( batch ); | ||||
|    return batch->last_fence; | ||||
| } | ||||
|  | ||||
| void intel_batchbuffer_finish( struct intel_batchbuffer *batch ) | ||||
| {    | ||||
|    bmFinishFence(batch->bm,  | ||||
| 		 intel_batchbuffer_flush(batch)); | ||||
| } | ||||
|     | ||||
|  | ||||
| /*  This is the only way buffers get added to the validate list. | ||||
|  */ | ||||
| GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch, | ||||
| 					GLuint buffer, | ||||
| 					GLuint flags, | ||||
| 					GLuint delta ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    assert(batch->nr_relocs <= MAX_RELOCS); | ||||
|  | ||||
|    for (i = 0; i < batch->list->nr; i++)  | ||||
|       if (buffer == batch->list->elem[i].buffer) | ||||
| 	 break; | ||||
|  | ||||
|    if (i == batch->list->nr) { | ||||
|       if (i == BM_LIST_MAX) | ||||
| 	 return GL_FALSE; | ||||
|  | ||||
|       bmAddBuffer(batch->list, | ||||
| 		  buffer, | ||||
| 		  flags, | ||||
| 		  NULL, | ||||
| 		  &batch->offset[i]); | ||||
|    } | ||||
|  | ||||
|    { | ||||
|       struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++]; | ||||
|       r->offset = batch->ptr - batch->map; | ||||
|       r->delta = delta; | ||||
|       r->elem = i; | ||||
|    } | ||||
|  | ||||
|    batch->ptr += 4; | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intel_batchbuffer_data(struct intel_batchbuffer *batch, | ||||
| 			    const void *data, | ||||
| 			    GLuint bytes, | ||||
| 			    GLuint flags) | ||||
| { | ||||
|    assert((bytes & 3) == 0); | ||||
|    intel_batchbuffer_require_space(batch, bytes, flags); | ||||
|    __memcpy(batch->ptr, data, bytes); | ||||
|    batch->ptr += bytes; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,123 +1,113 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "bufmgr.h" | ||||
|  | ||||
| struct intel_context; | ||||
|  | ||||
| #define BATCH_SZ 4096 | ||||
| #define BATCH_RESERVED 16 | ||||
|  | ||||
| #define MAX_RELOCS 100 | ||||
|  | ||||
| #define INTEL_BATCH_NO_CLIPRECTS 0x1 | ||||
| #define INTEL_BATCH_CLIPRECTS    0x2 | ||||
|  | ||||
| struct buffer_reloc { | ||||
|    GLuint offset; | ||||
|    GLuint elem;			/* elem in buffer list, not buffer id */ | ||||
|    GLuint delta;		/* not needed? */ | ||||
| }; | ||||
|  | ||||
| struct intel_batchbuffer { | ||||
|    struct bufmgr *bm; | ||||
|    struct intel_context *intel; | ||||
|  | ||||
|    GLuint buffer; | ||||
|    GLuint last_fence; | ||||
|    GLuint flags; | ||||
|  | ||||
|    /* In progress: | ||||
|     */ | ||||
|    GLuint offset[BM_LIST_MAX]; | ||||
|    struct bm_buffer_list *list;    | ||||
|    GLubyte *map; | ||||
|    GLubyte *ptr;  | ||||
|  | ||||
|    struct buffer_reloc reloc[MAX_RELOCS]; | ||||
|    GLuint nr_relocs; | ||||
| }; | ||||
|  | ||||
| struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel ); | ||||
|  | ||||
| void intel_batchbuffer_free( struct intel_batchbuffer *batch ); | ||||
|  | ||||
|  | ||||
| #define BATCH_LOCALS	GLubyte *batch_ptr; | ||||
| void intel_batchbuffer_finish( struct intel_batchbuffer *batch ); | ||||
|  | ||||
| /* #define VERBOSE 0 */ | ||||
| #ifndef VERBOSE | ||||
| extern int VERBOSE; | ||||
| #endif | ||||
| GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch ); | ||||
|  | ||||
|  | ||||
| #define BEGIN_BATCH(n)							\ | ||||
| do {									\ | ||||
|    if (VERBOSE) fprintf(stderr, 					\ | ||||
| 			"BEGIN_BATCH(%d) in %s, %d dwords free\n",	\ | ||||
| 			(n), __FUNCTION__, intel->batch.space/4);	\ | ||||
|    if (intel->batch.space < (n)*4)					\ | ||||
|       intelFlushBatch(intel, GL_TRUE);					\ | ||||
|    batch_ptr = intel->batch.ptr;					\ | ||||
| } while (0) | ||||
| /* Unlike bmBufferData, this currently requires the buffer be mapped. | ||||
|  * Consider it a convenience function wrapping multple | ||||
|  * intel_buffer_dword() calls. | ||||
|  */ | ||||
| void intel_batchbuffer_data(struct intel_batchbuffer *batch, | ||||
| 			    const void *data, | ||||
| 			    GLuint bytes, | ||||
| 			    GLuint flags); | ||||
|  | ||||
| #define OUT_BATCH(n)					\ | ||||
| do {							\ | ||||
|    *(GLuint *)batch_ptr = (n);				\ | ||||
|    if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__);	\ | ||||
|    batch_ptr += 4;					\ | ||||
| } while (0) | ||||
| void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, | ||||
| 				   GLuint bytes); | ||||
|  | ||||
| #define ADVANCE_BATCH()						\ | ||||
| do {								\ | ||||
|    if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n");		\ | ||||
|    intel->batch.space -= (batch_ptr - intel->batch.ptr);	\ | ||||
|    intel->batch.ptr = batch_ptr;				\ | ||||
|    assert(intel->batch.space >= 0);				\ | ||||
| } while(0) | ||||
| GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch, | ||||
| 					GLuint buffer, | ||||
| 					GLuint flags, | ||||
| 					GLuint offset ); | ||||
|  | ||||
| extern void intelInitBatchBuffer( GLcontext *ctx ); | ||||
| extern void intelDestroyBatchBuffer( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ); | ||||
| extern void intelWrapInlinePrimitive( intelContextPtr intel ); | ||||
| extern void intelRestartInlinePrimitive( intelContextPtr intel ); | ||||
| extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  | ||||
| 					      int primitive, int dwords, | ||||
| 					      int vertex_size); | ||||
| extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv ); | ||||
| extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 			     GLint cx1, GLint cy1, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelEmitCopyBlitLocked( intelContextPtr intel, | ||||
| 				     GLuint cpp, | ||||
| 				     GLshort src_pitch, | ||||
| 				     GLuint  src_offset, | ||||
| 				     GLshort dst_pitch, | ||||
| 				     GLuint  dst_offset, | ||||
| 				     GLshort srcx, GLshort srcy, | ||||
| 				     GLshort dstx, GLshort dsty, | ||||
| 				     GLshort w, GLshort h ); | ||||
|  | ||||
| extern void intelEmitFillBlitLocked( intelContextPtr intel, | ||||
| 				     GLuint cpp, | ||||
| 				     GLshort dst_pitch, | ||||
| 				     GLuint dst_offset, | ||||
| 				     GLshort x, GLshort y,  | ||||
| 				     GLshort w, GLshort h, | ||||
| 				     GLuint color ); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,  | ||||
| 						GLuint dwords ) | ||||
| /* Inline functions - might actually be better off with these | ||||
|  * non-inlined.  Certainly better off switching all command packets to | ||||
|  * be passed as structs rather than dwords, but that's a little bit of | ||||
|  * work... | ||||
|  */ | ||||
| static inline GLuint  | ||||
| intel_batchbuffer_space( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    GLuint sz = dwords * sizeof(GLuint); | ||||
|    GLuint *ptr; | ||||
|  | ||||
|    if (intel->batch.space < sz) { | ||||
|       intelWrapInlinePrimitive( intel ); | ||||
| /*       assert(intel->batch.space >= sz); */ | ||||
|    } | ||||
|  | ||||
| /*    assert(intel->prim.primitive != ~0); */ | ||||
|    ptr = (GLuint *)intel->batch.ptr; | ||||
|    intel->batch.ptr += sz; | ||||
|    intel->batch.space -= sz; | ||||
|  | ||||
|    return ptr; | ||||
|    return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->map); | ||||
| } | ||||
|  | ||||
|  | ||||
| static inline void  | ||||
| intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, | ||||
| 			     GLuint dword) | ||||
| { | ||||
|    assert(batch->map); | ||||
|    assert(intel_batchbuffer_space(batch) >= 4); | ||||
|    *(GLuint *)(batch->ptr) = dword; | ||||
|    batch->ptr += 4; | ||||
| } | ||||
|  | ||||
| static inline void  | ||||
| intel_batchbuffer_require_space(struct intel_batchbuffer *batch, | ||||
| 				GLuint sz, | ||||
| 				GLuint flags) | ||||
| { | ||||
|    assert(sz < BATCH_SZ - 8); | ||||
|    if (intel_batchbuffer_space(batch) < sz || | ||||
|        (batch->flags != 0 && flags != 0 && batch->flags != flags)) | ||||
|       intel_batchbuffer_flush(batch); | ||||
|     | ||||
|    batch->flags |= flags; | ||||
| } | ||||
|  | ||||
| /* Here are the crusty old macros, to be removed: | ||||
|  */ | ||||
| #define BATCH_LOCALS  | ||||
| #define BEGIN_BATCH(n, flags) intel_batchbuffer_require_space(intel->batch, n*4, flags) | ||||
| #define OUT_BATCH(d)  intel_batchbuffer_emit_dword(intel->batch, d) | ||||
| #define OUT_RELOC(buf,flags,delta) intel_batchbuffer_emit_reloc(intel->batch, buf, flags, delta) | ||||
| #define ADVANCE_BATCH() do { } while(0) | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										384
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,384 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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_reg.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Copy the back buffer to the front buffer.  | ||||
|  */ | ||||
| void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )  | ||||
| { | ||||
|    struct intel_context *intel; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|  | ||||
|    intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; | ||||
|    intelFlush( &intel->ctx ); | ||||
|  | ||||
|  | ||||
|    bmFinishFence(intel->bm, intel->last_swap_fence); | ||||
|  | ||||
|    /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets | ||||
|     * should work regardless. | ||||
|     */ | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *pbox = dPriv->pClipRects; | ||||
|       int pitch = intelScreen->front.pitch; | ||||
|       int cpp = intelScreen->cpp; | ||||
|       int BR13, CMD; | ||||
|       int i; | ||||
|  | ||||
|  | ||||
|       if (cpp == 2) { | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); | ||||
| 	 CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       }  | ||||
|       else { | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25); | ||||
| 	 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 		XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       } | ||||
|  | ||||
|       for (i = 0 ; i < nbox; i++, pbox++)  | ||||
|       { | ||||
| 	 if (pbox->x1 > pbox->x2 || | ||||
| 	     pbox->y1 > pbox->y2 || | ||||
| 	     pbox->x2 > intelScreen->width || | ||||
| 	     pbox->y2 > intelScreen->height) | ||||
| 	    continue; | ||||
|   | ||||
| 	 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); | ||||
| 	 OUT_BATCH( CMD ); | ||||
| 	 OUT_BATCH( BR13 ); | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( (pbox->y2 << 16) | pbox->x2 ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_RELOC( intel->front_region->buffer, BM_MEM_AGP|BM_WRITE, 0 ); | ||||
| 	 else | ||||
| 	    OUT_RELOC( intel->back_region->buffer, BM_MEM_AGP|BM_WRITE, 0 );  | ||||
|  | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( BR13 & 0xffff ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_RELOC( intel->back_region->buffer, BM_MEM_AGP|BM_READ, 0 );  | ||||
| 	 else | ||||
| 	    OUT_RELOC( intel->front_region->buffer, BM_MEM_AGP|BM_READ, 0 ); | ||||
|  | ||||
| 	 ADVANCE_BATCH(); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intel->last_swap_fence = intel_batchbuffer_flush( intel->batch ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelEmitFillBlit( struct intel_context *intel, | ||||
| 			GLuint cpp, | ||||
| 			GLshort dst_pitch, | ||||
| 			GLuint dst_buffer, | ||||
| 			GLuint dst_offset, | ||||
| 			GLshort x, GLshort y,  | ||||
| 			GLshort w, GLshort h, | ||||
| 			GLuint color ) | ||||
| { | ||||
|    GLuint BR13, CMD; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24); | ||||
|       CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | | ||||
| 	     XY_COLOR_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); | ||||
|    OUT_BATCH( CMD ); | ||||
|    OUT_BATCH( BR13 ); | ||||
|    OUT_BATCH( (y << 16) | x ); | ||||
|    OUT_BATCH( ((y+h) << 16) | (x+w) ); | ||||
|    OUT_RELOC( dst_buffer, BM_MEM_AGP|BM_WRITE, dst_offset ); | ||||
|    OUT_BATCH( color ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Copy BitBlt | ||||
|  */ | ||||
| void intelEmitCopyBlit( struct intel_context *intel, | ||||
| 			GLuint cpp, | ||||
| 			GLshort src_pitch, | ||||
| 			GLuint  src_buffer, | ||||
| 			GLuint  src_offset, | ||||
| 			GLshort dst_pitch, | ||||
| 			GLuint  dst_buffer, | ||||
| 			GLuint  dst_offset, | ||||
| 			GLshort src_x, GLshort src_y, | ||||
| 			GLshort dst_x, GLshort dst_y, | ||||
| 			GLshort w, GLshort h ) | ||||
| { | ||||
|    GLuint CMD, BR13; | ||||
|    int dst_y2 = dst_y + h; | ||||
|    int dst_x2 = dst_x + w; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|  | ||||
|    DBG("%s src:buf(%d)/%d %d,%d dst:buf(%d)/%d %d,%d sz:%dx%d\n", | ||||
|        __FUNCTION__, | ||||
|        src_buffer, src_pitch, src_x, src_y, | ||||
|        dst_buffer, dst_pitch, dst_x, dst_y, | ||||
|        w,h); | ||||
|  | ||||
|    src_pitch *= cpp; | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = dst_pitch | (0xCC << 16) | (1<<24); | ||||
|       CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 	     XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (dst_y2 < dst_y || | ||||
|        dst_x2 < dst_x) { | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* Initial y values don't seem to work with negative pitches.  If | ||||
|     * we adjust the offsets manually (below), it seems to work fine. | ||||
|     */ | ||||
|    if (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, BM_MEM_AGP|BM_WRITE, dst_offset );	 | ||||
|       OUT_BATCH( (src_y << 16) | src_x ); | ||||
|       OUT_BATCH( ((GLint)src_pitch&0xffff) ); | ||||
|       OUT_RELOC( src_buffer, BM_MEM_AGP|BM_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, BM_MEM_AGP|BM_WRITE, dst_offset + dst_y * dst_pitch );	 | ||||
|       OUT_BATCH( (0 << 16) | src_x ); | ||||
|       OUT_BATCH( ((GLint)src_pitch&0xffff) ); | ||||
|       OUT_RELOC( src_buffer, BM_MEM_AGP|BM_READ, src_offset + src_y * src_pitch );  | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, | ||||
| 		      GLint cx1, GLint cy1, GLint cw, GLint ch) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|    GLuint clear_depth, clear_color; | ||||
|    GLint cx, cy; | ||||
|    GLint pitch = intelScreen->front.pitch; | ||||
|    GLint cpp = intelScreen->cpp; | ||||
|    GLint i; | ||||
|    GLuint BR13, CMD, D_CMD; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|     | ||||
|    clear_color = intel->ClearColor; | ||||
|    clear_depth = 0; | ||||
|  | ||||
|    if (flags & BUFFER_BIT_DEPTH) { | ||||
|       clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth); | ||||
|    } | ||||
|  | ||||
|    if (flags & BUFFER_BIT_STENCIL) { | ||||
|       clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; | ||||
|    } | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 2:  | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); | ||||
|       D_CMD = CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | | ||||
| 	     XY_COLOR_BLT_WRITE_ALPHA |  | ||||
| 	     XY_COLOR_BLT_WRITE_RGB); | ||||
|       D_CMD = XY_COLOR_BLT_CMD; | ||||
|       if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB; | ||||
|       if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA; | ||||
|       break; | ||||
|    default: | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); | ||||
|       D_CMD = CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       /* flip top to bottom */ | ||||
|       cy = intel->driDrawable->h-cy1-ch; | ||||
|       cx = cx1 + intel->drawX; | ||||
|       cy += intel->drawY; | ||||
|  | ||||
|       /* adjust for page flipping */ | ||||
|       if ( intel->sarea->pf_current_page == 1 ) { | ||||
| 	 GLuint tmp = flags; | ||||
|  | ||||
| 	 flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); | ||||
| 	 if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT; | ||||
| 	 if ( tmp & BUFFER_BIT_BACK_LEFT )  flags |= BUFFER_BIT_FRONT_LEFT; | ||||
|       } | ||||
|  | ||||
|       for (i = 0 ; i < intel->numClipRects ; i++)  | ||||
|       { 	  | ||||
| 	 drm_clip_rect_t *box = &intel->pClipRects[i];	  | ||||
| 	 drm_clip_rect_t b; | ||||
|  | ||||
| 	 if (!all) { | ||||
| 	    GLint x = box[i].x1; | ||||
| 	    GLint y = box[i].y1; | ||||
| 	    GLint w = box[i].x2 - x; | ||||
| 	    GLint h = box[i].y2 - y; | ||||
|  | ||||
| 	    if (x < cx) w -= cx - x, x = cx;  | ||||
| 	    if (y < cy) h -= cy - y, y = cy; | ||||
| 	    if (x + w > cx + cw) w = cx + cw - x; | ||||
| 	    if (y + h > cy + ch) h = cy + ch - y; | ||||
| 	    if (w <= 0) continue; | ||||
| 	    if (h <= 0) continue; | ||||
|  | ||||
| 	    b.x1 = x; | ||||
| 	    b.y1 = y; | ||||
| 	    b.x2 = x + w; | ||||
| 	    b.y2 = y + h;       | ||||
| 	 } else { | ||||
| 	    b = *box; | ||||
| 	 } | ||||
|  | ||||
|  | ||||
| 	 if (b.x1 > b.x2 || | ||||
| 	     b.y1 > b.y2 || | ||||
| 	     b.x2 > intelScreen->width || | ||||
| 	     b.y2 > intelScreen->height) | ||||
| 	    continue; | ||||
|  | ||||
| 	 if ( flags & BUFFER_BIT_FRONT_LEFT ) {	     | ||||
| 	    BEGIN_BATCH(6, 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( intel->front_region->buffer, BM_MEM_AGP|BM_WRITE, 0 ); | ||||
| 	    OUT_BATCH( clear_color ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 } | ||||
|  | ||||
| 	 if ( flags & BUFFER_BIT_BACK_LEFT ) { | ||||
| 	    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( intel->back_region->buffer, BM_MEM_AGP|BM_WRITE, 0 ); | ||||
| 	    OUT_BATCH( clear_color ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 } | ||||
|  | ||||
| 	 if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) { | ||||
| 	    BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); | ||||
| 	    OUT_BATCH( D_CMD ); | ||||
| 	    OUT_BATCH( BR13 ); | ||||
| 	    OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
| 	    OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
| 	    OUT_RELOC( intel->depth_region->buffer, BM_MEM_AGP|BM_WRITE, 0 ); | ||||
| 	    OUT_BATCH( clear_depth ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 }       | ||||
|       } | ||||
|    } | ||||
|    intel_batchbuffer_flush( intel->batch ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										60
									
								
								src/mesa/drivers/dri/i915/intel_blit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/mesa/drivers/dri/i915/intel_blit.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BLIT_H | ||||
| #define INTEL_BLIT_H | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
| extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv ); | ||||
| extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 			     GLint cx1, GLint cy1, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelEmitCopyBlit( struct intel_context *intel, | ||||
| 			       GLuint cpp, | ||||
| 			       GLshort src_pitch, | ||||
| 			       GLuint  src_buffer, | ||||
| 			       GLuint  src_offset, | ||||
| 			       GLshort dst_pitch, | ||||
| 			       GLuint  dst_buffer, | ||||
| 			       GLuint  dst_offset, | ||||
| 			       GLshort srcx, GLshort srcy, | ||||
| 			       GLshort dstx, GLshort dsty, | ||||
| 			       GLshort w, GLshort h ); | ||||
|  | ||||
| extern void intelEmitFillBlit( struct intel_context *intel, | ||||
| 			       GLuint cpp, | ||||
| 			       GLshort dst_pitch, | ||||
| 			       GLuint dst_buffer, | ||||
| 			       GLuint dst_offset, | ||||
| 			       GLshort x, GLshort y,  | ||||
| 			       GLshort w, GLshort h, | ||||
| 			       GLuint color ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										505
									
								
								src/mesa/drivers/dri/i915/intel_buffers.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										505
									
								
								src/mesa/drivers/dri/i915/intel_buffers.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,505 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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_tris.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "context.h" | ||||
| #include "framebuffer.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
| struct intel_region *intel_drawbuf_region( struct intel_context *intel ) | ||||
| { | ||||
|    switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) { | ||||
|    case BUFFER_BIT_FRONT_LEFT: | ||||
|       return intel->front_region; | ||||
|    case BUFFER_BIT_BACK_LEFT: | ||||
|       return intel->back_region; | ||||
|    default: | ||||
|       /* Not necessary to fallback - could handle either NONE or | ||||
|        * FRONT_AND_BACK cases below. | ||||
|        */ | ||||
|       return NULL;		 | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct intel_region *intel_readbuf_region( struct intel_context *intel ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|    /* This will have to change to support EXT_fbo's, but is correct | ||||
|     * for now: | ||||
|     */ | ||||
|    switch (ctx->ReadBuffer->_ColorReadBufferIndex) { | ||||
|    case BUFFER_FRONT_LEFT: | ||||
|       return intel->front_region; | ||||
|    case BUFFER_BACK_LEFT: | ||||
|       return intel->back_region; | ||||
|    default: | ||||
|       assert(0); | ||||
|       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. | ||||
|     */ | ||||
|    LOCK_HARDWARE(intel); | ||||
|    if (intel->driDrawable) { | ||||
|       *width = intel->driDrawable->w; | ||||
|       *height = intel->driDrawable->h; | ||||
|    } | ||||
|    else { | ||||
|       *width = 0; | ||||
|       *height = 0; | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelSetBackClipRects( struct intel_context *intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { | ||||
|       intel->numClipRects = dPriv->numClipRects; | ||||
|       intel->pClipRects = dPriv->pClipRects; | ||||
|       intel->drawX = dPriv->x; | ||||
|       intel->drawY = dPriv->y; | ||||
|    } else { | ||||
|       intel->numClipRects = dPriv->numBackClipRects; | ||||
|       intel->pClipRects = dPriv->pBackClipRects; | ||||
|       intel->drawX = dPriv->backX; | ||||
|       intel->drawY = dPriv->backY; | ||||
|        | ||||
|       if (dPriv->numBackClipRects == 1 && | ||||
| 	  dPriv->x == dPriv->backX && | ||||
| 	  dPriv->y == dPriv->backY) { | ||||
|        | ||||
| 	 /* Repeat the calculation of the back cliprect dimensions here | ||||
| 	  * as early versions of dri.a in the Xserver are incorrect.  Try | ||||
| 	  * very hard not to restrict future versions of dri.a which | ||||
| 	  * might eg. allocate truly private back buffers. | ||||
| 	  */ | ||||
| 	 int x1, y1; | ||||
| 	 int x2, y2; | ||||
| 	  | ||||
| 	 x1 = dPriv->x; | ||||
| 	 y1 = dPriv->y;       | ||||
| 	 x2 = dPriv->x + dPriv->w; | ||||
| 	 y2 = dPriv->y + dPriv->h; | ||||
| 	  | ||||
| 	 if (x1 < 0) x1 = 0; | ||||
| 	 if (y1 < 0) y1 = 0; | ||||
| 	 if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width; | ||||
| 	 if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height; | ||||
|  | ||||
| 	 if (x1 == dPriv->pBackClipRects[0].x1 && | ||||
| 	     y1 == dPriv->pBackClipRects[0].y1) { | ||||
|  | ||||
| 	    dPriv->pBackClipRects[0].x2 = x2; | ||||
| 	    dPriv->pBackClipRects[0].y2 = y2; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelWindowMoved( struct intel_context *intel ) | ||||
| { | ||||
|    if (!intel->ctx.DrawBuffer) { | ||||
|       intelSetFrontClipRects( intel ); | ||||
|    } | ||||
|    else { | ||||
|       switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) { | ||||
|       case BUFFER_BIT_FRONT_LEFT: | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
| 	 break; | ||||
|       case BUFFER_BIT_BACK_LEFT: | ||||
| 	 intelSetBackClipRects( intel ); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Set state we know depends on drawable parameters: | ||||
|     */ | ||||
|    { | ||||
|       GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|       ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			   ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|        | ||||
|       ctx->Driver.DepthRange( ctx,  | ||||
| 			      ctx->Viewport.Near, | ||||
| 			      ctx->Viewport.Far ); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void emit_clip_rect_quads(struct intel_context *intel, | ||||
| 				 const drm_clip_rect_t *clear) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0; i < intel->numClipRects; i++) { | ||||
|       drm_clip_rect_t rect; | ||||
|  | ||||
|       if (intel_intersect_cliprects(&rect,  | ||||
| 				    clear, | ||||
| 				    &intel->pClipRects[i])) | ||||
|       { | ||||
| 	 intel_meta_draw_quad(intel,  | ||||
| 			      rect.x1, rect.x2,  | ||||
| 			      rect.y1, rect.y2,  | ||||
| 			      0, | ||||
| 			      intel->ClearColor,  | ||||
| 			      0, 0, 0, 0, | ||||
| 			      INTEL_BATCH_NO_CLIPRECTS); | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* 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) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    drm_clip_rect_t clear; | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|    intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|    if(!all) { | ||||
|       clear.x1 = cx; | ||||
|       clear.y1 = cy; | ||||
|       clear.x2 = cx + cw; | ||||
|       clear.y2 = cy + ch; | ||||
|    } else { | ||||
|       clear.x1 = 0; | ||||
|       clear.y1 = 0; | ||||
|       clear.x2 = dPriv->w; | ||||
|       clear.y2 = dPriv->h; | ||||
|    } | ||||
|  | ||||
|    /* Back and stencil cliprects are the same.  Try and do both | ||||
|     * buffers at once: | ||||
|     */ | ||||
|    if (mask & (BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL)) {  | ||||
|       intel->vtbl.meta_draw_region(intel,  | ||||
| 				   intel->back_region, | ||||
| 				   intel->depth_region ); | ||||
|  | ||||
|       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_depth_stencil_write(intel); | ||||
|        | ||||
|       /* Do cliprects explicitly: | ||||
|        */ | ||||
|       emit_clip_rect_quads(intel, &clear); | ||||
|    } | ||||
|  | ||||
|    /* Front may have different cliprects:  | ||||
|     */ | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) { | ||||
|       intel->vtbl.meta_no_depth_stencil_write(intel); | ||||
|       intel->vtbl.meta_color_mask(intel, GL_TRUE ); | ||||
|       intel->vtbl.meta_draw_region(intel,  | ||||
| 				   intel->front_region, | ||||
| 				   intel->depth_region); | ||||
|  | ||||
|       emit_clip_rect_quads(intel, &clear); | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.leave_meta_state( intel ); | ||||
|    intel_batchbuffer_flush( intel->batch ); | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 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; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|  | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       blit_mask |= BUFFER_BIT_DEPTH; | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       if (!intel->hw_stencil) { | ||||
| 	 swrast_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|       else if (ctx->Stencil.WriteMask[0] != 0xff) { | ||||
| 	 tri_mask |= BUFFER_BIT_STENCIL; | ||||
|       }  | ||||
|       else { | ||||
| 	 blit_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    swrast_mask |= (mask & BUFFER_BIT_ACCUM); | ||||
|  | ||||
|    intelFlush( ctx ); | ||||
|  | ||||
|    if (blit_mask)  | ||||
|       intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch ); | ||||
|  | ||||
|    if (tri_mask)  | ||||
|       intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch); | ||||
|  | ||||
|    if (swrast_mask) | ||||
|       _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Flip the front & back buffers | ||||
|  */ | ||||
| static void intelPageFlip( const __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
| #if 0 | ||||
|    struct intel_context *intel; | ||||
|    int tmp, ret; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|  | ||||
|    intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (dPriv->pClipRects) { | ||||
|       *(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0]; | ||||
|       intel->sarea->nbox = 1; | ||||
|    } | ||||
|  | ||||
|    ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);  | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    tmp = intel->sarea->last_enqueue; | ||||
|    intelRefillBatchLocked( intel ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|  | ||||
|    intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer ); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelSwapBuffers( __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
|    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | ||||
|       struct intel_context *intel; | ||||
|       GLcontext *ctx; | ||||
|       intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; | ||||
|       ctx = &intel->ctx; | ||||
|       if (ctx->Visual.doubleBufferMode) { | ||||
| 	 _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */ | ||||
| 	 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */ | ||||
| 	    intelPageFlip( dPriv ); | ||||
| 	 } else { | ||||
| 	    intelCopyBuffer( dPriv ); | ||||
| 	 } | ||||
|       } | ||||
|    } else { | ||||
|       /* XXX this shouldn't be an error but we can't handle it for now */ | ||||
|       fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelDrawBuffer(GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    int front = 0; | ||||
|   | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|  | ||||
|    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) { | ||||
|    case BUFFER_BIT_FRONT_LEFT: | ||||
|       front = 1; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    case BUFFER_BIT_BACK_LEFT: | ||||
|       front = 0; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    default: | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE ); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if ( intel->sarea->pf_current_page == 1 )  | ||||
|       front ^= 1; | ||||
|     | ||||
|    intelSetFrontClipRects( intel ); | ||||
|  | ||||
|  | ||||
|    if (front) { | ||||
|       if (intel->draw_region != intel->front_region) { | ||||
| 	 intel_region_release(intel, &intel->draw_region); | ||||
| 	 intel_region_reference(&intel->draw_region, intel->front_region); | ||||
|       } | ||||
|    } else { | ||||
|       if (intel->draw_region != intel->back_region) { | ||||
| 	 intel_region_release(intel, &intel->draw_region); | ||||
| 	 intel_region_reference(&intel->draw_region, intel->back_region); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.set_draw_region( intel,  | ||||
| 				intel->draw_region, | ||||
| 				intel->depth_region); | ||||
| } | ||||
|  | ||||
| static void intelReadBuffer( GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelInitBufferFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->Clear = intelClear; | ||||
|    functions->GetBufferSize = intelBufferSize; | ||||
|    functions->ResizeBuffers = _mesa_resize_framebuffer; | ||||
|    functions->DrawBuffer = intelDrawBuffer; | ||||
|    functions->ReadBuffer = intelReadBuffer; | ||||
| } | ||||
| @@ -54,6 +54,11 @@ | ||||
| #include "intel_tris.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "bufmgr.h" | ||||
|  | ||||
| #include "utils.h" | ||||
| #ifndef INTEL_DEBUG | ||||
| @@ -77,9 +82,6 @@ int INTEL_DEBUG = (0); | ||||
| #define need_GL_NV_vertex_program | ||||
| #include "extension_helper.h" | ||||
|  | ||||
| #ifndef VERBOSE | ||||
| int VERBOSE = 0; | ||||
| #endif | ||||
|  | ||||
| #if DEBUG_LOCKING | ||||
| char *prevLockFile; | ||||
| @@ -90,9 +92,9 @@ int prevLockLine; | ||||
|  * Mesa's Driver Functions | ||||
|  ***************************************/ | ||||
|  | ||||
| #define DRIVER_DATE                     "20050225" | ||||
| #define DRIVER_DATE                     "20060212" | ||||
|  | ||||
| const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
| static const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
| { | ||||
|    const char * chipset; | ||||
|    static char buffer[128]; | ||||
| @@ -103,7 +105,7 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
|       break; | ||||
|        | ||||
|    case GL_RENDERER: | ||||
|       switch (INTEL_CONTEXT(ctx)->intelScreen->deviceID) { | ||||
|       switch (intel_context(ctx)->intelScreen->deviceID) { | ||||
|       case PCI_CHIP_845_G: | ||||
| 	 chipset = "Intel(R) 845G"; break; | ||||
|       case PCI_CHIP_I830_M: | ||||
| @@ -130,27 +132,6 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelBufferSize(GLframebuffer *buffer, | ||||
| 			   GLuint *width, GLuint *height) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    /* Need to lock to make sure the driDrawable is uptodate.  This | ||||
|     * information is used to resize Mesa's software buffers, so it has | ||||
|     * to be correct. | ||||
|     */ | ||||
|    LOCK_HARDWARE(intel); | ||||
|    if (intel->driDrawable) { | ||||
|       *width = intel->driDrawable->w; | ||||
|       *height = intel->driDrawable->h; | ||||
|    } | ||||
|    else { | ||||
|       *width = 0; | ||||
|       *height = 0; | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Extension strings exported by the intel driver. | ||||
| @@ -197,7 +178,7 @@ const struct dri_extension card_extensions[] = | ||||
|     { "GL_NV_blend_square",                NULL }, | ||||
|     { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }, | ||||
|     { "GL_NV_vertex_program1_1",           NULL }, | ||||
|     { "GL_SGIS_generate_mipmap",           NULL }, | ||||
| /*     { "GL_SGIS_generate_mipmap",           NULL }, */ | ||||
|     { NULL,                                NULL } | ||||
| }; | ||||
|  | ||||
| @@ -214,7 +195,7 @@ static const struct tnl_pipeline_stage *intel_pipeline[] = { | ||||
|    &_tnl_point_attenuation_stage, | ||||
|    &_tnl_arb_vertex_program_stage, | ||||
|    &_tnl_vertex_program_stage, | ||||
| #if 1 | ||||
| #if 0 | ||||
|    &_intel_render_stage,     /* ADD: unclipped rastersetup-to-dma */ | ||||
| #endif | ||||
|    &_tnl_render_stage, | ||||
| @@ -237,6 +218,7 @@ static const struct dri_debug_control debug_control[] = | ||||
|     { "sync",  DEBUG_SYNC }, | ||||
|     { "sleep", DEBUG_SLEEP }, | ||||
|     { "pix",   DEBUG_PIXEL }, | ||||
|     { "buf",   DEBUG_BUFMGR }, | ||||
|     { NULL,    0 } | ||||
| }; | ||||
|  | ||||
| @@ -248,7 +230,32 @@ static void intelInvalidateState( GLcontext *ctx, GLuint new_state ) | ||||
|    _ac_InvalidateState( ctx, new_state ); | ||||
|    _tnl_InvalidateState( ctx, new_state ); | ||||
|    _tnl_invalidate_vertex_state( ctx, new_state ); | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= new_state; | ||||
|    intel_context(ctx)->NewGLState |= new_state; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelFlush( GLcontext *ctx ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|  | ||||
|    if (intel->Fallback) | ||||
|       _swrast_flush( ctx ); | ||||
|  | ||||
|    INTEL_FIREVERTICES( intel ); | ||||
|  | ||||
|    if (intel->batch->map != intel->batch->ptr) | ||||
|       intel_batchbuffer_flush( intel->batch ); | ||||
|  | ||||
|    /* XXX: Need to do an MI_FLUSH here.  Actually, the bufmgr_fake.c | ||||
|     * code will have done one already. | ||||
|     */ | ||||
| } | ||||
|  | ||||
| void intelFinish( GLcontext *ctx )  | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    intelFlush( ctx ); | ||||
|    bmFinishFence( intel->bm, intel->last_fence ); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -257,10 +264,7 @@ void intelInitDriverFunctions( struct dd_function_table *functions ) | ||||
|    _mesa_init_driver_functions( functions ); | ||||
|  | ||||
|    functions->Flush = intelFlush; | ||||
|    functions->Clear = intelClear; | ||||
|    functions->Finish = intelFinish; | ||||
|    functions->GetBufferSize = intelBufferSize; | ||||
|    functions->ResizeBuffers = _mesa_resize_framebuffer; | ||||
|    functions->GetString = intelGetString; | ||||
|    functions->UpdateState = intelInvalidateState; | ||||
|    functions->CopyColorTable = _swrast_CopyColorTable; | ||||
| @@ -271,11 +275,12 @@ void intelInitDriverFunctions( struct dd_function_table *functions ) | ||||
|    intelInitTextureFuncs( functions ); | ||||
|    intelInitPixelFuncs( functions ); | ||||
|    intelInitStateFuncs( functions ); | ||||
|    intelInitBufferFuncs( functions ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| GLboolean intelInitContext( intelContextPtr intel, | ||||
| GLboolean intelInitContext( struct intel_context *intel, | ||||
| 			    const __GLcontextModes *mesaVis, | ||||
| 			    __DRIcontextPrivate *driContextPriv, | ||||
| 			    void *sharedContextPrivate, | ||||
| @@ -300,9 +305,6 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    intel->sarea = saPriv; | ||||
|  | ||||
|  | ||||
|    (void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) ); | ||||
|    make_empty_list( & intel->swapped ); | ||||
|  | ||||
|    ctx->Const.MaxTextureMaxAnisotropy = 2.0; | ||||
|  | ||||
|    ctx->Const.MinLineWidth = 1.0; | ||||
| @@ -371,7 +373,57 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|  | ||||
|    _math_matrix_ctr (&intel->ViewportMatrix); | ||||
|  | ||||
|    driInitExtensions( ctx, card_extensions, GL_TRUE ); | ||||
|    /* Disable imaging extension until convolution is working in | ||||
|     * teximage paths: | ||||
|     */ | ||||
|    driInitExtensions( ctx, card_extensions,  | ||||
| /* 		      GL_TRUE, */ | ||||
| 		      GL_FALSE); | ||||
|  | ||||
|  | ||||
|    /* Buffer manager:  | ||||
|     */ | ||||
|    intel->bm = bm_fake_intel_Attach( intel ); | ||||
|  | ||||
|    bmInitPool(intel->bm, | ||||
|               intel->intelScreen->tex.offset, /* low offset */ | ||||
|               intel->intelScreen->tex.map, /* low virtual */ | ||||
|               intel->intelScreen->tex.size, | ||||
| 	      BM_MEM_AGP); | ||||
|  | ||||
|    /* These are still static, but create regions for them.   | ||||
|     */ | ||||
|    intel->front_region =  | ||||
|       intel_region_create_static(intel, | ||||
| 				 BM_MEM_AGP, | ||||
| 				 intelScreen->front.offset, | ||||
| 				 intelScreen->front.map, | ||||
| 				 intelScreen->cpp, | ||||
| 				 intelScreen->front.pitch, | ||||
| 				 intelScreen->height); | ||||
|  | ||||
|  | ||||
|    intel->back_region =  | ||||
|       intel_region_create_static(intel, | ||||
| 				 BM_MEM_AGP, | ||||
| 				 intelScreen->back.offset, | ||||
| 				 intelScreen->back.map, | ||||
| 				 intelScreen->cpp, | ||||
| 				 intelScreen->back.pitch, | ||||
| 				 intelScreen->height); | ||||
|  | ||||
|    /* Still assuming front.cpp == depth.cpp | ||||
|     */ | ||||
|    intel->depth_region =  | ||||
|       intel_region_create_static(intel, | ||||
| 				 BM_MEM_AGP, | ||||
| 				 intelScreen->depth.offset, | ||||
| 				 intelScreen->depth.map, | ||||
| 				 intelScreen->cpp, | ||||
| 				 intelScreen->depth.pitch, | ||||
| 				 intelScreen->height); | ||||
|     | ||||
|    intel->batch = intel_batchbuffer_alloc( intel ); | ||||
|  | ||||
|    if (intel->ctx.Mesa_DXTn) { | ||||
|      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" ); | ||||
| @@ -387,24 +439,16 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_RECT ); */ | ||||
|  | ||||
|  | ||||
|    intel->prim.flush = intelInitBatchBuffer; | ||||
|    intel->prim.primitive = ~0; | ||||
|  | ||||
|  | ||||
| #if DO_DEBUG | ||||
|    INTEL_DEBUG  = driParseDebugString( getenv( "INTEL_DEBUG" ), | ||||
| 				       debug_control ); | ||||
|    INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ), | ||||
| 				       debug_control ); | ||||
| #endif | ||||
|  | ||||
| #ifndef VERBOSE | ||||
|    if (getenv("INTEL_VERBOSE")) | ||||
|       VERBOSE=1; | ||||
| #endif | ||||
|  | ||||
|    if (getenv("INTEL_NO_RAST") ||  | ||||
|        getenv("INTEL_NO_RAST")) { | ||||
|    if (getenv("INTEL_NO_RAST")) { | ||||
|       fprintf(stderr, "disabling 3D rasterization\n"); | ||||
|       FALLBACK(intel, INTEL_FALLBACK_USER, 1);  | ||||
|    } | ||||
| @@ -414,7 +458,7 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|  | ||||
| void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | ||||
| { | ||||
|    intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate; | ||||
|    struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; | ||||
|  | ||||
|    assert(intel); /* should never be null */ | ||||
|    if (intel) { | ||||
| @@ -431,21 +475,14 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | ||||
|       _swrast_DestroyContext (&intel->ctx); | ||||
|       intel->Fallback = 0;	/* don't call _swrast_Flush later */ | ||||
|  | ||||
|       intelDestroyBatchBuffer(&intel->ctx); | ||||
|       intel_batchbuffer_free(intel->batch); | ||||
|        | ||||
|  | ||||
|       if ( release_texture_heaps ) { | ||||
|          /* This share group is about to go away, free our private | ||||
|           * texture object data. | ||||
|           */ | ||||
|          int i; | ||||
|  | ||||
|          for ( i = 0 ; i < intel->nr_heaps ; i++ ) { | ||||
| 	    driDestroyTextureHeap( intel->texture_heaps[ i ] ); | ||||
| 	    intel->texture_heaps[ i ] = NULL; | ||||
|          } | ||||
|  | ||||
| 	 assert( is_empty_list( & intel->swapped ) ); | ||||
| 	 fprintf(stderr, "do somethign to free texture heaps\n"); | ||||
|       } | ||||
|  | ||||
|       /* free the Mesa context */ | ||||
| @@ -453,102 +490,6 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelSetFrontClipRects( intelContextPtr intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    intel->numClipRects = dPriv->numClipRects; | ||||
|    intel->pClipRects = dPriv->pClipRects; | ||||
|    intel->drawX = dPriv->x; | ||||
|    intel->drawY = dPriv->y; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelSetBackClipRects( intelContextPtr intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { | ||||
|       intel->numClipRects = dPriv->numClipRects; | ||||
|       intel->pClipRects = dPriv->pClipRects; | ||||
|       intel->drawX = dPriv->x; | ||||
|       intel->drawY = dPriv->y; | ||||
|    } else { | ||||
|       intel->numClipRects = dPriv->numBackClipRects; | ||||
|       intel->pClipRects = dPriv->pBackClipRects; | ||||
|       intel->drawX = dPriv->backX; | ||||
|       intel->drawY = dPriv->backY; | ||||
|        | ||||
|       if (dPriv->numBackClipRects == 1 && | ||||
| 	  dPriv->x == dPriv->backX && | ||||
| 	  dPriv->y == dPriv->backY) { | ||||
|        | ||||
| 	 /* Repeat the calculation of the back cliprect dimensions here | ||||
| 	  * as early versions of dri.a in the Xserver are incorrect.  Try | ||||
| 	  * very hard not to restrict future versions of dri.a which | ||||
| 	  * might eg. allocate truly private back buffers. | ||||
| 	  */ | ||||
| 	 int x1, y1; | ||||
| 	 int x2, y2; | ||||
| 	  | ||||
| 	 x1 = dPriv->x; | ||||
| 	 y1 = dPriv->y;       | ||||
| 	 x2 = dPriv->x + dPriv->w; | ||||
| 	 y2 = dPriv->y + dPriv->h; | ||||
| 	  | ||||
| 	 if (x1 < 0) x1 = 0; | ||||
| 	 if (y1 < 0) y1 = 0; | ||||
| 	 if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width; | ||||
| 	 if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height; | ||||
|  | ||||
| 	 if (x1 == dPriv->pBackClipRects[0].x1 && | ||||
| 	     y1 == dPriv->pBackClipRects[0].y1) { | ||||
|  | ||||
| 	    dPriv->pBackClipRects[0].x2 = x2; | ||||
| 	    dPriv->pBackClipRects[0].y2 = y2; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelWindowMoved( intelContextPtr intel ) | ||||
| { | ||||
|    if (!intel->ctx.DrawBuffer) { | ||||
|       intelSetFrontClipRects( intel ); | ||||
|    } | ||||
|    else { | ||||
|       switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) { | ||||
|       case BUFFER_BIT_FRONT_LEFT: | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
| 	 break; | ||||
|       case BUFFER_BIT_BACK_LEFT: | ||||
| 	 intelSetBackClipRects( intel ); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Set state we know depends on drawable parameters: | ||||
|     */ | ||||
|    { | ||||
|       GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|       ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			   ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|        | ||||
|       ctx->Driver.DepthRange( ctx,  | ||||
| 			      ctx->Viewport.Near, | ||||
| 			      ctx->Viewport.Far ); | ||||
|    } | ||||
| } | ||||
|  | ||||
| GLboolean intelUnbindContext(__DRIcontextPrivate *driContextPriv) | ||||
| { | ||||
|    return GL_TRUE; | ||||
| @@ -560,7 +501,7 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, | ||||
| { | ||||
|  | ||||
|    if (driContextPriv) { | ||||
|       intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate; | ||||
|       struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; | ||||
|  | ||||
|       if ( intel->driDrawable != driDrawPriv ) { | ||||
| 	 /* Shouldn't the readbuffer be stored also? */ | ||||
| @@ -580,13 +521,12 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| void intelGetLock( intelContextPtr intel, GLuint flags ) | ||||
| void intelGetLock( struct intel_context *intel, GLuint flags ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    __DRIscreenPrivate *sPriv = intel->driScreen; | ||||
|    drmI830Sarea * sarea = intel->sarea; | ||||
|    int me = intel->hHWContext; | ||||
|    unsigned   i; | ||||
|  | ||||
|    drmGetLock(intel->driFd, intel->hHWContext, flags); | ||||
|  | ||||
| @@ -598,143 +538,19 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) | ||||
|    if (dPriv) | ||||
|       DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); | ||||
|  | ||||
|    /* If we lost context, need to dump all registers to hardware. | ||||
|     * Note that we don't care about 2d contexts, even if they perform | ||||
|     * accelerated commands, so the DRI locking in the X server is even | ||||
|     * more broken than usual. | ||||
|    /* Lost context? | ||||
|     */ | ||||
|  | ||||
|    if (sarea->ctxOwner != me) { | ||||
|       intel->perf_boxes |= I830_BOX_LOST_CONTEXT; | ||||
|       sarea->ctxOwner = me; | ||||
|    } | ||||
|  | ||||
|    /* Shared texture managment - if another client has played with | ||||
|     * texture space, figure out which if any of our textures have been | ||||
|     * ejected, and update our global LRU. | ||||
|    /* Drawable changed? | ||||
|     */ | ||||
|  | ||||
|    for ( i = 0 ; i < intel->nr_heaps ; i++ ) { | ||||
|       DRI_AGE_TEXTURES( intel->texture_heaps[ i ] ); | ||||
|    } | ||||
|  | ||||
|    if (dPriv && intel->lastStamp != dPriv->lastStamp) { | ||||
|       intelWindowMoved( intel ); | ||||
|       intel->lastStamp = dPriv->lastStamp; | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelSwapBuffers( __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
|    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | ||||
|       intelContextPtr intel; | ||||
|       GLcontext *ctx; | ||||
|       intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|       ctx = &intel->ctx; | ||||
|       if (ctx->Visual.doubleBufferMode) { | ||||
| 	 _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */ | ||||
| 	 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */ | ||||
| 	    intelPageFlip( dPriv ); | ||||
| 	 } else { | ||||
| 	    intelCopyBuffer( dPriv ); | ||||
| 	 } | ||||
|       } | ||||
|    } else { | ||||
|       /* XXX this shouldn't be an error but we can't handle it for now */ | ||||
|       fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitState( GLcontext *ctx ) | ||||
| { | ||||
|    /* Mesa should do this for us: | ||||
|     */ | ||||
|    ctx->Driver.AlphaFunc( ctx,  | ||||
| 			  ctx->Color.AlphaFunc, | ||||
| 			  ctx->Color.AlphaRef); | ||||
|  | ||||
|    ctx->Driver.BlendColor( ctx, | ||||
| 			   ctx->Color.BlendColor ); | ||||
|  | ||||
|    ctx->Driver.BlendEquationSeparate( ctx,  | ||||
| 				      ctx->Color.BlendEquationRGB, | ||||
| 				      ctx->Color.BlendEquationA); | ||||
|  | ||||
|    ctx->Driver.BlendFuncSeparate( ctx, | ||||
| 				  ctx->Color.BlendSrcRGB, | ||||
| 				  ctx->Color.BlendDstRGB, | ||||
| 				  ctx->Color.BlendSrcA, | ||||
| 				  ctx->Color.BlendDstA); | ||||
|  | ||||
|    ctx->Driver.ColorMask( ctx,  | ||||
| 			  ctx->Color.ColorMask[RCOMP], | ||||
| 			  ctx->Color.ColorMask[GCOMP], | ||||
| 			  ctx->Color.ColorMask[BCOMP], | ||||
| 			  ctx->Color.ColorMask[ACOMP]); | ||||
|  | ||||
|    ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode ); | ||||
|    ctx->Driver.DepthFunc( ctx, ctx->Depth.Func ); | ||||
|    ctx->Driver.DepthMask( ctx, ctx->Depth.Mask ); | ||||
|  | ||||
|    ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test ); | ||||
|    ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE ); | ||||
|  | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); | ||||
|  | ||||
|    ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace ); | ||||
|  | ||||
|    { | ||||
|       GLfloat f = (GLfloat)ctx->Light.Model.ColorControl; | ||||
|       ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f ); | ||||
|    } | ||||
|  | ||||
|    ctx->Driver.LineWidth( ctx, ctx->Line.Width ); | ||||
|    ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp ); | ||||
|    ctx->Driver.PointSize( ctx, ctx->Point.Size ); | ||||
|    ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple ); | ||||
|    ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|    ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT, | ||||
|                                     ctx->Stencil.Function[0], | ||||
|                                     ctx->Stencil.Ref[0], | ||||
|                                     ctx->Stencil.ValueMask[0] ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_BACK, | ||||
|                                     ctx->Stencil.Function[1], | ||||
|                                     ctx->Stencil.Ref[1], | ||||
|                                     ctx->Stencil.ValueMask[1] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] ); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_FRONT, | ||||
|                                   ctx->Stencil.FailFunc[0], | ||||
|                                   ctx->Stencil.ZFailFunc[0], | ||||
|                                   ctx->Stencil.ZPassFunc[0]); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_BACK, | ||||
|                                   ctx->Stencil.FailFunc[1], | ||||
|                                   ctx->Stencil.ZFailFunc[1], | ||||
|                                   ctx->Stencil.ZPassFunc[1]); | ||||
|  | ||||
|  | ||||
|    ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); | ||||
| } | ||||
|   | ||||
| @@ -47,82 +47,123 @@ | ||||
| #define DV_PF_565  (2<<8) | ||||
| #define DV_PF_8888 (3<<8) | ||||
|  | ||||
| #define INTEL_CONTEXT(ctx)	((intelContextPtr)(ctx)) | ||||
| struct intel_region; | ||||
| struct intel_context; | ||||
|  | ||||
| typedef struct intel_context intelContext; | ||||
| typedef struct intel_context *intelContextPtr; | ||||
| typedef struct intel_texture_object *intelTextureObjectPtr; | ||||
|  | ||||
| typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *, | ||||
| typedef void (*intel_tri_func)(struct intel_context *, intelVertex *, intelVertex *, | ||||
| 							  intelVertex *); | ||||
| typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *); | ||||
| typedef void (*intel_point_func)(intelContextPtr, intelVertex *); | ||||
| typedef void (*intel_line_func)(struct intel_context *, intelVertex *, intelVertex *); | ||||
| typedef void (*intel_point_func)(struct intel_context *, intelVertex *); | ||||
|  | ||||
| #define INTEL_FALLBACK_DRAW_BUFFER	 0x1 | ||||
| #define INTEL_FALLBACK_READ_BUFFER	 0x2 | ||||
| #define INTEL_FALLBACK_USER		 0x4 | ||||
| #define INTEL_FALLBACK_NO_BATCHBUFFER	 0x8 | ||||
| #define INTEL_FALLBACK_NO_TEXMEM	 0x10 | ||||
| #define INTEL_FALLBACK_RENDERMODE	 0x20 | ||||
| #define INTEL_FALLBACK_RENDERMODE	 0x8 | ||||
|  | ||||
| extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ); | ||||
| extern void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode ); | ||||
| #define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode ) | ||||
|  | ||||
|  | ||||
| #define INTEL_TEX_MAXLEVELS 10 | ||||
|  | ||||
|  | ||||
| struct intel_texture_object | ||||
| { | ||||
|    driTextureObject    base;	/* the parent class */ | ||||
|    struct gl_texture_object base; /* The "parent" object */ | ||||
|  | ||||
|    GLuint texelBytes; | ||||
|    GLuint age; | ||||
|    GLuint Pitch; | ||||
|    GLuint Height; | ||||
|    GLuint TextureOffset; | ||||
|    GLubyte *BufAddr;    | ||||
|    /* The mipmap tree must include at least these levels once | ||||
|     * validated: | ||||
|     */ | ||||
|    GLuint firstLevel; | ||||
|    GLuint lastLevel; | ||||
|  | ||||
|    GLuint min_level; | ||||
|    GLuint max_level; | ||||
|    GLuint depth_pitch; | ||||
|    /* Offset for firstLevel image: | ||||
|     */ | ||||
|    GLuint textureOffset; | ||||
|  | ||||
|    struct { | ||||
|       const struct gl_texture_image *image; | ||||
|       GLuint offset;       /* into BufAddr */ | ||||
|       GLuint height; | ||||
|       GLuint internalFormat; | ||||
|    } image[6][INTEL_TEX_MAXLEVELS]; | ||||
|  | ||||
|    GLuint dirty; | ||||
|    GLuint firstLevel,lastLevel; | ||||
|    /* On validation any active images held in main memory or in other | ||||
|     * regions will be copied to this region and the old storage freed. | ||||
|     */ | ||||
|    struct intel_mipmap_tree *mt; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| struct intel_texture_image  | ||||
| { | ||||
|    struct gl_texture_image base; | ||||
|  | ||||
|    /* These aren't stored in gl_texture_image  | ||||
|     */ | ||||
|    GLuint level; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* If intelImage->mt != NULL, image data is stored here. | ||||
|     * Else if intelImage->base.Data != NULL, image is stored there. | ||||
|     * Else there is no image data. | ||||
|     */ | ||||
|    struct intel_mipmap_tree *mt; | ||||
| }; | ||||
|  | ||||
|  | ||||
| #define INTEL_MAX_FIXUP 64 | ||||
|  | ||||
| struct intel_context | ||||
| { | ||||
|    GLcontext ctx;		/* the parent class */ | ||||
|  | ||||
|    struct { | ||||
|       void (*destroy)( intelContextPtr intel );  | ||||
|       void (*emit_state)( intelContextPtr intel ); | ||||
|       void (*emit_invarient_state)( intelContextPtr intel ); | ||||
|       void (*lost_hardware)( intelContextPtr intel ); | ||||
|       void (*update_texture_state)( intelContextPtr intel ); | ||||
|       void (*destroy)( struct intel_context *intel );  | ||||
|       void (*emit_state)( struct intel_context *intel ); | ||||
|       void (*emit_invarient_state)( struct intel_context *intel ); | ||||
|       void (*lost_hardware)( struct intel_context *intel ); | ||||
|       void (*update_texture_state)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*render_start)( intelContextPtr intel ); | ||||
|       void (*set_draw_offset)( intelContextPtr intel, int offset ); | ||||
|       void (*emit_flush)( intelContextPtr intel ); | ||||
|       void (*render_start)( struct intel_context *intel ); | ||||
|       void (*set_draw_region)( struct intel_context *intel,  | ||||
| 			       struct intel_region *draw_region, | ||||
| 			       struct intel_region *depth_region ); | ||||
|  | ||||
|       void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim ); | ||||
|       GLuint (*flush_cmd)( void ); | ||||
|  | ||||
|       GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected ); | ||||
|       void (*reduced_primitive_state)( struct intel_context *intel, GLenum rprim ); | ||||
|  | ||||
|       void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask, | ||||
|       GLboolean (*check_vertex_size)( struct intel_context *intel, GLuint expected ); | ||||
|  | ||||
|       void (*clear_with_tris)( struct intel_context *intel, GLbitfield mask, | ||||
| 			       GLboolean all,  | ||||
| 			       GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|  | ||||
|       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_no_depth_stencil_write)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*meta_no_texture)( struct intel_context *intel ); | ||||
|       void (*meta_texture_blend_replace)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*meta_tex_rect_source)( struct intel_context *intel, | ||||
| 				    struct intel_region *region, | ||||
| 				    GLuint textureFormat ); | ||||
|  | ||||
|       void (*meta_draw_format)( struct intel_context *intel, | ||||
| 				GLuint format, | ||||
| 				GLuint depth_format ); | ||||
|        | ||||
|        | ||||
|  | ||||
|  | ||||
|    } vtbl; | ||||
|  | ||||
| @@ -130,41 +171,27 @@ struct intel_context | ||||
|    GLuint Fallback; | ||||
|    GLuint NewGLState; | ||||
|     | ||||
|    struct { | ||||
|       GLuint start_offset; | ||||
|       GLint size; | ||||
|       GLint space; | ||||
|       GLubyte *ptr; | ||||
|    } batch; | ||||
|        | ||||
|    struct { | ||||
|       void *ptr; | ||||
|       GLint size; | ||||
|       GLuint offset; | ||||
|       GLuint active_buf; | ||||
|       GLuint irq_emitted; | ||||
|    } alloc; | ||||
|    GLuint last_fence; | ||||
|    GLuint last_swap_fence; | ||||
|  | ||||
|    struct intel_batchbuffer *batch; | ||||
|  | ||||
|    struct { | ||||
|       GLuint id; | ||||
|       GLuint primitive; | ||||
|       GLubyte *start_ptr;       | ||||
|       void (*flush)( GLcontext * ); | ||||
|       void (*flush)( struct intel_context * ); | ||||
|    } prim; | ||||
|  | ||||
|    GLboolean locked; | ||||
|  | ||||
|    GLubyte clear_red; | ||||
|    GLubyte clear_green; | ||||
|    GLubyte clear_blue; | ||||
|    GLubyte clear_alpha; | ||||
|    GLuint ClearColor; | ||||
|    GLuint ClearDepth; | ||||
|  | ||||
|    /* 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; | ||||
|  | ||||
| @@ -179,14 +206,10 @@ struct intel_context | ||||
|    GLboolean hw_stencil; | ||||
|    GLboolean hw_stipple; | ||||
|     | ||||
|    /* Texture object bookkeeping | ||||
|    /* AGP memory buffer manager: | ||||
|     */ | ||||
|    GLuint                nr_heaps; | ||||
|    driTexHeap          * texture_heaps[1]; | ||||
|    driTextureObject      swapped; | ||||
|    GLuint                lastStamp; | ||||
|    struct bufmgr *bm; | ||||
|  | ||||
|    struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS]; | ||||
|  | ||||
|    /* State for intelvb.c and inteltris.c. | ||||
|     */ | ||||
| @@ -195,7 +218,13 @@ struct intel_context | ||||
|    GLenum render_primitive; | ||||
|    GLenum reduced_primitive; | ||||
|    GLuint vertex_size; | ||||
|    char *verts;			/* points to tnl->clipspace.vertex_buf */ | ||||
|    GLubyte *verts;			/* points to tnl->clipspace.vertex_buf */ | ||||
|  | ||||
|  | ||||
|    struct intel_region *front_region; | ||||
|    struct intel_region *back_region; | ||||
|    struct intel_region *draw_region; | ||||
|    struct intel_region *depth_region; | ||||
|  | ||||
|  | ||||
|    /* Fallback rasterization functions  | ||||
| @@ -206,13 +235,11 @@ struct intel_context | ||||
|  | ||||
|    /* These refer to the current draw (front vs. back) buffer: | ||||
|     */ | ||||
|    GLuint drawOffset;		/* agp offset of drawbuffer */ | ||||
|    int drawX;			/* origin of drawable in draw buffer */ | ||||
|    int drawY; | ||||
|    GLuint numClipRects;		/* cliprects for that buffer */ | ||||
|    drm_clip_rect_t *pClipRects; | ||||
|  | ||||
|    int dirtyAge; | ||||
|    int perf_boxes; | ||||
|    int do_irqs; | ||||
|  | ||||
| @@ -229,6 +256,8 @@ struct intel_context | ||||
|    intelScreenPrivate *intelScreen;  | ||||
|    drmI830Sarea *sarea;  | ||||
|     | ||||
|    GLuint lastStamp; | ||||
|  | ||||
|    /** | ||||
|     * Configuration cache | ||||
|     */ | ||||
| @@ -321,8 +350,7 @@ do {									\ | ||||
|  | ||||
| #define INTEL_FIREVERTICES(intel)		\ | ||||
| do {						\ | ||||
|    if ((intel)->prim.flush)			\ | ||||
|       (intel)->prim.flush(&(intel)->ctx);		\ | ||||
|    assert(!(intel)->prim.flush);		\ | ||||
| } while (0) | ||||
|  | ||||
| /* ================================================================ | ||||
| @@ -356,7 +384,7 @@ do {						\ | ||||
|  * than COPY_DWORDS would: | ||||
|  */ | ||||
| #if defined(i386) || defined(__i386__) | ||||
| static __inline__ void * __memcpy(void * to, const void * from, size_t n) | ||||
| static inline void * __memcpy(void * to, const void * from, size_t n) | ||||
| { | ||||
|    int d0, d1, d2; | ||||
|    __asm__ __volatile__( | ||||
| @@ -417,21 +445,19 @@ extern int INTEL_DEBUG; | ||||
|  * intel_context.c: | ||||
|  */ | ||||
|  | ||||
| extern void intelInitDriverFunctions( struct dd_function_table *functions ); | ||||
|  | ||||
| extern GLboolean intelInitContext( intelContextPtr intel,  | ||||
| extern GLboolean intelInitContext( struct intel_context *intel,  | ||||
| 				   const __GLcontextModes *mesaVis, | ||||
| 				   __DRIcontextPrivate *driContextPriv, | ||||
| 				   void *sharedContextPrivate, | ||||
| 				   struct dd_function_table *functions ); | ||||
|  | ||||
| extern void intelGetLock(intelContextPtr intel, GLuint flags); | ||||
| extern void intelSetBackClipRects(intelContextPtr intel); | ||||
| extern void intelSetFrontClipRects(intelContextPtr intel); | ||||
| extern void intelWindowMoved( intelContextPtr intel ); | ||||
| extern void intelGetLock(struct intel_context *intel, GLuint flags); | ||||
|  | ||||
| extern void intelInitState( GLcontext *ctx ); | ||||
| extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name ); | ||||
| extern void intelFinish( GLcontext *ctx ); | ||||
| extern void intelFlush( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelInitDriverFunctions( struct dd_function_table *functions ); | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
| @@ -491,6 +517,8 @@ extern void intelInitStateFuncs( struct dd_function_table *functions ); | ||||
| #define BLENDFACT_INV_CONST_ALPHA	0x0f | ||||
| #define BLENDFACT_MASK          	0x0f | ||||
|  | ||||
| #define MI_BATCH_BUFFER_END 	(0xA<<23) | ||||
|  | ||||
|  | ||||
| extern int intel_translate_compare_func( GLenum func ); | ||||
| extern int intel_translate_stencil_op( GLenum op ); | ||||
| @@ -499,18 +527,39 @@ extern int intel_translate_logic_op( GLenum opcode ); | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * intel_ioctl.c: | ||||
|  * intel_buffers.c: | ||||
|  */ | ||||
| extern void intel_dump_batchbuffer( long offset, | ||||
| 				    int *ptr, | ||||
| 				    int count ); | ||||
| void intelInitBufferFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| struct intel_region *intel_readbuf_region( struct intel_context *intel ); | ||||
| struct intel_region *intel_drawbuf_region( struct intel_context *intel ); | ||||
|  | ||||
| extern void intelWindowMoved( struct intel_context *intel ); | ||||
|  | ||||
| extern GLboolean intel_intersect_cliprects( drm_clip_rect_t *dest, | ||||
| 					    const drm_clip_rect_t *a, | ||||
| 					    const drm_clip_rect_t *b ); | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * intel_pixel.c: | ||||
|  | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.   | ||||
|  * These are better-typed than the macros used previously: | ||||
|  */ | ||||
| extern void intelInitPixelFuncs( struct dd_function_table *functions ); | ||||
| 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; | ||||
| } | ||||
|  | ||||
| static inline struct intel_texture_image *intel_texture_image( struct gl_texture_image *img ) | ||||
| { | ||||
|    return (struct intel_texture_image *)img; | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -38,11 +38,13 @@ | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_regions.h" | ||||
| #include "drm.h" | ||||
| #include "bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static int intelEmitIrqLocked( intelContextPtr intel ) | ||||
| int intelEmitIrqLocked( struct intel_context *intel ) | ||||
| { | ||||
|    drmI830IrqEmit ie; | ||||
|    int ret, seq = 0; | ||||
| @@ -65,7 +67,7 @@ static int intelEmitIrqLocked( intelContextPtr intel ) | ||||
|    return seq; | ||||
| } | ||||
|  | ||||
| static void intelWaitIrq( intelContextPtr intel, int seq ) | ||||
| void intelWaitIrq( struct intel_context *intel, int seq ) | ||||
| { | ||||
|    drmI830IrqWait iw; | ||||
|    int ret; | ||||
| @@ -81,527 +83,63 @@ static void intelWaitIrq( intelContextPtr intel, int seq ) | ||||
|  | ||||
|    if ( ret ) { | ||||
|       fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret ); | ||||
|       if (0) | ||||
| 	 intel_dump_batchbuffer( intel->alloc.offset, | ||||
| 				 intel->alloc.ptr, | ||||
| 				 intel->alloc.size ); | ||||
|       exit(1); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void age_intel( intelContextPtr intel, int age ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) | ||||
|       if (intel->CurrentTexObj[i])  | ||||
| 	 intel->CurrentTexObj[i]->age = age; | ||||
| } | ||||
|  | ||||
| void intel_dump_batchbuffer( long offset, | ||||
| 			     int *ptr, | ||||
| 			     int count ) | ||||
| { | ||||
|    int i; | ||||
|    fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count); | ||||
|    for (i = 0; i < count/4; i += 4)  | ||||
|       fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",  | ||||
| 	      (unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); | ||||
|    fprintf(stderr, "END BATCH\n\n\n"); | ||||
| } | ||||
|  | ||||
| void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ) | ||||
| { | ||||
|    GLuint last_irq = intel->alloc.irq_emitted; | ||||
|    GLuint half = intel->alloc.size / 2; | ||||
|    GLuint buf = (intel->alloc.active_buf ^= 1); | ||||
|  | ||||
|    intel->alloc.irq_emitted = intelEmitIrqLocked( intel ); | ||||
|  | ||||
|    if (last_irq) { | ||||
|       if (allow_unlock) UNLOCK_HARDWARE( intel );  | ||||
|       intelWaitIrq( intel, last_irq ); | ||||
|       if (allow_unlock) LOCK_HARDWARE( intel );  | ||||
|    } | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf); | ||||
|  | ||||
|    intel->batch.start_offset = intel->alloc.offset + buf * half; | ||||
|    intel->batch.ptr = (GLubyte *)intel->alloc.ptr + buf * half; | ||||
|    intel->batch.size = half - 8; | ||||
|    intel->batch.space = half - 8; | ||||
|    assert(intel->batch.space >= 0); | ||||
| } | ||||
|  | ||||
| #define MI_BATCH_BUFFER_END 	(0xA<<23) | ||||
|  | ||||
|  | ||||
| void intelFlushBatchLocked( intelContextPtr intel,  | ||||
| 			    GLboolean ignore_cliprects, | ||||
| 			    GLboolean refill, | ||||
| 			    GLboolean allow_unlock) | ||||
| void intel_batch_ioctl( struct intel_context *intel,  | ||||
| 			GLuint start_offset, | ||||
| 			GLuint used, | ||||
| 			GLboolean ignore_cliprects) | ||||
| { | ||||
|    drmI830BatchBuffer batch; | ||||
|  | ||||
|    assert(intel->locked); | ||||
|    assert(used); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n", | ||||
|       fprintf(stderr, "%s used %d offset %x..%x ignore_cliprects %d\n", | ||||
| 	      __FUNCTION__,  | ||||
| 	      (intel->batch.size - intel->batch.space),  | ||||
| 	      intel->batch.size, | ||||
| 	      intel->batch.start_offset, | ||||
| 	      intel->batch.start_offset +  | ||||
| 	      (intel->batch.size - intel->batch.space),  | ||||
| 	      refill); | ||||
| 	      used,  | ||||
| 	      start_offset, | ||||
| 	      start_offset + used, | ||||
| 	      ignore_cliprects); | ||||
|  | ||||
|    /* Throw away non-effective packets.  Won't work once we have | ||||
|     * hardware contexts which would preserve statechanges beyond a | ||||
|     * single buffer. | ||||
|     */ | ||||
|    if (intel->numClipRects == 0 && !ignore_cliprects) { | ||||
|        | ||||
|       /* Without this yeild, an application with no cliprects can hog | ||||
|        * the hardware.  Without unlocking, the effect is much worse - | ||||
|        * effectively a lock-out of other contexts. | ||||
|        */ | ||||
|       if (allow_unlock) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 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) { | ||||
|       batch.start = intel->batch.start_offset; | ||||
|       batch.used = intel->batch.size - intel->batch.space; | ||||
|       batch.cliprects = intel->pClipRects; | ||||
|       batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; | ||||
|       batch.DR1 = 0; | ||||
|       batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |  | ||||
| 		   (((GLuint)intel->drawY) << 16)); | ||||
|        | ||||
|       if (intel->alloc.offset) { | ||||
| 	 if ((batch.used & 0x4) == 0) { | ||||
| 	    ((int *)intel->batch.ptr)[0] = 0; | ||||
| 	    ((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END; | ||||
| 	    batch.used += 0x8; | ||||
| 	    intel->batch.ptr += 0x8; | ||||
| 	 } | ||||
| 	 else { | ||||
| 	    ((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END; | ||||
| 	    batch.used += 0x4; | ||||
| 	    intel->batch.ptr += 0x4; | ||||
| 	 }       | ||||
|       } | ||||
|  | ||||
|       if (0) | ||||
|  	 intel_dump_batchbuffer( batch.start, | ||||
| 				 (int *)(intel->batch.ptr - batch.used), | ||||
| 				 batch.used ); | ||||
|  | ||||
|       if (0) | ||||
| 	 fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", | ||||
| 		 __FUNCTION__,  | ||||
| 		 batch.start,  | ||||
| 		 batch.start + batch.used, | ||||
| 		 batch.DR4, batch.num_cliprects); | ||||
|  | ||||
|       intel->batch.start_offset += batch.used; | ||||
|       intel->batch.size -= batch.used; | ||||
|  | ||||
|       if (intel->batch.size < 8) { | ||||
| 	 refill = GL_TRUE; | ||||
| 	 intel->batch.space = intel->batch.size = 0; | ||||
|       } | ||||
|       else { | ||||
| 	 intel->batch.size -= 8; | ||||
| 	 intel->batch.space = intel->batch.size; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       assert(intel->batch.space >= 0); | ||||
|       assert(batch.start >= intel->alloc.offset); | ||||
|       assert(batch.start < intel->alloc.offset + intel->alloc.size); | ||||
|       assert(batch.start + batch.used > intel->alloc.offset); | ||||
|       assert(batch.start + batch.used <=  | ||||
| 	     intel->alloc.offset + intel->alloc.size); | ||||
|  | ||||
|  | ||||
|       if (intel->alloc.offset) { | ||||
| 	 if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,  | ||||
| 			      sizeof(batch))) { | ||||
| 	    fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n",  -errno); | ||||
| 	    UNLOCK_HARDWARE(intel); | ||||
| 	    exit(1); | ||||
| 	 } | ||||
|       } else { | ||||
| 	 drmI830CmdBuffer cmd; | ||||
| 	 cmd.buf = (char *)intel->alloc.ptr + batch.start; | ||||
| 	 cmd.sz = batch.used; | ||||
| 	 cmd.DR1 = batch.DR1; | ||||
| 	 cmd.DR4 = batch.DR4; | ||||
| 	 cmd.num_cliprects = batch.num_cliprects; | ||||
| 	 cmd.cliprects = batch.cliprects; | ||||
| 	  | ||||
| 	 if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd,  | ||||
| 			      sizeof(cmd))) { | ||||
| 	    fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n",  -errno); | ||||
| 	    UNLOCK_HARDWARE(intel); | ||||
| 	    exit(1); | ||||
| 	 } | ||||
|       }	  | ||||
|  | ||||
|        | ||||
|       age_intel(intel, intel->sarea->last_enqueue); | ||||
|  | ||||
|       /* FIXME: use hardware contexts to avoid 'losing' hardware after | ||||
|        * each buffer flush. | ||||
|        */ | ||||
|       intel->vtbl.lost_hardware( intel ); | ||||
|    } | ||||
|  | ||||
|    if (refill) | ||||
|       intelRefillBatchLocked( intel, allow_unlock ); | ||||
| } | ||||
|  | ||||
| void intelFlushBatch( intelContextPtr intel, GLboolean refill ) | ||||
| { | ||||
|    if (intel->locked) { | ||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE ); | ||||
|    }  | ||||
|    else { | ||||
|       LOCK_HARDWARE(intel); | ||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE ); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelWaitForIdle( intelContextPtr intel ) | ||||
| {    | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intel->vtbl.emit_flush( intel ); | ||||
|    intelFlushBatch( intel, GL_TRUE ); | ||||
|  | ||||
|    /* Use an irq to wait for dma idle -- Need to track lost contexts | ||||
|     * to shortcircuit consecutive calls to this function: | ||||
|     */ | ||||
|    intelWaitIrq( intel, intel->alloc.irq_emitted ); | ||||
|    intel->alloc.irq_emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelFlush( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|  | ||||
|    if (intel->Fallback) | ||||
|       _swrast_flush( ctx ); | ||||
|  | ||||
|    INTEL_FIREVERTICES( intel ); | ||||
|  | ||||
|    if (intel->batch.size != intel->batch.space) | ||||
|       intelFlushBatch( intel, GL_FALSE ); | ||||
| } | ||||
|  | ||||
| void intelFinish( GLcontext *ctx  )  | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    intelFlush( ctx ); | ||||
|    intelWaitForIdle( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 		GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); | ||||
|    GLbitfield tri_mask = 0; | ||||
|    GLbitfield blit_mask = 0; | ||||
|    GLbitfield swrast_mask = 0; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Take care of cliprects, which are handled differently for | ||||
|     * clears, etc. | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|  | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       blit_mask |= BUFFER_BIT_DEPTH; | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       if (!intel->hw_stencil) { | ||||
| 	 swrast_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|       else if (ctx->Stencil.WriteMask[0] != 0xff) { | ||||
| 	 tri_mask |= BUFFER_BIT_STENCIL; | ||||
|       }  | ||||
|       else { | ||||
| 	 blit_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    swrast_mask |= (mask & BUFFER_BIT_ACCUM); | ||||
|  | ||||
|    if (blit_mask)  | ||||
|       intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch ); | ||||
|  | ||||
|    if (tri_mask)  | ||||
|       intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch); | ||||
|  | ||||
|    if (swrast_mask) | ||||
|       _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) | ||||
| { | ||||
|    int region_offset = 0; | ||||
|    drmI830MemAlloc alloc; | ||||
|    int ret; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size); | ||||
|  | ||||
|    alloc.region = I830_MEM_REGION_AGP; | ||||
|    alloc.alignment = 0; | ||||
|    alloc.size = size; | ||||
|    alloc.region_offset = ®ion_offset; | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* Make sure the global heap is initialized | ||||
|     */ | ||||
|    if (intel->texture_heaps[0]) | ||||
|       driAgeTextures( intel->texture_heaps[0] ); | ||||
|  | ||||
|  | ||||
|    ret = drmCommandWriteRead( intel->driFd, | ||||
| 			      DRM_I830_ALLOC, | ||||
| 			      &alloc, sizeof(alloc)); | ||||
|     | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       return NULL; | ||||
|    } | ||||
|     | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size); | ||||
|  | ||||
|    /* Need to propogate this information (agp memory in use) to our | ||||
|     * local texture lru.  The kernel has already updated the global | ||||
|     * lru.  An alternative would have been to allocate memory the | ||||
|     * usual way and then notify the kernel to pin the allocation. | ||||
|     */ | ||||
|    if (intel->texture_heaps[0]) | ||||
|       driAgeTextures( intel->texture_heaps[0] ); | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel);    | ||||
|  | ||||
|    return (void *)((char *)intel->intelScreen->tex.map + region_offset); | ||||
| } | ||||
|  | ||||
| void intelFreeAGP( intelContextPtr intel, void *pointer ) | ||||
| { | ||||
|    int region_offset; | ||||
|    drmI830MemFree memfree; | ||||
|    int ret; | ||||
|  | ||||
|    region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map; | ||||
|  | ||||
|    if (region_offset < 0 ||  | ||||
|        region_offset > intel->intelScreen->tex.size) { | ||||
|       fprintf(stderr, "offset %d outside range 0..%d\n", region_offset, | ||||
| 	      intel->intelScreen->tex.size); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    memfree.region = I830_MEM_REGION_AGP; | ||||
|    memfree.region_offset = region_offset; | ||||
|    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)); | ||||
|        | ||||
|    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 ); | ||||
|    if (INTEL_DEBUG & DEBUG_DMA) | ||||
|       fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", | ||||
| 	      __FUNCTION__,  | ||||
| 	      batch.start,  | ||||
| 	      batch.start + batch.used * 4, | ||||
| 	      batch.DR4, batch.num_cliprects); | ||||
| #if 1 | ||||
|    if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,  | ||||
| 			sizeof(batch))) { | ||||
|       fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n",  -errno); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    tmp = intel->sarea->last_enqueue; | ||||
|    intelRefillBatchLocked( intel ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|  | ||||
|    intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer ); | ||||
| #endif | ||||
|        | ||||
|    /* FIXME: use hardware contexts to avoid 'losing' hardware after | ||||
|     * each buffer flush. | ||||
|     */ | ||||
|    intel->vtbl.lost_hardware( intel ); | ||||
| } | ||||
|   | ||||
| @@ -30,37 +30,13 @@ | ||||
|  | ||||
| #include "intel_context.h" | ||||
|  | ||||
| extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock ); | ||||
| void intelWaitIrq( struct intel_context *intel, int seq ); | ||||
| int intelEmitIrqLocked( struct intel_context *intel ); | ||||
|  | ||||
| extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 		       GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelPageFlip( const __DRIdrawablePrivate *dpriv ); | ||||
| extern void intelWaitForIdle( intelContextPtr intel ); | ||||
| extern void intelFlushBatch( intelContextPtr intel, GLboolean refill ); | ||||
| extern void intelFlushBatchLocked( intelContextPtr intel, | ||||
| 				   GLboolean ignore_cliprects, | ||||
| 				   GLboolean refill, | ||||
| 				   GLboolean allow_unlock); | ||||
| extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ); | ||||
| extern void intelFinish( GLcontext *ctx ); | ||||
| extern void intelFlush( GLcontext *ctx ); | ||||
|  | ||||
| extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size ); | ||||
| extern void intelFreeAGP( intelContextPtr intel, void *pointer ); | ||||
|  | ||||
| extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn,  | ||||
| 				      GLsizei size, GLfloat readfreq, | ||||
| 				      GLfloat writefreq, GLfloat priority ); | ||||
|  | ||||
| extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn,  | ||||
| 				 GLvoid *pointer ); | ||||
|  | ||||
| extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer ); | ||||
| extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, | ||||
| 				  GLint size ); | ||||
|  | ||||
| extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p ); | ||||
| void intel_batch_ioctl( struct intel_context *intel,  | ||||
| 			GLuint start_offset, | ||||
| 			GLuint used, | ||||
| 			GLboolean ignore_cliprects); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										296
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,296 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "bufmgr.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| static GLenum target_to_target( GLenum target ) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: | ||||
|       return GL_TEXTURE_CUBE_MAP_ARB; | ||||
|    default: | ||||
|       return target; | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel, | ||||
| 						GLenum target, | ||||
| 						GLenum internal_format, | ||||
| 						GLuint first_level, | ||||
| 						GLuint last_level, | ||||
| 						GLuint width0, | ||||
| 						GLuint height0, | ||||
| 						GLuint depth0, | ||||
| 						GLuint cpp, | ||||
| 						GLboolean compressed) | ||||
| { | ||||
|    GLboolean ok; | ||||
|    struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); | ||||
|  | ||||
|    DBG("%s target %s format %s level %d..%d\n", __FUNCTION__, | ||||
| 		_mesa_lookup_enum_by_nr(target), | ||||
| 		_mesa_lookup_enum_by_nr(internal_format), | ||||
| 		first_level, | ||||
| 		last_level); | ||||
|  | ||||
|    mt->target = target_to_target(target); | ||||
|    mt->internal_format = internal_format; | ||||
|    mt->first_level = first_level; | ||||
|    mt->last_level = last_level; | ||||
|    mt->width0 = width0; | ||||
|    mt->height0 = height0; | ||||
|    mt->depth0 = depth0; | ||||
|    mt->cpp = cpp; | ||||
|    mt->compressed = compressed; | ||||
|    mt->refcount = 1; | ||||
|  | ||||
|    switch (intel->intelScreen->deviceID) { | ||||
|    case PCI_CHIP_I945_G: | ||||
|       ok = i945_miptree_layout( mt ); | ||||
|       break; | ||||
|    case PCI_CHIP_I915_G: | ||||
|    case PCI_CHIP_I915_GM: | ||||
|       ok = i915_miptree_layout( mt ); | ||||
|       break; | ||||
|    default: | ||||
|       ok = 0; | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    if (ok) | ||||
|       mt->region = intel_region_alloc( intel,  | ||||
| 				       mt->cpp, | ||||
| 				       mt->pitch,  | ||||
| 				       mt->total_height ); | ||||
|  | ||||
|    if (!mt->region) { | ||||
|       free(mt); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return mt; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intel_miptree_reference( struct intel_mipmap_tree **dst,  | ||||
| 			      struct intel_mipmap_tree *src ) | ||||
| { | ||||
|    src->refcount++; | ||||
|    *dst = src; | ||||
| } | ||||
|  | ||||
| void intel_miptree_release( struct intel_context *intel, | ||||
| 			    struct intel_mipmap_tree **mt ) | ||||
| { | ||||
|    if (!*mt) | ||||
|       return; | ||||
|  | ||||
|    DBG("%s %d\n", __FUNCTION__, (*mt)->refcount-1); | ||||
|    if (--(*mt)->refcount == 0) { | ||||
|       intel_region_release(intel, &((*mt)->region)); | ||||
|       free(*mt); | ||||
|    } | ||||
|    *mt = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Can the image be pulled into a unified mipmap tree.  This mirrors | ||||
|  * the completeness test in a lot of ways. | ||||
|  * | ||||
|  * Not sure whether I want to pass gl_texture_image here. | ||||
|  */ | ||||
| GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,  | ||||
| 				     struct gl_texture_image *image, | ||||
| 				     GLuint face, | ||||
| 				     GLuint level ) | ||||
| { | ||||
|    DBG("%s %d %d/%d %d/%d\n", __FUNCTION__, | ||||
| 		image->Border, | ||||
| 		image->InternalFormat, mt->internal_format, | ||||
| 		image->IsCompressed, mt->compressed); | ||||
|  | ||||
|    /* Images with borders are never pulled into mipmap trees.  | ||||
|     */ | ||||
|    if (image->Border) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (image->InternalFormat != mt->internal_format || | ||||
|        image->IsCompressed != mt->compressed) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    DBG("%s: %d/%d %d/%d %d/%d\n", __FUNCTION__, | ||||
| 		image->Width, mt->offset[face][level].width, | ||||
| 		image->Height, mt->offset[face][level].height, | ||||
| 		image->Depth, mt->offset[face][level].depth); | ||||
|  | ||||
|    /* Test image dimensions against the base level image adjusted for | ||||
|     * minification.  This will also catch images not present in the | ||||
|     * tree, changed targets, etc. | ||||
|     */ | ||||
|    if (image->Width != mt->offset[face][level].width || | ||||
|        image->Height != mt->offset[face][level].height || | ||||
|        image->Depth != mt->offset[face][level].depth) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|    DBG("%s: success\n", __FUNCTION__); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt, | ||||
| 				  GLuint face, | ||||
| 				  GLuint level) | ||||
| { | ||||
|    return mt->offset[face][level].offset; | ||||
| } | ||||
|  | ||||
| GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt, | ||||
| 					GLuint face, | ||||
| 					GLuint level) | ||||
| { | ||||
|    return mt->offset[face][level].depth_image_stride; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, | ||||
| 				    GLuint face, | ||||
| 				    GLuint level, | ||||
| 				    GLuint x, GLuint y, | ||||
| 				    GLuint w, GLuint h, GLuint d) | ||||
| { | ||||
|    mt->offset[face][level].offset = (x + y * mt->pitch) * mt->cpp; | ||||
|    mt->offset[face][level].width = w; | ||||
|    mt->offset[face][level].height = h; | ||||
|    mt->offset[face][level].depth = d; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| GLubyte *intel_miptree_image_map(struct intel_context *intel,  | ||||
| 				 struct intel_mipmap_tree *mt, | ||||
| 				 GLuint face, | ||||
| 				 GLuint level, | ||||
| 				 GLuint *row_stride, | ||||
| 				 GLuint *image_stride) | ||||
| { | ||||
|    DBG("%s \n", __FUNCTION__); | ||||
|     | ||||
|    if (row_stride) | ||||
|       *row_stride = mt->pitch * mt->cpp; | ||||
|     | ||||
|    if (image_stride)  | ||||
|       *image_stride = mt->offset[face][level].depth_image_stride; | ||||
|  | ||||
|    return (intel_region_map(intel, mt->region) + | ||||
| 	   intel_miptree_image_offset(mt, face, level)); | ||||
| } | ||||
|  | ||||
| void intel_miptree_image_unmap(struct intel_context *intel,  | ||||
| 			       struct intel_mipmap_tree *mt) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    intel_region_unmap(intel, mt->region); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload data for a particular image. | ||||
|  */ | ||||
| void intel_miptree_image_data(struct intel_context *intel,  | ||||
| 			      struct intel_mipmap_tree *dst, | ||||
| 			      GLuint face, | ||||
| 			      GLuint level, | ||||
| 			      void *src,  | ||||
| 			      GLuint src_row_pitch, | ||||
| 			      GLuint src_image_pitch) | ||||
| { | ||||
|    GLuint depth = dst->offset[face][level].depth; | ||||
|    GLuint dst_offset = intel_miptree_image_offset(dst, face, level); | ||||
|    GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level); | ||||
|    GLuint i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    for (i = 0; i < depth; i++) { | ||||
|       intel_region_data(intel, | ||||
| 			dst->region, dst_offset, | ||||
| 			0, | ||||
| 			0, | ||||
| 			src, | ||||
| 			src_row_pitch, | ||||
| 			0, 0,	/* source x,y */ | ||||
| 			dst->offset[face][level].width, | ||||
| 			dst->offset[face][level].height); | ||||
|       dst_offset += dst_image_stride; | ||||
|       src += src_image_pitch; | ||||
|    } | ||||
| } | ||||
| 			   | ||||
| /* Copy mipmap image between trees | ||||
|  */ | ||||
| void intel_miptree_image_copy( struct intel_context *intel, | ||||
| 			       struct intel_mipmap_tree *dst, | ||||
| 			       GLuint face, GLuint level, | ||||
| 			       struct intel_mipmap_tree *src ) | ||||
| { | ||||
|    GLuint width = src->offset[face][level].width; | ||||
|    GLuint height = src->offset[face][level].height; | ||||
|    GLuint depth = src->offset[face][level].depth; | ||||
|    GLuint dst_offset = intel_miptree_image_offset(dst, face, level); | ||||
|    GLuint src_offset = intel_miptree_image_offset(src, face, level); | ||||
|    GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level); | ||||
|    GLuint src_image_stride = intel_miptree_depth_image_stride(src, face, level); | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0; i < depth; i++) { | ||||
|       intel_region_copy(intel, | ||||
| 			dst->region, dst_offset, | ||||
| 			0, | ||||
| 			0, | ||||
| 			src->region, src_offset, | ||||
| 			0, | ||||
| 			0, | ||||
| 			width, | ||||
| 			height); | ||||
|  | ||||
|       dst_offset += dst_image_stride; | ||||
|       src_offset += src_image_stride; | ||||
|    } | ||||
| 		      | ||||
| } | ||||
							
								
								
									
										180
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| struct intel_mipmap_offset { | ||||
|    GLuint offset;  | ||||
|    GLuint width; | ||||
|    GLuint height; | ||||
|    GLuint depth; | ||||
|    GLuint depth_image_stride; | ||||
| }; | ||||
|  | ||||
| struct intel_mipmap_tree { | ||||
|    /* Effectively the key: | ||||
|     */ | ||||
|    GLenum target; | ||||
|    GLenum internal_format; | ||||
|  | ||||
|    GLuint first_level; | ||||
|    GLuint last_level; | ||||
|  | ||||
|    GLuint width0, height0, depth0; | ||||
|    GLuint cpp; | ||||
|    GLboolean compressed; | ||||
|  | ||||
|    /* Derived from the above: | ||||
|     */    | ||||
|    GLuint pitch; | ||||
|    GLuint depth_pitch;		/* per-image on i945? */ | ||||
|    GLuint total_height; | ||||
|    struct intel_mipmap_offset offset[MAX_FACES][MAX_TEXTURE_LEVELS]; | ||||
|  | ||||
|    /* The data is held here: | ||||
|     */ | ||||
|    struct intel_region *region; | ||||
|  | ||||
|    /* These are also refcounted: | ||||
|     */ | ||||
|    GLuint refcount; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel, | ||||
| 						GLenum target, | ||||
| 						GLenum internal_format, | ||||
| 						GLuint first_level, | ||||
| 						GLuint last_level, | ||||
| 						GLuint width0, | ||||
| 						GLuint height0, | ||||
| 						GLuint depth0, | ||||
| 						GLuint cpp, | ||||
| 						GLboolean compressed); | ||||
|  | ||||
| void intel_miptree_reference( struct intel_mipmap_tree **dst, | ||||
| 			      struct intel_mipmap_tree *src ); | ||||
|  | ||||
| void intel_miptree_release( struct intel_context *intel, | ||||
| 			    struct intel_mipmap_tree **mt ); | ||||
|  | ||||
| /* Check if an image fits an existing mipmap tree layout | ||||
|  */ | ||||
| GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,  | ||||
| 				     struct gl_texture_image *image, | ||||
| 				     GLuint face, | ||||
| 				     GLuint level ); | ||||
|  | ||||
| /* Return a pointer to an image within a tree.  Return image stride as | ||||
|  * well. | ||||
|  */ | ||||
| GLubyte *intel_miptree_image_map( struct intel_context *intel, | ||||
| 				  struct intel_mipmap_tree *mt, | ||||
| 				  GLuint face, | ||||
| 				  GLuint level, | ||||
| 				  GLuint *row_stride, | ||||
| 				  GLuint *image_stride); | ||||
|  | ||||
| void intel_miptree_image_unmap( struct intel_context *intel, | ||||
| 				struct intel_mipmap_tree *mt ); | ||||
|  | ||||
|  | ||||
| /* Return the linear offset of an image relative to the start of the | ||||
|  * tree: | ||||
|  */ | ||||
| GLuint intel_miptree_image_offset( struct intel_mipmap_tree *mt, | ||||
| 				   GLuint face, | ||||
| 				   GLuint level ); | ||||
|  | ||||
| void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, | ||||
| 				    GLuint face, | ||||
| 				    GLuint level, | ||||
| 				    GLuint x, GLuint y, | ||||
| 				    GLuint w, GLuint h, GLuint d); | ||||
|  | ||||
| GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt, | ||||
| 					GLuint face, | ||||
| 					GLuint level); | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload an image into a tree | ||||
|  */ | ||||
| void intel_miptree_image_data(struct intel_context *intel,  | ||||
| 			      struct intel_mipmap_tree *dst, | ||||
| 			      GLuint face, | ||||
| 			      GLuint level, | ||||
| 			      void *src,  | ||||
| 			      GLuint src_row_pitch, | ||||
| 			      GLuint src_image_pitch); | ||||
|  | ||||
| /* Copy an image between two trees | ||||
|  */ | ||||
| void intel_miptree_image_copy( struct intel_context *intel, | ||||
| 			       struct intel_mipmap_tree *dst, | ||||
| 			       GLuint face, GLuint level, | ||||
| 			       struct intel_mipmap_tree *src ); | ||||
|  | ||||
| /* i915_mipmap_tree.c: | ||||
|  */ | ||||
| GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt ); | ||||
| GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt ); | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -1,109 +1,89 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_pixel.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 ) | ||||
| #if 0 | ||||
| struct intel_client_region *intel_pack_region( struct intel_context *intel, | ||||
| 					       const struct gl_pixelstore_attrib *pack, | ||||
| 					       GLenum format, | ||||
| 					       GLenum type, | ||||
| 					       GLvoid *pixels ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLuint cpp = intel->intelScreen->cpp; | ||||
| } | ||||
|  | ||||
|    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; | ||||
|    } | ||||
| struct intel_client_region *intel_unpack_region( struct intel_context *intel, | ||||
| 						 const struct gl_pixelstore_attrib *pack, | ||||
| 						 GLenum format, | ||||
| 						 GLenum type, | ||||
| 						 GLvoid *pixels ) | ||||
| { | ||||
|    GLint pitch = unpack->RowLength ? unpack->RowLength : width; | ||||
|    /* XXX: Need to adjust pixels pointer for unpack->skip pixels/rows | ||||
|     * offsets. | ||||
|     */ | ||||
|  | ||||
|    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__); | ||||
| } | ||||
|  | ||||
| void release_client_region( struct intel_context *intel, | ||||
| 			    struct intel_region *region ) | ||||
| { | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
| GLboolean intel_check_color_per_fragment_ops( const GLcontext *ctx ) | ||||
| { | ||||
|    return !(ctx->Color.AlphaEnabled ||  | ||||
| 	    ctx->Depth.Test || | ||||
| 	    ctx->Fog.Enabled || | ||||
| 	    ctx->Scissor.Enabled || | ||||
| 	    ctx->Stencil.Enabled || | ||||
| 	    !ctx->Color.ColorMask[0] || | ||||
| 	    !ctx->Color.ColorMask[1] || | ||||
| 	    !ctx->Color.ColorMask[2] || | ||||
| 	    !ctx->Color.ColorMask[3] || | ||||
| 	    ctx->Color.ColorLogicOpEnabled || | ||||
| 	    ctx->Texture._EnabledUnits); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| /* 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. | ||||
|  */ | ||||
| GLboolean intel_check_blit_format( struct intel_region *region, | ||||
| 				   struct intel_client_region *client_region ) | ||||
| { | ||||
|    if (region->cpp == 4  | ||||
|        client_region->cpp == 4 &&  | ||||
|        client_region->type == GL_UNSIGNED_INT_8_8_8_8_REV &&         | ||||
|        client_region->format == GL_BGRA ) { | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|     | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s: failed\n", __FUNCTION__); | ||||
|    if (region->cpp == 2 &&  | ||||
|        client_region->cpp == 2 && | ||||
|        client_region->type == GL_UNSIGNED_INT_5_6_5_REV &&  | ||||
|        client_region->format == GL_BGR ) { | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|     | ||||
|    fprintf(stderr, "%s: request doesn't match pixel format\n", __FUNCTION__); | ||||
|    return GL_FALSE; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static GLboolean | ||||
| check_color_per_fragment_ops( const GLcontext *ctx ) | ||||
|  | ||||
| GLboolean intel_clip_to_framebuffer( GLcontext *ctx, | ||||
| 				     const GLframebuffer *buffer, | ||||
| 				     GLint *x, GLint *y, | ||||
| 				     GLsizei *width, GLsizei *height ) | ||||
| { | ||||
|    int result; | ||||
|    result = (!(     ctx->Color.AlphaEnabled ||  | ||||
| 		    ctx->Depth.Test || | ||||
| 		    ctx->Fog.Enabled || | ||||
| 		    ctx->Scissor.Enabled || | ||||
| 		    ctx->Stencil.Enabled || | ||||
| 		    !ctx->Color.ColorMask[0] || | ||||
| 		    !ctx->Color.ColorMask[1] || | ||||
| 		    !ctx->Color.ColorMask[2] || | ||||
| 		    !ctx->Color.ColorMask[3] || | ||||
| 		    ctx->Color.ColorLogicOpEnabled || | ||||
| 		    ctx->Texture._EnabledUnits | ||||
|            ) && | ||||
| 	   ctx->Current.RasterPosValid); | ||||
|     | ||||
|    return result; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| clip_pixelrect( const GLcontext *ctx, | ||||
| 		const GLframebuffer *buffer, | ||||
| 		GLint *x, GLint *y, | ||||
| 		GLsizei *width, GLsizei *height, | ||||
| 		GLint *size ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    /* left clipping */ | ||||
|    if (*x < buffer->_Xmin) { | ||||
|       *width -= (buffer->_Xmin - *x); | ||||
| @@ -130,343 +110,9 @@ clip_pixelrect( const GLcontext *ctx, | ||||
|    if (*height <= 0) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    *size = ((*y + *height - 1) * intel->intelScreen->front.pitch + | ||||
| 	    (*x + *width - 1) * intel->intelScreen->cpp); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static GLboolean | ||||
| intelTryReadPixels( GLcontext *ctx, | ||||
| 		  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		  GLenum format, GLenum type, | ||||
| 		  const struct gl_pixelstore_attrib *pack, | ||||
| 		  GLvoid *pixels ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLint size = 0; | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Only accelerate reading to agp buffers. | ||||
|     */ | ||||
|    if ( !intelIsAgpMemory(intel, pixels,  | ||||
| 			pitch * height * intel->intelScreen->cpp ) ) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from | ||||
|     * blitter: | ||||
|     */ | ||||
|    if (!pack->Invert) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (!check_color(ctx, type, format, pack, pixels, size, pitch)) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    switch ( intel->intelScreen->cpp ) { | ||||
|    case 4: | ||||
|       break; | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* Although the blits go on the command buffer, need to do this and | ||||
|     * fire with lock held to guarentee cliprects and drawOffset are | ||||
|     * correct. | ||||
|     * | ||||
|     * This is an unusual situation however, as the code which flushes | ||||
|     * a full command buffer expects to be called unlocked.  As a | ||||
|     * workaround, immediately flush the buffer on aquiring the lock. | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       int src_offset = intel->drawOffset; | ||||
|       int src_pitch = intel->intelScreen->front.pitch; | ||||
|       int dst_offset = intelAgpOffsetFromVirtual( intel, pixels); | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       int i; | ||||
|  | ||||
|       if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, | ||||
| 			  &size)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s totally clipped -- nothing to do\n", | ||||
| 		    __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", | ||||
| 		 src_pitch, pitch); | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++) | ||||
|       { | ||||
| 	 GLint bx = box[i].x1; | ||||
| 	 GLint by = box[i].y1; | ||||
| 	 GLint bw = box[i].x2 - bx; | ||||
| 	 GLint bh = box[i].y2 - by; | ||||
| 	  | ||||
| 	 if (bx < x) bw -= x - bx, bx = x; | ||||
| 	 if (by < y) bh -= y - by, by = y; | ||||
| 	 if (bx + bw > x + width) bw = x + width - bx; | ||||
| 	 if (by + bh > y + height) bh = y + height - by; | ||||
| 	 if (bw <= 0) continue; | ||||
| 	 if (bh <= 0) continue; | ||||
|  | ||||
| 	 intelEmitCopyBlitLocked( intel, | ||||
| 			    intel->intelScreen->cpp, | ||||
| 			    src_pitch, src_offset, | ||||
| 			    pitch, dst_offset, | ||||
| 			    bx, by, | ||||
| 			    bx - x, by - y, | ||||
| 			    bw, bh ); | ||||
|       } | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( &intel->ctx ); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| intelReadPixels( GLcontext *ctx, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLenum format, GLenum type, | ||||
| 		 const struct gl_pixelstore_attrib *pack, | ||||
| 		 GLvoid *pixels ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,  | ||||
| 			   pixels)) | ||||
|       _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,  | ||||
| 			  pixels); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void do_draw_pix( GLcontext *ctx, | ||||
| 			 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			 GLint pitch, | ||||
| 			 const void *pixels, | ||||
| 			 GLuint dest ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|    int nbox = dPriv->numClipRects; | ||||
|    int i; | ||||
|    int size; | ||||
|    int src_offset = intelAgpOffsetFromVirtual( intel, pixels); | ||||
|    int src_pitch = pitch; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    if (ctx->DrawBuffer) | ||||
|    { | ||||
|       y -= height;			/* cope with pixel zoom */ | ||||
|     | ||||
|       if (!clip_pixelrect(ctx, ctx->DrawBuffer, | ||||
| 			  &x, &y, &width, &height, | ||||
| 			  &size)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 return; | ||||
|       } | ||||
|  | ||||
|       y = dPriv->h - y - height; 	/* convert from gl to hardware coords */ | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++ ) | ||||
|       { | ||||
| 	 GLint bx = box[i].x1; | ||||
| 	 GLint by = box[i].y1; | ||||
| 	 GLint bw = box[i].x2 - bx; | ||||
| 	 GLint bh = box[i].y2 - by; | ||||
|  | ||||
| 	 if (bx < x) bw -= x - bx, bx = x; | ||||
| 	 if (by < y) bh -= y - by, by = y; | ||||
| 	 if (bx + bw > x + width) bw = x + width - bx; | ||||
| 	 if (by + bh > y + height) bh = y + height - by; | ||||
| 	 if (bw <= 0) continue; | ||||
| 	 if (bh <= 0) continue; | ||||
|  | ||||
| 	 intelEmitCopyBlitLocked( intel, | ||||
| 			    intel->intelScreen->cpp, | ||||
| 			    src_pitch, src_offset, | ||||
| 			    intel->intelScreen->front.pitch, | ||||
| 			      intel->drawOffset, | ||||
| 			    bx - x, by - y, | ||||
| 			    bx, by, | ||||
| 			    bw, bh ); | ||||
|       } | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( &intel->ctx ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intelTryDrawPixels( GLcontext *ctx, | ||||
| 		  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		  GLenum format, GLenum type, | ||||
| 		  const struct gl_pixelstore_attrib *unpack, | ||||
| 		  const GLvoid *pixels ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLint pitch = unpack->RowLength ? unpack->RowLength : width; | ||||
|    GLuint dest; | ||||
|    GLuint cpp = intel->intelScreen->cpp; | ||||
|    GLint size = width * pitch * cpp; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    switch (format) { | ||||
|    case GL_RGB: | ||||
|    case GL_RGBA: | ||||
|    case GL_BGRA: | ||||
|       dest = intel->drawOffset; | ||||
|  | ||||
|       /* Planemask doesn't have full support in blits. | ||||
|        */ | ||||
|       if (!ctx->Color.ColorMask[RCOMP] || | ||||
| 	  !ctx->Color.ColorMask[GCOMP] || | ||||
| 	  !ctx->Color.ColorMask[BCOMP] || | ||||
| 	  !ctx->Color.ColorMask[ACOMP]) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s: planemask\n", __FUNCTION__); | ||||
| 	 return GL_FALSE;	 | ||||
|       } | ||||
|  | ||||
|       /* Can't do conversions on agp reads/draws.  | ||||
|        */ | ||||
|       if ( !intelIsAgpMemory( intel, pixels, size ) ) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s: not agp memory\n", __FUNCTION__); | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       if (!check_color_per_fragment_ops(ctx)) { | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       if (ctx->Pixel.ZoomX != 1.0F || | ||||
| 	  ctx->Pixel.ZoomY != -1.0F) | ||||
| 	 return GL_FALSE; | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if ( intelIsAgpMemory(intel, pixels, size) ) | ||||
|    { | ||||
|       do_draw_pix( ctx, x, y, width, height, pitch, pixels, | ||||
| 		   dest ); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|    else if (0) | ||||
|    { | ||||
|       /* Pixels is in regular memory -- get dma buffers and perform | ||||
|        * upload through them.  No point doing this for regular uploads | ||||
|        * but once we remove some of the restrictions above (colormask, | ||||
|        * pixelformat conversion, zoom?, etc), this could be a win. | ||||
|        */ | ||||
|    } | ||||
|    else | ||||
|       return GL_FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| intelDrawPixels( GLcontext *ctx, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLenum format, GLenum type, | ||||
| 		 const struct gl_pixelstore_attrib *unpack, | ||||
| 		 const GLvoid *pixels ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!intelTryDrawPixels( ctx, x, y, width, height, format, type, | ||||
| 			  unpack, pixels )) | ||||
|       _swrast_DrawPixels( ctx, x, y, width, height, format, type, | ||||
| 			  unpack, pixels ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Implement glCopyPixels for the front color buffer (or back buffer Pixmap) | ||||
|  * for the color buffer.  Don't support zooming, pixel transfer, etc. | ||||
|  * We do support copying from one window to another, ala glXMakeCurrentRead. | ||||
|  */ | ||||
| static void | ||||
| intelCopyPixels( GLcontext *ctx, | ||||
| 		 GLint srcx, GLint srcy, GLsizei width, GLsizei height, | ||||
| 		 GLint destx, GLint desty, GLenum type ) | ||||
| { | ||||
| #if 0 | ||||
|    const XMesaContext xmesa = XMESA_CONTEXT(ctx); | ||||
|    const SWcontext *swrast = SWRAST_CONTEXT( ctx ); | ||||
|    XMesaDisplay *dpy = xmesa->xm_visual->display; | ||||
|    const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer; | ||||
|    const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer; | ||||
|    const XMesaGC gc = xmesa->xm_draw_buffer->gc; | ||||
|  | ||||
|    ASSERT(dpy); | ||||
|    ASSERT(gc); | ||||
|  | ||||
|    if (drawBuffer &&  /* buffer != 0 means it's a Window or Pixmap */ | ||||
|        readBuffer && | ||||
|        type == GL_COLOR && | ||||
|        (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */ | ||||
|        ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */ | ||||
|        ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */ | ||||
|        ctx->Pixel.ZoomY == 1.0) { | ||||
|       /* Note: we don't do any special clipping work here.  We could, | ||||
|        * but X will do it for us. | ||||
|        */ | ||||
|       srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1; | ||||
|       desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1; | ||||
|       XCopyArea(dpy, readBuffer, drawBuffer, gc, | ||||
|                 srcx, srcy, width, height, destx, desty); | ||||
|    } | ||||
| #else | ||||
|    _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type ); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -476,14 +122,16 @@ void intelInitPixelFuncs( struct dd_function_table *functions ) | ||||
|     */ | ||||
|    functions->Accum = _swrast_Accum; | ||||
|    functions->Bitmap = _swrast_Bitmap; | ||||
|    functions->CopyPixels = intelCopyPixels; | ||||
|  | ||||
|    if (!getenv("INTEL_NO_BLITS")) { | ||||
|    if (getenv("INTEL_NO_BLITS") == 0) { | ||||
|       functions->CopyPixels = intelCopyPixels; | ||||
|       functions->ReadPixels = intelReadPixels;   | ||||
|       functions->DrawPixels = intelDrawPixels;  | ||||
|    } | ||||
|    else { | ||||
|       functions->CopyPixels = _swrast_CopyPixels; | ||||
|       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_color_per_fragment_ops( const GLcontext *ctx ); | ||||
|  | ||||
| GLboolean intel_clip_to_framebuffer( GLcontext *ctx, | ||||
| 				     const GLframebuffer *buffer, | ||||
| 				     GLint *x, GLint *y, | ||||
| 				     GLsizei *width, GLsizei *height ); | ||||
|  | ||||
| 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 | ||||
							
								
								
									
										196
									
								
								src/mesa/drivers/dri/i915/intel_pixel_copy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								src/mesa/drivers/dri/i915/intel_pixel_copy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,196 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "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_regions.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean do_texture_copypixels( GLcontext *ctx, | ||||
| 					GLint srcx, GLint srcy,  | ||||
| 					GLsizei width, GLsizei height, | ||||
| 					GLint dstx, GLint dsty,  | ||||
| 					GLenum type ) | ||||
| { | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 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 = NULL; | ||||
|  | ||||
|    /* Copypixels can be more than a straight copy.  Ensure all the | ||||
|     * extra operations are disabled: | ||||
|     */ | ||||
|    if (!intel_check_color_per_fragment_ops(ctx) || | ||||
|        ctx->Pixel.ZoomX != 1.0F ||  | ||||
|        ctx->Pixel.ZoomY != 1.0F) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    switch (type) { | ||||
|    case GL_COLOR: | ||||
|       src = intel_readbuf_region( intel ); | ||||
|       break; | ||||
|    case GL_DEPTH: | ||||
|       /* Don't think this is really possible execpt at 16bpp, when we have no stencil. | ||||
|        */ | ||||
|       if (intel->intelScreen->cpp == 2) | ||||
| 	 src = intel->depth_region; | ||||
|       break; | ||||
|    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? | ||||
|        */ | ||||
|       src = intel->depth_region; | ||||
|       break; | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    if (!src || !dst)  | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       GLint nbox = dPriv->numClipRects; | ||||
|       GLint delta_x = srcx - dstx; | ||||
|       GLint delta_y = srcy - dsty; | ||||
|       GLuint i; | ||||
|  | ||||
|       if (!intel_clip_to_framebuffer(ctx, ctx->DrawBuffer, &dstx, &dsty, &width, &height))  | ||||
| 	 goto out; | ||||
|  | ||||
|       /* Update source for clipped dest.  Need to also clip the source rect. | ||||
|        */ | ||||
|       srcx = dstx + delta_x; | ||||
|       srcy = dsty + delta_y; | ||||
|  | ||||
|       if (!intel_clip_to_framebuffer(ctx, ctx->DrawBuffer, &srcx, &srcy, &width, &height))  | ||||
| 	 goto out; | ||||
|  | ||||
|       /* Update dest for clipped source: | ||||
|        */ | ||||
|       dstx = srcx - delta_x; | ||||
|       dsty = srcy - delta_y; | ||||
|  | ||||
|  | ||||
|       srcy = dPriv->h - srcy - height; 	/* convert from gl to hardware coords */ | ||||
|       dsty = dPriv->h - dsty - height; 	/* convert from gl to hardware coords */ | ||||
|       srcx += dPriv->x; | ||||
|       dstx += dPriv->x; | ||||
|       srcy += dPriv->y; | ||||
|       dsty += dPriv->y; | ||||
|  | ||||
|  | ||||
|       /* 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++ ) | ||||
|       { | ||||
| 	 GLint bx = box[i].x1; | ||||
| 	 GLint by = box[i].y1; | ||||
| 	 GLint bw = box[i].x2 - bx; | ||||
| 	 GLint bh = box[i].y2 - by; | ||||
|  | ||||
| 	 if (bx < dstx) bw -= dstx - bx, bx = dstx; | ||||
| 	 if (by < dsty) bh -= dsty - by, by = dsty; | ||||
| 	 if (bx + bw > dstx + width) bw = dstx + width - bx; | ||||
| 	 if (by + bh > dsty + height) bh = dsty + height - by; | ||||
| 	 if (bw <= 0) continue; | ||||
| 	 if (bh <= 0) continue; | ||||
|  | ||||
| 	 intelEmitCopyBlit( intel, | ||||
| 			    dst->cpp, | ||||
| 			    src->pitch, src->buffer, 0, | ||||
| 			    dst->pitch, dst->buffer, 0, | ||||
| 			    bx + delta_x, by - delta_y, /* srcx, srcy */ | ||||
| 			    bx, by, /* dstx, dsty */ | ||||
| 			    bw, bh ); | ||||
|       } | ||||
|    } | ||||
|  out: | ||||
|    intel_batchbuffer_flush( intel->batch ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelCopyPixels( GLcontext *ctx, | ||||
| 		      GLint srcx, GLint srcy,  | ||||
| 		      GLsizei width, GLsizei height, | ||||
| 		      GLint destx, GLint desty,  | ||||
| 		      GLenum type ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type)) | ||||
|       return; | ||||
|  | ||||
|    if (do_texture_copypixels( ctx, srcx, srcy, width, height, destx, desty, type)) | ||||
|       return; | ||||
|  | ||||
|    _mesa_printf("fallback to _swrast_CopyPixels\n"); | ||||
|    _swrast_CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										242
									
								
								src/mesa/drivers/dri/i915/intel_pixel_draw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								src/mesa/drivers/dri/i915/intel_pixel_draw.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,242 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "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_regions.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean do_texture_draw_pixels( struct intel_context *intel, | ||||
| 					 GLint x, GLint y,  | ||||
| 					 GLsizei width, GLsizei height, | ||||
| 					 GLenum format, GLenum type, | ||||
| 					 const struct gl_pixelstore_attrib *unpack, | ||||
| 					 const GLvoid *pixels ) | ||||
| { | ||||
| #if 0 | ||||
|    GLint pitch = unpack->RowLength ? unpack->RowLength : width; | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    int textureFormat; | ||||
|    GLenum glTextureFormat; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|  | ||||
|    if (	ctx->_ImageTransferState || | ||||
| 	unpack->SwapBytes || | ||||
| 	unpack->LsbFirst || | ||||
| 	ctx->Texture._EnabledUnits || | ||||
| 	ctx->FragmentProgram._Enabled) { | ||||
|       fprintf(stderr, "%s: cannot use texture path\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|     | ||||
|    glGenTextures(); | ||||
|    glTextureImage2D(); | ||||
|    glBindTexture(); | ||||
|    glEnable(GL_TEXTURE_RECTANGLE_NV); | ||||
|     | ||||
|    glDisable(GL_POLYGON_STIPPLE); | ||||
|    glDisable(GL_CULL); | ||||
|  | ||||
|    _mesa_install_vp_passthrough(ctx); | ||||
|    _mesa_push_current(ctx); | ||||
|     | ||||
|    if (intel->Fallback) | ||||
|       goto Fail; | ||||
|  | ||||
|    glBegin(GL_QUADS); | ||||
|    glVertex3f(); | ||||
|    glTexCoord2f(); | ||||
|    glVertex3f(); | ||||
|    glTexCoord2f(); | ||||
|    glVertex3f(); | ||||
|    glTexCoord2f(); | ||||
|    glVertex3f(); | ||||
|    glTexCoord2f(); | ||||
|    glEnd(); | ||||
|    glFinish();  | ||||
|     | ||||
|    ASSIGN_4V(ctx->Current.Atrrib[VERT_ATTRIB_TEX0], tex0); | ||||
|  | ||||
|  fail: | ||||
|    glDisable(GL_TEXTURE_RECTANGLE_NV); | ||||
|    glDeleteTextures(); | ||||
|    glBindTexture(old); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* 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. | ||||
|  */ | ||||
| static GLboolean do_blit_draw_pixels( struct intel_context *intel, | ||||
| 				      GLint x, GLint y,  | ||||
| 				      GLsizei width, GLsizei height, | ||||
| 				      GLenum format, GLenum type, | ||||
| 				      const struct gl_pixelstore_attrib *unpack, | ||||
| 				      const GLvoid *pixels ) | ||||
| { | ||||
| #if 0 | ||||
|    struct intel_region *dest = intel_drawbuf_region(intel); | ||||
|    struct intel_region *src = NULL; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!src || !dest) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (!intel_check_blit_format(dest, src))  | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (!intel_check_blit_fragment_ops(ctx))  | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (ctx->Pixel.ZoomX != 1.0F) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (ctx->Pixel.ZoomY == -1.0F) | ||||
|       y -= height;			 | ||||
|    else if (ctx->Pixel.ZoomY == 1.0F) { | ||||
|       src_pitch = -src_pitch; | ||||
|       src_y += height; | ||||
|    } | ||||
|    else | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|    if (unpack->BufferObj->Name) { | ||||
|       src = intel_bufferobj_unpack_region(intel, unpack,  | ||||
| 					  width, height,  | ||||
| 					  format, type,  | ||||
| 					  unpack->BufferObj); | ||||
|       src_offset = (unsigned long)pixels; | ||||
|    } | ||||
|    else { | ||||
|       src = intel_client_unpack_region(intel, unpack,  | ||||
| 				       width, height,  | ||||
| 				       format, type, pixels); | ||||
|       src_offset = 0; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t rect; | ||||
|       int i; | ||||
|        | ||||
|       y = dPriv->h - y - height; 	/* convert from gl to hardware coords */ | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++ ) | ||||
|       { | ||||
| 	 if (!intel_intersect_cliprects(rect, db_rect, &box[i])) | ||||
| 	    continue; | ||||
|  | ||||
| 	 intelEmitCopyBlit( intel, | ||||
| 			    intel->intelScreen->cpp, | ||||
| 			    src->pitch, src->buffer, src_offset, | ||||
| 			    dst->pitch, dst->buffer, 0, | ||||
| 			    rect->x1 - x,  | ||||
| 			    rect->y1 - y, | ||||
| 			    rect->x1,  | ||||
| 			    rect->y1, | ||||
| 			    rect->x2 - rect->x1, | ||||
| 			    rect->y2 - rect->y1 ); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intel_release_unpack_region( intel, src ); | ||||
|    fence = intel_batchbuffer_flush( intel->batch ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|    bmWaitFence(intel->bm, fence); | ||||
|    intel_region_release(intel, &src); | ||||
| #endif | ||||
|     | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| 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 ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (do_texture_draw_pixels( intel, x, y, width, height, format, type, | ||||
| 			       unpack, pixels )) | ||||
|       return; | ||||
|  | ||||
|    if (do_blit_draw_pixels( intel, x, y, width, height, format, type, | ||||
| 			    unpack, pixels )) | ||||
|       return; | ||||
|  | ||||
|    _swrast_DrawPixels( ctx, x, y, width, height, format, type, | ||||
| 		       unpack, pixels ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										249
									
								
								src/mesa/drivers/dri/i915/intel_pixel_read.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/mesa/drivers/dri/i915/intel_pixel_read.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "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_regions.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 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) { | ||||
|       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)) | ||||
|    { | ||||
|       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 ); | ||||
|    intel->vtbl.install_meta_state(intel); | ||||
|    intel->vtbl.meta_no_depth_stencil_write(intel); | ||||
|  | ||||
|    if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       SET_STATE(i830, state); | ||||
|       fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|  | ||||
|    y = dPriv->h - y - height; | ||||
|    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 ) | ||||
| { | ||||
| #if 0 | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|    struct intel_region *src = intel_readbuf_region(intel); | ||||
|    struct intel_client_region *dst = intel_client_pack_region(intel, | ||||
| 							      pack,  | ||||
| 							      pixels); | ||||
|  | ||||
|    if (ctx->_ImageTransferState || | ||||
|        pack->SwapBytes || | ||||
|        pack->LsbFirst) { | ||||
|       fprintf(stderr, "%s: failed 1\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from | ||||
|     * blitter: | ||||
|     */ | ||||
|    if (!pack->Invert) { | ||||
|       fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (!intel_check_blit_format(src, format, type)) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    /* 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 ); | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       int i; | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", | ||||
| 		 src_pitch, pitch); | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++) | ||||
|       { | ||||
| 	 GLint bx = box[i].x1; | ||||
| 	 GLint by = box[i].y1; | ||||
| 	 GLint bw = box[i].x2 - bx; | ||||
| 	 GLint bh = box[i].y2 - by; | ||||
| 	  | ||||
| 	 if (bx < x) bw -= x - bx, bx = x; | ||||
| 	 if (by < y) bh -= y - by, by = y; | ||||
| 	 if (bx + bw > x + width) bw = x + width - bx; | ||||
| 	 if (by + bh > y + height) bh = y + height - by; | ||||
| 	 if (bw <= 0) continue; | ||||
| 	 if (bh <= 0) continue; | ||||
|  | ||||
| 	 intelEmitCopyBlit( intel, | ||||
| 			    src->cpp, | ||||
| 			    src->pitch, src->buffer, 0, | ||||
| 			    dst->pitch, dst->buffer, 0, | ||||
| 			    bx, by, | ||||
| 			    bx - x, by - y, | ||||
| 			    bw, bh ); | ||||
|       } | ||||
|  | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|       intel_client_region_release(intel, dst); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    return GL_TRUE; | ||||
| #endif | ||||
|  | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
| 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; | ||||
|  | ||||
|    _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels); | ||||
| } | ||||
|  | ||||
							
								
								
									
										269
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,269 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "bufmgr.h" | ||||
|  | ||||
| /* XXX: Thread safety? | ||||
|  */ | ||||
| GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    if (!region->map_refcount++) { | ||||
|       region->map = bmMapBuffer(intel->bm, region->buffer, 0); | ||||
|    } | ||||
|  | ||||
|    return region->map; | ||||
| } | ||||
|  | ||||
| void intel_region_unmap(struct intel_context *intel,  | ||||
| 			struct intel_region *region) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    if (!--region->map_refcount) { | ||||
|       bmUnmapBuffer(intel->bm, region->buffer); | ||||
|       region->map = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct intel_region *intel_region_alloc( struct intel_context *intel,  | ||||
| 					 GLuint cpp, | ||||
| 					 GLuint pitch,  | ||||
| 					 GLuint height ) | ||||
| { | ||||
|    struct intel_region *region = calloc(sizeof(*region), 1); | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    region->cpp = cpp; | ||||
|    region->pitch = pitch; | ||||
|    region->height = height; 	/* needed? */ | ||||
|    region->refcount = 1; | ||||
|  | ||||
|    bmGenBuffers(intel->bm, 1, ®ion->buffer); | ||||
|    bmBufferData(intel->bm, region->buffer, pitch * cpp * height, NULL, 0); | ||||
|  | ||||
|    return region; | ||||
| } | ||||
|  | ||||
| void intel_region_reference( struct intel_region **dst, | ||||
| 			     struct intel_region *src) | ||||
| { | ||||
|    src->refcount++; | ||||
|    assert(*dst == NULL); | ||||
|    *dst = src; | ||||
| } | ||||
|  | ||||
| void intel_region_release( struct intel_context *intel, | ||||
| 			   struct intel_region **region ) | ||||
| { | ||||
|    if (!*region) | ||||
|       return; | ||||
|  | ||||
|    DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1); | ||||
|     | ||||
|    if (--(*region)->refcount == 0) { | ||||
|       assert((*region)->map_refcount == 0); | ||||
|       bmDeleteBuffers(intel->bm, 1, &(*region)->buffer); | ||||
|       free(*region); | ||||
|    } | ||||
|    *region = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct intel_region *intel_region_create_static( struct intel_context *intel,  | ||||
| 						 GLuint mem_type, | ||||
| 						 GLuint offset, | ||||
| 						 void *virtual, | ||||
| 						 GLuint cpp, | ||||
| 						 GLuint pitch,  | ||||
| 						 GLuint height ) | ||||
| { | ||||
|    struct intel_region *region = calloc(sizeof(*region), 1); | ||||
|    GLuint size = cpp * pitch * height; | ||||
|    GLint pool; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    region->cpp = cpp; | ||||
|    region->pitch = pitch; | ||||
|    region->height = height; 	/* needed? */ | ||||
|    region->refcount = 1; | ||||
|  | ||||
|    /* Recipe for creating a static buffer - create a static pool with | ||||
|     * the right offset and size, generate a buffer and use a special | ||||
|     * call to bind it to all of the memory in that pool. | ||||
|     */ | ||||
|    pool = bmInitPool(intel->bm, offset, virtual, size,  | ||||
| 		     (BM_MEM_AGP | | ||||
| 		      BM_NO_UPLOAD |  | ||||
| 		      BM_NO_EVICT |  | ||||
| 		      BM_NO_MOVE)); | ||||
|    if (pool < 0) { | ||||
|       _mesa_printf("bmInitPool failed for static region\n"); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    bmGenBuffers(intel->bm, 1, ®ion->buffer); | ||||
|    bmBufferStatic(intel->bm, region->buffer, size, pool); | ||||
|  | ||||
|    return region; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void _mesa_copy_rect( GLubyte *dst, | ||||
| 			     GLuint cpp, | ||||
| 			     GLuint dst_pitch, | ||||
| 			     GLuint dst_x,  | ||||
| 			     GLuint dst_y, | ||||
| 			     GLuint width, | ||||
| 			     GLuint height, | ||||
| 			     GLubyte *src, | ||||
| 			     GLuint src_pitch, | ||||
| 			     GLuint src_x, | ||||
| 			     GLuint src_y ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|    src_pitch *= cpp; | ||||
|    dst += dst_x * cpp; | ||||
|    src += src_x * cpp; | ||||
|    dst += dst_y * dst_pitch; | ||||
|    src += src_y * dst_pitch; | ||||
|    width *= cpp; | ||||
|  | ||||
|    if (width == dst_pitch &&  | ||||
|        width == src_pitch) | ||||
|       memcpy(dst, src, height * width); | ||||
|    else { | ||||
|       for (i = 0; i < height; i++) { | ||||
| 	 memcpy(dst, src, width); | ||||
| 	 dst += dst_pitch; | ||||
| 	 src += src_pitch; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Upload data to a rectangular sub-region.  Lots of choices how to do this: | ||||
|  * | ||||
|  * - memcpy by span to current destination | ||||
|  * - upload data as new buffer and blit | ||||
|  * | ||||
|  * Currently always memcpy. | ||||
|  */ | ||||
| void intel_region_data(struct intel_context *intel,  | ||||
| 		       struct intel_region *dst, | ||||
| 		       GLuint dst_offset, | ||||
| 		       GLuint dstx, GLuint dsty, | ||||
| 		       void *src, GLuint src_pitch, | ||||
| 		       GLuint srcx, GLuint srcy, | ||||
| 		       GLuint width, GLuint height) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|     | ||||
|    _mesa_copy_rect(intel_region_map(intel, dst) + dst_offset, | ||||
| 		   dst->cpp, | ||||
| 		   dst->pitch, | ||||
| 		   dstx, dsty, | ||||
| 		   width, height, | ||||
| 		   src, | ||||
| 		   src_pitch, | ||||
| 		   srcx, srcy);       | ||||
|  | ||||
|    intel_region_unmap(intel, dst); | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|     | ||||
| } | ||||
| 			   | ||||
| /* Copy rectangular sub-regions. Need better logic about when to | ||||
|  * push buffers into AGP - will currently do so whenever possible. | ||||
|  */ | ||||
| void intel_region_copy( struct intel_context *intel, | ||||
| 			struct intel_region *dst, | ||||
| 			GLuint dst_offset, | ||||
| 			GLuint dstx, GLuint dsty, | ||||
| 			struct intel_region *src, | ||||
| 			GLuint src_offset, | ||||
| 			GLuint srcx, GLuint srcy, | ||||
| 			GLuint width, GLuint height ) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(src->cpp == dst->cpp); | ||||
|  | ||||
|    intelEmitCopyBlit(intel, | ||||
| 		     dst->cpp, | ||||
| 		     src->pitch, src->buffer, src_offset, | ||||
| 		     dst->pitch, dst->buffer, dst_offset,  | ||||
| 		     srcx, srcy, | ||||
| 		     dstx, dsty, | ||||
| 		     width, height); | ||||
| } | ||||
|  | ||||
| /* Fill a rectangular sub-region.  Need better logic about when to | ||||
|  * push buffers into AGP - will currently do so whenever possible. | ||||
|  */ | ||||
| void intel_region_fill( struct intel_context *intel, | ||||
| 			struct intel_region *dst, | ||||
| 			GLuint dst_offset, | ||||
| 			GLuint dstx, GLuint dsty, | ||||
| 			GLuint width, GLuint height, | ||||
| 			GLuint color ) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    intelEmitFillBlit(intel, | ||||
| 		     dst->cpp, | ||||
| 		     dst->pitch, dst->buffer, dst_offset,  | ||||
| 		     dstx, dsty, | ||||
| 		     width, height, | ||||
| 		     color ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										115
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "bufmgr.h"		/* for DBG! */ | ||||
| struct intel_context; | ||||
|  | ||||
| /* A layer on top of the bufmgr buffers that adds a few useful things: | ||||
|  * | ||||
|  * - Refcounting for local buffer references. | ||||
|  * - Refcounting for buffer maps | ||||
|  * - Buffer dimensions - pitch and height. | ||||
|  * - Blitter commands for copying 2D regions between buffers. | ||||
|  */ | ||||
| struct intel_region { | ||||
|    GLuint buffer; | ||||
|    GLuint refcount; | ||||
|    GLuint cpp; | ||||
|    GLuint pitch; | ||||
|    GLuint height; | ||||
|    GLubyte *map; | ||||
|    GLuint map_refcount; | ||||
| }; | ||||
|  | ||||
| /* Allocate a refcounted region.  Pointers to regions should only be | ||||
|  * copied by calling intel_reference_region(). | ||||
|  */ | ||||
| struct intel_region *intel_region_alloc( struct intel_context *intel, | ||||
| 					 GLuint cpp, | ||||
| 					 GLuint pitch,  | ||||
| 					 GLuint height ); | ||||
|  | ||||
| void intel_region_reference( struct intel_region **dst,  | ||||
| 			     struct intel_region *src ); | ||||
|  | ||||
| void intel_region_release(struct intel_context *intel, | ||||
| 			  struct intel_region **ib ); | ||||
|  | ||||
|  | ||||
| struct intel_region *intel_region_create_static( struct intel_context *intel, | ||||
| 						 GLuint mem_type, | ||||
| 						 GLuint offset, | ||||
| 						 void *virtual, | ||||
| 						 GLuint cpp, | ||||
| 						 GLuint pitch, | ||||
| 						 GLuint height ); | ||||
|  | ||||
| /* Map/unmap regions.  This is refcounted also:  | ||||
|  */ | ||||
| GLubyte *intel_region_map(struct intel_context *intel,  | ||||
| 		       struct intel_region *ib); | ||||
|  | ||||
| void intel_region_unmap(struct intel_context *intel, | ||||
| 			struct intel_region *ib); | ||||
|  | ||||
|  | ||||
| /* Upload data to a rectangular sub-region | ||||
|  */ | ||||
| void intel_region_data(struct intel_context *intel,  | ||||
| 		       struct intel_region *dest, | ||||
| 		       GLuint dest_offset, | ||||
| 		       GLuint destx, GLuint desty, | ||||
| 		       void *src, GLuint src_stride, | ||||
| 		       GLuint srcx, GLuint srcy, | ||||
| 		       GLuint width, GLuint height); | ||||
| 			   | ||||
| /* Copy rectangular sub-regions | ||||
|  */ | ||||
| void intel_region_copy( struct intel_context *intel, | ||||
| 			struct intel_region *dest, | ||||
| 			GLuint dest_offset, | ||||
| 			GLuint destx, GLuint desty, | ||||
| 			struct intel_region *src, | ||||
| 			GLuint src_offset, | ||||
| 			GLuint srcx, GLuint srcy, | ||||
| 			GLuint width, GLuint height ); | ||||
|  | ||||
| /* Fill a rectangular sub-region | ||||
|  */ | ||||
| void intel_region_fill( struct intel_context *intel, | ||||
| 			struct intel_region *dest, | ||||
| 			GLuint dest_offset, | ||||
| 			GLuint destx, GLuint desty, | ||||
| 			GLuint width, GLuint height, | ||||
| 			GLuint color ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -106,7 +106,7 @@ static const int scale_prim[GL_POLYGON+1] = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| static void intelDmaPrimitive( intelContextPtr intel, GLenum prim ) | ||||
| static void intelDmaPrimitive( struct intel_context *intel, GLenum prim ) | ||||
| { | ||||
|    if (0) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|    INTEL_FIREVERTICES(intel); | ||||
| @@ -115,7 +115,7 @@ static void intelDmaPrimitive( intelContextPtr intel, GLenum prim ) | ||||
| } | ||||
|  | ||||
|  | ||||
| #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 );		\ | ||||
| @@ -142,7 +142,7 @@ do {						\ | ||||
|  | ||||
| /* Heuristic to choose between the two render paths:   | ||||
|  */ | ||||
| static GLboolean choose_render( intelContextPtr intel, | ||||
| static GLboolean choose_render( struct intel_context *intel, | ||||
| 				struct vertex_buffer *VB ) | ||||
| { | ||||
|    int vertsz = intel->vertex_size; | ||||
| @@ -194,11 +194,15 @@ static GLboolean choose_render( intelContextPtr intel, | ||||
| static GLboolean intel_run_render( GLcontext *ctx,  | ||||
| 				 struct tnl_pipeline_stage *stage ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|    GLuint i; | ||||
|  | ||||
|    /* disabled | ||||
|     */ | ||||
|    return GL_TRUE; | ||||
|  | ||||
|    /* Don't handle clipping or indexed vertices. | ||||
|     */ | ||||
|    if (intel->RenderIndex != 0 ||  | ||||
|   | ||||
| @@ -104,14 +104,14 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|    intelScreen->cpp = gDRIPriv->cpp; | ||||
| 			  | ||||
|    switch (gDRIPriv->bitsPerPixel) { | ||||
|    case 15: intelScreen->fbFormat = DV_PF_555; break; | ||||
|    case 16: intelScreen->fbFormat = DV_PF_565; break; | ||||
|    case 32: intelScreen->fbFormat = DV_PF_8888; break; | ||||
|    default: exit(1); break; | ||||
|    } | ||||
|  | ||||
|    intelScreen->front.pitch = gDRIPriv->fbStride; | ||||
|    intelScreen->front.offset = gDRIPriv->fbOffset; | ||||
|    intelScreen->front.map = sPriv->pFB; | ||||
|    intelScreen->front.map = (char *)sPriv->pFB; | ||||
|  | ||||
|    intelScreen->back.offset = gDRIPriv->backOffset; | ||||
|    intelScreen->back.pitch = gDRIPriv->backPitch; | ||||
| @@ -166,7 +166,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
| 			  | ||||
|    intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; | ||||
|     | ||||
|    if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); | ||||
|    if (1) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); | ||||
|  | ||||
|    intelScreen->drmMinor = sPriv->drmMinor; | ||||
|  | ||||
| @@ -202,13 +202,8 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|  | ||||
|    if (glx_enable_extension != NULL) { | ||||
|       (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" ); | ||||
|       (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" ); | ||||
|    } | ||||
|     | ||||
|    sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA; | ||||
|    sPriv->psc->freeMemory     = (void *) intelFreeMemoryMESA; | ||||
|    sPriv->psc->memoryOffset   = (void *) intelGetMemoryOffsetMESA; | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
| 		 | ||||
| @@ -338,12 +333,16 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, | ||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; | ||||
|  | ||||
|    switch (intelScreen->deviceID) { | ||||
| #if 0 | ||||
|       /* 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 ); | ||||
| #endif | ||||
|  | ||||
|    case PCI_CHIP_I915_G: | ||||
|    case PCI_CHIP_I915_GM: | ||||
|   | ||||
| @@ -32,6 +32,9 @@ | ||||
| #include "dri_util.h" | ||||
| #include "xmlconfig.h" | ||||
|  | ||||
| /* XXX: change name or eliminate to avoid conflict with "struct | ||||
|  * intel_region"!!! | ||||
|  */ | ||||
| typedef struct { | ||||
|    drm_handle_t handle; | ||||
|    drmSize size;        /* region size in bytes */ | ||||
|   | ||||
| @@ -31,16 +31,18 @@ | ||||
| #include "colormac.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" | ||||
|  | ||||
|  | ||||
| #undef DBG | ||||
| #define DBG 0 | ||||
|  | ||||
| #define LOCAL_VARS						\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    struct intel_context *intel = intel_context(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch * drb->cpp;			\ | ||||
| @@ -52,7 +54,7 @@ | ||||
|    (void) buf; (void) p | ||||
|  | ||||
| #define LOCAL_DEPTH_VARS					\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    struct intel_context *intel = intel_context(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch * drb->cpp;			\ | ||||
| @@ -93,27 +95,6 @@ do {								\ | ||||
| #define TAG(x) intel##x##_565 | ||||
| #include "spantmp.h" | ||||
|  | ||||
| /* 15 bit, 555 rgb 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 WRITE_PIXEL( _x, _y, p )  \ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch)  = p | ||||
|  | ||||
| #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" | ||||
|  | ||||
| /* 16 bit depthbuffer functions. | ||||
|  */ | ||||
| @@ -130,7 +111,7 @@ do {								\ | ||||
|  | ||||
| #undef LOCAL_VARS | ||||
| #define LOCAL_VARS						\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    struct intel_context *intel = intel_context(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch * drb->cpp;			\ | ||||
| @@ -204,17 +185,47 @@ do {								\ | ||||
|  */ | ||||
| void intelSpanRenderStart( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint i; | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    intelWaitForIdle(intel); | ||||
|  | ||||
|    /* Just map the framebuffer and all textures.  Bufmgr code will | ||||
|     * take care of waiting on the necessary fences: | ||||
|     */ | ||||
|    intel_region_map(intel, intel->front_region); | ||||
|    intel_region_map(intel, intel->back_region); | ||||
|    intel_region_map(intel, intel->depth_region); | ||||
|  | ||||
|    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)); | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelSpanRenderFinish( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    GLuint i; | ||||
|  | ||||
|    _swrast_flush( ctx ); | ||||
|  | ||||
|    /* Now unmap the framebuffer: | ||||
|     */ | ||||
|    intel_region_unmap(intel, intel->front_region); | ||||
|    intel_region_unmap(intel, intel->back_region); | ||||
|    intel_region_unmap(intel, intel->depth_region); | ||||
|  | ||||
|    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)); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
| @@ -233,10 +244,7 @@ void | ||||
| intelSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) | ||||
| { | ||||
|    if (drb->Base.InternalFormat == GL_RGBA) { | ||||
|       if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) { | ||||
|          intelInitPointers_555(&drb->Base); | ||||
|       } | ||||
|       else if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { | ||||
|       if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { | ||||
|          intelInitPointers_565(&drb->Base); | ||||
|       } | ||||
|       else { | ||||
|   | ||||
| @@ -30,10 +30,12 @@ | ||||
| #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_regions.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| int intel_translate_compare_func( GLenum func ) | ||||
| @@ -164,70 +166,26 @@ int intel_translate_logic_op( GLenum opcode ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelDrawBuffer(GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    int front = 0; | ||||
|   | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|  | ||||
|    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) { | ||||
|    case BUFFER_BIT_FRONT_LEFT: | ||||
|       front = 1; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    case BUFFER_BIT_BACK_LEFT: | ||||
|       front = 0; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    default: | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE ); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if ( intel->sarea->pf_current_page == 1 )  | ||||
|       front ^= 1; | ||||
|     | ||||
|    intelSetFrontClipRects( intel ); | ||||
|  | ||||
|    if (front) { | ||||
|       intel->drawOffset = screen->front.offset; | ||||
|    } else { | ||||
|       intel->drawOffset = screen->back.offset; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.set_draw_offset( intel, intel->drawOffset ); | ||||
| } | ||||
|  | ||||
| static void intelReadBuffer( GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelClearColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    GLubyte clear_chan[4]; | ||||
|  | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]); | ||||
|    UNCLAMPED_FLOAT_TO_RGBA_CHAN(clear_chan, color); | ||||
|  | ||||
|    intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat, | ||||
| 				       intel->clear_red,  | ||||
| 				       intel->clear_green,  | ||||
| 				       intel->clear_blue,  | ||||
| 				       intel->clear_alpha); | ||||
| 				       clear_chan[0],  | ||||
| 				       clear_chan[1],  | ||||
| 				       clear_chan[2],  | ||||
| 				       clear_chan[3]); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelCalcViewport( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    const GLfloat *v = ctx->Viewport._WindowMap.m; | ||||
|    GLfloat *m = intel->ViewportMatrix.m; | ||||
|    GLint h = 0; | ||||
| @@ -263,18 +221,111 @@ static void intelDepthRange( GLcontext *ctx, | ||||
|  */ | ||||
| static void intelRenderMode( GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitStateFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->DrawBuffer = intelDrawBuffer; | ||||
|    functions->ReadBuffer = intelReadBuffer; | ||||
|    functions->RenderMode = intelRenderMode; | ||||
|    functions->Viewport = intelViewport; | ||||
|    functions->DepthRange = intelDepthRange; | ||||
|    functions->ClearColor = intelClearColor; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelInitState( GLcontext *ctx ) | ||||
| { | ||||
|    /* Mesa should do this for us: | ||||
|     */ | ||||
|    ctx->Driver.AlphaFunc( ctx,  | ||||
| 			  ctx->Color.AlphaFunc, | ||||
| 			  ctx->Color.AlphaRef); | ||||
|  | ||||
|    ctx->Driver.BlendColor( ctx, | ||||
| 			   ctx->Color.BlendColor ); | ||||
|  | ||||
|    ctx->Driver.BlendEquationSeparate( ctx,  | ||||
| 				      ctx->Color.BlendEquationRGB, | ||||
| 				      ctx->Color.BlendEquationA); | ||||
|  | ||||
|    ctx->Driver.BlendFuncSeparate( ctx, | ||||
| 				  ctx->Color.BlendSrcRGB, | ||||
| 				  ctx->Color.BlendDstRGB, | ||||
| 				  ctx->Color.BlendSrcA, | ||||
| 				  ctx->Color.BlendDstA); | ||||
|  | ||||
|    ctx->Driver.ColorMask( ctx,  | ||||
| 			  ctx->Color.ColorMask[RCOMP], | ||||
| 			  ctx->Color.ColorMask[GCOMP], | ||||
| 			  ctx->Color.ColorMask[BCOMP], | ||||
| 			  ctx->Color.ColorMask[ACOMP]); | ||||
|  | ||||
|    ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode ); | ||||
|    ctx->Driver.DepthFunc( ctx, ctx->Depth.Func ); | ||||
|    ctx->Driver.DepthMask( ctx, ctx->Depth.Mask ); | ||||
|  | ||||
|    ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test ); | ||||
|    ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE ); | ||||
|  | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); | ||||
|  | ||||
|    ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace ); | ||||
|  | ||||
|    { | ||||
|       GLfloat f = (GLfloat)ctx->Light.Model.ColorControl; | ||||
|       ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f ); | ||||
|    } | ||||
|  | ||||
|    ctx->Driver.LineWidth( ctx, ctx->Line.Width ); | ||||
|    ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp ); | ||||
|    ctx->Driver.PointSize( ctx, ctx->Point.Size ); | ||||
|    ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple ); | ||||
|    ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|    ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT, | ||||
|                                     ctx->Stencil.Function[0], | ||||
|                                     ctx->Stencil.Ref[0], | ||||
|                                     ctx->Stencil.ValueMask[0] ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_BACK, | ||||
|                                     ctx->Stencil.Function[1], | ||||
|                                     ctx->Stencil.Ref[1], | ||||
|                                     ctx->Stencil.ValueMask[1] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] ); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_FRONT, | ||||
|                                   ctx->Stencil.FailFunc[0], | ||||
|                                   ctx->Stencil.ZFailFunc[0], | ||||
|                                   ctx->Stencil.ZPassFunc[0]); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_BACK, | ||||
|                                   ctx->Stencil.FailFunc[1], | ||||
|                                   ctx->Stencil.ZFailFunc[1], | ||||
|                                   ctx->Stencil.ZPassFunc[1]); | ||||
|  | ||||
|  | ||||
|    ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); | ||||
| } | ||||
|   | ||||
| @@ -1,830 +1,162 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "mtypes.h" | ||||
| #include "imports.h" | ||||
| #include "macros.h" | ||||
| #include "simple_list.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "texstore.h" | ||||
| #include "texformat.h" | ||||
| #include "teximage.h" | ||||
| #include "texmem.h" | ||||
| #include "texobj.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "mm.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intelValidateClientStorage( intelContextPtr intel, GLenum target, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint srcWidth, GLint srcHeight,  | ||||
| 			    GLenum format, GLenum type,  const void *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage) | ||||
|  | ||||
| static GLboolean intelIsTextureResident(GLcontext *ctx, | ||||
|                                       struct gl_texture_object *texObj) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    int texelBytes; | ||||
| #if 0 | ||||
|    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 1; | ||||
|    } | ||||
|    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); | ||||
|    (void) ctx; | ||||
|    return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Handles 2D, CUBE, RECT: | ||||
| static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx,  | ||||
| 							GLuint name,  | ||||
| 							GLenum target ) | ||||
| { | ||||
|    struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); | ||||
|  | ||||
|    _mesa_initialize_texture_object(&obj->base, name, target); | ||||
|  | ||||
|    return &obj->base; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelFreeTextureImageData( GLcontext *ctx,  | ||||
| 				     struct gl_texture_image *texImage ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|    } | ||||
|     | ||||
|    if (texImage->Data) { | ||||
|       free(texImage->Data); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifndef __x86_64__ | ||||
| static unsigned | ||||
| fastrdtsc(void) | ||||
| { | ||||
|     unsigned eax; | ||||
|     __asm__ volatile ("\t" | ||||
| 	"pushl  %%ebx\n\t" | ||||
| 	"cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax) | ||||
| 	:"0"(0) | ||||
| 	:"ecx", "edx", "cc"); | ||||
|  | ||||
|     return eax; | ||||
| } | ||||
| #else | ||||
| static unsigned | ||||
| fastrdtsc(void) | ||||
| { | ||||
|     unsigned eax; | ||||
|     __asm__ volatile ("\t" | ||||
| 	"cpuid\n\t" ".byte 0x0f, 0x31\n\t" :"=a" (eax) | ||||
| 	:"0"(0) | ||||
| 		      :"ecx", "edx", "ebx", "cc"); | ||||
|  | ||||
|     return eax; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static unsigned | ||||
| time_diff(unsigned t, unsigned t2) | ||||
| { | ||||
|     return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* The system memcpy (at least on ubuntu 5.10) has problems copying | ||||
|  * to agp (writecombined) memory from a source which isn't 64-byte | ||||
|  * aligned - there is a 4x performance falloff. | ||||
|  * | ||||
|  * The x86 __memcpy is immune to this but is slightly slower | ||||
|  * (10%-ish) than the system memcpy. | ||||
|  * | ||||
|  * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but | ||||
|  * isn't much faster than x86_memcpy for agp copies. | ||||
|  *  | ||||
|  * TODO: switch dynamically. | ||||
|  */ | ||||
| static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint width, GLint height, GLint border, | ||||
| 			    GLenum format, GLenum type, const GLvoid *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage ) | ||||
| static void *do_memcpy( void *dest, const void *src, size_t n ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    if ( (((unsigned)src) & 63) || | ||||
| 	(((unsigned)dest) & 63)) { | ||||
|       return  __memcpy(dest, src, n);	 | ||||
|    } | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,  | ||||
| 				   internalFormat,  | ||||
| 				   width, height,  | ||||
| 				   format, type, pixels,  | ||||
| 				   packing, texObj, texImage)) { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);  | ||||
|    } | ||||
|    else { | ||||
|       _mesa_store_teximage2d( ctx, target, level, internalFormat, | ||||
| 			      width, height, border, format, type, | ||||
| 			      pixels, packing, texObj, texImage ); | ||||
|  | ||||
|       t->dirty_images[face] |= (1 << level); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelTexSubImage2D( GLcontext *ctx,  | ||||
| 			       GLenum target, | ||||
| 			       GLint level,	 | ||||
| 			       GLint xoffset, GLint yoffset, | ||||
| 			       GLsizei width, GLsizei height, | ||||
| 			       GLenum format, GLenum type, | ||||
| 			       const GLvoid *pixels, | ||||
| 			       const struct gl_pixelstore_attrib *packing, | ||||
| 			       struct gl_texture_object *texObj, | ||||
| 			       struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    } | ||||
|  | ||||
|    if (texImage->IsClientData && | ||||
|        (char *)pixels == (char *)texImage->Data +  | ||||
|        ((xoffset + yoffset * texImage->RowStride) *  | ||||
| 	texImage->TexFormat->TexelBytes)) { | ||||
|  | ||||
|       /* Notification only - no upload required */ | ||||
|    } | ||||
|    else { | ||||
|       assert( t ); /* this _should_ be true */ | ||||
|       intelFlush( ctx ); | ||||
|       driSwapOutTextureObject( t ); | ||||
|  | ||||
|       _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,  | ||||
| 				height, format, type, pixels, packing, texObj, | ||||
| 				texImage); | ||||
|  | ||||
|       t->dirty_images[face] |= (1 << level); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                               GLint internalFormat, | ||||
|                               GLint width, GLint height, GLint border, | ||||
|                               GLsizei imageSize, const GLvoid *data, | ||||
|                               struct gl_texture_object *texObj, | ||||
|                               struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    } | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|     | ||||
|    driSwapOutTextureObject( t ); | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
|      fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);  | ||||
|     | ||||
|    _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width, | ||||
| 				     height, border, imageSize, data, texObj, texImage); | ||||
|     | ||||
|    t->dirty_images[face] |= (1 << level); | ||||
|    else | ||||
|       return memcpy(dest, src, n); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                                  GLint xoffset, GLint yoffset, | ||||
|                                  GLsizei width, GLsizei height, | ||||
|                                  GLenum format, | ||||
|                                  GLsizei imageSize, const GLvoid *data, | ||||
|                                  struct gl_texture_object *texObj, | ||||
|                                  struct gl_texture_image *texImage ) | ||||
| static void *timed_memcpy( void *dest, const void *src, size_t n ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|    void *ret; | ||||
|    unsigned t1, t2; | ||||
|    double rate; | ||||
|  | ||||
|    if ( (((unsigned)src) & 63) || | ||||
| 	(((unsigned)dest) & 63))  | ||||
|       _mesa_printf("Warning - non-aligned texture copy!\n"); | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    } | ||||
|    t1 = fastrdtsc(); | ||||
|    ret =  do_memcpy(dest, src, n);	 | ||||
|    t2 = fastrdtsc(); | ||||
|  | ||||
|    assert( t ); /* this _should_ be true */ | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|     | ||||
|    _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width, | ||||
| 					height, format, imageSize, data, texObj, texImage); | ||||
|     | ||||
|    t->dirty_images[face] |= (1 << level); | ||||
|    rate = time_diff(t1, t2); | ||||
|    rate /= (double) n; | ||||
|    _mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate);  | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                             GLint internalFormat, | ||||
|                             GLint width, GLint height, GLint depth, | ||||
|                             GLint border, | ||||
|                             GLenum format, GLenum type, const GLvoid *pixels, | ||||
|                             const struct gl_pixelstore_attrib *packing, | ||||
|                             struct gl_texture_object *texObj, | ||||
|                             struct gl_texture_image *texImage ) | ||||
| void intelInitTextureFuncs(struct dd_function_table * functions) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    functions->ChooseTextureFormat = intelChooseTextureFormat; | ||||
|    functions->TexImage1D = intelTexImage1D; | ||||
|    functions->TexImage2D = intelTexImage2D; | ||||
|    functions->TexImage3D = intelTexImage3D; | ||||
|    functions->TexSubImage1D = intelTexSubImage1D; | ||||
|    functions->TexSubImage2D = intelTexSubImage2D; | ||||
|    functions->TexSubImage3D = intelTexSubImage3D; | ||||
|    functions->CopyTexImage1D = intelCopyTexImage1D; | ||||
|    functions->CopyTexImage2D = intelCopyTexImage2D; | ||||
|    functions->CopyTexSubImage1D = intelCopyTexSubImage1D; | ||||
|    functions->CopyTexSubImage2D = intelCopyTexSubImage2D; | ||||
|    functions->NewTextureObject = intelNewTextureObject; | ||||
|    functions->NewTextureImage = intelNewTextureImage; | ||||
|    functions->DeleteTexture = _mesa_delete_texture_object; | ||||
|    functions->FreeTexImageData = intelFreeTextureImageData; | ||||
|    functions->UpdateTexturePalette = 0; | ||||
|    functions->IsTextureResident = intelIsTextureResident; | ||||
|  | ||||
|    assert(t); | ||||
|    driSwapOutTextureObject( t ); | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    _mesa_store_teximage3d(ctx, target, level, internalFormat, | ||||
| 			  width, height, depth, border, | ||||
| 			  format, type, pixels, | ||||
| 			  &ctx->Unpack, texObj, texImage); | ||||
|     | ||||
|    t->dirty_images[0] |= (1 << level); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                    GLint xoffset, GLint yoffset, GLint zoffset, | ||||
|                    GLsizei width, GLsizei height, GLsizei depth, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const GLvoid *pixels, | ||||
|                    const struct gl_pixelstore_attrib *packing, | ||||
|                    struct gl_texture_object *texObj, | ||||
|                    struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|  | ||||
|    assert( t ); /* this _should_ be true */ | ||||
|    driSwapOutTextureObject( t ); | ||||
|  | ||||
|    _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset, | ||||
|                              width, height, depth, | ||||
|                              format, type, pixels, packing, texObj, texImage); | ||||
|  | ||||
|    t->dirty_images[0] |= (1 << level); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) tObj->DriverData; | ||||
|  | ||||
|    if ( t != NULL ) { | ||||
|       intelFlush( ctx ); | ||||
|       driDestroyTextureObject( t ); | ||||
|    } | ||||
|     | ||||
|    /* Free mipmap images and the texture object itself */ | ||||
|    _mesa_delete_texture_object(ctx, tObj); | ||||
| } | ||||
|  | ||||
|  | ||||
| static const struct gl_texture_format * | ||||
| intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, | ||||
| 			 GLenum format, GLenum type ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 && | ||||
| 			       intel->intelScreen->tex.size > 4*1024*1024); | ||||
|  | ||||
|    switch ( internalFormat ) { | ||||
|    case 4: | ||||
|    case GL_RGBA: | ||||
|    case GL_COMPRESSED_RGBA: | ||||
|       if ( format == GL_BGRA ) { | ||||
| 	 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | ||||
| 	    return &_mesa_texformat_argb8888; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { | ||||
|             return &_mesa_texformat_argb4444; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { | ||||
| 	    return &_mesa_texformat_argb1555; | ||||
| 	 } | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case 3: | ||||
|    case GL_RGB: | ||||
|    case GL_COMPRESSED_RGB: | ||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | ||||
| 	 return &_mesa_texformat_rgb565; | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGBA2: | ||||
|       return &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGB5_A1: | ||||
|       return &_mesa_texformat_argb1555; | ||||
|  | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGB5: | ||||
|    case GL_RGB4: | ||||
|    case GL_R3_G3_B2: | ||||
|       return &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_ALPHA: | ||||
|    case GL_ALPHA4: | ||||
|    case GL_ALPHA8: | ||||
|    case GL_ALPHA12: | ||||
|    case GL_ALPHA16: | ||||
|    case GL_COMPRESSED_ALPHA: | ||||
|       return &_mesa_texformat_a8; | ||||
|  | ||||
|    case 1: | ||||
|    case GL_LUMINANCE: | ||||
|    case GL_LUMINANCE4: | ||||
|    case GL_LUMINANCE8: | ||||
|    case GL_LUMINANCE12: | ||||
|    case GL_LUMINANCE16: | ||||
|    case GL_COMPRESSED_LUMINANCE: | ||||
|       return &_mesa_texformat_l8; | ||||
|  | ||||
|    case 2: | ||||
|    case GL_LUMINANCE_ALPHA: | ||||
|    case GL_LUMINANCE4_ALPHA4: | ||||
|    case GL_LUMINANCE6_ALPHA2: | ||||
|    case GL_LUMINANCE8_ALPHA8: | ||||
|    case GL_LUMINANCE12_ALPHA4: | ||||
|    case GL_LUMINANCE12_ALPHA12: | ||||
|    case GL_LUMINANCE16_ALPHA16: | ||||
|    case GL_COMPRESSED_LUMINANCE_ALPHA: | ||||
|       return &_mesa_texformat_al88; | ||||
|  | ||||
|    case GL_INTENSITY: | ||||
|    case GL_INTENSITY4: | ||||
|    case GL_INTENSITY8: | ||||
|    case GL_INTENSITY12: | ||||
|    case GL_INTENSITY16: | ||||
|    case GL_COMPRESSED_INTENSITY: | ||||
|       return &_mesa_texformat_i8; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if (type == GL_UNSIGNED_SHORT_8_8_MESA || | ||||
| 	  type == GL_UNSIGNED_BYTE) | ||||
|          return &_mesa_texformat_ycbcr; | ||||
|       else | ||||
|          return &_mesa_texformat_ycbcr_rev; | ||||
|  | ||||
|    case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgb_fxt1; | ||||
|    case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgba_fxt1; | ||||
|  | ||||
|    case GL_RGB_S3TC: | ||||
|    case GL_RGB4_S3TC: | ||||
|    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgb_dxt1; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt1; | ||||
|  | ||||
|    case GL_RGBA_S3TC: | ||||
|    case GL_RGBA4_S3TC: | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt3; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt5; | ||||
|  | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       return &_mesa_texformat_depth_component16; | ||||
|  | ||||
|    default: | ||||
|       fprintf(stderr, "unexpected texture format %s in %s\n",  | ||||
| 	      _mesa_lookup_enum_by_nr(internalFormat), | ||||
| 	      __FUNCTION__); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return NULL; /* never get here */ | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t) | ||||
| { | ||||
|    unsigned   i; | ||||
|  | ||||
|    if ( intel == NULL )  | ||||
|       return; | ||||
|  | ||||
|    if ( t->age > intel->dirtyAge ) | ||||
|       intel->dirtyAge = t->age; | ||||
|  | ||||
|    for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) { | ||||
|       if ( t == intel->CurrentTexObj[ i ] )  | ||||
| 	 intel->CurrentTexObj[ i ] = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload an image from mesa's internal copy.  Image may be 1D, 2D or | ||||
|  * 3D.  Cubemaps are expanded elsewhere. | ||||
|  */ | ||||
| static void intelUploadTexImage( intelContextPtr intel, | ||||
| 				 intelTextureObjectPtr t, | ||||
| 				 const struct gl_texture_image *image, | ||||
| 				 const GLuint offset ) | ||||
| { | ||||
|  | ||||
|    if (!image || !image->Data)  | ||||
|       return; | ||||
|  | ||||
|    if (image->Depth == 1 && image->IsClientData) { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "Blit uploading\n"); | ||||
|  | ||||
|       /* Do it with a blit. | ||||
|        */ | ||||
|       intelEmitCopyBlitLocked( intel, | ||||
| 			       image->TexFormat->TexelBytes, | ||||
| 			       image->RowStride, /* ? */ | ||||
| 			       intelGetMemoryOffsetMESA( NULL, 0, image->Data ), | ||||
| 			       t->Pitch / image->TexFormat->TexelBytes, | ||||
| 			       intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ), | ||||
| 			       0, 0, | ||||
| 			       0, 0, | ||||
| 			       image->Width, | ||||
| 			       image->Height); | ||||
|    } | ||||
|    else if (image->IsCompressed) { | ||||
|       GLuint row_len = image->Width * 2; | ||||
|       GLubyte *dst = (GLubyte *)(t->BufAddr + offset); | ||||
|       GLubyte *src = (GLubyte *)image->Data; | ||||
|       GLuint j; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr,  | ||||
| 		 "Upload image %dx%dx%d offset %xm row_len %x " | ||||
| 		 "pitch %x depth_pitch %x\n", | ||||
| 		 image->Width, image->Height, image->Depth, offset, | ||||
| 		 row_len, t->Pitch, t->depth_pitch); | ||||
|  | ||||
|       switch (image->InternalFormat) { | ||||
| 	case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
| 	case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
| 	case GL_RGB_S3TC: | ||||
| 	case GL_RGB4_S3TC: | ||||
| 	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
| 	  for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { | ||||
| 	    __memcpy(dst, src, row_len ); | ||||
| 	    src += row_len; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	case GL_RGBA_S3TC: | ||||
| 	case GL_RGBA4_S3TC: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
| 	  for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { | ||||
| 	    __memcpy(dst, src, (image->Width*4) ); | ||||
| 	    src += image->Width*4; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat); | ||||
| 	  break; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       GLuint row_len = image->Width * image->TexFormat->TexelBytes; | ||||
|       GLubyte *dst = (GLubyte *)(t->BufAddr + offset); | ||||
|       GLubyte *src = (GLubyte *)image->Data; | ||||
|       GLuint d, j; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr,  | ||||
| 		 "Upload image %dx%dx%d offset %xm row_len %x " | ||||
| 		 "pitch %x depth_pitch %x\n", | ||||
| 		 image->Width, image->Height, image->Depth, offset, | ||||
| 		 row_len, t->Pitch, t->depth_pitch); | ||||
|  | ||||
|       if (row_len == t->Pitch) { | ||||
| 	 for (d = 0; d < image->Depth; d++) { | ||||
| 	    memcpy( dst, src, t->Pitch * image->Height ); | ||||
| 	    dst += t->depth_pitch; | ||||
| 	    src += row_len * image->Height; | ||||
| 	 } | ||||
|       } | ||||
|       else {  | ||||
| 	 for (d = 0 ; d < image->Depth ; d++) { | ||||
| 	    for (j = 0 ; j < image->Height ; j++) { | ||||
| 	       __memcpy(dst, src, row_len ); | ||||
| 	       src += row_len; | ||||
| 	       dst += t->Pitch; | ||||
| 	    } | ||||
|  | ||||
| 	    dst += t->depth_pitch - (t->Pitch * image->Height); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| int intelUploadTexImages( intelContextPtr intel,  | ||||
| 			  intelTextureObjectPtr t, | ||||
| 			  GLuint face) | ||||
| { | ||||
|    const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; | ||||
|    const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image; | ||||
|    int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes; | ||||
|  | ||||
|    /* Can we texture out of the existing client data? */ | ||||
|    if ( numLevels == 1 && | ||||
| 	firstImage->IsClientData && | ||||
| 	(pitch & 3) == 0) { | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "AGP texturing from client memory\n"); | ||||
|  | ||||
|       t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data ); | ||||
|       t->BufAddr = 0; | ||||
|       t->dirty = ~0; | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|    else { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE)  | ||||
| 	 fprintf(stderr, "Uploading client data to agp\n"); | ||||
|  | ||||
|       INTEL_FIREVERTICES( intel ); | ||||
|       LOCK_HARDWARE( intel ); | ||||
|  | ||||
|       if ( t->base.memBlock == NULL ) { | ||||
| 	 int heap; | ||||
|  | ||||
| 	 heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps, | ||||
| 				    (driTextureObject *) t ); | ||||
| 	 if ( heap == -1 ) { | ||||
| 	    UNLOCK_HARDWARE( intel ); | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
|  | ||||
| 	 /* Set the base offset of the texture image */ | ||||
| 	 t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs; | ||||
| 	 t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs; | ||||
| 	 t->dirty = ~0; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* Let the world know we've used this memory recently. | ||||
|        */ | ||||
|       driUpdateTextureLRU( (driTextureObject *) t ); | ||||
|  | ||||
|  | ||||
|       /* Upload any images that are new */ | ||||
|       if (t->base.dirty_images[face]) { | ||||
| 	 int i; | ||||
|  | ||||
|  	 intelWaitForIdle( intel ); | ||||
| 	     | ||||
| 	 for (i = 0 ; i < numLevels ; i++) {  | ||||
| 	    int level = i + t->base.firstLevel; | ||||
|  | ||||
| 	    if (t->base.dirty_images[face] & (1<<level)) { | ||||
|  | ||||
| 	       const struct gl_texture_image *image = t->image[face][i].image; | ||||
| 	       GLuint offset = t->image[face][i].offset; | ||||
|  | ||||
|      	       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	          fprintf(stderr, "upload level %d, offset %x\n",  | ||||
| 			  level, offset); | ||||
|  | ||||
| 	       intelUploadTexImage( intel, t, image, offset ); | ||||
| 	    } | ||||
| 	 } | ||||
| 	 t->base.dirty_images[face] = 0; | ||||
| 	 intel->perf_boxes |= I830_BOX_TEXTURE_LOAD; | ||||
|       } | ||||
|        | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Allocate a new texture object. | ||||
|  * Called via ctx->Driver.NewTextureObject. | ||||
|  * Note: this function will be called during context creation to | ||||
|  * allocate the default texture objects. | ||||
|  * Note: we could use containment here to 'derive' the driver-specific | ||||
|  * texture object from the core mesa gl_texture_object.  Not done at this time. | ||||
|  */ | ||||
| static struct gl_texture_object * | ||||
| intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target ) | ||||
| { | ||||
|    struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target); | ||||
|    INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj ); | ||||
|    return obj; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitTextureFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->NewTextureObject          = intelNewTextureObject; | ||||
|    functions->ChooseTextureFormat       = intelChooseTextureFormat; | ||||
|    functions->TexImage1D                = intelTexImage1D; | ||||
|    functions->TexImage2D                = intelTexImage2D; | ||||
|    functions->TexImage3D                = intelTexImage3D; | ||||
|    functions->TexSubImage1D             = intelTexSubImage1D; | ||||
|    functions->TexSubImage2D             = intelTexSubImage2D; | ||||
|    functions->TexSubImage3D             = intelTexSubImage3D; | ||||
|    functions->CopyTexImage1D            = _swrast_copy_teximage1d; | ||||
|    functions->CopyTexImage2D            = _swrast_copy_teximage2d; | ||||
|    functions->CopyTexSubImage1D         = _swrast_copy_texsubimage1d; | ||||
|    functions->CopyTexSubImage2D         = _swrast_copy_texsubimage2d; | ||||
|    functions->CopyTexSubImage3D         = _swrast_copy_texsubimage3d; | ||||
|    functions->DeleteTexture             = intelDeleteTexture; | ||||
|    functions->UpdateTexturePalette      = NULL; | ||||
|    functions->IsTextureResident         = driIsTextureResident; | ||||
|    functions->TestProxyTexImage         = _mesa_test_proxy_teximage; | ||||
|    functions->DeleteTexture             = intelDeleteTexture; | ||||
|    functions->CompressedTexImage2D      = intelCompressedTexImage2D; | ||||
|    functions->CompressedTexSubImage2D   = intelCompressedTexSubImage2D; | ||||
|    if (INTEL_DEBUG & DEBUG_BUFMGR) | ||||
|       functions->TextureMemCpy = timed_memcpy; | ||||
|    else | ||||
|       functions->TextureMemCpy = do_memcpy; | ||||
| } | ||||
|   | ||||
| @@ -35,8 +35,97 @@ | ||||
|  | ||||
| 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 ); | ||||
|  | ||||
| GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit ); | ||||
|  | ||||
| void intel_tex_map_images( struct intel_context *intel, | ||||
| 			   struct intel_texture_object *intelObj ); | ||||
|  | ||||
| void intel_tex_unmap_images( struct intel_context *intel, | ||||
| 			     struct intel_texture_object *intelObj ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										303
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,303 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * 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 "teximage.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "bufmgr.h" | ||||
|  | ||||
| /* Do the best we can using the blitter.  A future project is to use | ||||
|  * the texture engine and fragment programs for these copies. | ||||
|  */ | ||||
|  | ||||
| static struct intel_region *get_teximage_source( struct intel_context *intel, | ||||
| 						 GLenum internalFormat ) | ||||
| { | ||||
|    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: | ||||
|       if (intel->intelScreen->cpp == 2) | ||||
| 	 return intel->depth_region; | ||||
|       return NULL; | ||||
|    case GL_DEPTH24_STENCIL8_EXT: | ||||
|    case GL_DEPTH_STENCIL_EXT: | ||||
|       if (intel->intelScreen->cpp == 4) | ||||
| 	 return intel->depth_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 check_copytex_fragment_ops( const GLcontext *ctx ) | ||||
| { | ||||
|    return GL_TRUE; | ||||
|  | ||||
|    return !(ctx->Color.AlphaEnabled ||  | ||||
| /* 	    ctx->Depth.Test || */ | ||||
| 	    ctx->Fog.Enabled || | ||||
| /* 	    ctx->Scissor.Enabled || */ | ||||
| 	    ctx->Stencil.Enabled || | ||||
| 	    !ctx->Color.ColorMask[0] || | ||||
| 	    !ctx->Color.ColorMask[1] || | ||||
| 	    !ctx->Color.ColorMask[2] || | ||||
| 	    !ctx->Color.ColorMask[3] || | ||||
| 	    ctx->Color.ColorLogicOpEnabled || | ||||
| 	    ctx->Texture._EnabledUnits); | ||||
| } | ||||
|  | ||||
|  | ||||
| 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; | ||||
|    struct intel_region *src = get_teximage_source(intel, internalFormat); | ||||
|    GLuint ret = GL_TRUE; | ||||
|  | ||||
|    if (!intelImage->mt || !src) | ||||
|       return GL_FALSE; | ||||
|   | ||||
|    if (!check_copytex_fragment_ops( ctx )) | ||||
|       return GL_FALSE; | ||||
|   | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       GLuint image_offset = intel_miptree_image_offset(intelImage->mt,  | ||||
| 						       intelImage->face, | ||||
| 						       intelImage->level); | ||||
|       GLint orig_x = x; | ||||
|       GLint orig_y = y; | ||||
|       GLuint window_y; | ||||
|  | ||||
|       if (!intel_clip_to_framebuffer(ctx, ctx->DrawBuffer, &x, &y, &width, &height)) { | ||||
| 	 ret = GL_TRUE; | ||||
| 	 goto out; | ||||
|       } | ||||
|  | ||||
|       /* Update dst for clipped src.  Need to also clip the source rect. | ||||
|        */ | ||||
|       dstx += x - orig_x; | ||||
|       dsty += y - orig_y; | ||||
|  | ||||
|       x += dPriv->x; | ||||
|  | ||||
|       window_y = intel->intelScreen->height - (dPriv->y + dPriv->h); | ||||
|  | ||||
|       y = window_y + y; | ||||
|  | ||||
|  | ||||
|  | ||||
|       /* 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 ); | ||||
|  | ||||
|    out: | ||||
|       intel_batchbuffer_flush( intel->batch ); | ||||
|    } | ||||
|     | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|    if (!ret) | ||||
|       return GL_FALSE; | ||||
|  | ||||
| #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 | ||||
|  | ||||
|    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; | ||||
|  | ||||
|    /* Need to check texture is compatible with source format.  | ||||
|     */ | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx),  | ||||
| 			    intel_texture_image(texImage), | ||||
| 			    internalFormat, | ||||
| 			    xoffset, 0, | ||||
| 			    x, y, width, 1)) { | ||||
|       _swrast_copy_texsubimage1d( ctx, target, level,  | ||||
| 				  xoffset, x, y, width ); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			     GLint xoffset, GLint yoffset, | ||||
| 			     GLint x, GLint y, GLsizei width, GLsizei height ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|    GLenum internalFormat = texImage->InternalFormat; | ||||
|  | ||||
|  | ||||
|    /* Need to check texture is compatible with source format.  | ||||
|     */ | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx),  | ||||
| 			    intel_texture_image(texImage), | ||||
| 			    internalFormat, | ||||
| 			    xoffset, yoffset, | ||||
| 			    x, y, width, height)) { | ||||
|       _swrast_copy_texsubimage2d( ctx, target, level, | ||||
| 				  xoffset, yoffset, | ||||
| 				  x, y, width, height ); | ||||
|    } | ||||
| } | ||||
							
								
								
									
										148
									
								
								src/mesa/drivers/dri/i915/intel_tex_format.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/mesa/drivers/dri/i915/intel_tex_format.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| #include "intel_context.h" | ||||
| #include "intel_tex.h" | ||||
| #include "texformat.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| /* It works out that this function is fine for all the supported | ||||
|  * hardware.  However, there is still a need to map the formats onto | ||||
|  * hardware descriptors. | ||||
|  */ | ||||
| /* Note that the i915 can actually support many more formats than | ||||
|  * these if we take the step of simply swizzling the colors | ||||
|  * immediately after sampling... | ||||
|  */ | ||||
| const struct gl_texture_format * | ||||
| intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, | ||||
|                           GLenum format, GLenum type ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    const GLboolean do32bpt = (intel->intelScreen->cpp == 4); | ||||
|  | ||||
|    switch ( internalFormat ) { | ||||
|    case 4: | ||||
|    case GL_RGBA: | ||||
|    case GL_COMPRESSED_RGBA: | ||||
|       if ( format == GL_BGRA ) { | ||||
| 	 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | ||||
| 	    return &_mesa_texformat_argb8888; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { | ||||
|             return &_mesa_texformat_argb4444; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { | ||||
| 	    return &_mesa_texformat_argb1555; | ||||
| 	 } | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case 3: | ||||
|    case GL_RGB: | ||||
|    case GL_COMPRESSED_RGB: | ||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | ||||
| 	 return &_mesa_texformat_rgb565; | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGBA2: | ||||
|       return &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGB5_A1: | ||||
|       return &_mesa_texformat_argb1555; | ||||
|  | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|       return &_mesa_texformat_argb8888; | ||||
|  | ||||
|    case GL_RGB5: | ||||
|    case GL_RGB4: | ||||
|    case GL_R3_G3_B2: | ||||
|       return &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_ALPHA: | ||||
|    case GL_ALPHA4: | ||||
|    case GL_ALPHA8: | ||||
|    case GL_ALPHA12: | ||||
|    case GL_ALPHA16: | ||||
|    case GL_COMPRESSED_ALPHA: | ||||
|       return &_mesa_texformat_a8; | ||||
|  | ||||
|    case 1: | ||||
|    case GL_LUMINANCE: | ||||
|    case GL_LUMINANCE4: | ||||
|    case GL_LUMINANCE8: | ||||
|    case GL_LUMINANCE12: | ||||
|    case GL_LUMINANCE16: | ||||
|    case GL_COMPRESSED_LUMINANCE: | ||||
|       return &_mesa_texformat_l8; | ||||
|  | ||||
|    case 2: | ||||
|    case GL_LUMINANCE_ALPHA: | ||||
|    case GL_LUMINANCE4_ALPHA4: | ||||
|    case GL_LUMINANCE6_ALPHA2: | ||||
|    case GL_LUMINANCE8_ALPHA8: | ||||
|    case GL_LUMINANCE12_ALPHA4: | ||||
|    case GL_LUMINANCE12_ALPHA12: | ||||
|    case GL_LUMINANCE16_ALPHA16: | ||||
|    case GL_COMPRESSED_LUMINANCE_ALPHA: | ||||
|       return &_mesa_texformat_al88; | ||||
|  | ||||
|    case GL_INTENSITY: | ||||
|    case GL_INTENSITY4: | ||||
|    case GL_INTENSITY8: | ||||
|    case GL_INTENSITY12: | ||||
|    case GL_INTENSITY16: | ||||
|    case GL_COMPRESSED_INTENSITY: | ||||
|       return &_mesa_texformat_i8; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if (type == GL_UNSIGNED_SHORT_8_8_MESA || | ||||
| 	  type == GL_UNSIGNED_BYTE) | ||||
|          return &_mesa_texformat_ycbcr; | ||||
|       else | ||||
|          return &_mesa_texformat_ycbcr_rev; | ||||
|  | ||||
|    case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgb_fxt1; | ||||
|    case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgba_fxt1; | ||||
|  | ||||
|    case GL_RGB_S3TC: | ||||
|    case GL_RGB4_S3TC: | ||||
|    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgb_dxt1; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt1; | ||||
|  | ||||
|    case GL_RGBA_S3TC: | ||||
|    case GL_RGBA4_S3TC: | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt3; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt5; | ||||
|  | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       return &_mesa_texformat_depth_component16; | ||||
|  | ||||
|    default: | ||||
|       fprintf(stderr, "unexpected texture format %s in %s\n",  | ||||
| 	      _mesa_lookup_enum_by_nr(internalFormat), | ||||
| 	      __FUNCTION__); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return NULL; /* never get here */ | ||||
| } | ||||
							
								
								
									
										400
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,400 @@ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "macros.h" | ||||
| #include "mtypes.h" | ||||
| #include "enums.h" | ||||
| #include "colortab.h" | ||||
| #include "convolve.h" | ||||
| #include "context.h" | ||||
| #include "simple_list.h" | ||||
| #include "texcompress.h" | ||||
| #include "texformat.h" | ||||
| #include "texobj.h" | ||||
| #include "texstore.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
|  | ||||
| /* Functions to store texture images.  Where possible, mipmap_tree's | ||||
|  * will be created or further instantiated with image data, otherwise | ||||
|  * images will be stored in malloc'd memory.  A validation step is | ||||
|  * required to pull those images into a mipmap tree, or otherwise | ||||
|  * decide a fallback is required. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| static int logbase2(int n) | ||||
| { | ||||
|    GLint i = 1; | ||||
|    GLint log2 = 0; | ||||
|  | ||||
|    while (n > i) { | ||||
|       i *= 2; | ||||
|       log2++; | ||||
|    } | ||||
|  | ||||
|    return log2; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Otherwise, store it in memory if (Border != 0) or (any dimension == | ||||
|  * 1). | ||||
|  *     | ||||
|  * Otherwise, if max_level >= level >= min_level, create tree with | ||||
|  * space for textures from min_level down to max_level. | ||||
|  * | ||||
|  * Otherwise, create tree with space for textures from (level | ||||
|  * 0)..(1x1).  Consider pruning this tree at a validation if the | ||||
|  * saving is worth it. | ||||
|  */ | ||||
| static void guess_and_alloc_mipmap_tree( struct intel_context *intel, | ||||
| 					 struct intel_texture_object *intelObj, | ||||
| 					 struct intel_texture_image *intelImage ) | ||||
| { | ||||
|    GLuint firstLevel; | ||||
|    GLuint lastLevel; | ||||
|    GLuint width = intelImage->base.Width; | ||||
|    GLuint height = intelImage->base.Height; | ||||
|    GLuint depth = intelImage->base.Depth; | ||||
|    GLuint l2width, l2height, l2depth; | ||||
|    GLuint i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (intelImage->base.Border) | ||||
|       return; | ||||
|  | ||||
|    if (intelImage->level > intelObj->base.BaseLevel && | ||||
|        (intelImage->base.Width == 1 || | ||||
| 	(intelObj->base.Target != GL_TEXTURE_1D &&  | ||||
| 	 intelImage->base.Height == 1) || | ||||
| 	(intelObj->base.Target == GL_TEXTURE_3D && | ||||
| 	 intelImage->base.Depth == 1))) | ||||
|       return; | ||||
|  | ||||
|    /* If this image disrespects BaseLevel, allocate from level zero. | ||||
|     * Usually BaseLevel == 0, so it's unlikely to happen. | ||||
|     */ | ||||
|    if (intelImage->level < intelObj->base.BaseLevel) | ||||
|       firstLevel = 0; | ||||
|    else | ||||
|       firstLevel = intelObj->base.BaseLevel; | ||||
|  | ||||
|  | ||||
|    /* Figure out image dimensions at start level.  | ||||
|     */ | ||||
|    for (i = intelImage->level; i > firstLevel; i--) { | ||||
|       width <<= 1; | ||||
|       if (height != 1) height <<= 1; | ||||
|       if (depth != 1) depth <<= 1; | ||||
|    } | ||||
|  | ||||
|    /* Guess a reasonable value for lastLevel.  This is probably going | ||||
|     * to be wrong fairly often and might mean that we have to look at | ||||
|     * resizable buffers, or require that buffers implement lazy | ||||
|     * pagetable arrangements. | ||||
|     */ | ||||
|    if ((intelObj->base.MinFilter == GL_NEAREST ||  | ||||
| 	intelObj->base.MinFilter == GL_LINEAR) && | ||||
|        intelImage->level == firstLevel) { | ||||
|       lastLevel = firstLevel; | ||||
|    } | ||||
|    else { | ||||
|       l2width = logbase2(width); | ||||
|       l2height = logbase2(height); | ||||
|       l2depth = logbase2(depth); | ||||
|       lastLevel = firstLevel + MAX2(MAX2(l2width,l2height),l2depth); | ||||
|    } | ||||
| 	  | ||||
|    assert(!intelObj->mt); | ||||
|    intelObj->mt = intel_miptree_create( intel, | ||||
| 					intelObj->base.Target, | ||||
| 					intelImage->base.InternalFormat, | ||||
| 					firstLevel, | ||||
| 					lastLevel, | ||||
| 					width, | ||||
| 					height, | ||||
| 					depth, | ||||
| 					intelImage->base.TexFormat->TexelBytes, | ||||
| 					intelImage->base.IsCompressed ); | ||||
|  | ||||
|    DBG("%s - success\n", __FUNCTION__); | ||||
| } | ||||
|     | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLuint target_to_face( GLenum target ) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: | ||||
|       return ((GLuint) target -  | ||||
| 	      (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); | ||||
|    default: | ||||
|       return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelTexImage(GLcontext *ctx,  | ||||
| 			  GLint dims, | ||||
| 			  GLenum target, GLint level, | ||||
| 			  GLint internalFormat, | ||||
| 			  GLint width, GLint height, GLint depth, | ||||
| 			  GLint border, | ||||
| 			  GLenum format, GLenum type, const void *pixels, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  struct gl_texture_object *texObj, | ||||
| 			  struct gl_texture_image *texImage) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(texObj); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|    GLint postConvWidth = width; | ||||
|    GLint postConvHeight = height; | ||||
|    GLint texelBytes, sizeInBytes; | ||||
|    GLuint dstRowStride; | ||||
|    GLuint dstImageStride; | ||||
|  | ||||
|  | ||||
|    DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, | ||||
| 		_mesa_lookup_enum_by_nr(target), | ||||
| 		level, | ||||
| 		width, height, depth, border); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    intelImage->face = target_to_face( target ); | ||||
|    intelImage->level = level; | ||||
|  | ||||
|    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { | ||||
|       _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, | ||||
|                                          &postConvHeight); | ||||
|    } | ||||
|  | ||||
|    /* choose the texture format */ | ||||
|    texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat,  | ||||
| 						  format, type); | ||||
|  | ||||
|    assert(texImage->TexFormat); | ||||
|  | ||||
|    switch (dims) { | ||||
|    case 1: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; | ||||
|       break; | ||||
|    case 2: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; | ||||
|       break; | ||||
|    case 3: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df; | ||||
|       break; | ||||
|    default: | ||||
|       assert(0); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    texelBytes = texImage->TexFormat->TexelBytes; | ||||
|  | ||||
|  | ||||
|    /* Minimum pitch of 32 bytes */ | ||||
|    if (postConvWidth * texelBytes < 32) { | ||||
|       postConvWidth = 32 / texelBytes; | ||||
|       texImage->RowStride = postConvWidth; | ||||
|    } | ||||
|  | ||||
|    assert(texImage->RowStride == postConvWidth); | ||||
|  | ||||
|    /* Release the reference to a potentially orphaned buffer.    | ||||
|     * Release any old malloced memory. | ||||
|     */ | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|       assert(!texImage->Data); | ||||
|    } | ||||
|    else if (texImage->Data) { | ||||
|       free(texImage->Data); | ||||
|    } | ||||
|  | ||||
|    /* If this is the only texture image in the tree, could call | ||||
|     * bmBufferData with NULL data to free the old block and avoid | ||||
|     * waiting on any outstanding fences. | ||||
|     */ | ||||
|    if (intelObj->mt &&  | ||||
|        intelObj->mt->first_level == level && | ||||
|        intelObj->mt->last_level == level && | ||||
|        intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB && | ||||
|        !intel_miptree_match_image(intelObj->mt, &intelImage->base, | ||||
| 				 intelImage->face, intelImage->level)) { | ||||
|  | ||||
|       DBG("release it\n"); | ||||
|       intel_miptree_release(intel, &intelObj->mt);  | ||||
|       assert(!intelObj->mt); | ||||
|    } | ||||
|     | ||||
|    if (!intelObj->mt) { | ||||
|       guess_and_alloc_mipmap_tree(intel, intelObj, intelImage); | ||||
|       if (!intelObj->mt) | ||||
| 	 _mesa_printf("guess_and_alloc_mipmap_tree: failed\n"); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (intelObj->mt &&  | ||||
|        intelObj->mt != intelImage->mt && | ||||
|        intel_miptree_match_image(intelObj->mt, &intelImage->base, | ||||
| 				 intelImage->face, intelImage->level)) { | ||||
|        | ||||
|       if (intelImage->mt) { | ||||
| 	 intel_miptree_release(intel, &intelImage->mt); | ||||
|       } | ||||
|  | ||||
|       intel_miptree_reference(&intelImage->mt, intelObj->mt); | ||||
|       assert(intelImage->mt); | ||||
|    } | ||||
|  | ||||
|    if (!intelImage->mt) | ||||
|       _mesa_printf("XXX: Image did not fit into tree - storing in local memory!\n"); | ||||
|  | ||||
|    /* intelCopyTexImage calls this function with pixels == NULL, with | ||||
|     * the expectation that the mipmap tree will be set up but nothing | ||||
|     * more will be done.  This is where those calls return: | ||||
|     */ | ||||
|    pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,  | ||||
| 					format, type, | ||||
| 					pixels, unpack, "glTexImage"); | ||||
|    if (!pixels)  | ||||
|       return; | ||||
|     | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|     | ||||
|    if (intelImage->mt) { | ||||
|       texImage->Data = intel_miptree_image_map(intel,  | ||||
| 					       intelImage->mt,  | ||||
| 					       intelImage->face,  | ||||
| 					       intelImage->level,  | ||||
| 					       &dstRowStride, | ||||
| 					       &dstImageStride);	  | ||||
|    } | ||||
|    else { | ||||
|       /* Allocate regular memory and store the image there temporarily.   */ | ||||
|       if (texImage->IsCompressed) { | ||||
| 	 sizeInBytes = texImage->CompressedSize; | ||||
|          dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width); | ||||
| 	 dstImageStride = 0;	/* ? */ | ||||
| 	 assert(dims != 3); | ||||
|       } | ||||
|       else { | ||||
|          dstRowStride = postConvWidth * texelBytes; | ||||
| 	 dstImageStride = dstRowStride * postConvHeight; | ||||
| 	 sizeInBytes = depth * dstImageStride; | ||||
|       } | ||||
|       texImage->Data = malloc(sizeInBytes); | ||||
|    } | ||||
|  | ||||
|    fprintf(stderr,  | ||||
| 	   "Upload image %dx%dx%d row_len %x " | ||||
| 	   "pitch %x depth_pitch %x\n", | ||||
| 	   width, height, depth, | ||||
| 	   width * texelBytes, dstRowStride, dstImageStride); | ||||
|       | ||||
|    /* Copy data.  Would like to know when it's ok for us to eg. use | ||||
|     * the blitter to copy.  Or, use the hardware to do the format | ||||
|     * conversion and copy: | ||||
|     */ | ||||
|    if (!texImage->TexFormat->StoreImage(ctx, dims, | ||||
| 					texImage->_BaseFormat, | ||||
| 					texImage->TexFormat, | ||||
| 					texImage->Data, | ||||
| 					0, 0, 0,  /* dstX/Y/Zoffset */ | ||||
| 					dstRowStride, dstImageStride, | ||||
| 					width, height, depth, | ||||
| 					format, type, pixels, unpack)) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); | ||||
|    } | ||||
|  | ||||
|    _mesa_unmap_teximage_pbo(ctx, unpack); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap -- this can be accelerated now. | ||||
|     */ | ||||
|    if (level == texObj->BaseLevel &&  | ||||
|        texObj->GenerateMipmap) { | ||||
|       intel_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void intelTexImage3D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint height, GLint depth, | ||||
| 		     GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *unpack, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage( ctx, 3, target, level,  | ||||
| 		  internalFormat, width, height, depth, border, | ||||
| 		  format, type, pixels, | ||||
| 		  unpack, texObj, texImage ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelTexImage2D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint height, GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *unpack, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage( ctx, 2, target, level,  | ||||
| 		  internalFormat, width, height, 1, border, | ||||
| 		  format, type, pixels, | ||||
| 		  unpack, texObj, texImage ); | ||||
| } | ||||
|  | ||||
| void intelTexImage1D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *unpack, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage( ctx, 1, target, level,  | ||||
| 		  internalFormat, width, 1, 1, border, | ||||
| 		  format, type, pixels, | ||||
| 		  unpack, texObj, texImage ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										178
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
|  | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "texobj.h" | ||||
| #include "texstore.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
|  | ||||
|  | ||||
| static void intelTexSubimage (GLcontext *ctx, | ||||
| 			      GLint dims, | ||||
| 			      GLenum target, GLint level, | ||||
| 			      GLint xoffset, GLint yoffset, GLint zoffset, | ||||
| 			      GLint width, GLint height, GLint depth, | ||||
| 			      GLenum format, GLenum type, const void *pixels, | ||||
| 			      const struct gl_pixelstore_attrib *packing, | ||||
| 			      struct gl_texture_object *texObj, | ||||
| 			      struct gl_texture_image *texImage) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|    GLuint dstImageStride; | ||||
|    GLuint dstRowStride; | ||||
|  | ||||
|    DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, | ||||
| 		_mesa_lookup_enum_by_nr(target), | ||||
| 		level, | ||||
| 		xoffset, yoffset, | ||||
| 		width, height); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type, | ||||
|                                         pixels, packing, "glTexSubImage2D"); | ||||
|    if (!pixels) | ||||
|       return; | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* Map buffer if necessary.  Need to lock to prevent other contexts | ||||
|     * from uploading the buffer under us. | ||||
|     */ | ||||
|    if (intelImage->mt)  | ||||
|       texImage->Data = intel_miptree_image_map(intel,  | ||||
| 					       intelImage->mt,  | ||||
| 					       intelImage->face,  | ||||
| 					       intelImage->level,  | ||||
| 					       &dstRowStride, | ||||
| 					       &dstImageStride ); | ||||
|        | ||||
|    assert(dstRowStride); | ||||
|  | ||||
|    if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, | ||||
| 					texImage->TexFormat, | ||||
| 					texImage->Data, | ||||
| 					xoffset, yoffset, zoffset, | ||||
| 					dstRowStride, dstImageStride, | ||||
| 					width, height, depth, | ||||
| 					format, type, pixels, packing)) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); | ||||
|    } | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap */ | ||||
|    if (level == texObj->BaseLevel && texObj->GenerateMipmap) { | ||||
|       _mesa_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    _mesa_unmap_teximage_pbo(ctx, packing); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelTexSubImage3D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, GLint yoffset, GLint zoffset, | ||||
| 			GLsizei width, GLsizei height, GLsizei depth, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage) | ||||
| { | ||||
|  | ||||
|    intelTexSubimage(ctx, 3, | ||||
| 		    target, level,  | ||||
| 		    xoffset, yoffset, zoffset, | ||||
| 		    width, height, depth, | ||||
| 		    format, type, pixels, packing, texObj, | ||||
| 		    texImage); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelTexSubImage2D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, GLint yoffset, | ||||
| 			GLsizei width, GLsizei height, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage) | ||||
| { | ||||
|  | ||||
|    intelTexSubimage(ctx, 2, | ||||
| 		    target, level,  | ||||
| 		    xoffset, yoffset, 0, | ||||
| 		    width, height, 1, | ||||
| 		    format, type, pixels, packing, texObj, | ||||
| 		    texImage); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelTexSubImage1D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, | ||||
| 			GLsizei width, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexSubimage(ctx, 1, | ||||
| 		    target, level,  | ||||
| 		    xoffset, 0, 0, | ||||
| 		    width, 1, 1, | ||||
| 		    format, type, pixels, packing, texObj, | ||||
| 		    texImage); | ||||
|  | ||||
| } | ||||
							
								
								
									
										249
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
| #include "bufmgr.h" | ||||
|  | ||||
| /** | ||||
|  * Compute which mipmap levels that really need to be sent to the hardware. | ||||
|  * This depends on the base image size, GL_TEXTURE_MIN_LOD, | ||||
|  * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. | ||||
|  */ | ||||
| static void intel_calculate_first_last_level( struct intel_texture_object *intelObj ) | ||||
| { | ||||
|    struct gl_texture_object *tObj = &intelObj->base; | ||||
|    const struct gl_texture_image * const baseImage = | ||||
|        tObj->Image[0][tObj->BaseLevel]; | ||||
|  | ||||
|    /* These must be signed values.  MinLod and MaxLod can be negative numbers, | ||||
|     * and having firstLevel and lastLevel as signed prevents the need for | ||||
|     * extra sign checks. | ||||
|     */ | ||||
|    int   firstLevel; | ||||
|    int   lastLevel; | ||||
|  | ||||
|    /* Yes, this looks overly complicated, but it's all needed. | ||||
|     */ | ||||
|    switch (tObj->Target) { | ||||
|    case GL_TEXTURE_1D: | ||||
|    case GL_TEXTURE_2D: | ||||
|    case GL_TEXTURE_3D: | ||||
|    case GL_TEXTURE_CUBE_MAP: | ||||
|       if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { | ||||
|          /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. | ||||
|           */ | ||||
|          firstLevel = lastLevel = tObj->BaseLevel; | ||||
|       } | ||||
|       else { | ||||
| 	 firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5); | ||||
| 	 firstLevel = MAX2(firstLevel, tObj->BaseLevel); | ||||
| 	 lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5); | ||||
| 	 lastLevel = MAX2(lastLevel, tObj->BaseLevel); | ||||
| 	 lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); | ||||
| 	 lastLevel = MIN2(lastLevel, tObj->MaxLevel); | ||||
| 	 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ | ||||
|       } | ||||
|       break; | ||||
|    case GL_TEXTURE_RECTANGLE_NV: | ||||
|    case GL_TEXTURE_4D_SGIS: | ||||
|       firstLevel = lastLevel = 0; | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* save these values */ | ||||
|    intelObj->firstLevel = firstLevel; | ||||
|    intelObj->lastLevel = lastLevel; | ||||
| } | ||||
|  | ||||
| static void copy_image_data_to_tree( struct intel_context *intel, | ||||
| 				     struct intel_texture_object *intelObj, | ||||
| 				     struct intel_texture_image *intelImage ) | ||||
| { | ||||
|    if (intelImage->mt) { | ||||
|       /* Copy potentially with the blitter: | ||||
|        */ | ||||
|       intel_miptree_image_copy(intel, | ||||
| 			       intelObj->mt, | ||||
| 			       intelImage->face, | ||||
| 			       intelImage->level, | ||||
| 			       intelImage->mt); | ||||
|  | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|    } | ||||
|    else { | ||||
|       assert(intelImage->base.Data != NULL); | ||||
|  | ||||
|       /* More straightforward upload.   | ||||
|        */ | ||||
|       intel_miptree_image_data(intel, | ||||
| 			       intelObj->mt, | ||||
| 			       intelImage->face, | ||||
| 			       intelImage->level, | ||||
| 			       intelImage->base.Data, | ||||
| 			       intelImage->base.RowStride, | ||||
| 			       intelImage->base.RowStride * intelImage->base.Height); | ||||
|  | ||||
|       free(intelImage->base.Data); | ||||
|       intelImage->base.Data = NULL; | ||||
|    } | ||||
|  | ||||
|    intel_miptree_reference(&intelImage->mt, intelObj->mt); | ||||
| } | ||||
|  | ||||
|  | ||||
| /*   | ||||
|  */ | ||||
| GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit ) | ||||
| { | ||||
|    struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(tObj); | ||||
|  | ||||
|    GLuint face, i; | ||||
|    GLuint nr_faces = 0; | ||||
|    struct intel_texture_image *firstImage; | ||||
|  | ||||
|    /* We know/require this is true by now:  | ||||
|     */ | ||||
|    assert(intelObj->base.Complete); | ||||
|  | ||||
|    /* What levels must the tree include at a minimum? | ||||
|     */ | ||||
|    intel_calculate_first_last_level( intelObj ); | ||||
|    firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]); | ||||
|  | ||||
|    /* Fallback case: | ||||
|     */ | ||||
|    if (firstImage->base.Border) { | ||||
|       if (intelObj->mt) { | ||||
| 	 intel_miptree_release(intel, &intelObj->mt); | ||||
|       } | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* If both firstImage and intelObj have a tree which can contain | ||||
|     * all active images, favour firstImage.  Note that because of the | ||||
|     * completeness requirement, we know that the image dimensions | ||||
|     * will match. | ||||
|     */ | ||||
|    if (firstImage->mt && | ||||
|        firstImage->mt != intelObj->mt && | ||||
|        firstImage->mt->first_level <= intelObj->firstLevel && | ||||
|        firstImage->mt->last_level >= intelObj->lastLevel) { | ||||
|  | ||||
|       if (intelObj->mt)  | ||||
| 	 intel_miptree_release(intel, &intelObj->mt); | ||||
|  | ||||
|       intel_miptree_reference(&intelObj->mt, firstImage->mt); | ||||
|    } | ||||
|  | ||||
|    /* Check tree can hold all active levels.  Check tree matches | ||||
|     * target, imageFormat, etc. | ||||
|     *  | ||||
|     * XXX: For some layouts (eg i945?), the test might have to be | ||||
|     * first_level == firstLevel, as the tree isn't valid except at the | ||||
|     * original start level.  Hope to get around this by | ||||
|     * programming minLod, maxLod, baseLevel into the hardware and | ||||
|     * leaving the tree alone. | ||||
|     */ | ||||
|    if (intelObj->mt && | ||||
|        ((intelObj->mt->first_level > intelObj->firstLevel) || | ||||
| 	(intelObj->mt->last_level < intelObj->lastLevel) || | ||||
| 	(intelObj->mt->internal_format != firstImage->base.InternalFormat))) { | ||||
|       intel_miptree_release(intel, &intelObj->mt); | ||||
|    } | ||||
|        | ||||
|  | ||||
|    /* May need to create a new tree: | ||||
|     */ | ||||
|    if (!intelObj->mt) { | ||||
|       intelObj->mt = intel_miptree_create(intel, | ||||
| 					  intelObj->base.Target, | ||||
| 					  firstImage->base.InternalFormat, | ||||
| 					  intelObj->firstLevel, | ||||
| 					  intelObj->lastLevel, | ||||
| 					  firstImage->base.Width, | ||||
| 					  firstImage->base.Height, | ||||
| 					  firstImage->base.Depth, | ||||
| 					  firstImage->base.TexFormat->TexelBytes, | ||||
| 					  firstImage->base.IsCompressed); | ||||
|    } | ||||
|  | ||||
|    /* Pull in any images not in the object's tree: | ||||
|     */ | ||||
|    nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) { | ||||
| 	 struct intel_texture_image *intelImage =  | ||||
| 	    intel_texture_image(intelObj->base.Image[face][i]); | ||||
| 	  | ||||
| 	 /* Need to import images in main memory or held in other trees. | ||||
| 	  */ | ||||
| 	 if (intelObj->mt != intelImage->mt) { | ||||
| 	    copy_image_data_to_tree(intel, | ||||
| 				    intelObj, | ||||
| 				    intelImage); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intel_tex_map_images( struct intel_context *intel, | ||||
| 			   struct intel_texture_object *intelObj ) | ||||
| { | ||||
|    GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    GLuint face, i; | ||||
|     | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) { | ||||
| 	 struct intel_texture_image *intelImage =  | ||||
| 	    intel_texture_image(intelObj->base.Image[face][i]); | ||||
|  | ||||
| 	 /* XXX: Fallbacks will fail for 3d textures because core mesa | ||||
| 	  * doesn't have a place to put ImageStride -- assumes each | ||||
| 	  * teximage's depth slices are packed contiguously.  This | ||||
| 	  * isn't true for i915. | ||||
| 	  */ | ||||
| 	 if (intelImage->mt) { | ||||
| 	    intelImage->base.Data =  | ||||
| 	       intel_miptree_image_map(intel,  | ||||
| 				       intelImage->mt, | ||||
| 				       intelImage->face, | ||||
| 				       intelImage->level, | ||||
| 				       &intelImage->base.RowStride, | ||||
| 				       NULL); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intel_tex_unmap_images( struct intel_context *intel, | ||||
| 			     struct intel_texture_object *intelObj ) | ||||
| { | ||||
|    GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    GLuint face, i; | ||||
|  | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) { | ||||
| 	 struct intel_texture_image *intelImage =  | ||||
| 	    intel_texture_image(intelObj->base.Image[face][i]); | ||||
|  | ||||
| 	 if (intelImage->mt) { | ||||
| 	    intel_miptree_image_unmap(intel, intelImage->mt); | ||||
| 	    intelImage->base.Data = NULL; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
| @@ -38,14 +38,108 @@ | ||||
| #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 ); | ||||
|  | ||||
| /* The simplest but least-good technique for integrating new buffer | ||||
|  * management: | ||||
|  * | ||||
|  * LOCK_HARDWARE | ||||
|  *   validate_buffers | ||||
|  *   emit_state to batch | ||||
|  *   emit_vertices to batch | ||||
|  *   flush batch | ||||
|  *   fence_buffers | ||||
|  * UNLOCK_HARDWARE | ||||
|  * | ||||
|  * Will look later at ways to get the emit_state and emit_vertices out | ||||
|  * of the locked region - vertex buffers, second batch buffer for | ||||
|  * primitives, relocation fixups for texture addresses. | ||||
|  */ | ||||
| static void intel_flush_inline_primitive( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint used = intel->batch->ptr - intel->prim.start_ptr; | ||||
|  | ||||
|    assert(intel->prim.primitive != ~0); | ||||
|  | ||||
|    if (used < 8) | ||||
|       goto do_discard; | ||||
|  | ||||
|    *(int *)intel->prim.start_ptr = (_3DPRIMITIVE |  | ||||
| 				    intel->prim.primitive | | ||||
| 				    (used/4-2)); | ||||
|  | ||||
|    goto finished; | ||||
|     | ||||
|  do_discard: | ||||
|    intel->batch->ptr -= used; | ||||
|  | ||||
|  finished: | ||||
|    intel->prim.primitive = ~0; | ||||
|    intel->prim.start_ptr = 0; | ||||
|    intel->prim.flush = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Emit a primitive referencing vertices in a vertex buffer. | ||||
|  */ | ||||
| void intelStartInlinePrimitive( struct intel_context *intel,  | ||||
| 				GLuint prim,  | ||||
| 				GLuint batch_flags ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|     | ||||
|    /* Emit a slot which will be filled with the inline primitive | ||||
|     * command later. | ||||
|     */ | ||||
|    BEGIN_BATCH(2, batch_flags); | ||||
|    OUT_BATCH( 0 ); | ||||
|  | ||||
|    intel->prim.start_ptr = intel->batch->ptr; | ||||
|    intel->prim.primitive = prim; | ||||
|    intel->prim.flush = intel_flush_inline_primitive; | ||||
|  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelWrapInlinePrimitive( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint prim = intel->prim.primitive; | ||||
|    GLuint batchflags = intel->batch->flags; | ||||
|  | ||||
|    intel_flush_inline_primitive(intel); | ||||
|    intel_batchbuffer_flush(intel->batch); | ||||
|  | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|    intelStartInlinePrimitive( intel, prim, batchflags ); /* ??? */ | ||||
| } | ||||
|  | ||||
| GLuint *intelExtendInlinePrimitive( struct intel_context *intel,  | ||||
| 				    GLuint dwords ) | ||||
| { | ||||
|    GLuint sz = dwords * sizeof(GLuint); | ||||
|    GLuint *ptr; | ||||
|  | ||||
|    if (intel_batchbuffer_space(intel->batch) < sz)  | ||||
|       intelWrapInlinePrimitive( intel ); | ||||
|  | ||||
|    ptr = (GLuint *)intel->batch->ptr; | ||||
|    intel->batch->ptr += sz; | ||||
|  | ||||
|    return ptr; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /*********************************************************************** | ||||
|  *                    Emit primitives as inline vertices               * | ||||
|  ***********************************************************************/ | ||||
| @@ -63,22 +157,18 @@ do {								\ | ||||
| #else | ||||
| #define COPY_DWORDS( j, vb, vertsize, v )	\ | ||||
| do {						\ | ||||
|    if (0) fprintf(stderr, "\n");	\ | ||||
|    for ( j = 0 ; j < vertsize ; j++ ) {		\ | ||||
|       if (0) fprintf(stderr, "   -- v(%d): %x/%f\n",j,	\ | ||||
| 	      ((GLuint *)v)[j],			\ | ||||
| 	      ((GLfloat *)v)[j]);		\ | ||||
|       vb[j] = ((GLuint *)v)[j];			\ | ||||
|    }						\ | ||||
|    vb += vertsize;				\ | ||||
| } while (0) | ||||
| #endif | ||||
|  | ||||
| static void __inline__ intel_draw_quad( intelContextPtr intel, | ||||
| 					intelVertexPtr v0, | ||||
| 					intelVertexPtr v1, | ||||
| 					intelVertexPtr v2, | ||||
| 					intelVertexPtr v3 ) | ||||
| static void intel_draw_quad( struct intel_context *intel, | ||||
| 			     intelVertexPtr v0, | ||||
| 			     intelVertexPtr v1, | ||||
| 			     intelVertexPtr v2, | ||||
| 			     intelVertexPtr v3 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize ); | ||||
| @@ -92,10 +182,10 @@ static void __inline__ intel_draw_quad( intelContextPtr intel, | ||||
|    COPY_DWORDS( j, vb, vertsize, v3 ); | ||||
| } | ||||
|  | ||||
| static void __inline__ intel_draw_triangle( intelContextPtr intel, | ||||
| 					    intelVertexPtr v0, | ||||
| 					    intelVertexPtr v1, | ||||
| 					    intelVertexPtr v2 ) | ||||
| static void intel_draw_triangle( struct intel_context *intel, | ||||
| 				 intelVertexPtr v0, | ||||
| 				 intelVertexPtr v1, | ||||
| 				 intelVertexPtr v2 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, 3 * vertsize ); | ||||
| @@ -107,9 +197,9 @@ static void __inline__ intel_draw_triangle( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ void intel_draw_line( intelContextPtr intel, | ||||
| 					intelVertexPtr v0, | ||||
| 					intelVertexPtr v1 ) | ||||
| static void intel_draw_line( struct intel_context *intel, | ||||
| 			     intelVertexPtr v0, | ||||
| 			     intelVertexPtr v1 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, 2 * vertsize ); | ||||
| @@ -120,8 +210,8 @@ static __inline__ void intel_draw_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ void intel_draw_point( intelContextPtr intel, | ||||
| 					 intelVertexPtr v0 ) | ||||
| static void intel_draw_point( struct intel_context *intel, | ||||
| 			      intelVertexPtr v0 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, vertsize ); | ||||
| @@ -140,7 +230,7 @@ static __inline__ void intel_draw_point( intelContextPtr intel, | ||||
|  *                Fixup for ARB_point_parameters                       * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 ) | ||||
| static void intel_atten_point( struct intel_context *intel, intelVertexPtr v0 ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLfloat psz[4], col[4], restore_psz, restore_alpha; | ||||
| @@ -189,7 +279,7 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intel_wpos_triangle( intelContextPtr intel, | ||||
| static void intel_wpos_triangle( struct intel_context *intel, | ||||
| 				 intelVertexPtr v0, | ||||
| 				 intelVertexPtr v1, | ||||
| 				 intelVertexPtr v2 ) | ||||
| @@ -205,7 +295,7 @@ static void intel_wpos_triangle( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intel_wpos_line( intelContextPtr intel, | ||||
| static void intel_wpos_line( struct intel_context *intel, | ||||
| 			     intelVertexPtr v0, | ||||
| 			     intelVertexPtr v1 ) | ||||
| { | ||||
| @@ -219,7 +309,7 @@ static void intel_wpos_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intel_wpos_point( intelContextPtr intel, | ||||
| static void intel_wpos_point( struct intel_context *intel, | ||||
| 			      intelVertexPtr v0 ) | ||||
| { | ||||
|    GLuint offset = intel->wpos_offset; | ||||
| @@ -349,7 +439,7 @@ do {							\ | ||||
| #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] | ||||
|  | ||||
| #define LOCAL_VARS(n)							\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);				\ | ||||
|    struct intel_context *intel = intel_context(ctx);				\ | ||||
|    GLuint color[n], spec[n];						\ | ||||
|    GLuint coloroffset = intel->coloroffset;		\ | ||||
|    GLboolean specoffset = intel->specoffset;			\ | ||||
| @@ -481,7 +571,7 @@ static void init_rast_tab( void ) | ||||
|  * primitives. | ||||
|  */ | ||||
| static void | ||||
| intel_fallback_tri( intelContextPtr intel, | ||||
| intel_fallback_tri( struct intel_context *intel, | ||||
| 		   intelVertex *v0, | ||||
| 		   intelVertex *v1, | ||||
| 		   intelVertex *v2 ) | ||||
| @@ -502,7 +592,7 @@ intel_fallback_tri( intelContextPtr intel, | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_fallback_line( intelContextPtr intel, | ||||
| intel_fallback_line( struct intel_context *intel, | ||||
| 		    intelVertex *v0, | ||||
| 		    intelVertex *v1 ) | ||||
| { | ||||
| @@ -520,22 +610,6 @@ intel_fallback_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_fallback_point( intelContextPtr intel, | ||||
| 		     intelVertex *v0 ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    SWvertex v[1]; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "\n%s\n", __FUNCTION__); | ||||
|  | ||||
|    _swsetup_Translate( ctx, v0, &v[0] ); | ||||
|    intelSpanRenderStart( ctx ); | ||||
|    _swrast_Point( ctx, &v[0] ); | ||||
|    intelSpanRenderFinish( ctx ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
| @@ -552,7 +626,7 @@ intel_fallback_point( intelContextPtr intel, | ||||
| #define INIT(x) intelRenderPrimitive( ctx, x ) | ||||
| #undef LOCAL_VARS | ||||
| #define LOCAL_VARS						\ | ||||
|     intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|     struct intel_context *intel = intel_context(ctx);			\ | ||||
|     GLubyte *vertptr = (GLubyte *)intel->verts;			\ | ||||
|     const GLuint vertsize = intel->vertex_size;       	\ | ||||
|     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;	\ | ||||
| @@ -578,7 +652,7 @@ intel_fallback_point( intelContextPtr intel, | ||||
| static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
| 				   GLuint n ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; | ||||
|    GLuint prim = intel->render_primitive; | ||||
| @@ -609,7 +683,7 @@ static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) | ||||
| static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
| 				       GLuint n ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    const GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, (n-2) * 3 * vertsize ); | ||||
|    GLubyte *vertptr = (GLubyte *)intel->verts; | ||||
| @@ -630,17 +704,13 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
|  | ||||
|  | ||||
|  | ||||
| #define POINT_FALLBACK (0) | ||||
| #define LINE_FALLBACK (DD_LINE_STIPPLE) | ||||
| #define TRI_FALLBACK (0) | ||||
| #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\ | ||||
|                             DD_TRI_STIPPLE|DD_POINT_ATTEN) | ||||
| #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED) | ||||
| #define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN) | ||||
| #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED) | ||||
|  | ||||
| void intelChooseRenderState(GLcontext *ctx) | ||||
| { | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint flags = ctx->_TriangleCaps; | ||||
|    struct fragment_program *fprog = ctx->FragmentProgram._Current; | ||||
|    GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS)); | ||||
| @@ -672,19 +742,14 @@ void intelChooseRenderState(GLcontext *ctx) | ||||
| 	 intel->draw_tri = intel_draw_triangle; | ||||
|       } | ||||
|  | ||||
| #if 0 | ||||
|       /* 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 & 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; | ||||
|  | ||||
| @@ -693,6 +758,8 @@ void intelChooseRenderState(GLcontext *ctx) | ||||
|  | ||||
| 	 index |= INTEL_FALLBACK_BIT; | ||||
|       } | ||||
| #endif | ||||
|  | ||||
|    } | ||||
|  | ||||
|    if (intel->RenderIndex != index) { | ||||
| @@ -740,7 +807,7 @@ static const GLenum reduced_prim[GL_POLYGON+1] = { | ||||
|  | ||||
| static void intelRunPipeline( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (intel->NewGLState) { | ||||
|       if (intel->NewGLState & _NEW_TEXTURE) { | ||||
| @@ -760,13 +827,21 @@ static void intelRunPipeline( GLcontext *ctx ) | ||||
|  | ||||
| static void intelRenderStart( GLcontext *ctx ) | ||||
| { | ||||
|    INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) ); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    intel->vtbl.render_start( intel_context(ctx) ); | ||||
|    intel->vtbl.emit_state( intel ); | ||||
| } | ||||
|  | ||||
| static void intelRenderFinish( GLcontext *ctx ) | ||||
| { | ||||
|    if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT) | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (intel->RenderIndex & INTEL_FALLBACK_BIT) | ||||
|       _swrast_flush( ctx ); | ||||
|  | ||||
|    if (intel->prim.flush) | ||||
|       intel->prim.flush(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -777,7 +852,7 @@ static void intelRenderFinish( GLcontext *ctx ) | ||||
|   */ | ||||
| static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %s %x\n", __FUNCTION__,  | ||||
| @@ -788,111 +863,175 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
|    /* Start a new primitive.  Arrange to have it flushed later on. | ||||
|     */ | ||||
|    if (hwprim != intel->prim.primitive)  | ||||
|       intelStartInlinePrimitive( intel, hwprim ); | ||||
|       intelStartInlinePrimitive( intel, hwprim, INTEL_BATCH_CLIPRECTS ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  /*  | ||||
|   */ | ||||
|  static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ) | ||||
|  { | ||||
|     intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
| static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|     if (0) | ||||
|        fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|  | ||||
|     /* Let some clipping routines know which primitive they're dealing | ||||
|      * with. | ||||
|      */ | ||||
|     intel->render_primitive = prim; | ||||
|    /* Let some clipping routines know which primitive they're dealing | ||||
|     * with. | ||||
|     */ | ||||
|    intel->render_primitive = prim; | ||||
|  | ||||
|     /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled | ||||
|      * triangles.  The rasterized primitive will always be reset by | ||||
|      * lower level functions in that case, potentially pingponging the | ||||
|      * state: | ||||
|      */ | ||||
|     if (reduced_prim[prim] == GL_TRIANGLES &&  | ||||
| 	(ctx->_TriangleCaps & DD_TRI_UNFILLED)) | ||||
|        return; | ||||
|    /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled | ||||
|     * triangles.  The rasterized primitive will always be reset by | ||||
|     * lower level functions in that case, potentially pingponging the | ||||
|     * state: | ||||
|     */ | ||||
|    if (reduced_prim[prim] == GL_TRIANGLES &&  | ||||
|        (ctx->_TriangleCaps & DD_TRI_UNFILLED)) | ||||
|       return; | ||||
|  | ||||
|     /* Set some primitive-dependent state and Start? a new primitive. | ||||
|      */ | ||||
|     intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] ); | ||||
|  } | ||||
|    /* Set some primitive-dependent state and Start? a new primitive. | ||||
|     */ | ||||
|    intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  /**********************************************************************/ | ||||
|  /*           Transition to/from hardware rasterization.               */ | ||||
|  /**********************************************************************/ | ||||
|  | ||||
|  static char *fallbackStrings[] = { | ||||
|     "Texture", | ||||
|     "Draw buffer", | ||||
|     "Read buffer", | ||||
|     "Color mask", | ||||
|     "Render mode", | ||||
|     "Stencil", | ||||
|     "Stipple", | ||||
|     "User disable" | ||||
|  }; | ||||
| static char *fallbackStrings[] = { | ||||
|    "Texture", | ||||
|    "Draw buffer", | ||||
|    "Read buffer", | ||||
|    "Color mask", | ||||
|    "Render mode", | ||||
|    "Stencil", | ||||
|    "Stipple", | ||||
|    "User disable" | ||||
| }; | ||||
|  | ||||
|  | ||||
|  static char *getFallbackString(GLuint bit) | ||||
|  { | ||||
|     int i = 0; | ||||
|     while (bit > 1) { | ||||
|        i++; | ||||
|        bit >>= 1; | ||||
|     } | ||||
|     return fallbackStrings[i]; | ||||
|  } | ||||
| static char *getFallbackString(GLuint bit) | ||||
| { | ||||
|    int i = 0; | ||||
|    while (bit > 1) { | ||||
|       i++; | ||||
|       bit >>= 1; | ||||
|    } | ||||
|    return fallbackStrings[i]; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ) | ||||
|  { | ||||
|     GLcontext *ctx = &intel->ctx; | ||||
|     TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|     GLuint oldfallback = intel->Fallback; | ||||
| void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    GLuint oldfallback = intel->Fallback; | ||||
|  | ||||
|     if (mode) { | ||||
|        intel->Fallback |= bit; | ||||
|        if (oldfallback == 0) { | ||||
| 	  intelFlush(ctx); | ||||
| 	  if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	     fprintf(stderr, "ENTER FALLBACK %x: %s\n", | ||||
| 		     bit, getFallbackString( bit )); | ||||
| 	  _swsetup_Wakeup( ctx ); | ||||
| 	  intel->RenderIndex = ~0; | ||||
|        } | ||||
|     } | ||||
|     else { | ||||
|        intel->Fallback &= ~bit; | ||||
|        if (oldfallback == bit) { | ||||
| 	  _swrast_flush( ctx ); | ||||
| 	  if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	     fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit )); | ||||
| 	  tnl->Driver.Render.Start = intelRenderStart; | ||||
| 	  tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; | ||||
| 	  tnl->Driver.Render.Finish = intelRenderFinish; | ||||
| 	  tnl->Driver.Render.BuildVertices = _tnl_build_vertices; | ||||
| 	  tnl->Driver.Render.CopyPV = _tnl_copy_pv; | ||||
| 	  tnl->Driver.Render.Interp = _tnl_interp; | ||||
|    if (mode) { | ||||
|       intel->Fallback |= bit; | ||||
|       if (oldfallback == 0) { | ||||
| 	 intelFlush(ctx); | ||||
| 	 if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	    fprintf(stderr, "ENTER FALLBACK %x: %s\n", | ||||
| 		    bit, getFallbackString( bit )); | ||||
| 	 _swsetup_Wakeup( ctx ); | ||||
| 	 intel->RenderIndex = ~0; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       intel->Fallback &= ~bit; | ||||
|       if (oldfallback == bit) { | ||||
| 	 _swrast_flush( ctx ); | ||||
| 	 if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	    fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit )); | ||||
| 	 tnl->Driver.Render.Start = intelRenderStart; | ||||
| 	 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; | ||||
| 	 tnl->Driver.Render.Finish = intelRenderFinish; | ||||
| 	 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; | ||||
| 	 tnl->Driver.Render.CopyPV = _tnl_copy_pv; | ||||
| 	 tnl->Driver.Render.Interp = _tnl_interp; | ||||
|  | ||||
| 	  _tnl_invalidate_vertex_state( ctx, ~0 ); | ||||
| 	  _tnl_invalidate_vertices( ctx, ~0 ); | ||||
| 	  _tnl_install_attrs( ctx,  | ||||
| 			      intel->vertex_attrs,  | ||||
| 			      intel->vertex_attr_count, | ||||
| 			      intel->ViewportMatrix.m, 0 );  | ||||
| 	 _tnl_invalidate_vertex_state( ctx, ~0 ); | ||||
| 	 _tnl_invalidate_vertices( ctx, ~0 ); | ||||
| 	 _tnl_install_attrs( ctx,  | ||||
| 			     intel->vertex_attrs,  | ||||
| 			     intel->vertex_attr_count, | ||||
| 			     intel->ViewportMatrix.m, 0 );  | ||||
|  | ||||
| 	  intel->NewGLState |= _INTEL_NEW_RENDERSTATE; | ||||
|        } | ||||
|     } | ||||
|  } | ||||
| 	 intel->NewGLState |= _INTEL_NEW_RENDERSTATE; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /*             Used only with the metaops callbacks.                  */ | ||||
| /**********************************************************************/ | ||||
| void intel_meta_draw_quad(struct intel_context *intel,  | ||||
| 			  GLfloat x0, GLfloat x1, | ||||
| 			  GLfloat y0, GLfloat y1,  | ||||
| 			  GLfloat z, | ||||
| 			  GLuint color, | ||||
| 			  GLfloat s0, GLfloat s1, | ||||
| 			  GLfloat t0, GLfloat t1, | ||||
| 			  GLuint flags) | ||||
| { | ||||
|    union fi *vb; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: %f,%f-%f,%f 0x%x %f,%f-%f,%f\n", | ||||
| 	      __FUNCTION__, | ||||
| 	      x0,y0,x1,y1,color,s0,t0,s1,t1); | ||||
|  | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|  | ||||
|    intelStartInlinePrimitive( intel, PRIM3D_TRIFAN, flags );   | ||||
|    vb = (union fi *)intelExtendInlinePrimitive( intel, 4 * 6 ); | ||||
|  | ||||
|  | ||||
|    /* initial vertex, left bottom */ | ||||
|    vb[0].f = x0; | ||||
|    vb[1].f = y0; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s0; | ||||
|    vb[5].f = t0; | ||||
|    vb += 6; | ||||
|  | ||||
|    /* right bottom */ | ||||
|    vb[0].f = x1; | ||||
|    vb[1].f = y0; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s1; | ||||
|    vb[5].f = t0; | ||||
|    vb += 6; | ||||
|  | ||||
|    /* right top */ | ||||
|    vb[0].f = x1; | ||||
|    vb[1].f = y1; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s1; | ||||
|    vb[5].f = t1; | ||||
|    vb += 6; | ||||
|  | ||||
|    /* left top */ | ||||
|    vb[0].f = x0; | ||||
|    vb[1].f = y1; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s0; | ||||
|    vb[5].f = t1; | ||||
|  | ||||
|    if (intel->prim.flush) | ||||
|       intel->prim.flush(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /*                            Initialization.                         */ | ||||
|   | ||||
| @@ -30,6 +30,8 @@ | ||||
|  | ||||
| #include "mtypes.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| #define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |		\ | ||||
| 			       _DD_NEW_TRI_UNFILLED |		\ | ||||
| 			       _DD_NEW_TRI_LIGHT_TWOSIDE |	\ | ||||
| @@ -40,7 +42,23 @@ | ||||
|  | ||||
| extern void intelInitTriFuncs( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelPrintRenderState( const char *msg, GLuint state ); | ||||
| extern void intelChooseRenderState( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelStartInlinePrimitive( struct intel_context *intel, GLuint prim, GLuint flags ); | ||||
| extern void intelWrapInlinePrimitive( struct intel_context *intel ); | ||||
|  | ||||
| GLuint *intelExtendInlinePrimitive( struct intel_context *intel,  | ||||
| 				    GLuint dwords ); | ||||
|  | ||||
|  | ||||
| void intel_meta_draw_quad(struct intel_context *intel,  | ||||
| 			  GLfloat x0, GLfloat x1, | ||||
| 			  GLfloat y0, GLfloat y1,  | ||||
| 			  GLfloat z, | ||||
| 			  GLuint color, | ||||
| 			  GLfloat s0, GLfloat s1, | ||||
| 			  GLfloat t0, GLfloat t1, | ||||
| 			  GLuint flags ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -32,6 +32,7 @@ | ||||
| #include "colormac.h" | ||||
| #include "mtypes.h" | ||||
| #include "program.h" | ||||
| #include "teximage.h" | ||||
| #include "swrast.h" | ||||
| #include "s_blend.h" | ||||
| #include "s_context.h" | ||||
| @@ -368,6 +369,83 @@ _swrast_validate_blend_func( GLcontext *ctx, GLuint n, | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Make sure we have texture image data for all the textures we may need | ||||
|  * for subsequent rendering. | ||||
|  */ | ||||
| static void | ||||
| _swrast_validate_texture_images(GLcontext *ctx) | ||||
| { | ||||
|    SWcontext *swrast = SWRAST_CONTEXT(ctx); | ||||
|    GLuint u; | ||||
|  | ||||
|    if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) { | ||||
|       /* no textures enabled, or no way to validate images! */ | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { | ||||
|       if (ctx->Texture.Unit[u]._ReallyEnabled) { | ||||
|          struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current; | ||||
|          ASSERT(texObj); | ||||
|          if (texObj) { | ||||
|             GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|             GLuint face; | ||||
|             for (face = 0; face < numFaces; face++) { | ||||
|                GLuint lvl; | ||||
|                for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) { | ||||
|                   struct gl_texture_image *texImg = texObj->Image[face][lvl]; | ||||
|                   if (texImg && !texImg->Data) { | ||||
|                      swrast->ValidateTextureImage(ctx, texObj, face, lvl); | ||||
|                      ASSERT(texObj->Image[face][lvl]->Data); | ||||
|                   } | ||||
|                } | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Free the texture image data attached to all currently enabled | ||||
|  * textures.  Meant to be called by device drivers when transitioning | ||||
|  * from software to hardware rendering. | ||||
|  */ | ||||
| void | ||||
| _swrast_eject_texture_images(GLcontext *ctx) | ||||
| { | ||||
|    GLuint u; | ||||
|  | ||||
|    if (!ctx->Texture._EnabledUnits) { | ||||
|       /* no textures enabled */ | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { | ||||
|       if (ctx->Texture.Unit[u]._ReallyEnabled) { | ||||
|          struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current; | ||||
|          ASSERT(texObj); | ||||
|          if (texObj) { | ||||
|             GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|             GLuint face; | ||||
|             for (face = 0; face < numFaces; face++) { | ||||
|                GLuint lvl; | ||||
|                for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) { | ||||
|                   struct gl_texture_image *texImg = texObj->Image[face][lvl]; | ||||
|                   if (texImg && texImg->Data) { | ||||
|                      _mesa_free_texmemory(texImg->Data); | ||||
|                      texImg->Data = NULL; | ||||
|                   } | ||||
|                } | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| _swrast_sleep( GLcontext *ctx, GLbitfield new_state ) | ||||
| { | ||||
| @@ -452,6 +530,9 @@ _swrast_validate_derived( GLcontext *ctx ) | ||||
|       if (swrast->NewState & _NEW_TEXTURE) | ||||
|          _swrast_update_texture_samplers( ctx ); | ||||
|  | ||||
|       if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) | ||||
|          _swrast_validate_texture_images( ctx ); | ||||
|  | ||||
|       swrast->NewState = 0; | ||||
|       swrast->StateChanges = 0; | ||||
|       swrast->InvalidateState = _swrast_invalidate_state; | ||||
|   | ||||
| @@ -226,6 +226,11 @@ typedef void (*swrast_tri_func)( GLcontext *ctx, const SWvertex *, | ||||
|                                  const SWvertex *, const SWvertex *); | ||||
|  | ||||
|  | ||||
| typedef void (*validate_texture_image_func)(GLcontext *ctx, | ||||
|                                             struct gl_texture_object *texObj, | ||||
|                                             GLuint face, GLuint level); | ||||
|  | ||||
|  | ||||
| /** \defgroup Bitmasks | ||||
|  * Bitmasks to indicate which rasterization options are enabled | ||||
|  * (RasterMask) | ||||
| @@ -354,6 +359,8 @@ typedef struct | ||||
|     */ | ||||
|    GLchan *TexelBuffer; | ||||
|  | ||||
|    validate_texture_image_func ValidateTextureImage; | ||||
|  | ||||
| } SWcontext; | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -244,6 +244,10 @@ _swrast_copy_texsubimage3d(GLcontext *ctx, | ||||
|                            GLint x, GLint y, GLsizei width, GLsizei height); | ||||
|  | ||||
|  | ||||
| extern void | ||||
| _swrast_eject_texture_images(GLcontext *ctx); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * The driver interface for the software rasterizer. | ||||
|  * XXX this may go away. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user