Compare commits
	
		
			35 Commits
		
	
	
		
			chadv/arc-
			...
			mesa_20060
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 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 | CC = gcc | ||||||
| CXX = g++ | CXX = g++ | ||||||
|  |  | ||||||
| MKDEP = /usr/X11R6/bin/makedepend | #MKDEP = /usr/X11R6/bin/makedepend | ||||||
| #MKDEP = gcc -M | #MKDEP = gcc -M | ||||||
| #MKDEP_OPTIONS = -MF depend | #MKDEP_OPTIONS = -MF depend | ||||||
|  |  | ||||||
| @@ -63,5 +63,7 @@ WINDOW_SYSTEM=dri | |||||||
|  |  | ||||||
| # gamma are missing because they have not been converted to use the new | # gamma are missing because they have not been converted to use the new | ||||||
| # interface. | # 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 | 	savage sis tdfx trident unichrome ffb | ||||||
|  |  | ||||||
|  | DRI_DIRS = i915  | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ PROGS = \ | |||||||
| 	fplight \ | 	fplight \ | ||||||
| 	gamma \ | 	gamma \ | ||||||
| 	gears \ | 	gears \ | ||||||
|  | 	gearbox \ | ||||||
| 	geartrain \ | 	geartrain \ | ||||||
| 	glinfo \ | 	glinfo \ | ||||||
| 	gloss \ | 	gloss \ | ||||||
| @@ -73,9 +74,8 @@ PROGS = \ | |||||||
|  |  | ||||||
| ##### TARGETS ##### | ##### TARGETS ##### | ||||||
|  |  | ||||||
| default: $(PROGS) | default: readtex.o $(PROGS) | ||||||
|  |  | ||||||
| $(PROGS): readtex.o |  | ||||||
|  |  | ||||||
| readtex.c: $(TOP)/progs/util/readtex.c | readtex.c: $(TOP)/progs/util/readtex.c | ||||||
| 	cp $< . | 	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. */ | ||||||
|  | } | ||||||
| @@ -116,6 +116,12 @@ 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<<7) | ||||||
|  |  | ||||||
| static void | static void | ||||||
| MeasureDownloadRate(void) | MeasureDownloadRate(void) | ||||||
| @@ -128,13 +134,20 @@ MeasureDownloadRate(void) | |||||||
|    int count; |    int count; | ||||||
|    int i; |    int i; | ||||||
|  |  | ||||||
|    texImage = (GLubyte *) malloc(bytes); |    texImage = (GLubyte *) malloc(bytes + ALIGN); | ||||||
|    getImage = (GLubyte *) malloc(bytes); |    getImage = (GLubyte *) malloc(bytes + ALIGN); | ||||||
|    if (!texImage || !getImage) { |    if (!texImage || !getImage) { | ||||||
|       DownloadRate = 0.0; |       DownloadRate = 0.0; | ||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|  |    texImage = (GLubyte *)((((unsigned)texImage) + ALIGN) & ~(ALIGN-1)); | ||||||
|  |    getImage = (GLubyte *)((((unsigned)getImage) + ALIGN) & ~(ALIGN-1)); | ||||||
|  |  | ||||||
|  |    for (i = 1; !(((unsigned)texImage) & i); i<<=1) | ||||||
|  |       ; | ||||||
|  |    printf("texture image alignment: %d bytes\n", i); | ||||||
|  |        | ||||||
|    for (i = 0; i < bytes; i++) { |    for (i = 0; i < bytes; i++) { | ||||||
|       texImage[i] = i & 0xff; |       texImage[i] = i & 0xff; | ||||||
|    } |    } | ||||||
| @@ -178,12 +191,15 @@ MeasureDownloadRate(void) | |||||||
|                       FormatTable[Format].Type, texImage); |                       FormatTable[Format].Type, texImage); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | #if 1 | ||||||
|       /* draw a tiny polygon to force texture into texram */ |       /* draw a tiny polygon to force texture into texram */ | ||||||
|       glBegin(GL_TRIANGLES); |       glBegin(GL_TRIANGLES); | ||||||
|       glTexCoord2f(0, 0);     glVertex2f(1, 1); |       glTexCoord2f(0, 0);     glVertex2f(1, 1); | ||||||
|       glTexCoord2f(1, 0);     glVertex2f(3, 1); |       glTexCoord2f(1, 0);     glVertex2f(3, 1); | ||||||
|       glTexCoord2f(0.5, 1);   glVertex2f(2, 3); |       glTexCoord2f(0.5, 1);   glVertex2f(2, 3); | ||||||
|       glEnd(); |       glEnd(); | ||||||
|  | /*       glFinish(); */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|       t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001; |       t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001; | ||||||
|       time = t1 - t0; |       time = t1 - t0; | ||||||
| @@ -209,8 +225,8 @@ MeasureDownloadRate(void) | |||||||
|    } |    } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|    free(texImage); | /*    free(texImage); */ | ||||||
|    free(getImage); | /*    free(getImage); */ | ||||||
|  |  | ||||||
|    { |    { | ||||||
|       GLint err = glGetError(); |       GLint err = glGetError(); | ||||||
|   | |||||||
| @@ -92,7 +92,7 @@ static void idle( void ) | |||||||
|    dt = t - t0; |    dt = t - t0; | ||||||
|    t0 = t; |    t0 = t; | ||||||
|    Angle += 120.0*dt; |    Angle += 120.0*dt; | ||||||
|    glutPostRedisplay(); | /*    glutPostRedisplay(); */ | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,6 +47,7 @@ SOURCES = antialias.c \ | |||||||
| 	sharedtex.c \ | 	sharedtex.c \ | ||||||
| 	stencilwrap.c \ | 	stencilwrap.c \ | ||||||
| 	stencil_wrap.c \ | 	stencil_wrap.c \ | ||||||
|  | 	subtexrate.c \ | ||||||
| 	tex1d.c \ | 	tex1d.c \ | ||||||
| 	texfilt.c \ | 	texfilt.c \ | ||||||
| 	texline.c \ | 	texline.c \ | ||||||
|   | |||||||
							
								
								
									
										352
									
								
								progs/tests/subtexrate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								progs/tests/subtexrate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,352 @@ | |||||||
|  | /* | ||||||
|  |  * 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 1 | ||||||
|  |       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_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); | ||||||
|  |    } | ||||||
|  |    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; | ||||||
|  |  | ||||||
|  |    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(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       iters++; | ||||||
|  |       rot += 2.0; | ||||||
|  |  | ||||||
|  |       t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||||
|  |       if (DrawQuad) { | ||||||
|  |          glutSwapBuffers(); | ||||||
|  |       } | ||||||
|  |    } while (t1 - t0 < 5.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); */ | ||||||
|  |    while (1) { | ||||||
|  |       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) | depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) | ||||||
| 	touch depend | 	touch depend | ||||||
| 	$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \ | 	$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \ | ||||||
| 		> /dev/null  | 		>& /dev/null  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Emacs tags | # Emacs tags | ||||||
|   | |||||||
| @@ -5,33 +5,45 @@ include $(TOP)/configs/current | |||||||
| LIBNAME = i915_dri.so | LIBNAME = i915_dri.so | ||||||
|  |  | ||||||
| DRIVER_SOURCES = \ | DRIVER_SOURCES = \ | ||||||
|  | 	bufmgr_fake.c \ | ||||||
|  | 	intel_regions.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 \ | ||||||
|  | 	i915_tex.c \ | ||||||
|  | 	i915_texstate.c \ | ||||||
| 	i915_context.c \ | 	i915_context.c \ | ||||||
| 	i915_debug.c \ | 	i915_debug.c \ | ||||||
| 	i915_fragprog.c \ | 	i915_fragprog.c \ | ||||||
| 	i915_metaops.c \ | 	i915_metaops.c \ | ||||||
| 	i915_program.c \ | 	i915_program.c \ | ||||||
| 	i915_state.c \ | 	i915_state.c \ | ||||||
| 	i915_tex.c \ |  | ||||||
| 	i915_texprog.c \ | 	i915_texprog.c \ | ||||||
| 	i915_texstate.c \ |  | ||||||
| 	i915_vtbl.c \ | 	i915_vtbl.c \ | ||||||
|  | 	intel_batchbuffer.c \ | ||||||
|  | 	intel_context.c \ | ||||||
|  | 	intel_ioctl.c \ | ||||||
|  | 	intel_pixel.c \ | ||||||
|  | 	intel_screen.c \ | ||||||
|  | 	intel_span.c \ | ||||||
|  | 	intel_state.c \ | ||||||
|  | 	intel_tris.c  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | DISABLED = \ | ||||||
|  | 	intel_render.c \ | ||||||
| 	i830_context.c \ | 	i830_context.c \ | ||||||
| 	i830_metaops.c \ | 	i830_metaops.c \ | ||||||
| 	i830_state.c \ | 	i830_state.c \ | ||||||
| 	i830_texblend.c \ | 	i830_texblend.c \ | ||||||
| 	i830_tex.c \ | 	i830_tex.c \ | ||||||
| 	i830_texstate.c \ | 	i830_texstate.c \ | ||||||
| 	i830_vtbl.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  |  | ||||||
|  |  | ||||||
| C_SOURCES = \ | C_SOURCES = \ | ||||||
| 	$(COMMON_SOURCES) \ | 	$(COMMON_SOURCES) \ | ||||||
|   | |||||||
							
								
								
									
										164
									
								
								src/mesa/drivers/dri/i915/bufmgr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								src/mesa/drivers/dri/i915/bufmgr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | |||||||
|  | #ifndef BUFMGR_H | ||||||
|  | #define BUFMGR_H | ||||||
|  |  | ||||||
|  | #include "intel_context.h" | ||||||
|  |  | ||||||
|  | /* Note that this is destined to be external to Mesa, so don't use GL | ||||||
|  |  * types like GLuint, etc. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* The buffer manager context.  Opaque. | ||||||
|  |  */ | ||||||
|  | struct bufmgr; | ||||||
|  | struct bm_buffer_list; | ||||||
|  |  | ||||||
|  | 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_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 * ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define DBG(...)  do { if (0) _mesa_printf(__VA_ARGS__); } while(0) | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										843
									
								
								src/mesa/drivers/dri/i915/bufmgr_fake.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										843
									
								
								src/mesa/drivers/dri/i915/bufmgr_fake.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,843 @@ | |||||||
|  | /* 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" | ||||||
|  |  | ||||||
|  | struct _mesa_HashTable; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Maximum number of buffers to pass to bmValidateBufferList: | ||||||
|  |  */ | ||||||
|  | #define BM_LIST_MAX 32 | ||||||
|  | #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 */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* List of buffers to validate:  | ||||||
|  |  */ | ||||||
|  | struct bm_buffer_list { | ||||||
|  |    struct { | ||||||
|  |       unsigned buffer; | ||||||
|  |       unsigned *offset_return; | ||||||
|  |       unsigned *memtype_return; | ||||||
|  |    } elem[BM_LIST_MAX]; | ||||||
|  |  | ||||||
|  |    unsigned nr; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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); | ||||||
|  |  | ||||||
|  |    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 = malloc(size); | ||||||
|  |    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; | ||||||
|  |  | ||||||
|  |    for (i = 0; i < bm->nr_pools; i++) { | ||||||
|  |       if (bm->pool[i].flags & BM_NO_ALLOC) | ||||||
|  | 	 continue; | ||||||
|  |  | ||||||
|  |       if ((bm->pool[i].flags & flags & BM_MEM_MASK) == 0) | ||||||
|  | 	 continue; | ||||||
|  |        | ||||||
|  |       return alloc_from_pool(bm, i, size, align); | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    if (flags & BM_MEM_LOCAL) | ||||||
|  |       return alloc_local(size); | ||||||
|  |  | ||||||
|  |    return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int bmAllocMem( struct bufmgr *bm, | ||||||
|  | 		       struct buffer *buf )	 | ||||||
|  | { | ||||||
|  |    buf->block = alloc_block(bm, buf->size, 4, buf->flags); | ||||||
|  |  | ||||||
|  |    if (buf->block) | ||||||
|  |       buf->block->buf = buf; | ||||||
|  |  | ||||||
|  |    assert(buf->block); | ||||||
|  |    return buf->block != NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Release the card storage associated with buf: | ||||||
|  |  */ | ||||||
|  | static void free_block( struct bufmgr *bm, struct block *block ) | ||||||
|  | { | ||||||
|  |    if (!block)  | ||||||
|  |       return; | ||||||
|  |  | ||||||
|  |    switch (block->mem_type) { | ||||||
|  |    case BM_MEM_AGP: | ||||||
|  |    case BM_MEM_VRAM: | ||||||
|  |       if (bmTestFence(bm, block->fence)) { | ||||||
|  |          mmFreeMem(block->mem); | ||||||
|  |          free(block); | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  | 	 block->buf = NULL; | ||||||
|  |          move_to_tail(&block->pool->freed, block); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |    case BM_MEM_LOCAL: | ||||||
|  |       free(block->virtual); | ||||||
|  |       free(block); | ||||||
|  |       break; | ||||||
|  |  | ||||||
|  |    default: | ||||||
|  |       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); | ||||||
|  | 	 } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    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; | ||||||
|  |  | ||||||
|  | 	 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. | ||||||
|  | 	     */ | ||||||
|  | 	    _mesa_printf("* %d\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]); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* 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 = 0; | ||||||
|  |    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 0 | ||||||
|  | /* How wise/useful is this? | ||||||
|  |  */ | ||||||
|  | void bmBufferSetParams( struct bufmgr *bm, | ||||||
|  | 			unsigned buffer, | ||||||
|  | 			unsigned flags, | ||||||
|  | 			unsigned alignment ) | ||||||
|  | { | ||||||
|  |    struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer ); | ||||||
|  |    assert(!buf->block); | ||||||
|  |    buf->flags = flags; | ||||||
|  |    buf->alignment = alignment; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* If buffer size changes, create new buffer in local memory. | ||||||
|  |  * 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); | ||||||
|  |       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); | ||||||
|  |  | ||||||
|  |    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 access ) | ||||||
|  | { | ||||||
|  |    struct buffer *buf = (struct buffer *)_mesa_HashLookup( bm->hash, buffer ); | ||||||
|  |  | ||||||
|  |    DBG("bmMapBuffer %d\n", buffer); | ||||||
|  |  | ||||||
|  |    if (buf->mapped) | ||||||
|  |       return NULL; | ||||||
|  |  | ||||||
|  |    buf->mapped = 1; | ||||||
|  |  | ||||||
|  |    if (buf->block == 0) | ||||||
|  |       bmAllocMem(bm, buf); | ||||||
|  |  | ||||||
|  |    /* 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; | ||||||
|  |       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); | ||||||
|  |  | ||||||
|  |       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->batch.space == bm->intel->batch.size); | ||||||
|  |    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"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -295,6 +295,7 @@ static void draw_quad(i830ContextPtr i830, | |||||||
| 		      GLfloat s0, GLfloat s1, | 		      GLfloat s0, GLfloat s1, | ||||||
| 		      GLfloat t0, GLfloat t1 ) | 		      GLfloat t0, GLfloat t1 ) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|    GLuint vertex_size = 8; |    GLuint vertex_size = 8; | ||||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,  |    GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,  | ||||||
| 						PRIM3D_TRIFAN,  | 						PRIM3D_TRIFAN,  | ||||||
| @@ -350,6 +351,7 @@ static void draw_quad(i830ContextPtr i830, | |||||||
|  |  | ||||||
| /*    fprintf(stderr, "%s: DV1: %x\n",  */ | /*    fprintf(stderr, "%s: DV1: %x\n",  */ | ||||||
| /* 	   __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */ | /* 	   __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */ | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| void  | void  | ||||||
| @@ -440,7 +442,7 @@ i830TryTextureReadPixels( GLcontext *ctx, | |||||||
|    int textureFormat; |    int textureFormat; | ||||||
|    GLenum glTextureFormat; |    GLenum glTextureFormat; | ||||||
|    int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; |    int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; | ||||||
|    int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels); |    int destOffset = 0; | ||||||
|    int destFormat, depthFormat, destPitch; |    int destFormat, depthFormat, destPitch; | ||||||
|    drm_clip_rect_t tmp; |    drm_clip_rect_t tmp; | ||||||
|  |  | ||||||
| @@ -594,7 +596,7 @@ i830TryTextureDrawPixels( GLcontext *ctx, | |||||||
|    int textureFormat; |    int textureFormat; | ||||||
|    GLenum glTextureFormat; |    GLenum glTextureFormat; | ||||||
|    int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; |    int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; | ||||||
|    int src_offset = intelAgpOffsetFromVirtual( intel, pixels ); |    int src_offset = 0; | ||||||
|  |  | ||||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) |    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||||
|       fprintf(stderr, "%s\n", __FUNCTION__); |       fprintf(stderr, "%s\n", __FUNCTION__); | ||||||
|   | |||||||
| @@ -200,7 +200,7 @@ intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj ) | |||||||
|  |  | ||||||
|    texObj->DriverData = t; |    texObj->DriverData = t; | ||||||
|    t->intel.base.tObj = texObj; |    t->intel.base.tObj = texObj; | ||||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; |    t->intel.dirty = ~0; | ||||||
|    make_empty_list( &t->intel.base ); |    make_empty_list( &t->intel.base ); | ||||||
|  |  | ||||||
|    t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */ |    t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */ | ||||||
| @@ -268,7 +268,7 @@ static void i830TexParameter( GLcontext *ctx, GLenum target, | |||||||
|       return; |       return; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; |    t->intel.dirty = ~0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -246,7 +246,7 @@ static GLboolean i830SetTexImages( i830ContextPtr i830, | |||||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK; |    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK; | ||||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK; |    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK; | ||||||
|    t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT; |    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 ); |    return intelUploadTexImages( &i830->intel, &t->intel, 0 ); | ||||||
| } | } | ||||||
| @@ -259,11 +259,7 @@ static void i830_import_tex_unit( i830ContextPtr i830, | |||||||
|    if(INTEL_DEBUG&DEBUG_TEXTURE) |    if(INTEL_DEBUG&DEBUG_TEXTURE) | ||||||
|       fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); |       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; |    i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t; | ||||||
|    t->intel.base.bound |= (1 << unit); |  | ||||||
|  |  | ||||||
|    I830_STATECHANGE( i830, I830_UPLOAD_TEX(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_CUBE] = t->Setup[I830_TEXREG_CUBE]; | ||||||
|    i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit); |    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. |     * time. | ||||||
|     */ |     */ | ||||||
|    if (i830->intel.CurrentTexObj[unit] != &t->intel ||  |    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); |       i830_import_tex_unit( i830, t, unit); | ||||||
|    } |    } | ||||||
|  |  | ||||||
| @@ -419,14 +415,10 @@ static GLboolean disable_tex( GLcontext *ctx, GLuint unit ) | |||||||
|     * one if nothing is enabled. |     * one if nothing is enabled. | ||||||
|     */ |     */ | ||||||
|  |  | ||||||
|    if ( i830->intel.CurrentTexObj[unit] != NULL ) { |    /* The old texture is no longer bound to this texture unit. | ||||||
|       /* The old texture is no longer bound to this texture unit. |     * Mark it as such. | ||||||
|        * Mark it as such. |     */ | ||||||
|        */ |    i830->intel.CurrentTexObj[unit] = NULL; | ||||||
|  |  | ||||||
|       i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0); |  | ||||||
|       i830->intel.CurrentTexObj[unit] = NULL; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    return GL_TRUE; |    return GL_TRUE; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -441,7 +441,6 @@ static void i830_emit_flush( intelContextPtr intel ) | |||||||
|  |  | ||||||
| void i830InitVtbl( i830ContextPtr i830 ) | void i830InitVtbl( i830ContextPtr i830 ) | ||||||
| { | { | ||||||
|    i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj; |  | ||||||
|    i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; |    i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; | ||||||
|    i830->intel.vtbl.clear_with_tris = i830ClearWithTris; |    i830->intel.vtbl.clear_with_tris = i830ClearWithTris; | ||||||
|    i830->intel.vtbl.destroy = i830_destroy_context; |    i830->intel.vtbl.destroy = i830_destroy_context; | ||||||
|   | |||||||
| @@ -41,6 +41,9 @@ | |||||||
| #include "utils.h" | #include "utils.h" | ||||||
| #include "i915_reg.h" | #include "i915_reg.h" | ||||||
|  |  | ||||||
|  | #include "bufmgr.h" | ||||||
|  | #include "intel_regions.h" | ||||||
|  |  | ||||||
| /*************************************** | /*************************************** | ||||||
|  * Mesa's Driver Functions |  * Mesa's Driver Functions | ||||||
|  ***************************************/ |  ***************************************/ | ||||||
| @@ -101,10 +104,13 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | |||||||
|    struct dd_function_table functions; |    struct dd_function_table functions; | ||||||
|    i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context); |    i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context); | ||||||
|    intelContextPtr intel = &i915->intel; |    intelContextPtr intel = &i915->intel; | ||||||
|  |    intelScreenPrivate *intelScreen; | ||||||
|    GLcontext *ctx = &intel->ctx; |    GLcontext *ctx = &intel->ctx; | ||||||
|  |  | ||||||
|    if (!i915) return GL_FALSE; |    if (!i915) return GL_FALSE; | ||||||
|  |  | ||||||
|  |    _mesa_printf( "\ntexmem branch (i915)\n\n"); | ||||||
|  |     | ||||||
|    i915InitVtbl( i915 ); |    i915InitVtbl( i915 ); | ||||||
|  |  | ||||||
|    i915InitDriverFunctions( &functions ); |    i915InitDriverFunctions( &functions ); | ||||||
| @@ -119,33 +125,57 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | |||||||
|    ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS; |    ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS; | ||||||
|    ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS; |    ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS; | ||||||
|  |  | ||||||
|    intel->nr_heaps = 1; |    intel->bm = bm_fake_intel_Attach( intel ); | ||||||
|    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 |    bmInitPool(intel->bm, | ||||||
|     * tightly packed, but they're not in Intel graphics |               intel->intelScreen->tex.offset, /* low offset */ | ||||||
|     * hardware. |               intel->intelScreen->tex.map, /* low virtual */ | ||||||
|  |               intel->intelScreen->tex.size, | ||||||
|  | 	      BM_MEM_AGP); | ||||||
|  |  | ||||||
|  |    intelScreen = intel->intelScreen; | ||||||
|  |  | ||||||
|  |    /* These are still static, but create regions for them.   | ||||||
|     */ |     */ | ||||||
|    ctx->Const.MaxTextureUnits = 1; |    intel->front_region =  | ||||||
|    driCalculateMaxTextureLevels( intel->texture_heaps, |       intel_region_create_static(intel, | ||||||
| 				 intel->nr_heaps, | 				 BM_MEM_AGP, | ||||||
| 				 &intel->ctx.Const, | 				 intelScreen->front.offset, | ||||||
| 				 4, | 				 intelScreen->front.map, | ||||||
| 				 11, /* max 2D texture size is 2048x2048 */ | 				 intelScreen->cpp, | ||||||
| 				 8,  /* 3D texture */ | 				 intelScreen->front.pitch, | ||||||
| 				 11, /* cube texture. */ | 				 intelScreen->height); | ||||||
| 				 11, /* rect texture */ |  | ||||||
| 				 12, |  | ||||||
| 				 GL_FALSE ); |    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); | ||||||
|  |  | ||||||
|  |    intelInitBatchBuffer(intel); | ||||||
|  |  | ||||||
|  |    /* Advertise the full hardware capabilities.  The new memory | ||||||
|  |     * manager should cope much better with overload situations: | ||||||
|  |     */ | ||||||
|  |    ctx->Const.MaxTextureLevels = 11; | ||||||
|  |    ctx->Const.Max3DTextureLevels = 8; | ||||||
|  |    ctx->Const.MaxCubeTextureLevels = 11; | ||||||
|  |    ctx->Const.MaxTextureRectSize = (1<<11); | ||||||
|    ctx->Const.MaxTextureUnits = I915_TEX_UNITS; |    ctx->Const.MaxTextureUnits = I915_TEX_UNITS; | ||||||
|  |  | ||||||
|    /* GL_ARB_fragment_program limits - don't think Mesa actually |    /* GL_ARB_fragment_program limits - don't think Mesa actually | ||||||
| @@ -153,14 +183,13 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | |||||||
|     * instruction can translate to more than one HW instruction, so |     * instruction can translate to more than one HW instruction, so | ||||||
|     * we'll still have to check and fallback each time. |     * we'll still have to check and fallback each time. | ||||||
|     */    |     */    | ||||||
|     |  | ||||||
|    ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY; |    ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY; | ||||||
|    ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */ |    ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */ | ||||||
|    ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT; |    ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT; | ||||||
|    ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN; |    ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN; | ||||||
|    ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN; |    ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN; | ||||||
|    ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_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.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT; | ||||||
|    ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */ |    ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ | |||||||
| #define I915_UPLOAD_PROGRAM          0x8 | #define I915_UPLOAD_PROGRAM          0x8 | ||||||
| #define I915_UPLOAD_CONSTANTS        0x10 | #define I915_UPLOAD_CONSTANTS        0x10 | ||||||
| #define I915_UPLOAD_FOG              0x20 | #define I915_UPLOAD_FOG              0x20 | ||||||
|  | #define I915_UPLOAD_INVARIENT        0x40 | ||||||
| #define I915_UPLOAD_TEX(i)           (0x00010000<<(i)) | #define I915_UPLOAD_TEX(i)           (0x00010000<<(i)) | ||||||
| #define I915_UPLOAD_TEX_ALL          (0x00ff0000) | #define I915_UPLOAD_TEX_ALL          (0x00ff0000) | ||||||
| #define I915_UPLOAD_TEX_0_SHIFT      16 | #define I915_UPLOAD_TEX_0_SHIFT      16 | ||||||
| @@ -163,8 +164,6 @@ struct i915_fragment_program { | |||||||
|    GLuint nr_params; |    GLuint nr_params; | ||||||
|        |        | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|    /* Helpers for i915_texprog.c: |    /* Helpers for i915_texprog.c: | ||||||
|     */ |     */ | ||||||
|    GLuint src_texture;		/* Reg containing sampled texture color, |    GLuint src_texture;		/* Reg containing sampled texture color, | ||||||
| @@ -185,13 +184,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 | #define I915_TEX_UNITS 8 | ||||||
|  |  | ||||||
| @@ -220,6 +212,8 @@ struct i915_context | |||||||
|  |  | ||||||
|    GLuint last_ReallyEnabled; |    GLuint last_ReallyEnabled; | ||||||
|    GLuint vertex_fog; |    GLuint vertex_fog; | ||||||
|  |    GLuint lodbias_ss2[MAX_TEXTURE_UNITS]; | ||||||
|  |  | ||||||
|  |  | ||||||
|    struct i915_fragment_program tex_program; |    struct i915_fragment_program tex_program; | ||||||
|    struct i915_fragment_program *current_program; |    struct i915_fragment_program *current_program; | ||||||
| @@ -229,10 +223,6 @@ struct i915_context | |||||||
|  |  | ||||||
|  |  | ||||||
| typedef struct i915_context *i915ContextPtr; | typedef struct i915_context *i915ContextPtr; | ||||||
| typedef struct i915_texture_object *i915TextureObjectPtr; |  | ||||||
|  |  | ||||||
| #define I915_CONTEXT(ctx)	((i915ContextPtr)(ctx)) |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define I915_STATECHANGE(i915, flag)					\ | #define I915_STATECHANGE(i915, flag)					\ | ||||||
| @@ -317,7 +307,6 @@ extern void i915_update_fog( GLcontext *ctx ); | |||||||
|  */ |  */ | ||||||
| extern void i915UpdateTextureState( intelContextPtr intel ); | extern void i915UpdateTextureState( intelContextPtr intel ); | ||||||
| extern void i915InitTextureFuncs( struct dd_function_table *functions ); | extern void i915InitTextureFuncs( struct dd_function_table *functions ); | ||||||
| extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ); |  | ||||||
|  |  | ||||||
| /*====================================================================== | /*====================================================================== | ||||||
|  * i915_metaops.c |  * i915_metaops.c | ||||||
| @@ -347,5 +336,21 @@ i915ClearWithTris( intelContextPtr intel, GLbitfield mask, | |||||||
| extern void i915ValidateFragmentProgram( i915ContextPtr i915 ); | extern void i915ValidateFragmentProgram( i915ContextPtr i915 ); | ||||||
| extern void i915InitFragProgFuncs( struct dd_function_table *functions ); | 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 | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -387,6 +387,7 @@ static void draw_quad(i915ContextPtr i915, | |||||||
| 		      GLfloat s0, GLfloat s1, | 		      GLfloat s0, GLfloat s1, | ||||||
| 		      GLfloat t0, GLfloat t1 ) | 		      GLfloat t0, GLfloat t1 ) | ||||||
| { | { | ||||||
|  | #if 0 | ||||||
|    GLuint vertex_size = 8; |    GLuint vertex_size = 8; | ||||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,  |    GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,  | ||||||
| 						PRIM3D_TRIFAN,  | 						PRIM3D_TRIFAN,  | ||||||
| @@ -440,6 +441,7 @@ static void draw_quad(i915ContextPtr i915, | |||||||
|    tmp.v.u0 = s0; |    tmp.v.u0 = s0; | ||||||
|    for (i = 0 ; i < vertex_size ; i++) |    for (i = 0 ; i < vertex_size ; i++) | ||||||
|       vb[i] = tmp.ui[i]; |       vb[i] = tmp.ui[i]; | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| void  | void  | ||||||
| @@ -447,7 +449,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask, | |||||||
| 		  GLboolean all, | 		  GLboolean all, | ||||||
| 		  GLint cx, GLint cy, GLint cw, GLint ch) | 		  GLint cx, GLint cy, GLint cw, GLint ch) | ||||||
| { | { | ||||||
|    i915ContextPtr i915 = I915_CONTEXT( intel ); |    i915ContextPtr i915 = i915_context( &intel->ctx ); | ||||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; |    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||||
|    intelScreenPrivate *screen = intel->intelScreen; |    intelScreenPrivate *screen = intel->intelScreen; | ||||||
|    int x0, y0, x1, y1; |    int x0, y0, x1, y1; | ||||||
|   | |||||||
| @@ -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,  | static void i915TexEnv( GLcontext *ctx, GLenum target,  | ||||||
| 			GLenum pname, const GLfloat *param ) | 			GLenum pname, const GLfloat *param ) | ||||||
| { | { | ||||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); |    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||||
|    GLuint unit = ctx->Texture.CurrentUnit; |  | ||||||
|  |  | ||||||
|    switch (pname) { |    switch (pname) { | ||||||
|    case GL_TEXTURE_ENV_COLOR: 	/* Should be a tracked param */ |    case GL_TEXTURE_ENV_COLOR: 	/* Should be a tracked param */ | ||||||
| @@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | |||||||
|       break; |       break; | ||||||
|  |  | ||||||
|    case GL_TEXTURE_LOD_BIAS: { |    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 > 255) b = 255; | ||||||
|       if (b < -256) b = -256; |       if (b < -256) b = -256; | ||||||
|       I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); |       I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); | ||||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK; |       i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); | ||||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] |=  |  | ||||||
| 	 ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); |  | ||||||
|       break; |       break; | ||||||
|    } |    } | ||||||
|  |  | ||||||
| @@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | |||||||
|  |  | ||||||
|  |  | ||||||
| static void i915BindTexture( 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. |    /* Need this if image format changes between bound textures. | ||||||
|     * Could try and shortcircuit by checking for differences in |     * Could try and shortcircuit by checking for differences in | ||||||
|     * state between incoming and outgoing textures: |     * state between incoming and outgoing textures: | ||||||
| @@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions ) | |||||||
| { | { | ||||||
|    functions->BindTexture = i915BindTexture; |    functions->BindTexture = i915BindTexture; | ||||||
|    functions->TexEnv = i915TexEnv; |    functions->TexEnv = i915TexEnv; | ||||||
|    functions->TexParameter = i915TexParameter; |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										340
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										340
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,340 @@ | |||||||
|  | /************************************************************************** | ||||||
|  |  *  | ||||||
|  |  * 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++) { | ||||||
|  | 	    mt->offset[face][i].x = x;  | ||||||
|  | 	    mt->offset[face][i].y = y;  | ||||||
|  | 	    mt->offset[face][i].width = d; | ||||||
|  | 	    mt->offset[face][i].height = d; | ||||||
|  | 	    mt->offset[face][i].depth = 1; | ||||||
|  | 	  | ||||||
|  | 	    d >>= 1; | ||||||
|  | 	    assert(d > 0); | ||||||
|  |  | ||||||
|  | 	    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.  Hardware demands a | ||||||
|  |        * minimum of 8 mipmaps, some of which might ultimately not be | ||||||
|  |        * used: | ||||||
|  |        */ | ||||||
|  |       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||||
|  |       mt->total_height = 0; | ||||||
|  |  | ||||||
|  |       /* XXX: fixme! hardware expects/requires 9 levels at minimum. | ||||||
|  |        */ | ||||||
|  |       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||||
|  | 	 mt->offset[0][i].x = 0; | ||||||
|  | 	 mt->offset[0][i].y = mt->total_height; | ||||||
|  | 	 mt->offset[0][i].width = width; | ||||||
|  | 	 mt->offset[0][i].height = height; | ||||||
|  | 	 mt->offset[0][i].depth = depth; | ||||||
|  |  | ||||||
|  | 	 mt->total_height += MAX2(2, height); | ||||||
|  |  | ||||||
|  | 	 width  = minify(width); | ||||||
|  | 	 height = minify(height); | ||||||
|  | 	 depth  = minify(depth); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |       /* Multiply slice size by texture depth for total size.  It's | ||||||
|  |        * remarkable how wasteful of memory the i915 texture layouts | ||||||
|  |        * are.  They are largely fixed in the i945. | ||||||
|  |        */ | ||||||
|  |       mt->depth_pitch = mt->total_height * mt->pitch; | ||||||
|  |       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++ ) { | ||||||
|  | 	 mt->offset[0][i].x = 0; | ||||||
|  | 	 mt->offset[0][i].y = mt->total_height; | ||||||
|  | 	 mt->offset[0][i].height = height; | ||||||
|  | 	 mt->offset[0][i].width = width; | ||||||
|  | 	 mt->offset[0][i].depth = 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++ ) { | ||||||
|  | 	    mt->offset[face][i].x = x;  | ||||||
|  | 	    mt->offset[face][i].y = y;  | ||||||
|  | 	    mt->offset[face][i].width = d; | ||||||
|  | 	    mt->offset[face][i].height = d; | ||||||
|  | 	    mt->offset[face][i].depth = 1; | ||||||
|  |  | ||||||
|  | 	    d >>= 1; | ||||||
|  | 	    assert(d > 0); | ||||||
|  | 	     | ||||||
|  | 	    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++ ) { | ||||||
|  |  | ||||||
|  | 	 mt->offset[0][i].x = 0; | ||||||
|  | 	 mt->offset[0][i].y = mt->total_height; | ||||||
|  | 	 mt->offset[0][i].width = width; | ||||||
|  | 	 mt->offset[0][i].height = height; | ||||||
|  | 	 mt->offset[0][i].depth = 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++ ) { | ||||||
|  | 	 mt->offset[0][i].x = x; | ||||||
|  | 	 mt->offset[0][i].y = y; | ||||||
|  | 	 mt->offset[0][i].height = height; | ||||||
|  | 	 mt->offset[0][i].width = width; | ||||||
|  | 	 mt->offset[0][i].depth = 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; | ||||||
|  | } | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -37,6 +37,7 @@ | |||||||
| #include "tnl/t_vertex.h" | #include "tnl/t_vertex.h" | ||||||
|  |  | ||||||
| #include "intel_batchbuffer.h" | #include "intel_batchbuffer.h" | ||||||
|  | #include "intel_tex.h" | ||||||
|  |  | ||||||
| #include "i915_reg.h" | #include "i915_reg.h" | ||||||
| #include "i915_context.h" | #include "i915_context.h" | ||||||
| @@ -44,7 +45,7 @@ | |||||||
| static void i915_render_start( intelContextPtr intel ) | static void i915_render_start( intelContextPtr intel ) | ||||||
| { | { | ||||||
|    GLcontext *ctx = &intel->ctx; |    GLcontext *ctx = &intel->ctx; | ||||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); |    i915ContextPtr i915 = i915_context(&intel->ctx); | ||||||
|  |  | ||||||
|    if (ctx->FragmentProgram._Active)  |    if (ctx->FragmentProgram._Active)  | ||||||
|       i915ValidateFragmentProgram( i915 ); |       i915ValidateFragmentProgram( i915 ); | ||||||
| @@ -56,7 +57,7 @@ static void i915_render_start( intelContextPtr intel ) | |||||||
| static void i915_reduced_primitive_state( intelContextPtr intel, | static void i915_reduced_primitive_state( intelContextPtr intel, | ||||||
| 					  GLenum rprim ) | 					  GLenum rprim ) | ||||||
| { | { | ||||||
|     i915ContextPtr i915 = I915_CONTEXT(intel); |    i915ContextPtr i915 = i915_context(&intel->ctx); | ||||||
|     GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; |     GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; | ||||||
|  |  | ||||||
|     st1 &= ~ST1_ENABLE; |     st1 &= ~ST1_ENABLE; | ||||||
| @@ -88,7 +89,7 @@ static void i915_reduced_primitive_state( intelContextPtr intel, | |||||||
| static GLboolean i915_check_vertex_size( intelContextPtr intel, | static GLboolean i915_check_vertex_size( intelContextPtr intel, | ||||||
| 					 GLuint expected ) | 					 GLuint expected ) | ||||||
| { | { | ||||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); |    i915ContextPtr i915 = i915_context(&intel->ctx); | ||||||
|    int lis2 = i915->current->Ctx[I915_CTXREG_LIS2]; |    int lis2 = i915->current->Ctx[I915_CTXREG_LIS2]; | ||||||
|    int lis4 = i915->current->Ctx[I915_CTXREG_LIS4]; |    int lis4 = i915->current->Ctx[I915_CTXREG_LIS4]; | ||||||
|    int i, sz = 0; |    int i, sz = 0; | ||||||
| @@ -218,7 +219,7 @@ do {							\ | |||||||
|  */ |  */ | ||||||
| static void i915_emit_state( intelContextPtr intel ) | static void i915_emit_state( intelContextPtr intel ) | ||||||
| { | { | ||||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); |    i915ContextPtr i915 = i915_context(&intel->ctx); | ||||||
|    struct i915_hw_state *state = i915->current; |    struct i915_hw_state *state = i915->current; | ||||||
|    int i; |    int i; | ||||||
|    GLuint dirty; |    GLuint dirty; | ||||||
| @@ -236,6 +237,11 @@ static void i915_emit_state( intelContextPtr intel ) | |||||||
|    if (VERBOSE)  |    if (VERBOSE)  | ||||||
|       fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); |       fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); | ||||||
|  |  | ||||||
|  |    if (dirty & I915_UPLOAD_INVARIENT) { | ||||||
|  |       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n");  | ||||||
|  |       i915_emit_invarient_state( intel ); | ||||||
|  |    } | ||||||
|  |  | ||||||
|    if (dirty & I915_UPLOAD_CTX) { |    if (dirty & I915_UPLOAD_CTX) { | ||||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");  |       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");  | ||||||
|       emit( i915, state->Ctx, sizeof(state->Ctx) ); |       emit( i915, state->Ctx, sizeof(state->Ctx) ); | ||||||
| @@ -271,7 +277,9 @@ static void i915_emit_state( intelContextPtr intel ) | |||||||
|       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); |       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); | ||||||
|       for (i = 0 ; i < I915_TEX_UNITS ; i++) |       for (i = 0 ; i < I915_TEX_UNITS ; i++) | ||||||
| 	 if (dirty & I915_UPLOAD_TEX(i)) { | 	 if (dirty & I915_UPLOAD_TEX(i)) { | ||||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]); | 	    /* Emit zero texture offset, will fixup before firing */ | ||||||
|  | 	    intel_add_texoffset_fixup(intel, i, (GLuint *)batch_ptr);  | ||||||
|  | 	    batch_ptr += 4; | ||||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); | 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); | ||||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); | 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); | ||||||
| 	 } | 	 } | ||||||
| @@ -314,14 +322,15 @@ static void i915_destroy_context( intelContextPtr intel ) | |||||||
|  |  | ||||||
| static void i915_set_draw_offset( intelContextPtr intel, int offset ) | static void i915_set_draw_offset( intelContextPtr intel, int offset ) | ||||||
| { | { | ||||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); |    i915ContextPtr i915 = i915_context(&intel->ctx); | ||||||
|    I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); |    I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); | ||||||
|    i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset; |    i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void i915_lost_hardware( intelContextPtr intel ) | static void i915_lost_hardware( intelContextPtr intel ) | ||||||
| { | { | ||||||
|    I915_CONTEXT(intel)->state.emitted = 0; |    i915ContextPtr i915 = i915_context(&intel->ctx); | ||||||
|  |    i915->state.emitted = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void i915_emit_flush( intelContextPtr intel ) | static void i915_emit_flush( intelContextPtr intel ) | ||||||
| @@ -337,7 +346,6 @@ static void i915_emit_flush( intelContextPtr intel ) | |||||||
|  |  | ||||||
| void i915InitVtbl( i915ContextPtr i915 ) | void i915InitVtbl( i915ContextPtr i915 ) | ||||||
| { | { | ||||||
|    i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj; |  | ||||||
|    i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; |    i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; | ||||||
|    i915->intel.vtbl.clear_with_tris = i915ClearWithTris; |    i915->intel.vtbl.clear_with_tris = i915ClearWithTris; | ||||||
|    i915->intel.vtbl.destroy = i915_destroy_context; |    i915->intel.vtbl.destroy = i915_destroy_context; | ||||||
|   | |||||||
| @@ -37,283 +37,10 @@ | |||||||
| #include "intel_batchbuffer.h" | #include "intel_batchbuffer.h" | ||||||
| #include "intel_context.h" | #include "intel_context.h" | ||||||
|  |  | ||||||
|  | #include "bufmgr.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* ================================================================ |  | ||||||
|  * Performance monitoring functions |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| 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. |  | ||||||
|  */ |  | ||||||
| void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ) |  | ||||||
| { |  | ||||||
|    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(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void intelRestartInlinePrimitive( intelContextPtr intel ) |  | ||||||
| { |  | ||||||
|    GLuint prim = intel->prim.primitive; |  | ||||||
|  |  | ||||||
|    intel_flush_inline_primitive( &intel->ctx ); |  | ||||||
|    if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */ |  | ||||||
|    intelStartInlinePrimitive( intel, prim ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void intelWrapInlinePrimitive( intelContextPtr intel ) |  | ||||||
| { |  | ||||||
|    GLuint prim = intel->prim.primitive; |  | ||||||
|  |  | ||||||
|    if (0) |  | ||||||
|       fprintf(stderr, "%s\n", __FUNCTION__); |  | ||||||
|    intel_flush_inline_primitive( &intel->ctx ); |  | ||||||
|    intelFlushBatch(intel, GL_TRUE); |  | ||||||
|    intelStartInlinePrimitive( intel, prim ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Emit a primitive with space for inline vertices. |  | ||||||
|  */ |  | ||||||
| GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  |  | ||||||
| 				       int primitive, |  | ||||||
| 				       int dwords, |  | ||||||
| 				       int vertex_size ) |  | ||||||
| { |  | ||||||
|    GLuint *tmp = 0; |  | ||||||
|    BATCH_LOCALS; |  | ||||||
|  |  | ||||||
|    if (0) |  | ||||||
|       fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords); |  | ||||||
|  |  | ||||||
|    /* Emit outstanding state: |  | ||||||
|     */ |  | ||||||
|    intel->vtbl.emit_state( intel ); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|    if (1) { |  | ||||||
|       int used = dwords * 4; |  | ||||||
|       int vertcount; |  | ||||||
|  |  | ||||||
|       /* Check vertex size against the vertex we're specifying to |  | ||||||
|        * hardware.  If it's wrong, ditch the primitive. |  | ||||||
|        */  |  | ||||||
|       if (!intel->vtbl.check_vertex_size( intel, vertex_size ))  |  | ||||||
| 	 goto do_discard; |  | ||||||
|  |  | ||||||
|       vertcount = dwords / vertex_size; |  | ||||||
|        |  | ||||||
|       if (dwords % vertex_size) { |  | ||||||
| 	 fprintf(stderr, "did not request a whole number of vertices\n"); |  | ||||||
| 	 goto do_discard; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       if (bad_prim_vertex_nr( primitive, vertcount )) { |  | ||||||
| 	 fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount); |  | ||||||
| 	 goto do_discard; |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       if (used < 8) |  | ||||||
| 	 goto do_discard; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    /* Emit 3D_PRIMITIVE commands: |  | ||||||
|     */ |  | ||||||
|    BEGIN_BATCH(1 + dwords); |  | ||||||
|    OUT_BATCH( _3DPRIMITIVE |  |  | ||||||
| 	      primitive | |  | ||||||
| 	      (dwords-1) ); |  | ||||||
|  |  | ||||||
|    tmp = (GLuint *)batch_ptr; |  | ||||||
|    batch_ptr += dwords * 4; |  | ||||||
|  |  | ||||||
|    ADVANCE_BATCH(); |  | ||||||
|  |  | ||||||
|  do_discard: |  | ||||||
|    return tmp; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Copy the back buffer to the front buffer.  |  * Copy the back buffer to the front buffer.  | ||||||
| @@ -333,6 +60,9 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) | |||||||
|  |  | ||||||
|    intelFlush( &intel->ctx ); |    intelFlush( &intel->ctx ); | ||||||
|    LOCK_HARDWARE( intel ); |    LOCK_HARDWARE( intel ); | ||||||
|  |    intelInstallBatchBuffer(intel);    | ||||||
|  |    intelValidateBuffers( intel ); | ||||||
|  |  | ||||||
|    { |    { | ||||||
|       intelScreenPrivate *intelScreen = intel->intelScreen; |       intelScreenPrivate *intelScreen = intel->intelScreen; | ||||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; |       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||||
| @@ -360,9 +90,6 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) | |||||||
| 	 break; | 	 break; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (0) |  | ||||||
| 	 intel_draw_performance_boxes( intel ); |  | ||||||
|  |  | ||||||
|       for (i = 0 ; i < nbox; i++, pbox++)  |       for (i = 0 ; i < nbox; i++, pbox++)  | ||||||
|       { |       { | ||||||
| 	 if (pbox->x1 > pbox->x2 || | 	 if (pbox->x1 > pbox->x2 || | ||||||
| @@ -394,6 +121,8 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) | |||||||
|       } |       } | ||||||
|    } |    } | ||||||
|    intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE ); |    intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE ); | ||||||
|  |    assert(intel->buffer_list == NULL); | ||||||
|  |  | ||||||
|    UNLOCK_HARDWARE( intel ); |    UNLOCK_HARDWARE( intel ); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -457,6 +186,14 @@ void intelEmitCopyBlitLocked( intelContextPtr intel, | |||||||
|    int dst_x2 = dst_x + w; |    int dst_x2 = dst_x + w; | ||||||
|    BATCH_LOCALS; |    BATCH_LOCALS; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    if (0) | ||||||
|  |       _mesa_printf("%s src:0x%x/%d %d,%d dst:0x%x/%d %d,%d sz:%dx%d\n", | ||||||
|  | 		   __FUNCTION__, | ||||||
|  | 		   src_offset, src_pitch, src_x, src_y, | ||||||
|  | 		   dst_offset, dst_pitch, dst_x, dst_y, | ||||||
|  | 		   w,h); | ||||||
|  |  | ||||||
|    src_pitch *= cpp; |    src_pitch *= cpp; | ||||||
|    dst_pitch *= cpp; |    dst_pitch *= cpp; | ||||||
|  |  | ||||||
| @@ -542,6 +279,8 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, | |||||||
|  |  | ||||||
|    intelFlush( &intel->ctx ); |    intelFlush( &intel->ctx ); | ||||||
|    LOCK_HARDWARE( intel ); |    LOCK_HARDWARE( intel ); | ||||||
|  |    intelInstallBatchBuffer(intel);    | ||||||
|  |    intelValidateBuffers( intel ); | ||||||
|    { |    { | ||||||
|       /* flip top to bottom */ |       /* flip top to bottom */ | ||||||
|       cy = intel->driDrawable->h-cy1-ch; |       cy = intel->driDrawable->h-cy1-ch; | ||||||
| @@ -631,58 +370,72 @@ void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void intelDestroyBatchBuffer( GLcontext *ctx ) | void intelDestroyBatchBuffer( struct intel_context *intel ) | ||||||
| { | { | ||||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); |  | ||||||
|  |  | ||||||
|    if (intel->alloc.ptr) { |  | ||||||
|       intelFreeAGP( intel, intel->alloc.ptr ); |  | ||||||
|       intel->alloc.ptr = 0; |  | ||||||
|    } |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| void intelInitBatchBuffer( GLcontext *ctx ) | void intelInstallBatchBuffer( struct intel_context *intel ) | ||||||
| { | { | ||||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); |    assert(!intel->batch.ptr); | ||||||
|  |  | ||||||
|    if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) { |    intel->alloc.current++; | ||||||
|       intel->alloc.size = 8 * 1024; |    intel->alloc.current %= INTEL_ALLOC_NR; | ||||||
|       intel->alloc.ptr = malloc( intel->alloc.size ); |  | ||||||
|       intel->alloc.offset = 0; |    DBG("%s: %d\n", __FUNCTION__, intel->alloc.current); | ||||||
|    } |  | ||||||
|    else { |    intel->batch.size = INTEL_ALLOC_SIZE; | ||||||
|       switch (intel->intelScreen->deviceID) { |    intel->batch.space = intel->batch.size; | ||||||
|       case PCI_CHIP_I865_G: |    intel->batch.start_offset = 0; | ||||||
| 	 /* HW bug?  Seems to crash if batchbuffer crosses 4k boundary. |  | ||||||
| 	  */ |    intel->batch.ptr = bmMapBuffer( intel->bm,  | ||||||
| 	 intel->alloc.size = 8 * 1024;  | 				   intel->alloc.buffer[intel->alloc.current], | ||||||
| 	 break; | 				   BM_WRITE | BM_MEM_AGP ); | ||||||
|       default: |  | ||||||
| 	 /* This is the smallest amount of memory the kernel deals with. |  | ||||||
| 	  * We'd ideally like to make this smaller. |    assert(!intel->buffer_list); | ||||||
| 	  */ |    intel->buffer_list = bmNewBufferList(); | ||||||
| 	 intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity; |        | ||||||
| 	 break; |    /* Add the batchbuffer  | ||||||
|  |     */ | ||||||
|  |    bmAddBuffer(intel->buffer_list, | ||||||
|  | 	       intel->alloc.buffer[intel->alloc.current], | ||||||
|  | 	       BM_READ, | ||||||
|  | 	       NULL, | ||||||
|  | 	       &intel->batch.start_offset); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    if (0) { | ||||||
|  |       static int foo; | ||||||
|  |       if (foo++ > 10) { | ||||||
|  | 	 _mesa_printf("foo\n"); | ||||||
|  | 	 exit(1); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size ); |  | ||||||
|       if (intel->alloc.ptr) |  | ||||||
| 	 intel->alloc.offset =  |  | ||||||
| 	    intelAgpOffsetFromVirtual( intel, intel->alloc.ptr ); |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    if (!intel->alloc.ptr) { |  | ||||||
|       FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1); |  | ||||||
|    } |  | ||||||
|    else { |  | ||||||
|       intel->prim.flush = 0; |  | ||||||
|       intel->vtbl.emit_invarient_state( intel ); |  | ||||||
|  |  | ||||||
|       /* Make sure this gets to the hardware, even if we have no cliprects: |  | ||||||
|        */ |  | ||||||
|       LOCK_HARDWARE( intel ); |  | ||||||
|       intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE ); |  | ||||||
|       UNLOCK_HARDWARE( intel ); |  | ||||||
|    } |    } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void intelInitBatchBuffer( struct intel_context *intel ) | ||||||
|  | { | ||||||
|  |    GLint i; | ||||||
|  |  | ||||||
|  |    _mesa_printf("%s: %d\n", __FUNCTION__, intel->alloc.current); | ||||||
|  |    bmGenBuffers(intel->bm, | ||||||
|  | 		INTEL_ALLOC_NR, | ||||||
|  | 		intel->alloc.buffer); | ||||||
|  |  | ||||||
|  |    for (i = 0; i < INTEL_ALLOC_NR; i++) | ||||||
|  |       bmBufferData(intel->bm,  | ||||||
|  | 		   intel->alloc.buffer[i], | ||||||
|  | 		   INTEL_ALLOC_SIZE, | ||||||
|  | 		   NULL, | ||||||
|  | 		   BM_MEM_AGP); | ||||||
|  | 		 | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void intelValidateBuffers( struct intel_context *intel ) | ||||||
|  | { | ||||||
|  |    if (!bmValidateBufferList(intel->bm, intel->buffer_list, BM_MEM_AGP)) | ||||||
|  |       assert(0); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -34,10 +34,7 @@ | |||||||
|  |  | ||||||
| #define BATCH_LOCALS	GLubyte *batch_ptr; | #define BATCH_LOCALS	GLubyte *batch_ptr; | ||||||
|  |  | ||||||
| /* #define VERBOSE 0 */ | #define VERBOSE 0 | ||||||
| #ifndef VERBOSE |  | ||||||
| extern int VERBOSE; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define BEGIN_BATCH(n)							\ | #define BEGIN_BATCH(n)							\ | ||||||
| @@ -45,6 +42,7 @@ do {									\ | |||||||
|    if (VERBOSE) fprintf(stderr, 					\ |    if (VERBOSE) fprintf(stderr, 					\ | ||||||
| 			"BEGIN_BATCH(%d) in %s, %d dwords free\n",	\ | 			"BEGIN_BATCH(%d) in %s, %d dwords free\n",	\ | ||||||
| 			(n), __FUNCTION__, intel->batch.space/4);	\ | 			(n), __FUNCTION__, intel->batch.space/4);	\ | ||||||
|  |    assert(intel->locked); \ | ||||||
|    if (intel->batch.space < (n)*4)					\ |    if (intel->batch.space < (n)*4)					\ | ||||||
|       intelFlushBatch(intel, GL_TRUE);					\ |       intelFlushBatch(intel, GL_TRUE);					\ | ||||||
|    batch_ptr = intel->batch.ptr;					\ |    batch_ptr = intel->batch.ptr;					\ | ||||||
| @@ -65,12 +63,14 @@ do {								\ | |||||||
|    assert(intel->batch.space >= 0);				\ |    assert(intel->batch.space >= 0);				\ | ||||||
| } while(0) | } while(0) | ||||||
|  |  | ||||||
| extern void intelInitBatchBuffer( GLcontext *ctx ); | extern void intelInitBatchBuffer( struct intel_context *intel ); | ||||||
| extern void intelDestroyBatchBuffer( GLcontext *ctx ); | extern void intelDestroyBatchBuffer( struct intel_context *intel ); | ||||||
|  |  | ||||||
|  | void intelInstallBatchBuffer( struct intel_context *intel ); | ||||||
|  |  | ||||||
|  |  | ||||||
| extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ); | extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ); | ||||||
| extern void intelWrapInlinePrimitive( intelContextPtr intel ); | extern void intelWrapInlinePrimitive( intelContextPtr intel ); | ||||||
| extern void intelRestartInlinePrimitive( intelContextPtr intel ); |  | ||||||
| extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  | extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  | ||||||
| 					      int primitive, int dwords, | 					      int primitive, int dwords, | ||||||
| 					      int vertex_size); | 					      int vertex_size); | ||||||
| @@ -99,25 +99,8 @@ extern void intelEmitFillBlitLocked( intelContextPtr intel, | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,  | GLuint *intelExtendInlinePrimitive( intelContextPtr intel,  | ||||||
| 						GLuint dwords ) | 				    GLuint dwords ); | ||||||
| { | void intelValidateBuffers( struct intel_context *intel ); | ||||||
|    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; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							| @@ -90,7 +90,7 @@ int prevLockLine; | |||||||
|  * Mesa's Driver Functions |  * Mesa's Driver Functions | ||||||
|  ***************************************/ |  ***************************************/ | ||||||
|  |  | ||||||
| #define DRIVER_DATE                     "20050225" | #define DRIVER_DATE                     "20060201" | ||||||
|  |  | ||||||
| const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||||
| { | { | ||||||
| @@ -197,7 +197,7 @@ const struct dri_extension card_extensions[] = | |||||||
|     { "GL_NV_blend_square",                NULL }, |     { "GL_NV_blend_square",                NULL }, | ||||||
|     { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }, |     { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }, | ||||||
|     { "GL_NV_vertex_program1_1",           NULL }, |     { "GL_NV_vertex_program1_1",           NULL }, | ||||||
|     { "GL_SGIS_generate_mipmap",           NULL }, | /*     { "GL_SGIS_generate_mipmap",           NULL }, */ | ||||||
|     { NULL,                                NULL } |     { NULL,                                NULL } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -214,7 +214,7 @@ static const struct tnl_pipeline_stage *intel_pipeline[] = { | |||||||
|    &_tnl_point_attenuation_stage, |    &_tnl_point_attenuation_stage, | ||||||
|    &_tnl_arb_vertex_program_stage, |    &_tnl_arb_vertex_program_stage, | ||||||
|    &_tnl_vertex_program_stage, |    &_tnl_vertex_program_stage, | ||||||
| #if 1 | #if 0 | ||||||
|    &_intel_render_stage,     /* ADD: unclipped rastersetup-to-dma */ |    &_intel_render_stage,     /* ADD: unclipped rastersetup-to-dma */ | ||||||
| #endif | #endif | ||||||
|    &_tnl_render_stage, |    &_tnl_render_stage, | ||||||
| @@ -300,9 +300,6 @@ GLboolean intelInitContext( intelContextPtr intel, | |||||||
|    intel->sarea = saPriv; |    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.MaxTextureMaxAnisotropy = 2.0; | ||||||
|  |  | ||||||
|    ctx->Const.MinLineWidth = 1.0; |    ctx->Const.MinLineWidth = 1.0; | ||||||
| @@ -371,7 +368,12 @@ GLboolean intelInitContext( intelContextPtr intel, | |||||||
|  |  | ||||||
|    _math_matrix_ctr (&intel->ViewportMatrix); |    _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); | ||||||
|  |  | ||||||
|    if (intel->ctx.Mesa_DXTn) { |    if (intel->ctx.Mesa_DXTn) { | ||||||
|      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" ); |      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" ); | ||||||
| @@ -387,7 +389,7 @@ GLboolean intelInitContext( intelContextPtr intel, | |||||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_RECT ); */ | /* 			  DRI_TEXMGR_DO_TEXTURE_RECT ); */ | ||||||
|  |  | ||||||
|  |  | ||||||
|    intel->prim.flush = intelInitBatchBuffer; |    intel->prim.flush = NULL; | ||||||
|    intel->prim.primitive = ~0; |    intel->prim.primitive = ~0; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -431,21 +433,14 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | |||||||
|       _swrast_DestroyContext (&intel->ctx); |       _swrast_DestroyContext (&intel->ctx); | ||||||
|       intel->Fallback = 0;	/* don't call _swrast_Flush later */ |       intel->Fallback = 0;	/* don't call _swrast_Flush later */ | ||||||
|  |  | ||||||
|       intelDestroyBatchBuffer(&intel->ctx); |       intelDestroyBatchBuffer(intel); | ||||||
|        |        | ||||||
|  |  | ||||||
|       if ( release_texture_heaps ) { |       if ( release_texture_heaps ) { | ||||||
|          /* This share group is about to go away, free our private |          /* This share group is about to go away, free our private | ||||||
|           * texture object data. |           * texture object data. | ||||||
|           */ |           */ | ||||||
|          int i; | 	 fprintf(stderr, "do somethign to free texture heaps\n"); | ||||||
|  |  | ||||||
|          for ( i = 0 ; i < intel->nr_heaps ; i++ ) { |  | ||||||
| 	    driDestroyTextureHeap( intel->texture_heaps[ i ] ); |  | ||||||
| 	    intel->texture_heaps[ i ] = NULL; |  | ||||||
|          } |  | ||||||
|  |  | ||||||
| 	 assert( is_empty_list( & intel->swapped ) ); |  | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       /* free the Mesa context */ |       /* free the Mesa context */ | ||||||
| @@ -586,7 +581,13 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) | |||||||
|    __DRIscreenPrivate *sPriv = intel->driScreen; |    __DRIscreenPrivate *sPriv = intel->driScreen; | ||||||
|    drmI830Sarea * sarea = intel->sarea; |    drmI830Sarea * sarea = intel->sarea; | ||||||
|    int me = intel->hHWContext; |    int me = intel->hHWContext; | ||||||
|    unsigned   i; |    static int foo = 0; | ||||||
|  |  | ||||||
|  | /*    _mesa_printf("%s\n", __FUNCTION__); */ | ||||||
|  | /*    if (foo++ > 1) { */ | ||||||
|  | /*       _mesa_printf("%s - foo\n", __FUNCTION__); */ | ||||||
|  | /*       abort(); */ | ||||||
|  | /*    } */ | ||||||
|  |  | ||||||
|    drmGetLock(intel->driFd, intel->hHWContext, flags); |    drmGetLock(intel->driFd, intel->hHWContext, flags); | ||||||
|  |  | ||||||
| @@ -609,15 +610,6 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) | |||||||
|       sarea->ctxOwner = me; |       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. |  | ||||||
|     */ |  | ||||||
|  |  | ||||||
|    for ( i = 0 ; i < intel->nr_heaps ; i++ ) { |  | ||||||
|       DRI_AGE_TEXTURES( intel->texture_heaps[ i ] ); |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    if (dPriv && intel->lastStamp != dPriv->lastStamp) { |    if (dPriv && intel->lastStamp != dPriv->lastStamp) { | ||||||
|       intelWindowMoved( intel ); |       intelWindowMoved( intel ); | ||||||
|       intel->lastStamp = dPriv->lastStamp; |       intel->lastStamp = dPriv->lastStamp; | ||||||
|   | |||||||
| @@ -47,11 +47,9 @@ | |||||||
| #define DV_PF_565  (2<<8) | #define DV_PF_565  (2<<8) | ||||||
| #define DV_PF_8888 (3<<8) | #define DV_PF_8888 (3<<8) | ||||||
|  |  | ||||||
| #define INTEL_CONTEXT(ctx)	((intelContextPtr)(ctx)) | struct intel_region; | ||||||
|  |  | ||||||
| typedef struct intel_context intelContext; |  | ||||||
| typedef struct intel_context *intelContextPtr; | typedef struct intel_context *intelContextPtr; | ||||||
| typedef struct intel_texture_object *intelTextureObjectPtr; |  | ||||||
|  |  | ||||||
| typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *, | typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *, | ||||||
| 							  intelVertex *); | 							  intelVertex *); | ||||||
| @@ -72,33 +70,53 @@ extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ); | |||||||
| #define INTEL_TEX_MAXLEVELS 10 | #define INTEL_TEX_MAXLEVELS 10 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| struct intel_texture_object | struct intel_texture_object | ||||||
| { | { | ||||||
|    driTextureObject    base;	/* the parent class */ |    struct gl_texture_object base; /* The "parent" object */ | ||||||
|  |  | ||||||
|    GLuint texelBytes; |    /* The mipmap tree must include at least these levels once | ||||||
|    GLuint age; |     * validated: | ||||||
|    GLuint Pitch; |     */ | ||||||
|    GLuint Height; |    GLuint firstLevel; | ||||||
|    GLuint TextureOffset; |    GLuint lastLevel; | ||||||
|    GLubyte *BufAddr;    |  | ||||||
|  |  | ||||||
|    GLuint min_level; |    /* Offset for firstLevel image: | ||||||
|    GLuint max_level; |     */ | ||||||
|    GLuint depth_pitch; |    GLuint textureOffset; | ||||||
|  |  | ||||||
|    struct { |    /* On validation any active images held in main memory or in other | ||||||
|       const struct gl_texture_image *image; |     * regions will be copied to this region and the old storage freed. | ||||||
|       GLuint offset;       /* into BufAddr */ |     */ | ||||||
|       GLuint height; |    struct intel_mipmap_tree *mt; | ||||||
|       GLuint internalFormat; |  | ||||||
|    } image[6][INTEL_TEX_MAXLEVELS]; |  | ||||||
|  |  | ||||||
|    GLuint dirty; |  | ||||||
|    GLuint firstLevel,lastLevel; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct intel_reloc { | ||||||
|  |    GLuint *value; | ||||||
|  |    GLuint delta; | ||||||
|  |    GLuint *dest; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define INTEL_MAX_FIXUP 64 | ||||||
|  |  | ||||||
| struct intel_context | struct intel_context | ||||||
| { | { | ||||||
|    GLcontext ctx;		/* the parent class */ |    GLcontext ctx;		/* the parent class */ | ||||||
| @@ -122,14 +140,14 @@ struct intel_context | |||||||
| 			       GLboolean all,  | 			       GLboolean all,  | ||||||
| 			       GLint cx, GLint cy, GLint cw, GLint ch); | 			       GLint cx, GLint cy, GLint cw, GLint ch); | ||||||
|  |  | ||||||
|       intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj ); |  | ||||||
|  |  | ||||||
|    } vtbl; |    } vtbl; | ||||||
|  |  | ||||||
|    GLint refcount;    |    GLint refcount;    | ||||||
|    GLuint Fallback; |    GLuint Fallback; | ||||||
|    GLuint NewGLState; |    GLuint NewGLState; | ||||||
|     |     | ||||||
|  |    GLuint last_fence; | ||||||
|  |  | ||||||
|    struct { |    struct { | ||||||
|       GLuint start_offset; |       GLuint start_offset; | ||||||
|       GLint size; |       GLint size; | ||||||
| @@ -137,15 +155,16 @@ struct intel_context | |||||||
|       GLubyte *ptr; |       GLubyte *ptr; | ||||||
|    } batch; |    } batch; | ||||||
|        |        | ||||||
|  | #define INTEL_ALLOC_NR 64 | ||||||
|  | #define INTEL_ALLOC_SIZE 4096 | ||||||
|  |  | ||||||
|    struct { |    struct { | ||||||
|       void *ptr; |       GLuint buffer[INTEL_ALLOC_NR]; | ||||||
|       GLint size; |       GLuint current; | ||||||
|       GLuint offset; |  | ||||||
|       GLuint active_buf; |  | ||||||
|       GLuint irq_emitted; |  | ||||||
|    } alloc; |    } alloc; | ||||||
|  |  | ||||||
|    struct { |    struct { | ||||||
|  |       GLuint id; | ||||||
|       GLuint primitive; |       GLuint primitive; | ||||||
|       GLubyte *start_ptr;       |       GLubyte *start_ptr;       | ||||||
|       void (*flush)( GLcontext * ); |       void (*flush)( GLcontext * ); | ||||||
| @@ -179,14 +198,14 @@ struct intel_context | |||||||
|    GLboolean hw_stencil; |    GLboolean hw_stencil; | ||||||
|    GLboolean hw_stipple; |    GLboolean hw_stipple; | ||||||
|     |     | ||||||
|    /* Texture object bookkeeping |    /* AGP memory buffer manager: | ||||||
|     */ |     */ | ||||||
|    GLuint                nr_heaps; |    struct bufmgr *bm; | ||||||
|    driTexHeap          * texture_heaps[1]; |    struct bm_buffer_list *buffer_list; | ||||||
|    driTextureObject      swapped; |  | ||||||
|    GLuint                lastStamp; |    struct intel_reloc fixup[INTEL_MAX_FIXUP]; | ||||||
|  |    GLuint nr_fixups; | ||||||
|  |  | ||||||
|    struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS]; |  | ||||||
|  |  | ||||||
|    /* State for intelvb.c and inteltris.c. |    /* State for intelvb.c and inteltris.c. | ||||||
|     */ |     */ | ||||||
| @@ -195,7 +214,13 @@ struct intel_context | |||||||
|    GLenum render_primitive; |    GLenum render_primitive; | ||||||
|    GLenum reduced_primitive; |    GLenum reduced_primitive; | ||||||
|    GLuint vertex_size; |    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  |    /* Fallback rasterization functions  | ||||||
| @@ -212,7 +237,6 @@ struct intel_context | |||||||
|    GLuint numClipRects;		/* cliprects for that buffer */ |    GLuint numClipRects;		/* cliprects for that buffer */ | ||||||
|    drm_clip_rect_t *pClipRects; |    drm_clip_rect_t *pClipRects; | ||||||
|  |  | ||||||
|    int dirtyAge; |  | ||||||
|    int perf_boxes; |    int perf_boxes; | ||||||
|    int do_irqs; |    int do_irqs; | ||||||
|  |  | ||||||
| @@ -229,6 +253,8 @@ struct intel_context | |||||||
|    intelScreenPrivate *intelScreen;  |    intelScreenPrivate *intelScreen;  | ||||||
|    drmI830Sarea *sarea;  |    drmI830Sarea *sarea;  | ||||||
|     |     | ||||||
|  |    GLuint lastStamp; | ||||||
|  |  | ||||||
|    /** |    /** | ||||||
|     * Configuration cache |     * Configuration cache | ||||||
|     */ |     */ | ||||||
| @@ -511,6 +537,38 @@ extern void intel_dump_batchbuffer( long offset, | |||||||
|  */	 |  */	 | ||||||
| extern void intelInitPixelFuncs( struct dd_function_table *functions ); | extern 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 ); | ||||||
|  |  | ||||||
|  | struct intel_region *intel_readbuf_region( struct intel_context *intel ); | ||||||
|  | struct intel_region *intel_drawbuf_region( struct intel_context *intel ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /*====================================================================== | ||||||
|  |  * Inline conversion functions.   | ||||||
|  |  * These are better-typed than the macros used previously: | ||||||
|  |  */ | ||||||
|  | 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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define INTEL_CONTEXT(ctx)	intel_context(ctx) | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -38,11 +38,12 @@ | |||||||
| #include "intel_context.h" | #include "intel_context.h" | ||||||
| #include "intel_ioctl.h" | #include "intel_ioctl.h" | ||||||
| #include "intel_batchbuffer.h" | #include "intel_batchbuffer.h" | ||||||
|  | #include "intel_regions.h" | ||||||
| #include "drm.h" | #include "drm.h" | ||||||
|  | #include "bufmgr.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int intelEmitIrqLocked( intelContextPtr intel ) | ||||||
| static int intelEmitIrqLocked( intelContextPtr intel ) |  | ||||||
| { | { | ||||||
|    drmI830IrqEmit ie; |    drmI830IrqEmit ie; | ||||||
|    int ret, seq = 0; |    int ret, seq = 0; | ||||||
| @@ -52,12 +53,14 @@ static int intelEmitIrqLocked( intelContextPtr intel ) | |||||||
|  |  | ||||||
|    ie.irq_seq = &seq; |    ie.irq_seq = &seq; | ||||||
|  |  | ||||||
|  | #if 1 | ||||||
|    ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT,  |    ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT,  | ||||||
| 			      &ie, sizeof(ie) ); | 			      &ie, sizeof(ie) ); | ||||||
|    if ( ret ) { |    if ( ret ) { | ||||||
|       fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret ); |       fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret ); | ||||||
|       exit(1); |       exit(1); | ||||||
|    }    |    }    | ||||||
|  | #endif | ||||||
|  |  | ||||||
|    if (0) |    if (0) | ||||||
|       fprintf(stderr, "%s -->  %d\n", __FUNCTION__, seq ); |       fprintf(stderr, "%s -->  %d\n", __FUNCTION__, seq ); | ||||||
| @@ -65,7 +68,7 @@ static int intelEmitIrqLocked( intelContextPtr intel ) | |||||||
|    return seq; |    return seq; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void intelWaitIrq( intelContextPtr intel, int seq ) | void intelWaitIrq( intelContextPtr intel, int seq ) | ||||||
| { | { | ||||||
|    drmI830IrqWait iw; |    drmI830IrqWait iw; | ||||||
|    int ret; |    int ret; | ||||||
| @@ -75,31 +78,20 @@ static void intelWaitIrq( intelContextPtr intel, int seq ) | |||||||
|  |  | ||||||
|    iw.irq_seq = seq; |    iw.irq_seq = seq; | ||||||
| 	  | 	  | ||||||
|  | #if 1 | ||||||
|    do { |    do { | ||||||
|       ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) ); |       ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) ); | ||||||
|    } while (ret == -EAGAIN || ret == -EINTR); |    } while (ret == -EAGAIN || ret == -EINTR); | ||||||
|  |  | ||||||
|    if ( ret ) { |    if ( ret ) { | ||||||
|       fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, 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); |       exit(1); | ||||||
|    } |    } | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 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, | void intel_dump_batchbuffer( long offset, | ||||||
| 			     int *ptr, | 			     int *ptr, | ||||||
| 			     int count ) | 			     int count ) | ||||||
| @@ -107,34 +99,12 @@ void intel_dump_batchbuffer( long offset, | |||||||
|    int i; |    int i; | ||||||
|    fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count); |    fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count); | ||||||
|    for (i = 0; i < count/4; i += 4)  |    for (i = 0; i < count/4; i += 4)  | ||||||
|       fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",  |       fprintf(stderr, "\t0x%08x 0x%08x 0x%08x 0x%08x\n",  | ||||||
| 	      (unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); | /* 	      (unsigned int)offset + i*4,  */ | ||||||
|  | 	      ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); | ||||||
|    fprintf(stderr, "END BATCH\n\n\n"); |    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) | #define MI_BATCH_BUFFER_END 	(0xA<<23) | ||||||
|  |  | ||||||
| @@ -147,6 +117,9 @@ void intelFlushBatchLocked( intelContextPtr intel, | |||||||
|    drmI830BatchBuffer batch; |    drmI830BatchBuffer batch; | ||||||
|  |  | ||||||
|    assert(intel->locked); |    assert(intel->locked); | ||||||
|  |    assert(intel->buffer_list); | ||||||
|  |    assert(intel->batch.ptr); | ||||||
|  |  | ||||||
|  |  | ||||||
|    if (0) |    if (0) | ||||||
|       fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n", |       fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n", | ||||||
| @@ -163,17 +136,6 @@ void intelFlushBatchLocked( intelContextPtr intel, | |||||||
|     * single buffer. |     * single buffer. | ||||||
|     */ |     */ | ||||||
|    if (intel->numClipRects == 0 && !ignore_cliprects) { |    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 |       /* Note that any state thought to have been emitted actually | ||||||
|        * hasn't: |        * hasn't: | ||||||
|        */ |        */ | ||||||
| @@ -191,18 +153,16 @@ void intelFlushBatchLocked( intelContextPtr intel, | |||||||
|       batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |  |       batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |  | ||||||
| 		   (((GLuint)intel->drawY) << 16)); | 		   (((GLuint)intel->drawY) << 16)); | ||||||
|        |        | ||||||
|       if (intel->alloc.offset) { |       if ((batch.used & 0x4) == 0) { | ||||||
| 	 if ((batch.used & 0x4) == 0) { | 	 ((int *)intel->batch.ptr)[0] = 0; | ||||||
| 	    ((int *)intel->batch.ptr)[0] = 0; | 	 ((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END; | ||||||
| 	    ((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END; | 	 batch.used += 0x8; | ||||||
| 	    batch.used += 0x8; | 	 intel->batch.ptr += 0x8; | ||||||
| 	    intel->batch.ptr += 0x8; |       } | ||||||
| 	 } |       else { | ||||||
| 	 else { | 	 ((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END; | ||||||
| 	    ((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END; | 	 batch.used += 0x4; | ||||||
| 	    batch.used += 0x4; | 	 intel->batch.ptr += 0x4; | ||||||
| 	    intel->batch.ptr += 0x4; |  | ||||||
| 	 }       |  | ||||||
|       }       |       }       | ||||||
|  |  | ||||||
|       if (0) |       if (0) | ||||||
| @@ -214,56 +174,17 @@ void intelFlushBatchLocked( intelContextPtr intel, | |||||||
| 	 fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", | 	 fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", | ||||||
| 		 __FUNCTION__,  | 		 __FUNCTION__,  | ||||||
| 		 batch.start,  | 		 batch.start,  | ||||||
| 		 batch.start + batch.used, | 		 batch.start + batch.used * 4, | ||||||
| 		 batch.DR4, batch.num_cliprects); | 		 batch.DR4, batch.num_cliprects); | ||||||
|  |  | ||||||
|       intel->batch.start_offset += batch.used; | #if 1 | ||||||
|       intel->batch.size -= batch.used; |       if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,  | ||||||
|  | 			   sizeof(batch))) { | ||||||
|       if (intel->batch.size < 8) { | 	 fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n",  -errno); | ||||||
| 	 refill = GL_TRUE; | 	 UNLOCK_HARDWARE(intel); | ||||||
| 	 intel->batch.space = intel->batch.size = 0; | 	 exit(1); | ||||||
|       } |       } | ||||||
|       else { | #endif | ||||||
| 	 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 |       /* FIXME: use hardware contexts to avoid 'losing' hardware after | ||||||
|        * each buffer flush. |        * each buffer flush. | ||||||
| @@ -271,8 +192,17 @@ void intelFlushBatchLocked( intelContextPtr intel, | |||||||
|       intel->vtbl.lost_hardware( intel ); |       intel->vtbl.lost_hardware( intel ); | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    if (refill) |    bmUnmapBuffer( intel->bm, | ||||||
|       intelRefillBatchLocked( intel, allow_unlock ); | 		  intel->alloc.buffer[intel->alloc.current] ); | ||||||
|  |    intel->batch.ptr = NULL; | ||||||
|  |    intel->batch.size = 0; | ||||||
|  |    intel->batch.space = 0; | ||||||
|  |  | ||||||
|  |    intel->last_fence = bmFenceBufferList(intel->bm, intel->buffer_list); | ||||||
|  |    bmFreeBufferList(intel->buffer_list); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    intel->buffer_list = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| void intelFlushBatch( intelContextPtr intel, GLboolean refill ) | void intelFlushBatch( intelContextPtr intel, GLboolean refill ) | ||||||
| @@ -281,9 +211,7 @@ void intelFlushBatch( intelContextPtr intel, GLboolean refill ) | |||||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE ); |       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE ); | ||||||
|    }  |    }  | ||||||
|    else { |    else { | ||||||
|       LOCK_HARDWARE(intel); |       assert(intel->batch.size == intel->batch.space); | ||||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE ); |  | ||||||
|       UNLOCK_HARDWARE(intel); |  | ||||||
|    } |    } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -291,21 +219,31 @@ void intelFlushBatch( intelContextPtr intel, GLboolean refill ) | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void wait_for_idle_locked( struct intel_context *intel ) | ||||||
|  |  | ||||||
| void intelWaitForIdle( intelContextPtr intel ) |  | ||||||
| { | { | ||||||
|    if (0) |    intelInstallBatchBuffer(intel); | ||||||
|       fprintf(stderr, "%s\n", __FUNCTION__); |  | ||||||
|  |    bmAddBuffer(intel->buffer_list, intel->draw_region->buffer, | ||||||
|  | 	       BM_WRITE, NULL, NULL); | ||||||
|  |     | ||||||
|  |    intelValidateBuffers(intel); | ||||||
|  |  | ||||||
|    intel->vtbl.emit_flush( intel ); |    intel->vtbl.emit_flush( intel ); | ||||||
|    intelFlushBatch( intel, GL_TRUE ); |    intelFlushBatch( intel, GL_TRUE ); | ||||||
|  |  | ||||||
|    /* Use an irq to wait for dma idle -- Need to track lost contexts |    bmFinishFence( intel->bm, intel->last_fence ); | ||||||
|     * to shortcircuit consecutive calls to this function: | } | ||||||
|     */ |  | ||||||
|    intelWaitIrq( intel, intel->alloc.irq_emitted ); | void intelWaitForIdle( intelContextPtr intel ) | ||||||
|    intel->alloc.irq_emitted = 0; | {    | ||||||
|  |    if (intel->locked) { | ||||||
|  |       wait_for_idle_locked( intel ); | ||||||
|  |    } | ||||||
|  |    else { | ||||||
|  |       LOCK_HARDWARE(intel); | ||||||
|  |       wait_for_idle_locked( intel ); | ||||||
|  |       UNLOCK_HARDWARE(intel); | ||||||
|  |    } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -396,171 +334,6 @@ void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) |  | ||||||
| { |  | ||||||
|    int region_offset = 0; |  | ||||||
|    drmI830MemAlloc alloc; |  | ||||||
|    int ret; |  | ||||||
|  |  | ||||||
|    if (0) |  | ||||||
|       fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size); |  | ||||||
|  |  | ||||||
|    alloc.region = I830_MEM_REGION_AGP; |  | ||||||
|    alloc.alignment = 0; |  | ||||||
|    alloc.size = size; |  | ||||||
|    alloc.region_offset = ®ion_offset; |  | ||||||
|  |  | ||||||
|    LOCK_HARDWARE(intel); |  | ||||||
|  |  | ||||||
|    /* Make sure the global heap is initialized |  | ||||||
|     */ |  | ||||||
|    if (intel->texture_heaps[0]) |  | ||||||
|       driAgeTextures( intel->texture_heaps[0] ); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|    ret = drmCommandWriteRead( intel->driFd, |  | ||||||
| 			      DRM_I830_ALLOC, |  | ||||||
| 			      &alloc, sizeof(alloc)); |  | ||||||
|     |  | ||||||
|    if (ret) { |  | ||||||
|       fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret); |  | ||||||
|       UNLOCK_HARDWARE(intel); |  | ||||||
|       return NULL; |  | ||||||
|    } |  | ||||||
|     |  | ||||||
|    if (0) |  | ||||||
|       fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size); |  | ||||||
|  |  | ||||||
|    /* Need to propogate this information (agp memory in use) to our |  | ||||||
|     * local texture lru.  The kernel has already updated the global |  | ||||||
|     * lru.  An alternative would have been to allocate memory the |  | ||||||
|     * usual way and then notify the kernel to pin the allocation. |  | ||||||
|     */ |  | ||||||
|    if (intel->texture_heaps[0]) |  | ||||||
|       driAgeTextures( intel->texture_heaps[0] ); |  | ||||||
|  |  | ||||||
|    UNLOCK_HARDWARE(intel);    |  | ||||||
|  |  | ||||||
|    return (void *)((char *)intel->intelScreen->tex.map + region_offset); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void intelFreeAGP( intelContextPtr intel, void *pointer ) |  | ||||||
| { |  | ||||||
|    int region_offset; |  | ||||||
|    drmI830MemFree memfree; |  | ||||||
|    int ret; |  | ||||||
|  |  | ||||||
|    region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map; |  | ||||||
|  |  | ||||||
|    if (region_offset < 0 ||  |  | ||||||
|        region_offset > intel->intelScreen->tex.size) { |  | ||||||
|       fprintf(stderr, "offset %d outside range 0..%d\n", region_offset, |  | ||||||
| 	      intel->intelScreen->tex.size); |  | ||||||
|       return; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    memfree.region = I830_MEM_REGION_AGP; |  | ||||||
|    memfree.region_offset = region_offset; |  | ||||||
|     |  | ||||||
|    ret = drmCommandWrite( intel->driFd, |  | ||||||
| 			  DRM_I830_FREE, |  | ||||||
| 			  &memfree, sizeof(memfree)); |  | ||||||
|     |  | ||||||
|    if (ret)  |  | ||||||
|       fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* This version of AllocateMemoryMESA allocates only agp memory, and |  | ||||||
|  * only does so after the point at which the driver has been |  | ||||||
|  * initialized. |  | ||||||
|  * |  | ||||||
|  * Theoretically a valid context isn't required.  However, in this |  | ||||||
|  * implementation, it is, as I'm using the hardware lock to protect |  | ||||||
|  * the kernel data structures, and the current context to get the |  | ||||||
|  * device fd. |  | ||||||
|  */ |  | ||||||
| void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn, |  | ||||||
| 			      GLsizei size, GLfloat readfreq, |  | ||||||
| 			      GLfloat writefreq, GLfloat priority) |  | ||||||
| { |  | ||||||
|    GET_CURRENT_CONTEXT(ctx); |  | ||||||
|  |  | ||||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) |  | ||||||
|       fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,  |  | ||||||
| 	      writefreq, priority); |  | ||||||
|  |  | ||||||
|    if (getenv("INTEL_NO_ALLOC")) |  | ||||||
|       return NULL; |  | ||||||
|     |  | ||||||
|    if (!ctx || INTEL_CONTEXT(ctx) == 0)  |  | ||||||
|       return NULL; |  | ||||||
|     |  | ||||||
|    return intelAllocateAGP( INTEL_CONTEXT(ctx), size ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Called via glXFreeMemoryMESA() */ |  | ||||||
| void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer) |  | ||||||
| { |  | ||||||
|    GET_CURRENT_CONTEXT(ctx); |  | ||||||
|    if (INTEL_DEBUG & DEBUG_IOCTL)  |  | ||||||
|       fprintf(stderr, "%s %p\n", __FUNCTION__, pointer); |  | ||||||
|  |  | ||||||
|    if (!ctx || INTEL_CONTEXT(ctx) == 0) { |  | ||||||
|       fprintf(stderr, "%s: no context\n", __FUNCTION__); |  | ||||||
|       return; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    intelFreeAGP( INTEL_CONTEXT(ctx), pointer ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Called via glXGetMemoryOffsetMESA()  |  | ||||||
|  * |  | ||||||
|  * Returns offset of pointer from the start of agp aperture. |  | ||||||
|  */ |  | ||||||
| GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn,  |  | ||||||
| 				const GLvoid *pointer) |  | ||||||
| { |  | ||||||
|    GET_CURRENT_CONTEXT(ctx); |  | ||||||
|    intelContextPtr intel; |  | ||||||
|  |  | ||||||
|    if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) { |  | ||||||
|       fprintf(stderr, "%s: no context\n", __FUNCTION__); |  | ||||||
|       return ~0; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    if (!intelIsAgpMemory( intel, pointer, 0 )) |  | ||||||
|       return ~0; |  | ||||||
|  |  | ||||||
|    return intelAgpOffsetFromVirtual( intel, pointer ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, |  | ||||||
| 			   GLint size ) |  | ||||||
| { |  | ||||||
|    int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; |  | ||||||
|    int valid = (size >= 0 && |  | ||||||
| 		offset >= 0 && |  | ||||||
| 		offset + size < intel->intelScreen->tex.size); |  | ||||||
|  |  | ||||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) |  | ||||||
|       fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid ); |  | ||||||
|     |  | ||||||
|    return valid; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer ) |  | ||||||
| { |  | ||||||
|    int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; |  | ||||||
|  |  | ||||||
|    if (offset < 0 || offset > intel->intelScreen->tex.size) |  | ||||||
|       return ~0; |  | ||||||
|    else |  | ||||||
|       return intel->intelScreen->tex.offset + offset; |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -46,21 +46,9 @@ extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unloc | |||||||
| extern void intelFinish( GLcontext *ctx ); | extern void intelFinish( GLcontext *ctx ); | ||||||
| extern void intelFlush( 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,  | void intelWaitIrq( intelContextPtr intel, int seq ); | ||||||
| 				      GLsizei size, GLfloat readfreq, | int intelEmitIrqLocked( intelContextPtr intel ); | ||||||
| 				      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 ); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										250
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,250 @@ | |||||||
|  | /************************************************************************** | ||||||
|  |  *  | ||||||
|  |  * 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; | ||||||
|  |  | ||||||
|  |    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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct intel_mipmap_tree *intel_miptree_reference( struct intel_mipmap_tree *mt ) | ||||||
|  | { | ||||||
|  |    mt->refcount++; | ||||||
|  |    return mt; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void intel_miptree_release( struct intel_context *intel, | ||||||
|  | 			   struct intel_mipmap_tree *mt ) | ||||||
|  | { | ||||||
|  |    if (--mt->refcount) { | ||||||
|  |       intel_region_release(intel, mt->region); | ||||||
|  |       free(mt); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* 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].x + | ||||||
|  | 	   mt->offset[face][level].y * mt->pitch) * mt->cpp; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | GLubyte *intel_miptree_image_map(struct intel_context *intel,  | ||||||
|  | 				 struct intel_mipmap_tree *mt, | ||||||
|  | 				 GLuint face, | ||||||
|  | 				 GLuint level, | ||||||
|  | 				 GLuint *stride) | ||||||
|  | { | ||||||
|  |    DBG("%s \n", __FUNCTION__); | ||||||
|  |     | ||||||
|  |    if (stride) | ||||||
|  |       *stride = mt->pitch * mt->cpp; | ||||||
|  |  | ||||||
|  |    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. | ||||||
|  |  * | ||||||
|  |  * TODO: 3D textures | ||||||
|  |  */ | ||||||
|  | void intel_miptree_image_data(struct intel_context *intel,  | ||||||
|  | 			      struct intel_mipmap_tree *dst, | ||||||
|  | 			      GLuint face, | ||||||
|  | 			      GLuint level, | ||||||
|  | 			      void *src, GLuint src_pitch ) | ||||||
|  | { | ||||||
|  |    DBG("%s\n", __FUNCTION__); | ||||||
|  |    intel_region_data(intel, | ||||||
|  | 		     dst->region, | ||||||
|  | 		     dst->offset[face][level].x, | ||||||
|  | 		     dst->offset[face][level].y, | ||||||
|  | 		     src, | ||||||
|  | 		     src_pitch, | ||||||
|  | 		     0, 0,	/* source x,y */ | ||||||
|  | 		     dst->offset[face][level].width, | ||||||
|  | 		     dst->offset[face][level].height);       | ||||||
|  | } | ||||||
|  | 			   | ||||||
|  | /* 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 ) | ||||||
|  | { | ||||||
|  |    DBG("%s\n", __FUNCTION__); | ||||||
|  |    assert(src->offset[face][level].width ==  | ||||||
|  | 	  dst->offset[face][level].width); | ||||||
|  |  | ||||||
|  |    assert(src->offset[face][level].height ==  | ||||||
|  | 	  dst->offset[face][level].height); | ||||||
|  |  | ||||||
|  |    intel_region_copy(intel, | ||||||
|  | 		     dst->region, | ||||||
|  | 		     dst->offset[face][level].x, | ||||||
|  | 		     dst->offset[face][level].y, | ||||||
|  | 		     src->region, | ||||||
|  | 		     src->offset[face][level].x, | ||||||
|  | 		     src->offset[face][level].y, | ||||||
|  | 		     src->offset[face][level].width, | ||||||
|  | 		     src->offset[face][level].height); | ||||||
|  | 		      | ||||||
|  | } | ||||||
							
								
								
									
										166
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | |||||||
|  | /************************************************************************** | ||||||
|  |  *  | ||||||
|  |  * 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 x;  | ||||||
|  |    GLuint y; | ||||||
|  |    GLuint width; | ||||||
|  |    GLuint height; | ||||||
|  |    GLuint depth;		/* how will this work? */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | 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); | ||||||
|  |  | ||||||
|  | struct intel_mipmap_tree *intel_miptree_reference( struct intel_mipmap_tree * ); | ||||||
|  |  | ||||||
|  | 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 *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 ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* 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_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 | ||||||
| @@ -35,11 +35,11 @@ | |||||||
| #include "intel_context.h" | #include "intel_context.h" | ||||||
| #include "intel_ioctl.h" | #include "intel_ioctl.h" | ||||||
| #include "intel_batchbuffer.h" | #include "intel_batchbuffer.h" | ||||||
|  | #include "intel_regions.h" | ||||||
|  | #include "bufmgr.h" | ||||||
|  |  | ||||||
| static GLboolean | static GLboolean | ||||||
| check_color( const GLcontext *ctx, GLenum type, GLenum format, | check_color( GLcontext *ctx, GLenum type, GLenum format, | ||||||
| 	     const struct gl_pixelstore_attrib *packing, | 	     const struct gl_pixelstore_attrib *packing, | ||||||
| 	     const void *pixels, GLint sz, GLint pitch ) | 	     const void *pixels, GLint sz, GLint pitch ) | ||||||
| { | { | ||||||
| @@ -72,38 +72,28 @@ check_color( const GLcontext *ctx, GLenum type, GLenum format, | |||||||
|    return GL_FALSE; |    return GL_FALSE; | ||||||
| } | } | ||||||
|  |  | ||||||
| static GLboolean | GLboolean intel_check_color_per_fragment_ops( const GLcontext *ctx ) | ||||||
| check_color_per_fragment_ops( const GLcontext *ctx ) |  | ||||||
| { | { | ||||||
|    int result; |    return !(ctx->Color.AlphaEnabled ||  | ||||||
|    result = (!(     ctx->Color.AlphaEnabled ||  | 	    ctx->Depth.Test || | ||||||
| 		    ctx->Depth.Test || | 	    ctx->Fog.Enabled || | ||||||
| 		    ctx->Fog.Enabled || | 	    ctx->Scissor.Enabled || | ||||||
| 		    ctx->Scissor.Enabled || | 	    ctx->Stencil.Enabled || | ||||||
| 		    ctx->Stencil.Enabled || | 	    !ctx->Color.ColorMask[0] || | ||||||
| 		    !ctx->Color.ColorMask[0] || | 	    !ctx->Color.ColorMask[1] || | ||||||
| 		    !ctx->Color.ColorMask[1] || | 	    !ctx->Color.ColorMask[2] || | ||||||
| 		    !ctx->Color.ColorMask[2] || | 	    !ctx->Color.ColorMask[3] || | ||||||
| 		    !ctx->Color.ColorMask[3] || | 	    ctx->Color.ColorLogicOpEnabled || | ||||||
| 		    ctx->Color.ColorLogicOpEnabled || | 	    ctx->Texture._EnabledUnits); | ||||||
| 		    ctx->Texture._EnabledUnits |  | ||||||
|            ) && |  | ||||||
| 	   ctx->Current.RasterPosValid); |  | ||||||
|     |  | ||||||
|    return result; |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static GLboolean | GLboolean intel_clip_to_framebuffer( GLcontext *ctx, | ||||||
| clip_pixelrect( const GLcontext *ctx, | 				     const GLframebuffer *buffer, | ||||||
| 		const GLframebuffer *buffer, | 				     GLint *x, GLint *y, | ||||||
| 		GLint *x, GLint *y, | 				     GLsizei *width, GLsizei *height ) | ||||||
| 		GLsizei *width, GLsizei *height, |  | ||||||
| 		GLint *size ) |  | ||||||
| { | { | ||||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); |  | ||||||
|  |  | ||||||
|    /* left clipping */ |    /* left clipping */ | ||||||
|    if (*x < buffer->_Xmin) { |    if (*x < buffer->_Xmin) { | ||||||
|       *width -= (buffer->_Xmin - *x); |       *width -= (buffer->_Xmin - *x); | ||||||
| @@ -130,9 +120,6 @@ clip_pixelrect( const GLcontext *ctx, | |||||||
|    if (*height <= 0) |    if (*height <= 0) | ||||||
|       return GL_FALSE; |       return GL_FALSE; | ||||||
|  |  | ||||||
|    *size = ((*y + *height - 1) * intel->intelScreen->front.pitch + |  | ||||||
| 	    (*x + *width - 1) * intel->intelScreen->cpp); |  | ||||||
|  |  | ||||||
|    return GL_TRUE; |    return GL_TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -152,8 +139,7 @@ intelTryReadPixels( GLcontext *ctx, | |||||||
|  |  | ||||||
|    /* Only accelerate reading to agp buffers. |    /* Only accelerate reading to agp buffers. | ||||||
|     */ |     */ | ||||||
|    if ( !intelIsAgpMemory(intel, pixels,  |    if ( 1 ) { | ||||||
| 			pitch * height * intel->intelScreen->cpp ) ) { |  | ||||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) |       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||||
| 	 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); | 	 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); | ||||||
|       return GL_FALSE; |       return GL_FALSE; | ||||||
| @@ -194,12 +180,11 @@ intelTryReadPixels( GLcontext *ctx, | |||||||
|       int nbox = dPriv->numClipRects; |       int nbox = dPriv->numClipRects; | ||||||
|       int src_offset = intel->drawOffset; |       int src_offset = intel->drawOffset; | ||||||
|       int src_pitch = intel->intelScreen->front.pitch; |       int src_pitch = intel->intelScreen->front.pitch; | ||||||
|       int dst_offset = intelAgpOffsetFromVirtual( intel, pixels); |       int dst_offset = 0; | ||||||
|       drm_clip_rect_t *box = dPriv->pClipRects; |       drm_clip_rect_t *box = dPriv->pClipRects; | ||||||
|       int i; |       int i; | ||||||
|  |  | ||||||
|       if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, |       if (!intel_clip_to_framebuffer(ctx, ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||||
| 			  &size)) { |  | ||||||
| 	 UNLOCK_HARDWARE( intel ); | 	 UNLOCK_HARDWARE( intel ); | ||||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||||
| 	    fprintf(stderr, "%s totally clipped -- nothing to do\n", | 	    fprintf(stderr, "%s totally clipped -- nothing to do\n", | ||||||
| @@ -276,8 +261,7 @@ static void do_draw_pix( GLcontext *ctx, | |||||||
|    drm_clip_rect_t *box = dPriv->pClipRects; |    drm_clip_rect_t *box = dPriv->pClipRects; | ||||||
|    int nbox = dPriv->numClipRects; |    int nbox = dPriv->numClipRects; | ||||||
|    int i; |    int i; | ||||||
|    int size; |    int src_offset = 0; | ||||||
|    int src_offset = intelAgpOffsetFromVirtual( intel, pixels); |  | ||||||
|    int src_pitch = pitch; |    int src_pitch = pitch; | ||||||
|  |  | ||||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) |    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||||
| @@ -289,9 +273,8 @@ static void do_draw_pix( GLcontext *ctx, | |||||||
|    { |    { | ||||||
|       y -= height;			/* cope with pixel zoom */ |       y -= height;			/* cope with pixel zoom */ | ||||||
|     |     | ||||||
|       if (!clip_pixelrect(ctx, ctx->DrawBuffer, |       if (!intel_clip_to_framebuffer(ctx, ctx->DrawBuffer, | ||||||
| 			  &x, &y, &width, &height, | 			  &x, &y, &width, &height)) { | ||||||
| 			  &size)) { |  | ||||||
| 	 UNLOCK_HARDWARE( intel ); | 	 UNLOCK_HARDWARE( intel ); | ||||||
| 	 return; | 	 return; | ||||||
|       } |       } | ||||||
| @@ -367,7 +350,7 @@ intelTryDrawPixels( GLcontext *ctx, | |||||||
|  |  | ||||||
|       /* Can't do conversions on agp reads/draws.  |       /* Can't do conversions on agp reads/draws.  | ||||||
|        */ |        */ | ||||||
|       if ( !intelIsAgpMemory( intel, pixels, size ) ) { |       if ( 1 ) { | ||||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||||
| 	    fprintf(stderr, "%s: not agp memory\n", __FUNCTION__); | 	    fprintf(stderr, "%s: not agp memory\n", __FUNCTION__); | ||||||
| 	 return GL_FALSE; | 	 return GL_FALSE; | ||||||
| @@ -376,9 +359,11 @@ intelTryDrawPixels( GLcontext *ctx, | |||||||
|       if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { |       if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { | ||||||
| 	 return GL_FALSE; | 	 return GL_FALSE; | ||||||
|       } |       } | ||||||
|       if (!check_color_per_fragment_ops(ctx)) { |       if (!intel_check_color_per_fragment_ops(ctx)) { | ||||||
| 	 return GL_FALSE; | 	 return GL_FALSE; | ||||||
|       } |       } | ||||||
|  |       if (!ctx->Current.RasterPosValid) | ||||||
|  | 	 return GL_FALSE; | ||||||
|  |  | ||||||
|       if (ctx->Pixel.ZoomX != 1.0F || |       if (ctx->Pixel.ZoomX != 1.0F || | ||||||
| 	  ctx->Pixel.ZoomY != -1.0F) | 	  ctx->Pixel.ZoomY != -1.0F) | ||||||
| @@ -389,7 +374,7 @@ intelTryDrawPixels( GLcontext *ctx, | |||||||
|       return GL_FALSE; |       return GL_FALSE; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    if ( intelIsAgpMemory(intel, pixels, size) ) |    if ( 0 ) | ||||||
|    { |    { | ||||||
|       do_draw_pix( ctx, x, y, width, height, pitch, pixels, |       do_draw_pix( ctx, x, y, width, height, pitch, pixels, | ||||||
| 		   dest ); | 		   dest ); | ||||||
| @@ -424,6 +409,41 @@ intelDrawPixels( GLcontext *ctx, | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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: | ||||||
|  |       return NULL; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -431,58 +451,180 @@ intelDrawPixels( GLcontext *ctx, | |||||||
|  * for the color buffer.  Don't support zooming, pixel transfer, etc. |  * for the color buffer.  Don't support zooming, pixel transfer, etc. | ||||||
|  * We do support copying from one window to another, ala glXMakeCurrentRead. |  * We do support copying from one window to another, ala glXMakeCurrentRead. | ||||||
|  */ |  */ | ||||||
|  | static GLboolean intelTryCopyPixels( 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->_ImageTransferState || | ||||||
|  |        ctx->Pixel.ZoomX != 1.0F ||  | ||||||
|  |        ctx->Pixel.ZoomY != 1.0F) | ||||||
|  |       return GL_FALSE; | ||||||
|  |  | ||||||
|  |    switch (type) { | ||||||
|  |    case GL_COLOR: | ||||||
|  |       src = intel_readbuf_region( intel ); | ||||||
|  |       /* No readbuffer, copypixels is a noop:  | ||||||
|  |        */ | ||||||
|  |       if (!src) | ||||||
|  | 	 return GL_TRUE; | ||||||
|  |       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 ); | ||||||
|  |    intelInstallBatchBuffer( 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 dst_offset = 0; | ||||||
|  |       GLuint src_offset = 0; | ||||||
|  |       GLuint i; | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  |       dsty -= height;			/* cope with pixel zoom */ | ||||||
|  |       srcy -= height;			/* cope with pixel zoom */ | ||||||
|  | #endif | ||||||
|  |       if (!ctx->DrawBuffer) | ||||||
|  | 	 goto out; | ||||||
|  |  | ||||||
|  |       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; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |       bmAddBuffer(intel->buffer_list, dst->buffer, BM_NO_EVICT|BM_NO_UPLOAD|BM_WRITE,  | ||||||
|  | 		  NULL, &dst_offset); | ||||||
|  |       bmAddBuffer(intel->buffer_list, src->buffer, BM_NO_EVICT|BM_NO_UPLOAD|BM_READ,  | ||||||
|  | 		  NULL, &src_offset); | ||||||
|  |  | ||||||
|  |       if (!bmValidateBufferList(intel->bm, intel->buffer_list, BM_MEM_AGP))  | ||||||
|  | 	 goto out; | ||||||
|  |        | ||||||
|  |       /* 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; | ||||||
|  |  | ||||||
|  | 	 assert(dst_offset == intel->drawOffset); | ||||||
|  |  | ||||||
|  | 	 intelEmitCopyBlitLocked( intel, | ||||||
|  | 				  dst->cpp, | ||||||
|  | 				  src->pitch, src_offset, | ||||||
|  | 				  dst->pitch, dst_offset, | ||||||
|  | 				  bx + delta_x, by - delta_y, /* srcx, srcy */ | ||||||
|  | 				  bx, by, /* dstx, dsty */ | ||||||
|  | 				  bw, bh ); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |  out: | ||||||
|  |    intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_FALSE); | ||||||
|  |    UNLOCK_HARDWARE( intel ); | ||||||
|  |    return GL_TRUE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static void | static void | ||||||
| intelCopyPixels( GLcontext *ctx, | intelCopyPixels( GLcontext *ctx, | ||||||
| 		 GLint srcx, GLint srcy, GLsizei width, GLsizei height, | 		 GLint srcx, GLint srcy, GLsizei width, GLsizei height, | ||||||
| 		 GLint destx, GLint desty, GLenum type ) | 		 GLint destx, GLint desty, GLenum type ) | ||||||
| { | { | ||||||
| #if 0 |    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||||
|    const XMesaContext xmesa = XMESA_CONTEXT(ctx); |       fprintf(stderr, "%s\n", __FUNCTION__); | ||||||
|    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); |    if (!intelTryCopyPixels( ctx, srcx, srcy, width, height, destx, desty, type)) { | ||||||
|    ASSERT(gc); | /*       if (INTEL_DEBUG & DEBUG_FALLBACKS) */ | ||||||
|  | 	 _mesa_printf("fallback to _swrast_CopyPixels\n"); | ||||||
|    if (drawBuffer &&  /* buffer != 0 means it's a Window or Pixmap */ |       _swrast_CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type); | ||||||
|        readBuffer && |  | ||||||
|        type == GL_COLOR && |  | ||||||
|        (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */ |  | ||||||
|        ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */ |  | ||||||
|        ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */ |  | ||||||
|        ctx->Pixel.ZoomY == 1.0) { |  | ||||||
|       /* Note: we don't do any special clipping work here.  We could, |  | ||||||
|        * but X will do it for us. |  | ||||||
|        */ |  | ||||||
|       srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1; |  | ||||||
|       desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1; |  | ||||||
|       XCopyArea(dpy, readBuffer, drawBuffer, gc, |  | ||||||
|                 srcx, srcy, width, height, destx, desty); |  | ||||||
|    } |    } | ||||||
| #else |  | ||||||
|    _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type ); |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| void intelInitPixelFuncs( struct dd_function_table *functions ) | void intelInitPixelFuncs( struct dd_function_table *functions ) | ||||||
| { | { | ||||||
|    /* Pixel path fallbacks. |    /* Pixel path fallbacks. | ||||||
|     */ |     */ | ||||||
|    functions->Accum = _swrast_Accum; |    functions->Accum = _swrast_Accum; | ||||||
|    functions->Bitmap = _swrast_Bitmap; |    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->ReadPixels = intelReadPixels;   | ||||||
|       functions->DrawPixels = intelDrawPixels;  |       functions->DrawPixels = intelDrawPixels;  | ||||||
|    } |    } | ||||||
|    else { |    else { | ||||||
|  |       functions->CopyPixels = _swrast_CopyPixels; | ||||||
|       functions->ReadPixels = _swrast_ReadPixels; |       functions->ReadPixels = _swrast_ReadPixels; | ||||||
|       functions->DrawPixels = _swrast_DrawPixels; |       functions->DrawPixels = _swrast_DrawPixels; | ||||||
|    } |    } | ||||||
|   | |||||||
							
								
								
									
										363
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,363 @@ | |||||||
|  | /************************************************************************** | ||||||
|  |  *  | ||||||
|  |  * 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_batchbuffer.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); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct intel_region *intel_region_reference( struct intel_region *region ) | ||||||
|  | { | ||||||
|  |    region->refcount++; | ||||||
|  |    return region; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void intel_region_release( struct intel_context *intel, | ||||||
|  | 			   struct intel_region *region ) | ||||||
|  | { | ||||||
|  |    if (--region->refcount) { | ||||||
|  |       assert(region->map_refcount == 0); | ||||||
|  |       bmDeleteBuffers(intel->bm, 1, ®ion->buffer); | ||||||
|  |       free(region); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Could make color a char * to handle deeper buffers. | ||||||
|  |  */ | ||||||
|  | static void _mesa_fill_rect( GLubyte *dst, | ||||||
|  | 			     GLuint cpp, | ||||||
|  | 			     GLuint dst_pitch, | ||||||
|  | 			     GLuint dst_x,  | ||||||
|  | 			     GLuint dst_y, | ||||||
|  | 			     GLuint width, | ||||||
|  | 			     GLuint height, | ||||||
|  | 			     GLuint color ) | ||||||
|  | { | ||||||
|  |    GLuint i,j; | ||||||
|  |  | ||||||
|  |    switch (cpp) { | ||||||
|  |    case 1: | ||||||
|  |       dst += dst_x; | ||||||
|  |       dst += dst_y * dst_pitch; | ||||||
|  |       for (i = 0; i < height; i++) {  | ||||||
|  | 	 memset(dst, color, width); | ||||||
|  | 	 dst += dst_pitch; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |    case 2: { | ||||||
|  |       GLushort color_short = color & 0xffff; | ||||||
|  |       GLushort *dst_short = (GLushort *)dst; | ||||||
|  |       dst_short += dst_x; | ||||||
|  |       dst_short += dst_y * dst_pitch; | ||||||
|  |  | ||||||
|  |       for (i = 0; i < height; i++) {  | ||||||
|  | 	 for (j = 0; j < width; j++)  | ||||||
|  | 	    dst_short[j] = color_short; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |    } | ||||||
|  |    case 4: { | ||||||
|  |       GLuint *dst_int = (GLuint *)dst; | ||||||
|  |       dst_int += dst_x; | ||||||
|  |       dst_int += dst_y * dst_pitch; | ||||||
|  |  | ||||||
|  |       for (i = 0; i < height; i++) {  | ||||||
|  | 	 for (j = 0; j < width; j++)  | ||||||
|  | 	    dst_int[j] = color; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |    } | ||||||
|  |    default: | ||||||
|  |       assert(0); | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* 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 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->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 dstx, GLuint dsty, | ||||||
|  | 			struct intel_region *src, | ||||||
|  | 			GLuint srcx, GLuint srcy, | ||||||
|  | 			GLuint width, GLuint height ) | ||||||
|  | { | ||||||
|  |    unsigned dst_offset; | ||||||
|  |    unsigned src_offset; | ||||||
|  |    struct bm_buffer_list *list = bmNewBufferList(); | ||||||
|  |  | ||||||
|  |    DBG("%s\n", __FUNCTION__); | ||||||
|  |  | ||||||
|  |    assert(src->cpp == dst->cpp); | ||||||
|  |  | ||||||
|  |    LOCK_HARDWARE(intel); | ||||||
|  |    bmAddBuffer(list, dst->buffer, BM_WRITE, NULL, &dst_offset); | ||||||
|  |    bmAddBuffer(list, src->buffer, BM_READ, NULL, &src_offset); | ||||||
|  |  | ||||||
|  |    /* Query if both buffers are already uploaded: | ||||||
|  |     */ | ||||||
|  |    if (bmValidateBufferList(intel->bm, list, BM_NO_EVICT|BM_NO_UPLOAD|BM_MEM_AGP)) { | ||||||
|  |       intelEmitCopyBlitLocked(intel, | ||||||
|  | 			      dst->cpp, | ||||||
|  | 			      src->pitch, src_offset, | ||||||
|  | 			      dst->pitch, dst_offset,  | ||||||
|  | 			      srcx, srcy, | ||||||
|  | 			      dstx, dsty, | ||||||
|  | 			      width, height); | ||||||
|  |  | ||||||
|  |       bmFenceBufferList(intel->bm, list); | ||||||
|  |    } | ||||||
|  |    else { | ||||||
|  |       _mesa_copy_rect(intel_region_map(intel, dst), | ||||||
|  | 		      dst->cpp, | ||||||
|  | 		      dst->pitch, | ||||||
|  | 		      dstx, dsty, | ||||||
|  | 		      width, height, | ||||||
|  | 		      intel_region_map(intel, src), | ||||||
|  | 		      srcx, srcy, | ||||||
|  | 		      src->pitch);       | ||||||
|  |  | ||||||
|  |       intel_region_unmap(intel, dst); | ||||||
|  |       intel_region_unmap(intel, src);       | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    bmFreeBufferList(list); | ||||||
|  |    UNLOCK_HARDWARE(intel); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* 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 dstx, GLuint dsty, | ||||||
|  | 			GLuint width, GLuint height, | ||||||
|  | 			GLuint color ) | ||||||
|  | { | ||||||
|  |    unsigned dst_offset; | ||||||
|  |    struct bm_buffer_list *list = bmNewBufferList(); | ||||||
|  |  | ||||||
|  |    DBG("%s\n", __FUNCTION__); | ||||||
|  |  | ||||||
|  |    LOCK_HARDWARE(intel); | ||||||
|  |    bmAddBuffer(list, dst->buffer, BM_WRITE, NULL, &dst_offset); | ||||||
|  |  | ||||||
|  |    if (bmValidateBufferList(intel->bm, list, BM_NO_EVICT|BM_NO_UPLOAD|BM_MEM_AGP)) { | ||||||
|  |       intelEmitFillBlitLocked(intel, | ||||||
|  | 			      dst->cpp, | ||||||
|  | 			      dst->pitch, | ||||||
|  | 			      dst_offset,  | ||||||
|  | 			      dstx, dsty, | ||||||
|  | 			      width, height, | ||||||
|  | 			      color ); | ||||||
|  |  | ||||||
|  |       bmFenceBufferList(intel->bm, list); | ||||||
|  |    } | ||||||
|  |    else { | ||||||
|  |       _mesa_fill_rect(intel_region_map(intel, dst), | ||||||
|  | 		      dst->cpp, | ||||||
|  | 		      dst->pitch, | ||||||
|  | 		      dstx, dsty, | ||||||
|  | 		      width, height, | ||||||
|  | 		      color);       | ||||||
|  |  | ||||||
|  |       intel_region_unmap(intel, dst); | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    bmFreeBufferList(list); | ||||||
|  |    UNLOCK_HARDWARE(intel); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										108
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | |||||||
|  | /************************************************************************** | ||||||
|  |  *  | ||||||
|  |  * 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 ); | ||||||
|  | struct intel_region *intel_region_reference( struct intel_region *ib ); | ||||||
|  | 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 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 destx, GLuint desty, | ||||||
|  | 			struct intel_region *src, | ||||||
|  | 			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 destx, GLuint desty, | ||||||
|  | 			GLuint width, GLuint height, | ||||||
|  | 			GLuint color ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -199,6 +199,10 @@ static GLboolean intel_run_render( GLcontext *ctx, | |||||||
|    struct vertex_buffer *VB = &tnl->vb; |    struct vertex_buffer *VB = &tnl->vb; | ||||||
|    GLuint i; |    GLuint i; | ||||||
|  |  | ||||||
|  |    /* disabled | ||||||
|  |     */ | ||||||
|  |    return GL_TRUE; | ||||||
|  |  | ||||||
|    /* Don't handle clipping or indexed vertices. |    /* Don't handle clipping or indexed vertices. | ||||||
|     */ |     */ | ||||||
|    if (intel->RenderIndex != 0 ||  |    if (intel->RenderIndex != 0 ||  | ||||||
|   | |||||||
| @@ -166,7 +166,7 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | |||||||
| 			  | 			  | ||||||
|    intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; |    intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; | ||||||
|     |     | ||||||
|    if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); |    if (1) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); | ||||||
|  |  | ||||||
|    intelScreen->drmMinor = sPriv->drmMinor; |    intelScreen->drmMinor = sPriv->drmMinor; | ||||||
|  |  | ||||||
| @@ -202,13 +202,8 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | |||||||
|  |  | ||||||
|    if (glx_enable_extension != NULL) { |    if (glx_enable_extension != NULL) { | ||||||
|       (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" ); |       (*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; |    return GL_TRUE; | ||||||
| } | } | ||||||
| 		 | 		 | ||||||
| @@ -338,12 +333,16 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, | |||||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; |    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; | ||||||
|  |  | ||||||
|    switch (intelScreen->deviceID) { |    switch (intelScreen->deviceID) { | ||||||
|  | #if 0 | ||||||
|  |       /* Don't deal with i830 until texture work complete: | ||||||
|  |        */ | ||||||
|    case PCI_CHIP_845_G: |    case PCI_CHIP_845_G: | ||||||
|    case PCI_CHIP_I830_M: |    case PCI_CHIP_I830_M: | ||||||
|    case PCI_CHIP_I855_GM: |    case PCI_CHIP_I855_GM: | ||||||
|    case PCI_CHIP_I865_G: |    case PCI_CHIP_I865_G: | ||||||
|       return i830CreateContext( mesaVis, driContextPriv,  |       return i830CreateContext( mesaVis, driContextPriv,  | ||||||
| 				sharedContextPrivate ); | 				sharedContextPrivate ); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|    case PCI_CHIP_I915_G: |    case PCI_CHIP_I915_G: | ||||||
|    case PCI_CHIP_I915_GM: |    case PCI_CHIP_I915_GM: | ||||||
|   | |||||||
| @@ -32,6 +32,9 @@ | |||||||
| #include "dri_util.h" | #include "dri_util.h" | ||||||
| #include "xmlconfig.h" | #include "xmlconfig.h" | ||||||
|  |  | ||||||
|  | /* XXX: change name or eliminate to avoid conflict with "struct | ||||||
|  |  * intel_region"!!! | ||||||
|  |  */ | ||||||
| typedef struct { | typedef struct { | ||||||
|    drm_handle_t handle; |    drm_handle_t handle; | ||||||
|    drmSize size;        /* region size in bytes */ |    drmSize size;        /* region size in bytes */ | ||||||
|   | |||||||
| @@ -31,12 +31,14 @@ | |||||||
| #include "colormac.h" | #include "colormac.h" | ||||||
|  |  | ||||||
| #include "intel_screen.h" | #include "intel_screen.h" | ||||||
|  |  | ||||||
| #include "intel_span.h" | #include "intel_span.h" | ||||||
|  | #include "intel_regions.h" | ||||||
| #include "intel_ioctl.h" | #include "intel_ioctl.h" | ||||||
|  | #include "intel_tex.h" | ||||||
|  |  | ||||||
| #include "swrast/swrast.h" | #include "swrast/swrast.h" | ||||||
|  |  | ||||||
|  | #undef DBG | ||||||
| #define DBG 0 | #define DBG 0 | ||||||
|  |  | ||||||
| #define LOCAL_VARS						\ | #define LOCAL_VARS						\ | ||||||
| @@ -205,16 +207,47 @@ do {								\ | |||||||
| void intelSpanRenderStart( GLcontext *ctx ) | void intelSpanRenderStart( GLcontext *ctx ) | ||||||
| { | { | ||||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); |    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||||
|  |    GLuint i; | ||||||
|  |  | ||||||
|    intelFlush(&intel->ctx); |    intelFlush(&intel->ctx); | ||||||
|    LOCK_HARDWARE(intel); |    LOCK_HARDWARE(intel); | ||||||
|    intelWaitForIdle(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 ) | void intelSpanRenderFinish( GLcontext *ctx ) | ||||||
| { | { | ||||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); |    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||||
|  |    GLuint i; | ||||||
|  |  | ||||||
|    _swrast_flush( ctx ); |    _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 ); |    UNLOCK_HARDWARE( intel ); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -192,10 +192,17 @@ static void intelDrawBuffer(GLcontext *ctx, GLenum mode ) | |||||||
|     |     | ||||||
|    intelSetFrontClipRects( intel ); |    intelSetFrontClipRects( intel ); | ||||||
|  |  | ||||||
|  | /*    if (intel->draw_region) */ | ||||||
|  | /*       intel_region_release(intel, intel->draw_region); */ | ||||||
|  |  | ||||||
|    if (front) { |    if (front) { | ||||||
|       intel->drawOffset = screen->front.offset; |       intel->drawOffset = screen->front.offset; | ||||||
|  | /*       intel->draw_region = intel_region_reference(intel->front_region); */ | ||||||
|  |       intel->draw_region = intel->front_region; | ||||||
|    } else { |    } else { | ||||||
|       intel->drawOffset = screen->back.offset; |       intel->drawOffset = screen->back.offset; | ||||||
|  | /*       intel->draw_region = intel_region_reference(intel->back_region); */ | ||||||
|  |       intel->draw_region = intel->back_region; | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    intel->vtbl.set_draw_offset( intel, intel->drawOffset ); |    intel->vtbl.set_draw_offset( intel, intel->drawOffset ); | ||||||
|   | |||||||
| @@ -1,830 +1,101 @@ | |||||||
| /************************************************************************** |  | ||||||
|  *  |  | ||||||
|  * 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 "texobj.h" | ||||||
| #include "swrast/swrast.h" |  | ||||||
|  |  | ||||||
| #include "mm.h" |  | ||||||
|  |  | ||||||
| #include "intel_screen.h" |  | ||||||
| #include "intel_batchbuffer.h" |  | ||||||
| #include "intel_context.h" | #include "intel_context.h" | ||||||
|  | #include "intel_mipmap_tree.h" | ||||||
| #include "intel_tex.h" | #include "intel_tex.h" | ||||||
| #include "intel_ioctl.h" |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static GLboolean intelIsTextureResident(GLcontext *ctx, | ||||||
| static GLboolean |                                       struct gl_texture_object *texObj) | ||||||
| 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) |  | ||||||
|  |  | ||||||
| { | { | ||||||
|    GLcontext *ctx = &intel->ctx; | #if 0 | ||||||
|    int texelBytes; |    struct intel_context *intel = intel_context(ctx); | ||||||
|  |    struct intel_texture_object *intelObj = intel_texture_object(texObj); | ||||||
|     |     | ||||||
|    if (0) |    return  | ||||||
|       fprintf(stderr, "intformat %s format %s type %s\n", |       intelObj->mt &&  | ||||||
| 	      _mesa_lookup_enum_by_nr( internalFormat ), |       intelObj->mt->region &&  | ||||||
| 	      _mesa_lookup_enum_by_nr( format ), |       intel_is_region_resident(intel, intelObj->mt->region); | ||||||
| 	      _mesa_lookup_enum_by_nr( type )); | #endif | ||||||
|  |    return 1; | ||||||
|    if (!ctx->Unpack.ClientStorage) | } | ||||||
|       return 0; |  | ||||||
|  |  | ||||||
|    if (ctx->_ImageTransferState || |  | ||||||
|        texImage->IsCompressed || |  | ||||||
|        texObj->GenerateMipmap) |  | ||||||
|       return 0; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|    /* This list is incomplete |  | ||||||
|  | static struct gl_texture_image *intelNewTextureImage( GLcontext *ctx ) | ||||||
|  | { | ||||||
|  |    (void) ctx; | ||||||
|  |    return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx,  | ||||||
|  | 							GLuint name,  | ||||||
|  | 							GLenum target ) | ||||||
|  | { | ||||||
|  |    struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); | ||||||
|  |  | ||||||
|  |    _mesa_initialize_texture_object(&obj->base, name, target); | ||||||
|  |  | ||||||
|  |    return &obj->base; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | static void intelFreeTextureImageData( GLcontext *ctx,  | ||||||
|  | 				     struct gl_texture_image *texImage ) | ||||||
|  | { | ||||||
|  |    struct intel_context *intel = intel_context(ctx); | ||||||
|  |    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||||
|  |  | ||||||
|  |    if (intelImage->mt) { | ||||||
|  |       intel_miptree_release(intel, intelImage->mt); | ||||||
|  |       intelImage->mt = NULL; | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |    if (texImage->Data) { | ||||||
|  |       free(texImage->Data); | ||||||
|  |       texImage->Data = NULL; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void *do_memcpy( void *dest, const void *src, size_t n ) | ||||||
|  | { | ||||||
|  |    if ( (((unsigned)src) & 63) || | ||||||
|  | 	(((unsigned)dest) & 63)) | ||||||
|  |       return __memcpy(dest, src, n);	 | ||||||
|  |    else | ||||||
|  |       return memcpy(dest, src, n); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void intelInitTextureFuncs(struct dd_function_table * functions) | ||||||
|  | { | ||||||
|  |    functions->ChooseTextureFormat = intelChooseTextureFormat; | ||||||
|  |    functions->TexImage1D = intelTexImage1D; | ||||||
|  |    functions->TexImage2D = intelTexImage2D; | ||||||
|  |    functions->TexSubImage1D = intelTexSubImage1D; | ||||||
|  |    functions->TexSubImage2D = intelTexSubImage2D; | ||||||
|  |    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; | ||||||
|  |  | ||||||
|  |    /* 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. | ||||||
|     */ |     */ | ||||||
|    switch ( internalFormat ) { |    functions->TextureMemCpy = do_memcpy; | ||||||
|    case GL_RGBA: |  | ||||||
|       if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) { |  | ||||||
| 	 texImage->TexFormat = &_mesa_texformat_argb8888; |  | ||||||
| 	 texelBytes = 4; |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
| 	 return 0; |  | ||||||
|       break; |  | ||||||
|  |  | ||||||
|    case GL_RGB: |  | ||||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { |  | ||||||
| 	 texImage->TexFormat = &_mesa_texformat_rgb565; |  | ||||||
| 	 texelBytes = 2; |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
| 	 return 0; |  | ||||||
|       break; |  | ||||||
|  |  | ||||||
|    case GL_YCBCR_MESA: |  | ||||||
|       if ( format == GL_YCBCR_MESA &&  |  | ||||||
| 	   type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) { |  | ||||||
| 	 texImage->TexFormat = &_mesa_texformat_ycbcr_rev; |  | ||||||
| 	 texelBytes = 2; |  | ||||||
|       } |  | ||||||
|       else if ( format == GL_YCBCR_MESA &&  |  | ||||||
| 		(type == GL_UNSIGNED_SHORT_8_8_APPLE ||  |  | ||||||
| 		 type == GL_UNSIGNED_BYTE)) { |  | ||||||
| 	 texImage->TexFormat = &_mesa_texformat_ycbcr; |  | ||||||
| 	 texelBytes = 2; |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
| 	 return 0; |  | ||||||
|       break; |  | ||||||
|        |  | ||||||
| 	  |  | ||||||
|    default: |  | ||||||
|       return 0; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    /* Could deal with these packing issues, but currently don't: |  | ||||||
|     */ |  | ||||||
|    if (packing->SkipPixels ||  |  | ||||||
|        packing->SkipRows ||  |  | ||||||
|        packing->SwapBytes || |  | ||||||
|        packing->LsbFirst) { |  | ||||||
|       return 0; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    {       |  | ||||||
|       GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, |  | ||||||
| 						  format, type); |  | ||||||
|  |  | ||||||
|        |  | ||||||
|       if (0) |  | ||||||
| 	 fprintf(stderr, "%s: srcRowStride %d/%x\n",  |  | ||||||
| 		 __FUNCTION__, srcRowStride, srcRowStride); |  | ||||||
|  |  | ||||||
|       /* Could check this later in upload, pitch restrictions could be |  | ||||||
|        * relaxed, but would need to store the image pitch somewhere, |  | ||||||
|        * as packing details might change before image is uploaded: |  | ||||||
|        */ |  | ||||||
|       if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) || |  | ||||||
| 	  (srcRowStride & 63)) |  | ||||||
| 	 return 0; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|       /* Have validated that _mesa_transfer_teximage would be a straight |  | ||||||
|        * memcpy at this point.  NOTE: future calls to TexSubImage will |  | ||||||
|        * overwrite the client data.  This is explicitly mentioned in the |  | ||||||
|        * extension spec. |  | ||||||
|        */ |  | ||||||
|       texImage->Data = (void *)pixels; |  | ||||||
|       texImage->IsClientData = GL_TRUE; |  | ||||||
|       texImage->RowStride = srcRowStride / texelBytes; |  | ||||||
|       return 1; |  | ||||||
|    } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|   |  | ||||||
|  |  | ||||||
| static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level, |  | ||||||
| 			    GLint internalFormat, |  | ||||||
| 			    GLint width, GLint border, |  | ||||||
| 			    GLenum format, GLenum type, const GLvoid *pixels, |  | ||||||
| 			    const struct gl_pixelstore_attrib *packing, |  | ||||||
| 			    struct gl_texture_object *texObj, |  | ||||||
| 			    struct gl_texture_image *texImage ) |  | ||||||
| { |  | ||||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; |  | ||||||
|  |  | ||||||
|    assert(t); |  | ||||||
|    intelFlush( ctx ); |  | ||||||
|    driSwapOutTextureObject( t ); |  | ||||||
|  |  | ||||||
|    texImage->IsClientData = GL_FALSE; |  | ||||||
|  |  | ||||||
|    _mesa_store_teximage1d( ctx, target, level, internalFormat, |  | ||||||
| 			   width, border, format, type, |  | ||||||
| 			   pixels, packing, texObj, texImage ); |  | ||||||
|  |  | ||||||
|    t->dirty_images[0] |= (1 << level); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void intelTexSubImage1D( GLcontext *ctx,  |  | ||||||
| 			       GLenum target, |  | ||||||
| 			       GLint level,	 |  | ||||||
| 			       GLint xoffset, |  | ||||||
| 				GLsizei width, |  | ||||||
| 			       GLenum format, GLenum type, |  | ||||||
| 			       const GLvoid *pixels, |  | ||||||
| 			       const struct gl_pixelstore_attrib *packing, |  | ||||||
| 			       struct gl_texture_object *texObj, |  | ||||||
| 			       struct gl_texture_image *texImage ) |  | ||||||
| { |  | ||||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; |  | ||||||
|  |  | ||||||
|    assert(t); |  | ||||||
|    intelFlush( ctx ); |  | ||||||
|    driSwapOutTextureObject( t ); |  | ||||||
|  |  | ||||||
|    _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,  |  | ||||||
| 			     format, type, pixels, packing, texObj, |  | ||||||
| 			     texImage); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Handles 2D, CUBE, RECT: |  | ||||||
|  */ |  | ||||||
| static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level, |  | ||||||
| 			    GLint internalFormat, |  | ||||||
| 			    GLint width, GLint height, GLint border, |  | ||||||
| 			    GLenum format, GLenum type, const GLvoid *pixels, |  | ||||||
| 			    const struct gl_pixelstore_attrib *packing, |  | ||||||
| 			    struct gl_texture_object *texObj, |  | ||||||
| 			    struct gl_texture_image *texImage ) |  | ||||||
| { |  | ||||||
|    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 (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); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, |  | ||||||
|                                  GLint xoffset, GLint yoffset, |  | ||||||
|                                  GLsizei width, GLsizei height, |  | ||||||
|                                  GLenum format, |  | ||||||
|                                  GLsizei imageSize, const GLvoid *data, |  | ||||||
|                                  struct gl_texture_object *texObj, |  | ||||||
|                                  struct gl_texture_image *texImage ) |  | ||||||
| { |  | ||||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; |  | ||||||
|    GLuint face; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|    /* which cube face or ordinary 2D image */ |  | ||||||
|    switch (target) { |  | ||||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: |  | ||||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: |  | ||||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: |  | ||||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: |  | ||||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: |  | ||||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: |  | ||||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; |  | ||||||
|       ASSERT(face < 6); |  | ||||||
|       break; |  | ||||||
|    default: |  | ||||||
|       face = 0; |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    assert( t ); /* this _should_ be true */ |  | ||||||
|    intelFlush( ctx ); |  | ||||||
|    driSwapOutTextureObject( t ); |  | ||||||
|     |  | ||||||
|    _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width, |  | ||||||
| 					height, format, imageSize, data, texObj, texImage); |  | ||||||
|     |  | ||||||
|    t->dirty_images[face] |= (1 << level); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level, |  | ||||||
|                             GLint internalFormat, |  | ||||||
|                             GLint width, GLint height, GLint depth, |  | ||||||
|                             GLint border, |  | ||||||
|                             GLenum format, GLenum type, const GLvoid *pixels, |  | ||||||
|                             const struct gl_pixelstore_attrib *packing, |  | ||||||
|                             struct gl_texture_object *texObj, |  | ||||||
|                             struct gl_texture_image *texImage ) |  | ||||||
| { |  | ||||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; |  | ||||||
|  |  | ||||||
|    assert(t); |  | ||||||
|    driSwapOutTextureObject( t ); |  | ||||||
|    texImage->IsClientData = GL_FALSE; |  | ||||||
|  |  | ||||||
|    _mesa_store_teximage3d(ctx, target, level, internalFormat, |  | ||||||
| 			  width, height, depth, border, |  | ||||||
| 			  format, type, pixels, |  | ||||||
| 			  &ctx->Unpack, texObj, texImage); |  | ||||||
|     |  | ||||||
|    t->dirty_images[0] |= (1 << level); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 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; |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -35,8 +35,88 @@ | |||||||
|  |  | ||||||
| void intelInitTextureFuncs( struct dd_function_table *functions ); | void intelInitTextureFuncs( struct dd_function_table *functions ); | ||||||
|  |  | ||||||
| void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t ); | const struct gl_texture_format * | ||||||
| int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t, | intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, | ||||||
| 			  GLuint face ); |                           GLenum format, GLenum type ); | ||||||
|  |  | ||||||
|  | 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_validate_mipmap_tree( struct intel_context *intel, | ||||||
|  | 				   struct intel_texture_object *intelObj ); | ||||||
|  |  | ||||||
|  | void intel_add_texoffset_fixup( struct intel_context *intel, | ||||||
|  | 				GLuint unit, | ||||||
|  | 				GLuint *ptr ); | ||||||
|  |  | ||||||
|  | void intel_apply_fixups( struct intel_context *intel ); | ||||||
|  |  | ||||||
|  | GLboolean intel_prevalidate_buffers( struct intel_context *intel ); | ||||||
|  | GLboolean intel_validate_buffers( struct intel_context *intel ); | ||||||
|  | void intel_fence_buffers( struct intel_context *intel ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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 | #endif | ||||||
|   | |||||||
							
								
								
									
										301
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,301 @@ | |||||||
|  | /************************************************************************** | ||||||
|  |  *  | ||||||
|  |  * 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 "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; | ||||||
|  |   | ||||||
|  |  | ||||||
|  |    LOCK_HARDWARE(intel); | ||||||
|  |    intelInstallBatchBuffer(intel); | ||||||
|  |    { | ||||||
|  |       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||||
|  |       GLuint image_offset = intel_miptree_image_offset(intelImage->mt,  | ||||||
|  | 						       intelImage->face, | ||||||
|  | 						       intelImage->level); | ||||||
|  |       GLuint dst_offset = 0; | ||||||
|  |       GLuint src_offset = 0; | ||||||
|  |       GLint orig_x = x; | ||||||
|  |       GLint orig_y = 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; | ||||||
|  |  | ||||||
|  |       y = dPriv->h - y - height; 	/* convert from gl to hardware coords */ | ||||||
|  |       x += dPriv->x; | ||||||
|  |       y += dPriv->y; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |       bmAddBuffer(intel->buffer_list,  | ||||||
|  | 		  intelImage->mt->region->buffer,  | ||||||
|  | 		  BM_WRITE, NULL, &dst_offset); | ||||||
|  |  | ||||||
|  |       bmAddBuffer(intel->buffer_list,  | ||||||
|  | 		  src->buffer,  | ||||||
|  | 		  BM_READ, NULL, &src_offset); | ||||||
|  |  | ||||||
|  |       if (!bmValidateBufferList(intel->bm, intel->buffer_list, BM_MEM_AGP)) { | ||||||
|  | 	 ret = GL_FALSE; | ||||||
|  | 	 goto out; | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       intelEmitCopyBlitLocked( intel, | ||||||
|  | 			       intelImage->mt->cpp, | ||||||
|  | 			       src->pitch, src_offset, | ||||||
|  | 			       intelImage->mt->pitch,  | ||||||
|  | 			       dst_offset + image_offset, | ||||||
|  | 			       x, y,  | ||||||
|  | 			       dstx, dsty, | ||||||
|  | 			       width, height ); | ||||||
|  |    out: | ||||||
|  |       intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_FALSE); | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |  | ||||||
|  |    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 ) | ||||||
|  | { | ||||||
|  |    intelContextPtr 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 */ | ||||||
|  | } | ||||||
							
								
								
									
										355
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										355
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,355 @@ | |||||||
|  |  | ||||||
|  | #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); | ||||||
|  |    } | ||||||
|  | 	  | ||||||
|  |  | ||||||
|  |    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 border, | ||||||
|  | 			  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_object *intelObj = intel_texture_object(texObj); | ||||||
|  |    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||||
|  |    GLint postConvWidth = width; | ||||||
|  |    GLint postConvHeight = height; | ||||||
|  |    GLint texelBytes, sizeInBytes; | ||||||
|  |    GLuint dstRowStride; | ||||||
|  |  | ||||||
|  |    DBG("%s target %s level %d %dx%d border %d\n", __FUNCTION__, | ||||||
|  | 		_mesa_lookup_enum_by_nr(target), | ||||||
|  | 		level, | ||||||
|  | 		width, height, border); | ||||||
|  |  | ||||||
|  |    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); | ||||||
|  |  | ||||||
|  |    if (dims == 1) { | ||||||
|  |       texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; | ||||||
|  |       texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; | ||||||
|  |    } | ||||||
|  |    else { | ||||||
|  |       texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; | ||||||
|  |       texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; | ||||||
|  |    } | ||||||
|  |    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); | ||||||
|  |       intelImage->mt = NULL; | ||||||
|  |       assert(!texImage->Data); | ||||||
|  |    } | ||||||
|  |    else if (texImage->Data) { | ||||||
|  |       free(texImage->Data); | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    /* XXX: 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. | ||||||
|  |     * | ||||||
|  |     * XXX: Better to do this internally to intel_mipmap_tree.c, | ||||||
|  |     * somehow? | ||||||
|  |     */ | ||||||
|  |    if (intelObj->mt &&  | ||||||
|  |        intelObj->mt->first_level == level && | ||||||
|  |        intelObj->mt->last_level == level && | ||||||
|  |        intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB) { | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    if (!intelObj->mt) { | ||||||
|  |       guess_and_alloc_mipmap_tree(intel, intelObj, intelImage); | ||||||
|  |    } | ||||||
|  |     | ||||||
|  |  | ||||||
|  |    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); | ||||||
|  |  | ||||||
|  |       intelImage->mt = intel_miptree_reference(intelObj->mt); | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    /* 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, packing, "glTexImage"); | ||||||
|  |    if (!pixels)  | ||||||
|  |       return; | ||||||
|  |     | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    LOCK_HARDWARE(intel); | ||||||
|  |     | ||||||
|  |    if (intelImage->mt) { | ||||||
|  |       texImage->Data = intel_miptree_image_map(intel,  | ||||||
|  | 					       intelImage->mt,  | ||||||
|  | 					       intelImage->face,  | ||||||
|  | 					       intelImage->level,  | ||||||
|  | 					       &dstRowStride);	  | ||||||
|  |    } | ||||||
|  |    else { | ||||||
|  |       /* Allocate regular memory and store the image there temporarily.   */ | ||||||
|  |       if (texImage->IsCompressed) { | ||||||
|  | 	 sizeInBytes = texImage->CompressedSize; | ||||||
|  |          dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width); | ||||||
|  |       } | ||||||
|  |       else { | ||||||
|  | 	 sizeInBytes = postConvWidth * postConvHeight * texelBytes; | ||||||
|  |          dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       texImage->Data = malloc(sizeInBytes); | ||||||
|  |    } | ||||||
|  |       | ||||||
|  |    /* 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, 0 /* dstImageStride */, | ||||||
|  | 					width, height, 1, | ||||||
|  | 					format, type, pixels, packing)) { | ||||||
|  |       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    _mesa_unmap_teximage_pbo(ctx, packing); | ||||||
|  |  | ||||||
|  |    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 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) | ||||||
|  | { | ||||||
|  |    intelTexImage( ctx, 2, target, level,  | ||||||
|  | 		internalFormat, width, height, border, | ||||||
|  | 		format, type, pixels, | ||||||
|  | 		packing, 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 *packing, | ||||||
|  | 		     struct gl_texture_object *texObj, | ||||||
|  | 		     struct gl_texture_image *texImage) | ||||||
|  | { | ||||||
|  |    intelTexImage( ctx, 1, target, level,  | ||||||
|  | 		  internalFormat, width, 1, border, | ||||||
|  | 		  format, type, pixels, | ||||||
|  | 		  packing, texObj, texImage ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										148
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | |||||||
|  |  | ||||||
|  | /************************************************************************** | ||||||
|  |  *  | ||||||
|  |  * 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 width, GLint height, | ||||||
|  | 			      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 = 0; | ||||||
|  |    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); | ||||||
|  |  | ||||||
|  |    pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, 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 ); | ||||||
|  |        | ||||||
|  |  | ||||||
|  |    if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, | ||||||
|  | 					texImage->TexFormat, | ||||||
|  | 					texImage->Data, | ||||||
|  | 					xoffset, yoffset, 0, | ||||||
|  | 					dstRowStride, dstImageStride, | ||||||
|  | 					width, height, 1, | ||||||
|  | 					format, type, pixels, packing)) { | ||||||
|  |       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); | ||||||
|  |    } | ||||||
|  |  | ||||||
|  | #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 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, width, | ||||||
|  | 		    height, 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, width, | ||||||
|  | 		    1, format, type, pixels, packing, texObj, | ||||||
|  | 		    texImage); | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										349
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,349 @@ | |||||||
|  | #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_mipmap_tree *mt, | ||||||
|  | 				     struct intel_texture_image *intelImage ) | ||||||
|  | { | ||||||
|  |    if (intelImage->mt) { | ||||||
|  |       /* Copy potentially with the blitter: | ||||||
|  |        */ | ||||||
|  |       intel_miptree_image_copy(intel, | ||||||
|  | 			       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, | ||||||
|  | 			       mt, | ||||||
|  | 			       intelImage->face, | ||||||
|  | 			       intelImage->level, | ||||||
|  | 			       intelImage->base.Data, | ||||||
|  | 			       intelImage->base.RowStride); | ||||||
|  |  | ||||||
|  |       free(intelImage->base.Data); | ||||||
|  |       intelImage->base.Data = NULL; | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    intelImage->mt = intel_miptree_reference(mt); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /*   | ||||||
|  |  */ | ||||||
|  | static 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); | ||||||
|  | 	 intelObj->mt = NULL; | ||||||
|  |       } | ||||||
|  |       return 0; | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |    /* If both firstImage and intelObj have a tree which can contain | ||||||
|  |     * all active images, favour firstImage. | ||||||
|  |     */ | ||||||
|  |    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); | ||||||
|  |  | ||||||
|  |       intelObj->mt = intel_miptree_reference(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); | ||||||
|  |       intelObj->mt = NULL; | ||||||
|  |    } | ||||||
|  |        | ||||||
|  |  | ||||||
|  |    /* 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->mt, | ||||||
|  | 				    intelImage); | ||||||
|  | 	 } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    return GL_TRUE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void intel_add_texoffset_fixup( struct intel_context *intel, | ||||||
|  | 				GLuint unit, | ||||||
|  | 				GLuint *ptr ) | ||||||
|  | { | ||||||
|  |    struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; | ||||||
|  |    struct intel_texture_object *intelObj = intel_texture_object(tObj); | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  |    struct intel_reloc *f = &intel->fixup[intel->nr_fixups++]; | ||||||
|  |    assert(intel->nr_fixups <= INTEL_MAX_FIXUP); | ||||||
|  |    f->dest = ptr; | ||||||
|  |    f->value = &intelObj->textureOffset; | ||||||
|  |    f->delta = (intel->intelScreen->tex.offset +  | ||||||
|  | 	       intel_miptree_image_offset(intelObj->mt, 0, intelObj->firstLevel)); | ||||||
|  | #else | ||||||
|  |    *ptr = (intelObj->textureOffset + 	    | ||||||
|  | 	   intel_miptree_image_offset(intelObj->mt, 0, intelObj->firstLevel)); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Fix up the command buffer: | ||||||
|  |  */ | ||||||
|  | void intel_apply_fixups( struct intel_context *intel ) | ||||||
|  | { | ||||||
|  |    GLuint i; | ||||||
|  |  | ||||||
|  |    for (i = 0; i < intel->nr_fixups; i++) { | ||||||
|  |       struct intel_reloc *f = &intel->fixup[i]; | ||||||
|  |       *f->dest = *f->value + f->delta; | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    intel->nr_fixups = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* One upshot of the new manager is that it should be possible to tell | ||||||
|  |  * ahead of time whether a certain set of buffers will cause a | ||||||
|  |  * fallback.   | ||||||
|  |  * | ||||||
|  |  * Unless we do this we either have to a) hold the DRI lock | ||||||
|  |  * while emitting all vertices and fire after each vertex buffer, or | ||||||
|  |  * b) build a fallback path that operates on i915 command streams | ||||||
|  |  * rather than the state in the GLcontext. | ||||||
|  |  */ | ||||||
|  | GLboolean intel_prevalidate_buffers( struct intel_context *intel ) | ||||||
|  | { | ||||||
|  |    return GL_TRUE;		/* never fallback */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | GLboolean intel_validate_buffers( struct intel_context *intel ) | ||||||
|  | { | ||||||
|  |    GLcontext *ctx = &intel->ctx; | ||||||
|  |    GLboolean ok = GL_TRUE; | ||||||
|  |    GLuint i; | ||||||
|  |  | ||||||
|  |    DBG("%s\n", __FUNCTION__); | ||||||
|  |  | ||||||
|  |    assert(intel->locked); | ||||||
|  |  | ||||||
|  |    /* Add the color and depth buffers so that fences associated with | ||||||
|  |     * these buffers: | ||||||
|  |     */ | ||||||
|  |    bmAddBuffer(intel->buffer_list, | ||||||
|  | 	       intel->draw_region->buffer, | ||||||
|  | 	       BM_WRITE, | ||||||
|  | 	       NULL, | ||||||
|  | 	       NULL); | ||||||
|  |     | ||||||
|  |    bmAddBuffer(intel->buffer_list, | ||||||
|  | 	       intel->depth_region->buffer, | ||||||
|  | 	       BM_WRITE, | ||||||
|  | 	       NULL, | ||||||
|  | 	       NULL); | ||||||
|  |  | ||||||
|  |    /* Add each enabled texture: | ||||||
|  |     */ | ||||||
|  |    for (i = 0 ; i < ctx->Const.MaxTextureUnits && ok ; i++) { | ||||||
|  |       if (ctx->Texture.Unit[i]._ReallyEnabled) { | ||||||
|  | 	 struct gl_texture_object *tObj = intel->ctx.Texture.Unit[i]._Current; | ||||||
|  | 	 struct intel_texture_object *intelObj = intel_texture_object(tObj); | ||||||
|  |  | ||||||
|  | 	 ok = intel_finalize_mipmap_tree( intel, i ); | ||||||
|  | 	 if (ok) { | ||||||
|  | 	    bmAddBuffer(intel->buffer_list, | ||||||
|  | 			intelObj->mt->region->buffer, | ||||||
|  | 			BM_READ, | ||||||
|  | 			NULL, | ||||||
|  | 			&intelObj->textureOffset); | ||||||
|  | 	 } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    ok = bmValidateBufferList(intel->bm, intel->buffer_list, BM_MEM_AGP); | ||||||
|  |    assert(ok); | ||||||
|  |    return ok; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void intel_fence_buffers( struct intel_context *intel ) | ||||||
|  | { | ||||||
|  |    assert(intel->locked); | ||||||
|  |    assert(intel->buffer_list); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void intel_tex_map_images( struct intel_context *intel, | ||||||
|  | 			   struct intel_texture_object *intelObj ) | ||||||
|  | { | ||||||
|  |    GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||||
|  |    GLuint face, i; | ||||||
|  |     | ||||||
|  |    DBG("%s\n", __FUNCTION__); | ||||||
|  |  | ||||||
|  |    for (face = 0; face < nr_faces; face++) { | ||||||
|  |       for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) { | ||||||
|  | 	 struct intel_texture_image *intelImage =  | ||||||
|  | 	    intel_texture_image(intelObj->base.Image[face][i]); | ||||||
|  |  | ||||||
|  | 	 if (intelImage->mt) { | ||||||
|  | 	    intelImage->base.Data =  | ||||||
|  | 	       intel_miptree_image_map(intel,  | ||||||
|  | 				       intelImage->mt, | ||||||
|  | 				       intelImage->face, | ||||||
|  | 				       intelImage->level, | ||||||
|  | 				       &intelImage->base.RowStride); | ||||||
|  | 	 } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 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; | ||||||
|  | 	 } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
| @@ -42,10 +42,106 @@ | |||||||
| #include "intel_batchbuffer.h" | #include "intel_batchbuffer.h" | ||||||
| #include "intel_reg.h" | #include "intel_reg.h" | ||||||
| #include "intel_span.h" | #include "intel_span.h" | ||||||
|  | #include "intel_tex.h" | ||||||
|  |  | ||||||
| static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ); | static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ); | ||||||
| static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ); | 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( GLcontext *ctx ) | ||||||
|  | { | ||||||
|  |    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||||
|  |    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; | ||||||
|  |    intel->batch.space += used; | ||||||
|  |    assert(intel->batch.space >= 0); | ||||||
|  |  | ||||||
|  |  finished: | ||||||
|  |    intel->prim.primitive = ~0; | ||||||
|  |    intel->prim.start_ptr = 0; | ||||||
|  |    intel->prim.flush = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* Emit a primitive referencing vertices in a vertex buffer. | ||||||
|  |  */ | ||||||
|  | void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ) | ||||||
|  | { | ||||||
|  |    BATCH_LOCALS; | ||||||
|  |     | ||||||
|  |    /* Emit a slot which will be filled with the inline primitive | ||||||
|  |     * command later. | ||||||
|  |     */ | ||||||
|  |    BEGIN_BATCH(2); | ||||||
|  |    OUT_BATCH( 0 ); | ||||||
|  |  | ||||||
|  |    intel->prim.start_ptr = batch_ptr; | ||||||
|  |    intel->prim.primitive = prim; | ||||||
|  |    intel->prim.flush = intel_flush_inline_primitive; | ||||||
|  |  | ||||||
|  |    OUT_BATCH( 0 ); | ||||||
|  |    ADVANCE_BATCH(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | void intelWrapInlinePrimitive( intelContextPtr intel ) | ||||||
|  | { | ||||||
|  |    GLuint prim = intel->prim.primitive; | ||||||
|  |  | ||||||
|  |    intel_flush_inline_primitive( &intel->ctx ); | ||||||
|  |    intelFlushBatch(intel, GL_TRUE); | ||||||
|  |    intelInstallBatchBuffer( intel );     | ||||||
|  |    intel_validate_buffers( intel ); | ||||||
|  |    intel->vtbl.emit_state( intel ); | ||||||
|  |    intelStartInlinePrimitive( intel, prim ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | GLuint *intelExtendInlinePrimitive( intelContextPtr intel,  | ||||||
|  | 				    GLuint dwords ) | ||||||
|  | { | ||||||
|  |    GLuint sz = dwords * sizeof(GLuint); | ||||||
|  |    GLuint *ptr; | ||||||
|  |  | ||||||
|  |    if (intel->batch.space < sz) { | ||||||
|  |       intelWrapInlinePrimitive( intel ); | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    ptr = (GLuint *)intel->batch.ptr; | ||||||
|  |    intel->batch.ptr += sz; | ||||||
|  |    intel->batch.space -= sz; | ||||||
|  |  | ||||||
|  |    return ptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /*********************************************************************** | /*********************************************************************** | ||||||
|  *                    Emit primitives as inline vertices               * |  *                    Emit primitives as inline vertices               * | ||||||
|  ***********************************************************************/ |  ***********************************************************************/ | ||||||
| @@ -520,22 +616,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 ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /**********************************************************************/ | /**********************************************************************/ | ||||||
| @@ -630,12 +710,8 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define POINT_FALLBACK (0) | #define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN) | ||||||
| #define LINE_FALLBACK (DD_LINE_STIPPLE) | #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED) | ||||||
| #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) |  | ||||||
|  |  | ||||||
| void intelChooseRenderState(GLcontext *ctx) | void intelChooseRenderState(GLcontext *ctx) | ||||||
| { | { | ||||||
| @@ -672,19 +748,14 @@ void intelChooseRenderState(GLcontext *ctx) | |||||||
| 	 intel->draw_tri = intel_draw_triangle; | 	 intel->draw_tri = intel_draw_triangle; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|       /* Hook in fallbacks for specific primitives. |       /* Hook in fallbacks for specific primitives. | ||||||
|        */ |        */ | ||||||
|       if (flags & ANY_FALLBACK_FLAGS) |       if (flags & ANY_FALLBACK_FLAGS) | ||||||
|       { |       { | ||||||
| 	 if (flags & POINT_FALLBACK) | 	 if (flags & DD_LINE_STIPPLE) | ||||||
| 	    intel->draw_point = intel_fallback_point; |  | ||||||
|  |  | ||||||
| 	 if (flags & LINE_FALLBACK) |  | ||||||
| 	    intel->draw_line = intel_fallback_line; | 	    intel->draw_line = intel_fallback_line; | ||||||
|  |  | ||||||
| 	 if (flags & TRI_FALLBACK) |  | ||||||
| 	    intel->draw_tri = intel_fallback_tri; |  | ||||||
|  |  | ||||||
| 	 if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)  | 	 if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)  | ||||||
| 	    intel->draw_tri = intel_fallback_tri; | 	    intel->draw_tri = intel_fallback_tri; | ||||||
|  |  | ||||||
| @@ -693,6 +764,8 @@ void intelChooseRenderState(GLcontext *ctx) | |||||||
|  |  | ||||||
| 	 index |= INTEL_FALLBACK_BIT; | 	 index |= INTEL_FALLBACK_BIT; | ||||||
|       } |       } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|    } |    } | ||||||
|  |  | ||||||
|    if (intel->RenderIndex != index) { |    if (intel->RenderIndex != index) { | ||||||
| @@ -760,13 +833,28 @@ static void intelRunPipeline( GLcontext *ctx ) | |||||||
|  |  | ||||||
| static void intelRenderStart( GLcontext *ctx ) | static void intelRenderStart( GLcontext *ctx ) | ||||||
| { | { | ||||||
|    INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) ); |    struct intel_context *intel = intel_context(ctx); | ||||||
|  |  | ||||||
|  |    intel->vtbl.render_start( INTEL_CONTEXT(ctx) ); | ||||||
|  |  | ||||||
|  |    LOCK_HARDWARE(intel); | ||||||
|  |    intelInstallBatchBuffer( intel );     | ||||||
|  |    intel_validate_buffers( intel ); | ||||||
|  |    intel->vtbl.emit_state( intel ); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void intelRenderFinish( GLcontext *ctx ) | 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 ); |       _swrast_flush( ctx ); | ||||||
|  |  | ||||||
|  |    if (intel->prim.flush) | ||||||
|  |       intel->prim.flush(ctx); | ||||||
|  |  | ||||||
|  |    intelFlushBatch(intel, GL_TRUE);  | ||||||
|  |    UNLOCK_HARDWARE(intel); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ | |||||||
| #include "colormac.h" | #include "colormac.h" | ||||||
| #include "mtypes.h" | #include "mtypes.h" | ||||||
| #include "program.h" | #include "program.h" | ||||||
|  | #include "teximage.h" | ||||||
| #include "swrast.h" | #include "swrast.h" | ||||||
| #include "s_blend.h" | #include "s_blend.h" | ||||||
| #include "s_context.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 | static void | ||||||
| _swrast_sleep( GLcontext *ctx, GLbitfield new_state ) | _swrast_sleep( GLcontext *ctx, GLbitfield new_state ) | ||||||
| { | { | ||||||
| @@ -452,6 +530,9 @@ _swrast_validate_derived( GLcontext *ctx ) | |||||||
|       if (swrast->NewState & _NEW_TEXTURE) |       if (swrast->NewState & _NEW_TEXTURE) | ||||||
|          _swrast_update_texture_samplers( ctx ); |          _swrast_update_texture_samplers( ctx ); | ||||||
|  |  | ||||||
|  |       if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) | ||||||
|  |          _swrast_validate_texture_images( ctx ); | ||||||
|  |  | ||||||
|       swrast->NewState = 0; |       swrast->NewState = 0; | ||||||
|       swrast->StateChanges = 0; |       swrast->StateChanges = 0; | ||||||
|       swrast->InvalidateState = _swrast_invalidate_state; |       swrast->InvalidateState = _swrast_invalidate_state; | ||||||
|   | |||||||
| @@ -226,6 +226,11 @@ typedef void (*swrast_tri_func)( GLcontext *ctx, const SWvertex *, | |||||||
|                                  const SWvertex *, 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 | /** \defgroup Bitmasks | ||||||
|  * Bitmasks to indicate which rasterization options are enabled |  * Bitmasks to indicate which rasterization options are enabled | ||||||
|  * (RasterMask) |  * (RasterMask) | ||||||
| @@ -354,6 +359,8 @@ typedef struct | |||||||
|     */ |     */ | ||||||
|    GLchan *TexelBuffer; |    GLchan *TexelBuffer; | ||||||
|  |  | ||||||
|  |    validate_texture_image_func ValidateTextureImage; | ||||||
|  |  | ||||||
| } SWcontext; | } SWcontext; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -244,6 +244,10 @@ _swrast_copy_texsubimage3d(GLcontext *ctx, | |||||||
|                            GLint x, GLint y, GLsizei width, GLsizei height); |                            GLint x, GLint y, GLsizei width, GLsizei height); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | extern void | ||||||
|  | _swrast_eject_texture_images(GLcontext *ctx); | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * The driver interface for the software rasterizer. |  * The driver interface for the software rasterizer. | ||||||
|  * XXX this may go away. |  * XXX this may go away. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user