Compare commits
	
		
			70 Commits
		
	
	
		
			mesa-17.3.
			...
			texmem_0_3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 814cae6a45 | ||
|  | 410673f64c | ||
|  | a83a3cfa1c | ||
|  | da89238b13 | ||
|  | 984387b89c | ||
|  | 93bc5e8402 | ||
|  | 43722cae42 | ||
|  | f397a2a1e5 | ||
|  | 87a0312068 | ||
|  | ee525436cc | ||
|  | 520ba25dc3 | ||
|  | 6f9dc91045 | ||
|  | d17637d47f | ||
|  | 980a25cd92 | ||
|  | 607c474f2d | ||
|  | 2f54146c1f | ||
|  | 72aeeef7c3 | ||
|  | dadc8e2a50 | ||
|  | 02d401b475 | ||
|  | 9d695abcac | ||
|  | e070007d16 | ||
|  | 39c4c8d54b | ||
|  | 4fa3cf225f | ||
|  | 1c2c1c4560 | ||
|  | e3904516bb | ||
|  | ceb222798b | ||
|  | 6abcf6a3d3 | ||
|  | db0ed8942f | ||
|  | bd9f38ccaa | ||
|  | b15421c22b | ||
|  | 5db0e131ef | ||
|  | b249ff8a86 | ||
|  | 9d6e0f5d64 | ||
|  | 4f8549634e | ||
|  | 3345ab8ccf | ||
|  | cd3c9febda | ||
|  | 8c58a32360 | ||
|  | 0d646ea3a8 | ||
|  | 6a33e6d221 | ||
|  | fc4bc6fc97 | ||
|  | 4239cfd534 | ||
|  | b0902a4158 | ||
|  | 269219dc05 | ||
|  | 5dbadd418c | ||
|  | 71bce51324 | ||
|  | 308d377ca8 | ||
|  | 4f39d22c29 | ||
|  | 8dab7963b7 | ||
|  | ec30116c9f | ||
|  | 5ac3ad7722 | ||
|  | fe239744aa | ||
|  | 137dcd4a46 | ||
|  | 0d7755fc73 | ||
|  | c863e63549 | ||
|  | 62920e2ab2 | ||
|  | ce3885fc5f | ||
|  | bf0c1ca618 | ||
|  | 64bc9caa1c | ||
|  | 89a2ea6fd3 | ||
|  | 41123a85ec | ||
|  | f10469abe8 | ||
|  | 4a74de797c | ||
|  | c745394242 | ||
|  | f9f3de8c31 | ||
|  | 3d0a073a71 | ||
|  | 219ee91fa8 | ||
|  | 632eae3fec | ||
|  | f378bcd8bf | ||
|  | ded29089f3 | ||
|  | 527c05eb2a | 
| @@ -47,6 +47,7 @@ PROGS = \ | ||||
| 	renormal \ | ||||
| 	shadowtex \ | ||||
| 	singlebuffer \ | ||||
| 	streaming_rect \ | ||||
| 	spectex \ | ||||
| 	spriteblast \ | ||||
| 	stex3d \ | ||||
|   | ||||
							
								
								
									
										407
									
								
								progs/demos/streaming_rect.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										407
									
								
								progs/demos/streaming_rect.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,407 @@ | ||||
|  | ||||
| /* | ||||
|  * GL_ARB_multitexture demo | ||||
|  * | ||||
|  * Command line options: | ||||
|  *    -info      print GL implementation information | ||||
|  * | ||||
|  * | ||||
|  * Brian Paul  November 1998  This program is in the public domain. | ||||
|  * Modified on 12 Feb 2002 for > 2 texture units. | ||||
|  */ | ||||
|  | ||||
| #define GL_GLEXT_PROTOTYPES | ||||
|  | ||||
| #include <math.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| #include "readtex.h" | ||||
|  | ||||
| enum { | ||||
|    WHOLERECT, | ||||
|    RENDER, | ||||
|    SWAPBUF, | ||||
|  | ||||
|    UPLOAD_CONVENTIONAL, | ||||
|    UPLOAD_PBO_NAIVE, | ||||
|    UPLOAD_PBO_PINGPONG, | ||||
|    UPLOAD_PBO_WITH_RESET, | ||||
|    UPLOAD_NOOP, | ||||
|  | ||||
|    QUIT | ||||
| }; | ||||
|  | ||||
| static GLint upload_style = UPLOAD_CONVENTIONAL; | ||||
| static GLboolean whole_rect = 1; | ||||
| static GLboolean do_render = 1; | ||||
| static GLboolean do_swapbuffers = 1; | ||||
|  | ||||
|  | ||||
| static GLuint col = 0x0; | ||||
| static GLfloat Xrot = 20.0, Yrot = 30.0; | ||||
|  | ||||
| static GLuint Width = 1024; | ||||
| static GLuint Height = 512; | ||||
|  | ||||
| #define NR_PBO 2 | ||||
| static GLuint texObj, DrawPBO[NR_PBO]; | ||||
|  | ||||
|  | ||||
| static void Idle( void ) | ||||
| { | ||||
|    col++; | ||||
|     | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
| static int min( int a, int b ) { return a < b ? a : b; } | ||||
|  | ||||
| static void DrawObject() | ||||
| { | ||||
|    GLint size = Width * Height * 4; | ||||
|    static char *static_image = NULL; | ||||
|    static int current = 0; | ||||
|  | ||||
|    switch (upload_style) { | ||||
|    case UPLOAD_PBO_NAIVE: | ||||
|       /* Continually upload from the one pbo without any attempt to | ||||
|        * decouple from hardware trying to access the same data: | ||||
|        */ | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[0]); | ||||
|  | ||||
|       { | ||||
| 	 char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB); | ||||
| 	 memset(image, col&0xff, size); | ||||
| 	 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); | ||||
|       } | ||||
|     | ||||
|       glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0, | ||||
| 		   GL_BGRA, GL_UNSIGNED_BYTE, NULL); | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
|       break; | ||||
|  | ||||
|    case UPLOAD_PBO_PINGPONG: | ||||
|       /* Cycle through the available upload buffers to avoid waiting | ||||
|        * on buffers currently enqueued on the hardware.  Avoids | ||||
|        * waiting on buffer contents that may still be referenced by | ||||
|        * hardware. | ||||
|        */ | ||||
|       current = (current + 1) % NR_PBO; | ||||
|  | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[current]); | ||||
|  | ||||
|       { | ||||
| 	 char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB); | ||||
| 	 memset(image, col&0xff, size); | ||||
| 	 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); | ||||
|       } | ||||
|     | ||||
|       glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0, | ||||
| 		   GL_BGRA, GL_UNSIGNED_BYTE, NULL); | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
|       break; | ||||
|  | ||||
|  | ||||
|    case UPLOAD_PBO_WITH_RESET: | ||||
|       /* Alternate approach, uses BufferDataARB(NULL) to explicitly | ||||
|        * release the old image contents from the pbo prior to upload. | ||||
|        * Similar effect to double buffering pbos as above, but a | ||||
|        * little more subtle as the implications of the NULL data are | ||||
|        * not entirely clear.  I don't know if all drivers will take | ||||
|        * full advantage of the optimization or not. | ||||
|        */ | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[0]); | ||||
|  | ||||
|       /* XXX: This is extremely important - semantically makes the buffer | ||||
|        * contents undefined, but in practice means that the driver can | ||||
|        * release the old copy of the texture and allocate a new one | ||||
|        * without waiting for outstanding rendering to complete. | ||||
|        */ | ||||
|       glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, size, NULL, GL_STREAM_DRAW_ARB); | ||||
|  | ||||
|       { | ||||
| 	 char *image = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY_ARB); | ||||
| 	 memset(image, col&0xff, size); | ||||
| 	 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT); | ||||
|       } | ||||
|     | ||||
|       glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0, | ||||
| 		   GL_BGRA, GL_UNSIGNED_BYTE, NULL); | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
|       break; | ||||
|  | ||||
|  | ||||
|    case UPLOAD_CONVENTIONAL:  | ||||
|       if (static_image == NULL)  | ||||
| 	 static_image = malloc(size); | ||||
|  | ||||
|       memset(static_image, col&0xff, size); | ||||
|  | ||||
|       /* BGRA should be the fast path for regular uploads as well. | ||||
|        */ | ||||
|       glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, Width, Height, 0, | ||||
| 		   GL_BGRA, GL_UNSIGNED_BYTE, static_image); | ||||
|       break; | ||||
|  | ||||
|    case UPLOAD_NOOP: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    if (do_render) | ||||
|    { | ||||
|       int x,y,w,h; | ||||
|  | ||||
|       if (whole_rect) { | ||||
| 	 x = y = 0; | ||||
| 	 w = Width; | ||||
| 	 h = Height; | ||||
|       } | ||||
|       else { | ||||
| 	 x = y = 0; | ||||
| 	 w = min(10, Width); | ||||
| 	 h = min(10, Height); | ||||
|       } | ||||
|  | ||||
|       glBegin(GL_QUADS); | ||||
|  | ||||
|       glTexCoord2f( x, y); | ||||
|       glVertex2f( x, y ); | ||||
|  | ||||
|       glTexCoord2f( x, y + h); | ||||
|       glVertex2f( x, y + h); | ||||
|  | ||||
|       glTexCoord2f( x + w, y + h); | ||||
|       glVertex2f( x + w, y + h ); | ||||
|  | ||||
|       glTexCoord2f( x + w, y); | ||||
|       glVertex2f( x + w, y ); | ||||
|  | ||||
|       glEnd(); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void Display( void ) | ||||
| { | ||||
|    static GLint T0 = 0; | ||||
|    static GLint Frames = 0; | ||||
|    GLint t; | ||||
|  | ||||
|    glClear( GL_COLOR_BUFFER_BIT ); | ||||
|  | ||||
|    glPushMatrix(); | ||||
|       DrawObject(); | ||||
|    glPopMatrix(); | ||||
|  | ||||
|    if (do_swapbuffers)  | ||||
|       glutSwapBuffers(); | ||||
|    else | ||||
|       glFlush(); | ||||
|  | ||||
|    Frames++; | ||||
|  | ||||
|    t = glutGet(GLUT_ELAPSED_TIME); | ||||
|    if (t - T0 >= 1000) { | ||||
|       GLfloat seconds = (t - T0) / 1000.0; | ||||
|  | ||||
|       GLfloat fps = Frames / seconds; | ||||
|       printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); | ||||
|  | ||||
|       T0 = t; | ||||
|       Frames = 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Reshape( int width, int height ) | ||||
| { | ||||
|    glViewport( 0, 0, width, height ); | ||||
|    glMatrixMode( GL_PROJECTION ); | ||||
|    glLoadIdentity(); | ||||
| /*    glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); */ | ||||
|    gluOrtho2D( 0, width, height, 0 ); | ||||
|    glMatrixMode( GL_MODELVIEW ); | ||||
|    glLoadIdentity(); | ||||
| /*    glTranslatef(0.375, 0.375, 0); */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static void ModeMenu(int entry) | ||||
| { | ||||
|    switch (entry) { | ||||
|    case WHOLERECT: | ||||
|       whole_rect = !whole_rect; | ||||
|       break; | ||||
|    case RENDER: | ||||
|       do_render = !do_render; | ||||
|       break; | ||||
|    case SWAPBUF: | ||||
|       do_swapbuffers = !do_swapbuffers; | ||||
|       break; | ||||
|  | ||||
|    case UPLOAD_CONVENTIONAL: | ||||
|    case UPLOAD_PBO_NAIVE: | ||||
|    case UPLOAD_PBO_PINGPONG: | ||||
|    case UPLOAD_PBO_WITH_RESET: | ||||
|    case UPLOAD_NOOP: | ||||
|       upload_style = entry; | ||||
|       break; | ||||
|  | ||||
|    case QUIT: | ||||
|       exit(0); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Key( unsigned char key, int x, int y ) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case 27: | ||||
|          exit(0); | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void SpecialKey( int key, int x, int y ) | ||||
| { | ||||
|    float step = 3.0; | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|  | ||||
|    switch (key) { | ||||
|       case GLUT_KEY_UP: | ||||
|          Xrot += step; | ||||
|          break; | ||||
|       case GLUT_KEY_DOWN: | ||||
|          Xrot -= step; | ||||
|          break; | ||||
|       case GLUT_KEY_LEFT: | ||||
|          Yrot += step; | ||||
|          break; | ||||
|       case GLUT_KEY_RIGHT: | ||||
|          Yrot -= step; | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Init( int argc, char *argv[] ) | ||||
| { | ||||
|    const char *exten = (const char *) glGetString(GL_EXTENSIONS); | ||||
|    GLint size; | ||||
|  | ||||
|  | ||||
|    if (!strstr(exten, "GL_ARB_multitexture")) { | ||||
|       printf("Sorry, GL_ARB_multitexture not supported by this renderer.\n"); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size); | ||||
|    printf("%d x %d max texture size\n", size, size); | ||||
|  | ||||
|    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|  | ||||
|    /* allocate two texture objects */ | ||||
|    glGenTextures(1, &texObj); | ||||
|  | ||||
|    /* setup the texture objects */ | ||||
|    glActiveTextureARB(GL_TEXTURE0_ARB); | ||||
|    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texObj); | ||||
|  | ||||
|    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
|    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
|  | ||||
|    glGenBuffersARB(NR_PBO, DrawPBO); | ||||
|  | ||||
|    { | ||||
|       int i; | ||||
|       for (i = 0; i < NR_PBO; i++) { | ||||
| 	 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO[i]); | ||||
| 	 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, Width * Height * 4, NULL, GL_STREAM_DRAW_ARB); | ||||
|       } | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
|    } | ||||
|     | ||||
|    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | ||||
|  | ||||
|    glEnable(GL_TEXTURE_RECTANGLE_ARB); | ||||
|  | ||||
|    glShadeModel(GL_SMOOTH); | ||||
|    glClearColor(0.3, 0.3, 0.4, 1.0); | ||||
|  | ||||
|    if (argc > 1 && strcmp(argv[1], "-info")==0) { | ||||
|       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|       printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION)); | ||||
|       printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR)); | ||||
|       printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| int main( int argc, char *argv[] ) | ||||
| { | ||||
|    GLint i; | ||||
|  | ||||
|    glutInit( &argc, argv ); | ||||
|  | ||||
|    for (i = 1; i < argc; i++) { | ||||
|       if (strcmp(argv[i], "-w") == 0) { | ||||
|          Width = atoi(argv[i+1]); | ||||
|          if (Width <= 0) { | ||||
|             printf("Error, bad width\n"); | ||||
|             exit(1); | ||||
|          } | ||||
|          i++; | ||||
|       } | ||||
|       else if (strcmp(argv[i], "-h") == 0) { | ||||
|          Height = atoi(argv[i+1]); | ||||
|          if (Height <= 0) { | ||||
|             printf("Error, bad height\n"); | ||||
|             exit(1); | ||||
|          } | ||||
|          i++; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    glutInitWindowSize( Width, Height ); | ||||
|    glutInitWindowPosition( 0, 0 ); | ||||
|    glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); | ||||
|    glutCreateWindow(argv[0] ); | ||||
|  | ||||
|    Init( argc, argv ); | ||||
|  | ||||
|    glutReshapeFunc( Reshape ); | ||||
|    glutKeyboardFunc( Key ); | ||||
|    glutSpecialFunc( SpecialKey ); | ||||
|    glutDisplayFunc( Display ); | ||||
|    glutIdleFunc( Idle ); | ||||
|  | ||||
|    glutCreateMenu(ModeMenu); | ||||
|    glutAddMenuEntry("Wholerect", WHOLERECT); | ||||
|    glutAddMenuEntry("Render", RENDER); | ||||
|    glutAddMenuEntry("Swapbuf", SWAPBUF); | ||||
|  | ||||
|    glutAddMenuEntry("Upload style CONVENTIONAL", UPLOAD_CONVENTIONAL); | ||||
|    glutAddMenuEntry("Upload style PBO_NAIVE", UPLOAD_PBO_NAIVE); | ||||
|    glutAddMenuEntry("Upload style PBO_PINGPONG", UPLOAD_PBO_PINGPONG); | ||||
|    glutAddMenuEntry("Upload style PBO_WITH_RESET", UPLOAD_PBO_WITH_RESET); | ||||
|    glutAddMenuEntry("Upload style NOOP", UPLOAD_NOOP); | ||||
|  | ||||
|    glutAddMenuEntry("Quit", QUIT); | ||||
|    glutAttachMenu(GLUT_RIGHT_BUTTON); | ||||
|  | ||||
|    glutMainLoop(); | ||||
|    return 0; | ||||
| } | ||||
| @@ -38,8 +38,8 @@ | ||||
| #include <GL/glut.h> | ||||
|  | ||||
|  | ||||
| static GLsizei MaxSize = 1024; | ||||
| static GLsizei TexWidth = 256, TexHeight = 256, TexBorder = 0; | ||||
| static GLsizei MaxSize = 2048; | ||||
| static GLsizei TexWidth = 1024, TexHeight = 1024, TexBorder = 0; | ||||
| static GLboolean ScaleAndBias = GL_FALSE; | ||||
| static GLboolean SubImage = GL_FALSE; | ||||
| static GLdouble DownloadRate = 0.0;  /* texels/sec */ | ||||
| @@ -47,6 +47,32 @@ static GLdouble DownloadRate = 0.0;  /* texels/sec */ | ||||
| static GLuint Mode = 0; | ||||
|  | ||||
|  | ||||
| /* Try and avoid L2 cache effects by cycling through a small number of | ||||
|  * textures. | ||||
|  *  | ||||
|  * At the initial size of 1024x1024x4 == 4mbyte, say 8 textures will | ||||
|  * keep us out of most caches at 32mb total. | ||||
|  * | ||||
|  * This turns into a fairly interesting question of what exactly you | ||||
|  * expect to be in cache in normal usage, and what you think should be | ||||
|  * outside.  There's no rules for this, no reason to favour one usage | ||||
|  * over another except what the application you care about happens to | ||||
|  * resemble most closely. | ||||
|  * | ||||
|  * - Should the client texture image be in L2 cache?  Has it just been | ||||
|  *   generated or read from disk? | ||||
|  * - Does the application really use >1 texture, or is it constantly  | ||||
|  *   updating one image in-place? | ||||
|  * | ||||
|  * Different answers will favour different texture upload mechanisms. | ||||
|  * To upload an image that is purely outside of cache, a DMA-based | ||||
|  * upload will probably win, whereas for small, in-cache textures, | ||||
|  * copying looks good. | ||||
|  */ | ||||
| #define NR_TEXOBJ 4 | ||||
| static GLuint TexObj[NR_TEXOBJ]; | ||||
|  | ||||
|  | ||||
| struct FormatRec { | ||||
|    GLenum Format; | ||||
|    GLenum Type; | ||||
| @@ -116,25 +142,57 @@ TypeStr(GLenum type) | ||||
|    } | ||||
| } | ||||
|  | ||||
| /* On x86, there is a performance cliff for memcpy to texture memory | ||||
|  * for sources below 64 byte alignment.  We do our best with this in | ||||
|  * the driver, but it is better if the images are correctly aligned to | ||||
|  * start with: | ||||
|  */ | ||||
| #define ALIGN (1<<12) | ||||
|  | ||||
| static unsigned align(unsigned value, unsigned a) | ||||
| { | ||||
|    return (value + a - 1) & ~(a-1); | ||||
| } | ||||
|  | ||||
| static int MIN2(int a, int b) | ||||
| { | ||||
|    return a < b ? a : b; | ||||
| } | ||||
|  | ||||
| static void | ||||
| MeasureDownloadRate(void) | ||||
| { | ||||
|    const int w = TexWidth + 2 * TexBorder; | ||||
|    const int h = TexHeight + 2 * TexBorder; | ||||
|    const int bytes = w * h * BytesPerTexel(Format); | ||||
|    const int image_bytes = align(w * h * BytesPerTexel(Format), ALIGN); | ||||
|    const int bytes = image_bytes * NR_TEXOBJ; | ||||
|    GLubyte *orig_texImage, *orig_getImage; | ||||
|    GLubyte *texImage, *getImage; | ||||
|    GLdouble t0, t1, time; | ||||
|    int count; | ||||
|    int i; | ||||
|    int offset = 0; | ||||
|    GLdouble total = 0;		/* ints will tend to overflow */ | ||||
|  | ||||
|    texImage = (GLubyte *) malloc(bytes); | ||||
|    getImage = (GLubyte *) malloc(bytes); | ||||
|    if (!texImage || !getImage) { | ||||
|    printf("allocating %d bytes for %d %dx%d images\n", | ||||
| 	  bytes, NR_TEXOBJ, w, h); | ||||
|  | ||||
|    orig_texImage = (GLubyte *) malloc(bytes + ALIGN); | ||||
|    orig_getImage = (GLubyte *) malloc(image_bytes + ALIGN); | ||||
|    if (!orig_texImage || !orig_getImage) { | ||||
|       DownloadRate = 0.0; | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    printf("alloc %p %p\n", orig_texImage, orig_getImage); | ||||
|  | ||||
|    texImage = (GLubyte *)align((unsigned)orig_texImage, ALIGN); | ||||
|    getImage = (GLubyte *)align((unsigned)orig_getImage, ALIGN);    | ||||
|  | ||||
|    for (i = 1; !(((unsigned)texImage) & i); i<<=1) | ||||
|       ; | ||||
|    printf("texture image alignment: %d bytes (%p)\n", i, texImage); | ||||
|        | ||||
|    for (i = 0; i < bytes; i++) { | ||||
|       texImage[i] = i & 0xff; | ||||
|    } | ||||
| @@ -166,16 +224,50 @@ MeasureDownloadRate(void) | ||||
|    count = 0; | ||||
|    t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001; | ||||
|    do { | ||||
|       int img = count%NR_TEXOBJ; | ||||
|       GLubyte *img_ptr = texImage + img * image_bytes; | ||||
|  | ||||
|       glBindTexture(GL_TEXTURE_2D, TexObj[img]); | ||||
|  | ||||
|       if (SubImage && count > 0) { | ||||
|          glTexSubImage2D(GL_TEXTURE_2D, 0, -TexBorder, -TexBorder, w, h, | ||||
| 	 /* Only update a portion of the image each iteration.  This | ||||
| 	  * is presumably why you'd want to use texsubimage, otherwise | ||||
| 	  * you may as well just call teximage again. | ||||
| 	  * | ||||
| 	  * A bigger question is whether to use a pointer that moves | ||||
| 	  * with each call, ie does the incoming data come from L2 | ||||
| 	  * cache under normal circumstances, or is it pulled from | ||||
| 	  * uncached memory?   | ||||
| 	  *  | ||||
| 	  * There's a good argument to say L2 cache, ie you'd expect | ||||
| 	  * the data to have been recently generated.  It's possible | ||||
| 	  * that it could have come from a file read, which may or may | ||||
| 	  * not have gone through the cpu. | ||||
| 	  */ | ||||
|          glTexSubImage2D(GL_TEXTURE_2D, 0,  | ||||
| 			 -TexBorder,  | ||||
| 			 -TexBorder + offset * h/8,  | ||||
| 			 w,  | ||||
| 			 h/8, | ||||
|                          FormatTable[Format].Format, | ||||
|                          FormatTable[Format].Type, texImage); | ||||
|                          FormatTable[Format].Type,  | ||||
| #if 1 | ||||
| 			 texImage /* likely in L2$ */ | ||||
| #else | ||||
| 			 img_ptr + offset * bytes/8 /* unlikely in L2$ */ | ||||
| #endif | ||||
| 	    ); | ||||
| 	 offset += 1; | ||||
| 	 offset %= 8; | ||||
| 	 total += w * h / 8; | ||||
|       } | ||||
|       else { | ||||
|          glTexImage2D(GL_TEXTURE_2D, 0, | ||||
|                       FormatTable[Format].IntFormat, w, h, TexBorder, | ||||
|                       FormatTable[Format].Format, | ||||
|                       FormatTable[Format].Type, texImage); | ||||
|                       FormatTable[Format].Type,  | ||||
| 		      img_ptr); | ||||
| 	 total += w*h; | ||||
|       } | ||||
|  | ||||
|       /* draw a tiny polygon to force texture into texram */ | ||||
| @@ -192,25 +284,12 @@ MeasureDownloadRate(void) | ||||
|  | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
|  | ||||
|    printf("w*h=%d  count=%d  time=%f\n", w*h, count, time); | ||||
|    DownloadRate = w * h * count / time; | ||||
|    printf("total texels=%f  time=%f\n", total, time); | ||||
|    DownloadRate = total / time; | ||||
|  | ||||
| #if 0 | ||||
|    if (!ScaleAndBias) { | ||||
|       /* verify texture readback */ | ||||
|       glGetTexImage(GL_TEXTURE_2D, 0, | ||||
|                     FormatTable[Format].Format, | ||||
|                     FormatTable[Format].Type, getImage); | ||||
|       for (i = 0; i < w * h; i++) { | ||||
|          if (texImage[i] != getImage[i]) { | ||||
|             printf("[%d] %d != %d\n", i, texImage[i], getImage[i]); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    free(texImage); | ||||
|    free(getImage); | ||||
|    free(orig_texImage);  | ||||
|    free(orig_getImage);  | ||||
|  | ||||
|    { | ||||
|       GLint err = glGetError(); | ||||
|   | ||||
							
								
								
									
										184
									
								
								progs/tests/arbnpot-mipmap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								progs/tests/arbnpot-mipmap.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
|  | ||||
| /* Copyright (c) Mark J. Kilgard, 1994. */ | ||||
|  | ||||
| /* | ||||
|  * (c) Copyright 1993, Silicon Graphics, Inc. | ||||
|  * ALL RIGHTS RESERVED | ||||
|  * Permission to use, copy, modify, and distribute this software for | ||||
|  * any purpose and without fee is hereby granted, provided that the above | ||||
|  * copyright notice appear in all copies and that both the copyright notice | ||||
|  * and this permission notice appear in supporting documentation, and that | ||||
|  * the name of Silicon Graphics, Inc. not be used in advertising | ||||
|  * or publicity pertaining to distribution of the software without specific, | ||||
|  * written prior permission. | ||||
|  * | ||||
|  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" | ||||
|  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, | ||||
|  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON | ||||
|  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, | ||||
|  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY | ||||
|  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, | ||||
|  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF | ||||
|  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN | ||||
|  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON | ||||
|  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE | ||||
|  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  * | ||||
|  * US Government Users Restricted Rights | ||||
|  * Use, duplication, or disclosure by the Government is subject to | ||||
|  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph | ||||
|  * (c)(1)(ii) of the Rights in Technical Data and Computer Software | ||||
|  * clause at DFARS 252.227-7013 and/or in similar or successor | ||||
|  * clauses in the FAR or the DOD or NASA FAR Supplement. | ||||
|  * Unpublished-- rights reserved under the copyright laws of the | ||||
|  * United States.  Contractor/manufacturer is Silicon Graphics, | ||||
|  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311. | ||||
|  * | ||||
|  * OpenGL(TM) is a trademark of Silicon Graphics, Inc. | ||||
|  */ | ||||
| /*  mipmap.c | ||||
|  *  This program demonstrates using mipmaps for texture maps. | ||||
|  *  To overtly show the effect of mipmaps, each mipmap reduction | ||||
|  *  level has a solidly colored, contrasting texture image. | ||||
|  *  Thus, the quadrilateral which is drawn is drawn with several | ||||
|  *  different colors. | ||||
|  */ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| GLubyte mipmapImage32[40][46][3]; | ||||
| GLubyte mipmapImage16[20][23][3]; | ||||
| GLubyte mipmapImage8[10][11][3]; | ||||
| GLubyte mipmapImage4[5][5][3]; | ||||
| GLubyte mipmapImage2[2][2][3]; | ||||
| GLubyte mipmapImage1[1][1][3]; | ||||
|  | ||||
| static void makeImages(void) | ||||
| { | ||||
|     int i, j; | ||||
|  | ||||
|     for (i = 0; i < 40; i++) { | ||||
| 	for (j = 0; j < 46; j++) { | ||||
| 	    mipmapImage32[i][j][0] = 255; | ||||
| 	    mipmapImage32[i][j][1] = 255; | ||||
| 	    mipmapImage32[i][j][2] = 0; | ||||
| 	} | ||||
|     } | ||||
|     for (i = 0; i < 20; i++) { | ||||
| 	for (j = 0; j < 23; j++) { | ||||
| 	    mipmapImage16[i][j][0] = 255; | ||||
| 	    mipmapImage16[i][j][1] = 0; | ||||
| 	    mipmapImage16[i][j][2] = 255; | ||||
| 	} | ||||
|     } | ||||
|     for (i = 0; i < 10; i++) { | ||||
| 	for (j = 0; j < 11; j++) { | ||||
| 	    mipmapImage8[i][j][0] = 255; | ||||
| 	    mipmapImage8[i][j][1] = 0; | ||||
| 	    mipmapImage8[i][j][2] = 0; | ||||
| 	} | ||||
|     } | ||||
|     for (i = 0; i < 5; i++) { | ||||
| 	for (j = 0; j < 5; j++) { | ||||
| 	    mipmapImage4[i][j][0] = 0; | ||||
| 	    mipmapImage4[i][j][1] = 255; | ||||
| 	    mipmapImage4[i][j][2] = 0; | ||||
| 	} | ||||
|     } | ||||
|     for (i = 0; i < 2; i++) { | ||||
| 	for (j = 0; j < 2; j++) { | ||||
| 	    mipmapImage2[i][j][0] = 0; | ||||
| 	    mipmapImage2[i][j][1] = 0; | ||||
| 	    mipmapImage2[i][j][2] = 255; | ||||
| 	} | ||||
|     } | ||||
|     mipmapImage1[0][0][0] = 255; | ||||
|     mipmapImage1[0][0][1] = 255; | ||||
|     mipmapImage1[0][0][2] = 255; | ||||
| } | ||||
|  | ||||
| static void myinit(void) | ||||
| { | ||||
|     if (!glutExtensionSupported("GL_ARB_texture_non_power_of_two")) { | ||||
|        printf("Sorry, this program requires GL_ARB_texture_non_power_of_two\n"); | ||||
|        exit(1); | ||||
|     } | ||||
|  | ||||
|     glEnable(GL_DEPTH_TEST); | ||||
|     glDepthFunc(GL_LESS); | ||||
|     glShadeModel(GL_FLAT); | ||||
|  | ||||
|     glTranslatef(0.0, 0.0, -3.6); | ||||
|     makeImages(); | ||||
|     glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 0, 3, 40, 46, 0, | ||||
| 		 GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage32[0][0][0]); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 1, 3, 20, 23, 0, | ||||
| 		 GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage16[0][0][0]); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 2, 3, 10, 11, 0, | ||||
| 		 GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage8[0][0][0]); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 3, 3, 5, 5, 0, | ||||
| 		 GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage4[0][0][0]); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 4, 3, 2, 2, 0, | ||||
| 		 GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage2[0][0][0]); | ||||
|     glTexImage2D(GL_TEXTURE_2D, 5, 3, 1, 1, 0, | ||||
| 		 GL_RGB, GL_UNSIGNED_BYTE, &mipmapImage1[0][0][0]); | ||||
|     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | ||||
|     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | ||||
|     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
|     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | ||||
| 	GL_NEAREST_MIPMAP_NEAREST); | ||||
|     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); | ||||
|     glEnable(GL_TEXTURE_2D); | ||||
| } | ||||
|  | ||||
| static void display(void) | ||||
| { | ||||
|     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
|     glBegin(GL_QUADS); | ||||
|     glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); | ||||
|     glTexCoord2f(0.0, 8.0); glVertex3f(-2.0, 1.0, 0.0); | ||||
|     glTexCoord2f(8.0, 8.0); glVertex3f(2000.0, 1.0, -6000.0); | ||||
|     glTexCoord2f(8.0, 0.0); glVertex3f(2000.0, -1.0, -6000.0); | ||||
|     glEnd(); | ||||
|     glFlush(); | ||||
| } | ||||
|  | ||||
| static void myReshape(int w, int h) | ||||
| { | ||||
|     glViewport(0, 0, w, h); | ||||
|     glMatrixMode(GL_PROJECTION); | ||||
|     glLoadIdentity(); | ||||
|     gluPerspective(60.0, 1.0*(GLfloat)w/(GLfloat)h, 1.0, 30000.0); | ||||
|     glMatrixMode(GL_MODELVIEW); | ||||
|     glLoadIdentity(); | ||||
| } | ||||
|  | ||||
| static void | ||||
| key(unsigned char k, int x, int y) | ||||
| { | ||||
|   switch (k) { | ||||
|   case 27:  /* Escape */ | ||||
|     exit(0); | ||||
|     break; | ||||
|   default: | ||||
|     return; | ||||
|   } | ||||
|   glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     glutInit(&argc, argv); | ||||
|     glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); | ||||
|     glutInitWindowSize (500, 500); | ||||
|     glutCreateWindow (argv[0]); | ||||
|     myinit(); | ||||
|     glutReshapeFunc (myReshape); | ||||
|     glutDisplayFunc(display); | ||||
|     glutKeyboardFunc(key); | ||||
|     glutMainLoop(); | ||||
|     return 0;             /* ANSI C requires main to return int. */ | ||||
| } | ||||
| @@ -38,7 +38,9 @@ SOURCES = \ | ||||
| 	quad-offset-unfilled.c \ | ||||
| 	quad-unfilled.c \ | ||||
| 	quad-tex-2d.c \ | ||||
| 	quad-tex-pbo.c \ | ||||
| 	quad-tex-3d.c \ | ||||
| 	quad-tex-dep.c \ | ||||
| 	quad.c \ | ||||
| 	quads.c \ | ||||
| 	quadstrip.c \ | ||||
|   | ||||
							
								
								
									
										245
									
								
								progs/trivial/quad-tex-dep.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								progs/trivial/quad-tex-dep.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #define GL_GLEXT_PROTOTYPES | ||||
| #include <GL/glut.h> | ||||
|  | ||||
|  | ||||
|  | ||||
| GLenum doubleBuffer; | ||||
|  | ||||
| /* Demonstrate an equivalent to paletted texturing using fragment | ||||
|  * programs and dependent texturing.  This requires at least one | ||||
|  * texture unit to be reserved for the palette lookup. | ||||
|  */ | ||||
|  | ||||
| static void Init( void ) | ||||
| { | ||||
|    static const char *modulate2D = | ||||
|       "!!ARBfp1.0\n" | ||||
|       "TEMP index; \n" | ||||
|       "TEX index, fragment.texcoord[0], texture[0], 2D; \n" | ||||
|       "TEX result.color, index, texture[1], 1D; \n" | ||||
|       "END" | ||||
|       ; | ||||
|    GLuint modulateProg; | ||||
|    GLuint Texture; | ||||
|  | ||||
|    if (!glutExtensionSupported("GL_ARB_fragment_program")) { | ||||
|       printf("Error: GL_ARB_fragment_program not supported!\n"); | ||||
|       exit(1); | ||||
|    } | ||||
|    printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|  | ||||
|    /* Setup the fragment program */ | ||||
|    glGenProgramsARB(1, &modulateProg); | ||||
|    glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, modulateProg); | ||||
|    glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, | ||||
| 		      strlen(modulate2D), (const GLubyte *)modulate2D); | ||||
|  | ||||
|    printf("glGetError = 0x%x\n", (int) glGetError()); | ||||
|    printf("glError(GL_PROGRAM_ERROR_STRING_ARB) = %s\n", | ||||
|           (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB)); | ||||
|    assert(glIsProgramARB(modulateProg)); | ||||
|  | ||||
|    glEnable(GL_FRAGMENT_PROGRAM_ARB); | ||||
|  | ||||
|  | ||||
|    { | ||||
| #define HEIGHT 8 | ||||
| #define WIDTH 32 | ||||
|  | ||||
| #define B 0 | ||||
| #define G 1 | ||||
| #define R 2 | ||||
| #define A 3 | ||||
|  | ||||
|      static char texture[HEIGHT * WIDTH + 1] = | ||||
| 	"                                " | ||||
| 	"    MMM    EEEE   SSS    AAA    " | ||||
| 	"   M M M  E      S   S  A   A   " | ||||
| 	"   M M M  EEEE    SS    A   A   " | ||||
| 	"   M M M  E         SS  AAAAA   " | ||||
| 	"   M   M  E      S   S  A   A   " | ||||
| 	"   M   M   EEEE   SSS   A   A   "; | ||||
|        | ||||
|       GLubyte table[256][4]; | ||||
|  | ||||
|        | ||||
|        | ||||
|       /* load the color table for each texel-index */ | ||||
|       memset(table, 0xff, 256*4); | ||||
|       table[' '][B] = 255; | ||||
|       table[' '][G] = 255; | ||||
|       table[' '][R] = 255; | ||||
|       table[' '][A] = 64; | ||||
|       table['M'][B] = 0; | ||||
|       table['M'][G] = 0; | ||||
|       table['M'][R] = 255; | ||||
|       table['M'][A] = 255; | ||||
|       table['E'][B] = 0; | ||||
|       table['E'][G] = 255; | ||||
|       table['E'][R] = 0; | ||||
|       table['E'][A] = 255; | ||||
|       table['S'][B] = 255; | ||||
|       table['S'][G] = 0; | ||||
|       table['S'][R] = 0; | ||||
|       table['S'][A] = 255; | ||||
|       table['A'][B] = 0; | ||||
|       table['A'][G] = 255; | ||||
|       table['A'][R] = 255; | ||||
|       table['A'][A] = 255; | ||||
|  | ||||
|       glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|  | ||||
|  | ||||
|       /* Load indexed texture as a 2D I8 texture */ | ||||
|       glActiveTextureARB(GL_TEXTURE0_ARB); | ||||
|       glGenTextures(1, &Texture); | ||||
|       glBindTexture(GL_TEXTURE_2D, Texture); | ||||
|  | ||||
|       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
|       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
|  | ||||
|       glTexImage2D(GL_TEXTURE_2D,       /* target */ | ||||
| 		   0,                   /* level */ | ||||
| 		   GL_INTENSITY, /* internal format */ | ||||
| 		   WIDTH, HEIGHT,       /* width, height */ | ||||
| 		   0,                   /* border */ | ||||
| 		   GL_LUMINANCE,      /* texture format */ | ||||
| 		   GL_UNSIGNED_BYTE,    /* texture type */ | ||||
| 		   texture);            /* the texture */ | ||||
|  | ||||
|  | ||||
|    printf("glGetError = 0x%x\n", (int) glGetError()); | ||||
|    printf("glError(GL_PROGRAM_ERROR_STRING_ARB) = %s\n", | ||||
|           (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB)); | ||||
|  | ||||
|       glEnable(GL_TEXTURE_2D); | ||||
|  | ||||
|       /* Load "pallete" as a 1D BGRA8888 texture */ | ||||
|       glActiveTextureARB(GL_TEXTURE1_ARB); | ||||
|       glGenTextures(1, &Texture); | ||||
|       glBindTexture(GL_TEXTURE_1D, Texture); | ||||
|  | ||||
|       glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
|       glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
|  | ||||
|       glTexImage1D(GL_TEXTURE_1D,       /* target */ | ||||
| 		   0,                   /* level */ | ||||
| 		   GL_RGBA,	/* internal format */ | ||||
| 		   256,		/* width */ | ||||
| 		   0,                   /* border */ | ||||
| 		   GL_BGRA,      /* texture format */ | ||||
| 		   GL_UNSIGNED_BYTE,    /* texture type */ | ||||
| 		   table);            /* the texture */ | ||||
|  | ||||
|       glEnable(GL_TEXTURE_1D); | ||||
|  | ||||
| /*       glEnable(GL_BLEND); */ | ||||
| /*       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); */ | ||||
| #undef HEIGHT | ||||
| #undef WIDTH | ||||
|    } | ||||
|  | ||||
|  | ||||
|    glClearColor(.3, .3, .3, 0); | ||||
| } | ||||
|  | ||||
| static void Reshape(int width, int height) | ||||
| { | ||||
|  | ||||
|     glViewport(0, 0, (GLint)width, (GLint)height); | ||||
|  | ||||
|     glMatrixMode(GL_PROJECTION); | ||||
|     glLoadIdentity(); | ||||
|     glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0); | ||||
|     glMatrixMode(GL_MODELVIEW); | ||||
| } | ||||
|  | ||||
| static void Key(unsigned char key, int x, int y) | ||||
| { | ||||
|  | ||||
|     switch (key) { | ||||
|       case 27: | ||||
| 	exit(1); | ||||
|       default: | ||||
| 	return; | ||||
|     } | ||||
|  | ||||
|     glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
| static void Draw(void) | ||||
| { | ||||
|    glClear(GL_COLOR_BUFFER_BIT);  | ||||
|  | ||||
|    glBegin(GL_QUADS); | ||||
|    glTexCoord2f(1,1);  | ||||
|    glVertex3f( 0.9, -0.9, -30.0); | ||||
|    glTexCoord2f(1,0);  | ||||
|    glVertex3f( 0.9,  0.9, -30.0); | ||||
|    glTexCoord2f(0,0);  | ||||
|    glVertex3f(-0.9,  0.9, -30.0); | ||||
|    glTexCoord2f(0,1);  | ||||
|    glVertex3f(-0.9,  -0.9, -30.0); | ||||
|    glEnd(); | ||||
|  | ||||
|    glFlush(); | ||||
|  | ||||
|    if (doubleBuffer) { | ||||
|       glutSwapBuffers(); | ||||
|    } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| static GLenum Args(int argc, char **argv) | ||||
| { | ||||
|     GLint i; | ||||
|  | ||||
|     doubleBuffer = GL_FALSE; | ||||
|  | ||||
|     for (i = 1; i < argc; i++) { | ||||
|         if (strcmp(argv[i], "-sb") == 0) { | ||||
| 	    doubleBuffer = GL_FALSE; | ||||
| 	} else if (strcmp(argv[i], "-db") == 0) { | ||||
| 	    doubleBuffer = GL_TRUE; | ||||
| 	} else { | ||||
| 	    fprintf(stderr, "%s (Bad option).\n", argv[i]); | ||||
| 	    return GL_FALSE; | ||||
| 	} | ||||
|     } | ||||
|     return GL_TRUE; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     GLenum type; | ||||
|  | ||||
|     glutInit(&argc, argv); | ||||
|  | ||||
|     if (Args(argc, argv) == GL_FALSE) { | ||||
| 	exit(1); | ||||
|     } | ||||
|  | ||||
|     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250); | ||||
|  | ||||
|     type = GLUT_RGB; | ||||
|     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; | ||||
|     glutInitDisplayMode(type); | ||||
|  | ||||
|     if (glutCreateWindow("First Tri") == GL_FALSE) { | ||||
| 	exit(1); | ||||
|     } | ||||
|  | ||||
|     Init(); | ||||
|  | ||||
|     glutReshapeFunc(Reshape); | ||||
|     glutKeyboardFunc(Key); | ||||
|     glutDisplayFunc(Draw); | ||||
|     glutMainLoop(); | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										181
									
								
								progs/trivial/quad-tex-pbo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								progs/trivial/quad-tex-pbo.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,181 @@ | ||||
| /* | ||||
|  * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc. | ||||
|  * | ||||
|  * Permission to use, copy, modify, distribute, and sell this software and | ||||
|  * its documentation for any purpose is hereby granted without fee, provided | ||||
|  * that (i) the above copyright notices and this permission notice appear in | ||||
|  * all copies of the software and related documentation, and (ii) the name of | ||||
|  * Silicon Graphics may not be used in any advertising or | ||||
|  * publicity relating to the software without the specific, prior written | ||||
|  * permission of Silicon Graphics. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF | ||||
|  * ANY KIND, | ||||
|  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY | ||||
|  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | ||||
|  * | ||||
|  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR | ||||
|  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, | ||||
|  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | ||||
|  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF | ||||
|  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||||
|  * OF THIS SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #define GL_GLEXT_PROTOTYPES | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
|  | ||||
| #define CI_OFFSET_1 16 | ||||
| #define CI_OFFSET_2 32 | ||||
|  | ||||
| GLenum doubleBuffer; | ||||
|  | ||||
| static GLuint DrawPBO; | ||||
|  | ||||
| static void Init(void) | ||||
| { | ||||
|    fprintf(stderr, "GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|    fprintf(stderr, "GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION)); | ||||
|    fprintf(stderr, "GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR)); | ||||
|  | ||||
|    glClearColor(0.0, 0.0, 1.0, 0.0); | ||||
|  | ||||
| #define SIZE 16 | ||||
|    { | ||||
|       GLubyte tex2d[SIZE][SIZE][4]; | ||||
|       GLint s, t; | ||||
|  | ||||
|       for (s = 0; s < SIZE; s++) { | ||||
| 	 for (t = 0; t < SIZE; t++) { | ||||
| 	    /* bgra: | ||||
| 	     */ | ||||
| 	    tex2d[t][s][0] = 0x30; | ||||
| 	    tex2d[t][s][1] = t*255/(SIZE-1); | ||||
| 	    tex2d[t][s][2] = s*255/(SIZE-1); | ||||
| 	    tex2d[t][s][3] = 0xff; | ||||
| 	 } | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* put image into DrawPBO */ | ||||
|       glGenBuffersARB(1, &DrawPBO); | ||||
|       glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, DrawPBO); | ||||
|       glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, | ||||
| 		      SIZE * SIZE * 4, tex2d, GL_STATIC_DRAW); | ||||
|       glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0); | ||||
|  | ||||
|  | ||||
|       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | ||||
|       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT); | ||||
|       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
|       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||||
|  | ||||
|       glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO); | ||||
|       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE, SIZE, 0, | ||||
| 		   GL_BGRA, GL_UNSIGNED_BYTE, NULL); | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
|       glPixelStorei(GL_UNPACK_ALIGNMENT, 4); | ||||
|       glEnable(GL_TEXTURE_2D); | ||||
|    } | ||||
|  | ||||
| } | ||||
|  | ||||
| static void Reshape(int width, int height) | ||||
| { | ||||
|  | ||||
|     glViewport(0, 0, (GLint)width, (GLint)height); | ||||
|  | ||||
|     glMatrixMode(GL_PROJECTION); | ||||
|     glLoadIdentity(); | ||||
|     glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0); | ||||
|     glMatrixMode(GL_MODELVIEW); | ||||
| } | ||||
|  | ||||
| static void Key(unsigned char key, int x, int y) | ||||
| { | ||||
|  | ||||
|     switch (key) { | ||||
|       case 27: | ||||
| 	exit(1); | ||||
|       default: | ||||
| 	return; | ||||
|     } | ||||
|  | ||||
|     glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
| static void Draw(void) | ||||
| { | ||||
|    glClear(GL_COLOR_BUFFER_BIT);  | ||||
|  | ||||
|    glBegin(GL_QUADS); | ||||
|    glTexCoord2f(1,0);  | ||||
|    glVertex3f( 0.9, -0.9, -30.0); | ||||
|    glTexCoord2f(1,1);  | ||||
|    glVertex3f( 0.9,  0.9, -30.0); | ||||
|    glTexCoord2f(0,1);  | ||||
|    glVertex3f(-0.9,  0.9, -30.0); | ||||
|    glTexCoord2f(0,0);  | ||||
|    glVertex3f(-0.9,  -0.9, -30.0); | ||||
|    glEnd(); | ||||
|  | ||||
|    glFlush(); | ||||
|  | ||||
|    if (doubleBuffer) { | ||||
|       glutSwapBuffers(); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static GLenum Args(int argc, char **argv) | ||||
| { | ||||
|     GLint i; | ||||
|  | ||||
|     doubleBuffer = GL_FALSE; | ||||
|  | ||||
|     for (i = 1; i < argc; i++) { | ||||
|         if (strcmp(argv[i], "-sb") == 0) { | ||||
| 	    doubleBuffer = GL_FALSE; | ||||
| 	} else if (strcmp(argv[i], "-db") == 0) { | ||||
| 	    doubleBuffer = GL_TRUE; | ||||
| 	} else { | ||||
| 	    fprintf(stderr, "%s (Bad option).\n", argv[i]); | ||||
| 	    return GL_FALSE; | ||||
| 	} | ||||
|     } | ||||
|     return GL_TRUE; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     GLenum type; | ||||
|  | ||||
|     glutInit(&argc, argv); | ||||
|  | ||||
|     if (Args(argc, argv) == GL_FALSE) { | ||||
| 	exit(1); | ||||
|     } | ||||
|  | ||||
|     glutInitWindowPosition(0, 0); glutInitWindowSize( 250, 250); | ||||
|  | ||||
|     type = GLUT_RGB; | ||||
|     type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE; | ||||
|     glutInitDisplayMode(type); | ||||
|  | ||||
|     if (glutCreateWindow("First Tri") == GL_FALSE) { | ||||
| 	exit(1); | ||||
|     } | ||||
|  | ||||
|     Init(); | ||||
|  | ||||
|     glutReshapeFunc(Reshape); | ||||
|     glutKeyboardFunc(Key); | ||||
|     glutDisplayFunc(Draw); | ||||
|     glutMainLoop(); | ||||
| 	return 0; | ||||
| } | ||||
| @@ -722,6 +722,68 @@ static const __DRIinterfaceMethods interface_methods = { | ||||
|     glXGetMscRateOML, | ||||
| }; | ||||
|  | ||||
| #define DRM_MAX_FDS 16 | ||||
| static struct { | ||||
|    char *BusID; | ||||
|    int fd; | ||||
|    int refcount; | ||||
| } connection[DRM_MAX_FDS]; | ||||
|  | ||||
| static int nr_fds = 0; | ||||
|  | ||||
| int drmOpenOnce(void *unused,  | ||||
| 		const char *BusID, | ||||
| 		int *newlyopened) | ||||
| { | ||||
|    int i; | ||||
|    int fd; | ||||
|     | ||||
|    for (i = 0; i < nr_fds; i++) | ||||
|       if (strcmp(BusID, connection[i].BusID) == 0) { | ||||
| 	 connection[i].refcount++; | ||||
| 	 *newlyopened = 0; | ||||
| 	 return connection[i].fd; | ||||
|       } | ||||
|  | ||||
|    fd = drmOpen(unused, BusID); | ||||
|    if (fd <= 0 || nr_fds == DRM_MAX_FDS) | ||||
|       return fd; | ||||
|     | ||||
|    connection[nr_fds].BusID = strdup(BusID); | ||||
|    connection[nr_fds].fd = fd; | ||||
|    connection[nr_fds].refcount = 1; | ||||
|    *newlyopened = 1; | ||||
|  | ||||
|    fprintf(stderr, "saved connection %d for %s %d\n",  | ||||
| 	  nr_fds, connection[nr_fds].BusID,  | ||||
| 	  strcmp(BusID, connection[nr_fds].BusID)); | ||||
|  | ||||
|    nr_fds++; | ||||
|  | ||||
|    return fd;    | ||||
| } | ||||
|  | ||||
| void drmCloseOnce(int fd) | ||||
| { | ||||
|    int i; | ||||
|  | ||||
|     | ||||
|  | ||||
|    for (i = 0; i < nr_fds; i++) { | ||||
|       if (fd == connection[i].fd) { | ||||
| 	 if (--connection[i].refcount == 0) { | ||||
| 	    drmClose(connection[i].fd); | ||||
| 	    free(connection[i].BusID); | ||||
| 	     | ||||
| 	    if (i < --nr_fds)  | ||||
| 	       connection[i] = connection[nr_fds]; | ||||
|  | ||||
| 	    return; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Perform the required libGL-side initialization and call the client-side | ||||
| @@ -773,7 +835,8 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, | ||||
|     framebuffer.dev_priv = NULL; | ||||
|  | ||||
|     if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { | ||||
| 	fd = drmOpen(NULL,BusID); | ||||
|         int newlyopened; | ||||
| 	fd = drmOpenOnce(NULL,BusID, &newlyopened); | ||||
| 	Xfree(BusID); /* No longer needed */ | ||||
|  | ||||
| 	err_msg = "open DRM"; | ||||
| @@ -800,7 +863,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, | ||||
| 		} | ||||
|  | ||||
| 		err_msg = "XF86DRIAuthConnection"; | ||||
| 		if (XF86DRIAuthConnection(dpy, scrn, magic)) { | ||||
| 		if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) { | ||||
| 		    char *driverName; | ||||
|  | ||||
| 		    /* | ||||
| @@ -904,7 +967,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, | ||||
| 	} | ||||
|  | ||||
| 	if ( fd >= 0 ) { | ||||
| 	    (void)drmClose(fd); | ||||
| 	    (void)drmCloseOnce(fd); | ||||
| 	} | ||||
|  | ||||
| 	(void)XF86DRICloseConnection(dpy, scrn); | ||||
|   | ||||
| @@ -9,7 +9,10 @@ COMMON_SOURCES = \ | ||||
|         ../common/vblank.c \ | ||||
|         ../common/dri_util.c \ | ||||
|         ../common/xmlconfig.c \ | ||||
|         ../common/drirenderbuffer.c | ||||
|         ../common/drirenderbuffer.c \ | ||||
| 	../common/dri_bufmgr.c \ | ||||
| 	../common/dri_drmpool.c | ||||
|  | ||||
|  | ||||
| ifeq ($(WINDOW_SYSTEM),dri) | ||||
| WINOBJ= | ||||
|   | ||||
							
								
								
									
										493
									
								
								src/mesa/drivers/dri/common/dri_bufmgr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										493
									
								
								src/mesa/drivers/dri/common/dri_bufmgr.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,493 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||||
|  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  | ||||
|  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  | ||||
|  * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
| /* | ||||
|  * Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com> | ||||
|  *          Keith Whitwell <keithw-at-tungstengraphics-dot-com> | ||||
|  */ | ||||
|  | ||||
| #include <xf86drm.h> | ||||
| #include <stdlib.h> | ||||
| #include "glthread.h" | ||||
| #include "errno.h" | ||||
| #include "dri_bufmgr.h" | ||||
| #include "string.h" | ||||
| #include "imports.h" | ||||
| #include "dri_bufpool.h" | ||||
|  | ||||
| _glthread_DECLARE_STATIC_MUTEX(bmMutex); | ||||
|  | ||||
| /* | ||||
|  * TODO: Introduce fence pools in the same way as  | ||||
|  * buffer object pools. | ||||
|  */ | ||||
|  | ||||
|  | ||||
|  | ||||
| typedef struct _DriFenceObject | ||||
| { | ||||
|    int fd; | ||||
|    _glthread_Mutex mutex; | ||||
|    int refCount; | ||||
|    const char *name; | ||||
|    drmFence fence; | ||||
| } DriFenceObject; | ||||
|  | ||||
| typedef struct _DriBufferObject | ||||
| { | ||||
|    DriBufferPool *pool; | ||||
|    _glthread_Mutex mutex; | ||||
|    int refCount; | ||||
|    const char *name; | ||||
|    unsigned flags; | ||||
|    unsigned hint; | ||||
|    unsigned alignment; | ||||
|    void *private; | ||||
| } DriBufferObject; | ||||
|  | ||||
|  | ||||
| void | ||||
| bmError(int val, const char *file, const char *function, int line) | ||||
| { | ||||
|    _mesa_printf("Fatal video memory manager error \"%s\".\n" | ||||
|                 "Check kernel logs or set the LIBGL_DEBUG\n" | ||||
|                 "environment variable to \"verbose\" for more info.\n" | ||||
|                 "Detected in file %s, line %d, function %s.\n", | ||||
|                 strerror(-val), file, line, function); | ||||
| #ifndef NDEBUG | ||||
|    abort(); | ||||
| #else | ||||
|    abort(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| DriFenceObject * | ||||
| driFenceBuffers(int fd, char *name, unsigned flags) | ||||
| { | ||||
|    DriFenceObject *fence = (DriFenceObject *) malloc(sizeof(*fence)); | ||||
|    int ret; | ||||
|  | ||||
|    if (!fence) | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    fence->refCount = 1; | ||||
|    fence->name = name; | ||||
|    fence->fd = fd; | ||||
|    _glthread_INIT_MUTEX(fence->mutex); | ||||
|    ret = drmFenceBuffers(fd, flags, &fence->fence); | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
|    if (ret) { | ||||
|       free(fence); | ||||
|       BM_CKFATAL(ret); | ||||
|    } | ||||
|    return fence; | ||||
| } | ||||
|  | ||||
|  | ||||
| unsigned  | ||||
| driFenceType(DriFenceObject * fence) | ||||
| { | ||||
|     unsigned ret; | ||||
|  | ||||
|     _glthread_LOCK_MUTEX(bmMutex); | ||||
|     ret = fence->fence.flags; | ||||
|     _glthread_UNLOCK_MUTEX(bmMutex); | ||||
|      | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| DriFenceObject * | ||||
| driFenceReference(DriFenceObject * fence) | ||||
| { | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    ++fence->refCount; | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
|    return fence; | ||||
| } | ||||
|  | ||||
| void | ||||
| driFenceUnReference(DriFenceObject * fence) | ||||
| { | ||||
|    if (!fence) | ||||
|       return; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    if (--fence->refCount == 0) { | ||||
|       drmFenceDestroy(fence->fd, &fence->fence); | ||||
|       free(fence); | ||||
|    } | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driFenceFinish(DriFenceObject * fence, unsigned type, int lazy) | ||||
| { | ||||
|    int ret; | ||||
|    unsigned flags = (lazy) ? DRM_FENCE_FLAG_WAIT_LAZY : 0; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(fence->mutex); | ||||
|    ret = drmFenceWait(fence->fd, flags, &fence->fence, type); | ||||
|    _glthread_UNLOCK_MUTEX(fence->mutex); | ||||
|    BM_CKFATAL(ret); | ||||
| } | ||||
|  | ||||
| int | ||||
| driFenceSignaled(DriFenceObject * fence, unsigned type) | ||||
| { | ||||
|    int signaled; | ||||
|    int ret; | ||||
|  | ||||
|    if (fence == NULL) | ||||
|       return GL_TRUE; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(fence->mutex); | ||||
|    ret = drmFenceSignaled(fence->fd, &fence->fence, type, &signaled); | ||||
|    _glthread_UNLOCK_MUTEX(fence->mutex); | ||||
|    BM_CKFATAL(ret); | ||||
|    return signaled; | ||||
| } | ||||
|  | ||||
|  | ||||
| extern drmBO * | ||||
| driBOKernel(struct _DriBufferObject *buf) | ||||
| { | ||||
|    drmBO *ret; | ||||
|  | ||||
|    assert(buf->private != NULL); | ||||
|    ret = buf->pool->kernel(buf->pool, buf->private); | ||||
|    if (!ret) | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|  | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOWaitIdle(struct _DriBufferObject *buf, int lazy) | ||||
| { | ||||
|    assert(buf->private != NULL); | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, lazy)); | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
| } | ||||
|  | ||||
| void * | ||||
| driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint) | ||||
| { | ||||
|    void *virtual; | ||||
|  | ||||
|    assert(buf->private != NULL); | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    BM_CKFATAL(buf->pool->map(buf->pool, buf->private, flags, hint, &virtual)); | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
|    return virtual; | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOUnmap(struct _DriBufferObject *buf) | ||||
| { | ||||
|    assert(buf->private != NULL); | ||||
|  | ||||
|    buf->pool->unmap(buf->pool, buf->private); | ||||
| } | ||||
|  | ||||
| unsigned long | ||||
| driBOOffset(struct _DriBufferObject *buf) | ||||
| { | ||||
|    unsigned long ret; | ||||
|  | ||||
|    assert(buf->private != NULL); | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    ret = buf->pool->offset(buf->pool, buf->private); | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
| unsigned | ||||
| driBOFlags(struct _DriBufferObject *buf) | ||||
| { | ||||
|    unsigned ret; | ||||
|  | ||||
|    assert(buf->private != NULL); | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    ret = buf->pool->flags(buf->pool, buf->private); | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
| struct _DriBufferObject * | ||||
| driBOReference(struct _DriBufferObject *buf) | ||||
| { | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    if (++buf->refCount == 1) { | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|    } | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
|    return buf; | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOUnReference(struct _DriBufferObject *buf) | ||||
| { | ||||
|    int tmp; | ||||
|  | ||||
|    if (!buf) | ||||
|       return; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    tmp = --buf->refCount; | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
|    if (!tmp) { | ||||
|       buf->pool->destroy(buf->pool, buf->private); | ||||
|       free(buf); | ||||
|    } | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOData(struct _DriBufferObject *buf, | ||||
|           unsigned size, const void *data, unsigned flags) | ||||
| { | ||||
|    void *virtual; | ||||
|    int newBuffer; | ||||
|    struct _DriBufferPool *pool; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    pool = buf->pool; | ||||
|    if (!pool->create) { | ||||
|       _mesa_error(NULL, GL_INVALID_OPERATION, | ||||
|                   "driBOData called on invalid buffer\n"); | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|    } | ||||
|    newBuffer = !buf->private || (pool->size(pool, buf->private) < size) || | ||||
|       pool->map(pool, buf->private, DRM_BO_FLAG_WRITE, | ||||
|                 DRM_BO_HINT_DONT_BLOCK, &virtual); | ||||
|  | ||||
|    if (newBuffer) { | ||||
|       if (buf->private) | ||||
|          pool->destroy(pool, buf->private); | ||||
|       if (!flags) | ||||
|          flags = buf->flags; | ||||
|       buf->private = pool->create(pool, size, flags, 0, buf->alignment); | ||||
|       if (!buf->private) | ||||
|          BM_CKFATAL(-ENOMEM); | ||||
|       BM_CKFATAL(pool->map(pool, buf->private, | ||||
|                            DRM_BO_FLAG_WRITE, | ||||
|                            DRM_BO_HINT_DONT_BLOCK, &virtual)); | ||||
|    } | ||||
|  | ||||
|    if (data != NULL) | ||||
|       memcpy(virtual, data, size); | ||||
|  | ||||
|    BM_CKFATAL(pool->unmap(pool, buf->private)); | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOSubData(struct _DriBufferObject *buf, | ||||
|              unsigned long offset, unsigned long size, const void *data) | ||||
| { | ||||
|    void *virtual; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    if (size && data) { | ||||
|       BM_CKFATAL(buf->pool->map(buf->pool, buf->private, | ||||
|                                 DRM_BO_FLAG_WRITE, 0, &virtual)); | ||||
|       memcpy((unsigned char *) virtual + offset, data, size); | ||||
|       BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private)); | ||||
|    } | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOGetSubData(struct _DriBufferObject *buf, | ||||
|                 unsigned long offset, unsigned long size, void *data) | ||||
| { | ||||
|    void *virtual; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    if (size && data) { | ||||
|       BM_CKFATAL(buf->pool->map(buf->pool, buf->private, | ||||
|                                 DRM_BO_FLAG_READ, 0, &virtual)); | ||||
|       memcpy(data, (unsigned char *) virtual + offset, size); | ||||
|       BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private)); | ||||
|    } | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOSetStatic(struct _DriBufferObject *buf, | ||||
|                unsigned long offset, | ||||
|                unsigned long size, void *virtual, unsigned flags) | ||||
| { | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    if (buf->private != NULL) { | ||||
|       _mesa_error(NULL, GL_INVALID_OPERATION, | ||||
|                   "Invalid buffer for setStatic\n"); | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|    } | ||||
|    if (buf->pool->setstatic == NULL) { | ||||
|       _mesa_error(NULL, GL_INVALID_OPERATION, | ||||
|                   "Invalid buffer pool for setStatic\n"); | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|    } | ||||
|  | ||||
|    if (!flags) | ||||
|       flags = buf->flags; | ||||
|  | ||||
|    buf->private = buf->pool->setstatic(buf->pool, offset, size, | ||||
|                                        virtual, flags); | ||||
|    if (!buf->private) { | ||||
|       _mesa_error(NULL, GL_OUT_OF_MEMORY, | ||||
|                   "Invalid buffer pool for setStatic\n"); | ||||
|       BM_CKFATAL(-ENOMEM); | ||||
|    } | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| driGenBuffers(struct _DriBufferPool *pool, | ||||
|               const char *name, | ||||
|               unsigned n, | ||||
|               struct _DriBufferObject *buffers[], | ||||
|               unsigned alignment, unsigned flags, unsigned hint) | ||||
| { | ||||
|    struct _DriBufferObject *buf; | ||||
|    int i; | ||||
|  | ||||
|    flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM | | ||||
|       DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE; | ||||
|  | ||||
|  | ||||
|    for (i = 0; i < n; ++i) { | ||||
|       buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf)); | ||||
|       if (!buf) | ||||
|          BM_CKFATAL(-ENOMEM); | ||||
|  | ||||
|       _glthread_INIT_MUTEX(buf->mutex); | ||||
|       _glthread_LOCK_MUTEX(buf->mutex); | ||||
|       _glthread_LOCK_MUTEX(bmMutex); | ||||
|       buf->refCount = 1; | ||||
|       _glthread_UNLOCK_MUTEX(bmMutex); | ||||
|       buf->flags = flags; | ||||
|       buf->hint = hint; | ||||
|       buf->name = name; | ||||
|       buf->alignment = alignment; | ||||
|       buf->pool = pool; | ||||
|       _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
|       buffers[i] = buf; | ||||
|    } | ||||
| } | ||||
|  | ||||
| void | ||||
| driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]) | ||||
| { | ||||
|    int i; | ||||
|  | ||||
|    for (i = 0; i < n; ++i) { | ||||
|       driBOUnReference(buffers[i]); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| driInitBufMgr(int fd) | ||||
| { | ||||
|    ; | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| driBOCreateList(int target, drmBOList * list) | ||||
| { | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    BM_CKFATAL(drmBOCreateList(20, list)); | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOResetList(drmBOList * list) | ||||
| { | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    BM_CKFATAL(drmBOResetList(list)); | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf, | ||||
|                  unsigned flags, unsigned mask) | ||||
| { | ||||
|    int newItem; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    BM_CKFATAL(drmAddValidateItem(list, driBOKernel(buf), | ||||
|                                  flags, mask, &newItem)); | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
|  | ||||
|    /* | ||||
|     * Tell userspace pools to validate the buffer. This should be a  | ||||
|     * noop if the pool is already validated. | ||||
|     * FIXME: We should have a list for this as well. | ||||
|     */ | ||||
|  | ||||
|    if (buf->pool->validate) { | ||||
|       BM_CKFATAL(buf->pool->validate(buf->pool, buf->private)); | ||||
|    } | ||||
|  | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence) | ||||
| { | ||||
|    _glthread_LOCK_MUTEX(buf->mutex); | ||||
|    BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence)); | ||||
|    _glthread_UNLOCK_MUTEX(buf->mutex); | ||||
|  | ||||
| } | ||||
|  | ||||
| void | ||||
| driBOValidateList(int fd, drmBOList * list) | ||||
| { | ||||
|    _glthread_LOCK_MUTEX(bmMutex); | ||||
|    BM_CKFATAL(drmBOValidateList(fd, list)); | ||||
|    _glthread_UNLOCK_MUTEX(bmMutex); | ||||
| } | ||||
|  | ||||
| void | ||||
| driPoolTakeDown(struct _DriBufferPool *pool) | ||||
| { | ||||
|    pool->takeDown(pool); | ||||
|  | ||||
| } | ||||
							
								
								
									
										99
									
								
								src/mesa/drivers/dri/common/dri_bufmgr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/mesa/drivers/dri/common/dri_bufmgr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||||
|  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  | ||||
|  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  | ||||
|  * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
| /* | ||||
|  * Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com> | ||||
|  *          Keith Whitwell <keithw-at-tungstengraphics-dot-com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _DRI_BUFMGR_H_ | ||||
| #define _DRI_BUFMGR_H_ | ||||
| #include <xf86drm.h> | ||||
|  | ||||
|  | ||||
| struct _DriFenceObject; | ||||
| struct _DriBufferObject; | ||||
| struct _DriBufferPool; | ||||
|  | ||||
| extern struct _DriFenceObject *driFenceBuffers(int fd, char *name, | ||||
|                                                unsigned flags); | ||||
|  | ||||
| extern struct _DriFenceObject *driFenceReference(struct _DriFenceObject *fence); | ||||
|  | ||||
| extern void driFenceUnReference(struct _DriFenceObject *fence); | ||||
|  | ||||
| extern void | ||||
| driFenceFinish(struct _DriFenceObject *fence, unsigned type, int lazy); | ||||
|  | ||||
| extern int driFenceSignaled(struct _DriFenceObject *fence, unsigned type); | ||||
| extern unsigned driFenceType(struct _DriFenceObject *fence); | ||||
|  | ||||
| /* | ||||
|  * Return a pointer to the libdrm buffer object this DriBufferObject | ||||
|  * uses. | ||||
|  */ | ||||
|  | ||||
| extern drmBO *driBOKernel(struct _DriBufferObject *buf); | ||||
| extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags, | ||||
|                       unsigned hint); | ||||
| extern void driBOUnmap(struct _DriBufferObject *buf); | ||||
| extern unsigned long driBOOffset(struct _DriBufferObject *buf); | ||||
| extern unsigned driBOFlags(struct _DriBufferObject *buf); | ||||
| extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf); | ||||
| extern void driBOUnReference(struct _DriBufferObject *buf); | ||||
| extern void driBOData(struct _DriBufferObject *r_buf, | ||||
|                       unsigned size, const void *data, unsigned flags); | ||||
| extern void driBOSubData(struct _DriBufferObject *buf, | ||||
|                          unsigned long offset, unsigned long size, | ||||
|                          const void *data); | ||||
| extern void driBOGetSubData(struct _DriBufferObject *buf, | ||||
|                             unsigned long offset, unsigned long size, | ||||
|                             void *data); | ||||
| extern void driGenBuffers(struct _DriBufferPool *pool, | ||||
|                           const char *name, | ||||
|                           unsigned n, | ||||
|                           struct _DriBufferObject *buffers[], | ||||
|                           unsigned alignment, unsigned flags, unsigned hint); | ||||
| extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]); | ||||
| extern void driInitBufMgr(int fd); | ||||
| extern void driBOCreateList(int target, drmBOList * list); | ||||
| extern void driBOResetList(drmBOList * list); | ||||
| extern void driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf, | ||||
|                              unsigned flags, unsigned mask); | ||||
| extern void driBOValidateList(int fd, drmBOList * list); | ||||
|  | ||||
| extern void driBOFence(struct _DriBufferObject *buf, | ||||
|                        struct _DriFenceObject *fence); | ||||
|  | ||||
| extern void driPoolTakeDown(struct _DriBufferPool *pool); | ||||
| extern void driBOSetStatic(struct _DriBufferObject *buf, | ||||
|                            unsigned long offset, | ||||
|                            unsigned long size, void *virtual, unsigned flags); | ||||
| extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy); | ||||
| extern void driPoolTakeDown(struct _DriBufferPool *pool); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										86
									
								
								src/mesa/drivers/dri/common/dri_bufpool.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/mesa/drivers/dri/common/dri_bufpool.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||||
|  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  | ||||
|  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  | ||||
|  * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
| /* | ||||
|  * Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _DRI_BUFPOOL_H_ | ||||
| #define _DRI_BUFPOOL_H_ | ||||
|  | ||||
| #include <xf86drm.h> | ||||
| struct _DriFenceObject; | ||||
|  | ||||
| typedef struct _DriBufferPool | ||||
| { | ||||
|    int fd; | ||||
|    int (*map) (struct _DriBufferPool * pool, void *private, | ||||
|                unsigned flags, int hint, void **virtual); | ||||
|    int (*unmap) (struct _DriBufferPool * pool, void *private); | ||||
|    int (*destroy) (struct _DriBufferPool * pool, void *private); | ||||
|    unsigned long (*offset) (struct _DriBufferPool * pool, void *private); | ||||
|    unsigned (*flags) (struct _DriBufferPool * pool, void *private); | ||||
|    unsigned long (*size) (struct _DriBufferPool * pool, void *private); | ||||
|    void *(*create) (struct _DriBufferPool * pool, unsigned long size, | ||||
|                     unsigned flags, unsigned hint, unsigned alignment); | ||||
|    int (*fence) (struct _DriBufferPool * pool, void *private, | ||||
|                  struct _DriFenceObject * fence); | ||||
|    drmBO *(*kernel) (struct _DriBufferPool * pool, void *private); | ||||
|    int (*validate) (struct _DriBufferPool * pool, void *private); | ||||
|    void *(*setstatic) (struct _DriBufferPool * pool, unsigned long offset, | ||||
|                        unsigned long size, void *virtual, unsigned flags); | ||||
|    int (*waitIdle) (struct _DriBufferPool *pool, void *private, | ||||
| 		    int lazy); | ||||
|    void (*takeDown) (struct _DriBufferPool * pool); | ||||
|    void *data; | ||||
| } DriBufferPool; | ||||
|  | ||||
| extern void bmError(int val, const char *file, const char *function, | ||||
|                     int line); | ||||
| #define BM_CKFATAL(val)					       \ | ||||
|   do{							       \ | ||||
|     int tstVal = (val);					       \ | ||||
|     if (tstVal) 					       \ | ||||
|       bmError(tstVal, __FILE__, __FUNCTION__, __LINE__);       \ | ||||
|   } while(0); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Builtin pools. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * Kernel buffer objects. Size in multiples of page size. Page size aligned. | ||||
|  */ | ||||
|  | ||||
| extern struct _DriBufferPool *driDRMPoolInit(int fd); | ||||
| extern struct _DriBufferPool *driDRMStaticPoolInit(int fd); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										221
									
								
								src/mesa/drivers/dri/common/dri_drmpool.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								src/mesa/drivers/dri/common/dri_drmpool.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,221 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||||
|  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  | ||||
|  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  | ||||
|  * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
| /* | ||||
|  * Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com> | ||||
|  */ | ||||
|  | ||||
| #include <xf86drm.h> | ||||
| #include <stdlib.h> | ||||
| #include "dri_bufpool.h" | ||||
|  | ||||
| /* | ||||
|  * Buffer pool implementation using DRM buffer objects as DRI buffer objects. | ||||
|  */ | ||||
|  | ||||
| static void * | ||||
| pool_create(struct _DriBufferPool *pool, | ||||
|             unsigned long size, unsigned flags, unsigned hint, | ||||
|             unsigned alignment) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) malloc(sizeof(*buf)); | ||||
|    int ret; | ||||
|  | ||||
|    if (!buf) | ||||
|       return NULL; | ||||
|  | ||||
|    if (alignment && ((4096 % alignment) != 0)) | ||||
|       return NULL; | ||||
|  | ||||
|    ret = drmBOCreate(pool->fd, NULL, 0, size, NULL, drm_bo_type_dc, | ||||
|                      flags, hint, buf); | ||||
|  | ||||
|    if (ret) { | ||||
|       free(buf); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return (void *) buf; | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_destroy(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) private; | ||||
|    return drmBODestroy(pool->fd, buf); | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_map(struct _DriBufferPool *pool, void *private, unsigned flags, | ||||
|          int hint, void **virtual) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) private; | ||||
|  | ||||
|    return drmBOMap(pool->fd, buf, flags, hint, virtual); | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_unmap(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) private; | ||||
|    return drmBOUnmap(pool->fd, buf); | ||||
| } | ||||
|  | ||||
| static unsigned long | ||||
| pool_offset(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) private; | ||||
|    return buf->offset; | ||||
| } | ||||
|  | ||||
| static unsigned | ||||
| pool_flags(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) private; | ||||
|    return buf->flags; | ||||
| } | ||||
|  | ||||
|  | ||||
| static unsigned long | ||||
| pool_size(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) private; | ||||
|    return buf->size; | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_fence(struct _DriBufferPool *pool, void *private, | ||||
|            struct _DriFenceObject *fence) | ||||
| { | ||||
|    /* | ||||
|     * Noop. The kernel handles all fencing. | ||||
|     */ | ||||
|  | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| static drmBO * | ||||
| pool_kernel(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    return (drmBO *) private; | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) private; | ||||
|    return drmBOWaitIdle(pool->fd, buf, (lazy) ? DRM_BO_HINT_WAIT_LAZY:0); | ||||
| } | ||||
|  | ||||
|      | ||||
| static void | ||||
| pool_takedown(struct _DriBufferPool *pool) | ||||
| { | ||||
|    free(pool); | ||||
| } | ||||
|  | ||||
|  | ||||
| struct _DriBufferPool * | ||||
| driDRMPoolInit(int fd) | ||||
| { | ||||
|    struct _DriBufferPool *pool; | ||||
|  | ||||
|    pool = (struct _DriBufferPool *) malloc(sizeof(*pool)); | ||||
|  | ||||
|    if (!pool) | ||||
|       return NULL; | ||||
|  | ||||
|    pool->fd = fd; | ||||
|    pool->map = &pool_map; | ||||
|    pool->unmap = &pool_unmap; | ||||
|    pool->destroy = &pool_destroy; | ||||
|    pool->offset = &pool_offset; | ||||
|    pool->flags = &pool_flags; | ||||
|    pool->size = &pool_size; | ||||
|    pool->create = &pool_create; | ||||
|    pool->fence = &pool_fence; | ||||
|    pool->kernel = &pool_kernel; | ||||
|    pool->validate = NULL; | ||||
|    pool->setstatic = NULL; | ||||
|    pool->waitIdle = &pool_waitIdle; | ||||
|    pool->takeDown = &pool_takedown; | ||||
|    pool->data = NULL; | ||||
|    return pool; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void * | ||||
| pool_setstatic(struct _DriBufferPool *pool, unsigned long offset, | ||||
|                unsigned long size, void *virtual, unsigned flags) | ||||
| { | ||||
|    drmBO *buf = (drmBO *) malloc(sizeof(*buf)); | ||||
|    int ret; | ||||
|  | ||||
|    if (!buf) | ||||
|       return NULL; | ||||
|  | ||||
|    ret = drmBOCreate(pool->fd, NULL, offset, size, NULL, drm_bo_type_fake, | ||||
|                      flags, 0, buf); | ||||
|  | ||||
|    if (ret) { | ||||
|       free(buf); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    buf->virtual = virtual; | ||||
|  | ||||
|    return (void *) buf; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct _DriBufferPool * | ||||
| driDRMStaticPoolInit(int fd) | ||||
| { | ||||
|    struct _DriBufferPool *pool; | ||||
|  | ||||
|    pool = (struct _DriBufferPool *) malloc(sizeof(*pool)); | ||||
|  | ||||
|    if (!pool) | ||||
|       return NULL; | ||||
|  | ||||
|    pool->fd = fd; | ||||
|    pool->map = &pool_map; | ||||
|    pool->unmap = &pool_unmap; | ||||
|    pool->destroy = &pool_destroy; | ||||
|    pool->offset = &pool_offset; | ||||
|    pool->flags = &pool_flags; | ||||
|    pool->size = &pool_size; | ||||
|    pool->create = NULL; | ||||
|    pool->fence = &pool_fence; | ||||
|    pool->kernel = &pool_kernel; | ||||
|    pool->validate = NULL; | ||||
|    pool->setstatic = &pool_setstatic; | ||||
|    pool->waitIdle = &pool_waitIdle; | ||||
|    pool->takeDown = &pool_takedown; | ||||
|    pool->data = NULL; | ||||
|    return pool; | ||||
| } | ||||
| @@ -403,8 +403,9 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) | ||||
|     __DRIcontextPrivate *pcp = pdp->driContextPriv; | ||||
|      | ||||
|     if (!pcp || (pdp != pcp->driDrawablePriv)) { | ||||
| 	/* ERROR!!! */ | ||||
| 	return; | ||||
| 	/* ERROR!!!  | ||||
| 	 * ..but we must ignore it. There can be many contexts bound to a drawable. | ||||
| 	 */ | ||||
|     } | ||||
|  | ||||
|     psp = pdp->driScreenPriv; | ||||
| @@ -435,6 +436,7 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) | ||||
| 	/* Error -- eg the window may have been destroyed.  Keep going | ||||
| 	 * with no cliprects. | ||||
| 	 */ | ||||
|         fprintf(stderr, "Drawable destroyed"); | ||||
|         pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */ | ||||
| 	pdp->numClipRects = 0; | ||||
| 	pdp->pClipRects = NULL; | ||||
| @@ -841,7 +843,7 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv | ||||
| 	(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX); | ||||
| 	(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize); | ||||
| 	_mesa_free(psp->pDevPriv); | ||||
| 	(void)drmClose(psp->fd); | ||||
| 	(void)drmCloseOnce(psp->fd); | ||||
| 	if ( psp->modes != NULL ) { | ||||
| 	    (*dri_interface->destroyContextModes)( psp->modes ); | ||||
| 	} | ||||
|   | ||||
| @@ -87,15 +87,15 @@ typedef struct __DRIutilversionRec2    __DRIutilversion2; | ||||
| #define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp)                            \ | ||||
| do {                                                                    \ | ||||
|     while (*(pdp->pStamp) != pdp->lastStamp) {                          \ | ||||
| 	DRM_UNLOCK(psp->fd, &psp->pSAREA->lock,                         \ | ||||
| 		   pdp->driContextPriv->hHWContext);                    \ | ||||
|         register unsigned int hwContext = psp->pSAREA->lock.lock &      \ | ||||
| 		     ~(DRM_LOCK_HELD | DRM_LOCK_CONT);                  \ | ||||
| 	DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, hwContext);             \ | ||||
|                                                                         \ | ||||
| 	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);     \ | ||||
| 	DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \ | ||||
| 	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);   \ | ||||
|                                                                         \ | ||||
| 	DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock,                     \ | ||||
| 		       pdp->driContextPriv->hHWContext);                \ | ||||
| 	DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, hwContext);         \ | ||||
|     }                                                                   \ | ||||
| } while (0) | ||||
|  | ||||
|   | ||||
| @@ -7,16 +7,6 @@ LIBNAME = i915_dri.so | ||||
| MINIGLX_SOURCES = server/intel_dri.c | ||||
|  | ||||
| DRIVER_SOURCES = \ | ||||
| 	i915_context.c \ | ||||
| 	i915_debug.c \ | ||||
| 	i915_fragprog.c \ | ||||
| 	i915_metaops.c \ | ||||
| 	i915_program.c \ | ||||
| 	i915_state.c \ | ||||
| 	i915_tex.c \ | ||||
| 	i915_texprog.c \ | ||||
| 	i915_texstate.c \ | ||||
| 	i915_vtbl.c \ | ||||
| 	i830_context.c \ | ||||
| 	i830_metaops.c \ | ||||
| 	i830_state.c \ | ||||
| @@ -24,19 +14,43 @@ DRIVER_SOURCES = \ | ||||
| 	i830_tex.c \ | ||||
| 	i830_texstate.c \ | ||||
| 	i830_vtbl.c \ | ||||
| 	intel_render.c \ | ||||
| 	intel_regions.c \ | ||||
| 	intel_buffer_objects.c \ | ||||
| 	intel_batchbuffer.c \ | ||||
| 	intel_mipmap_tree.c \ | ||||
| 	i915_tex_layout.c \ | ||||
| 	intel_tex_image.c \ | ||||
| 	intel_tex_subimage.c \ | ||||
| 	intel_tex_copy.c \ | ||||
| 	intel_tex_validate.c \ | ||||
| 	intel_tex_format.c \ | ||||
| 	intel_tex.c \ | ||||
| 	intel_pixel.c \ | ||||
| 	intel_pixel_copy.c \ | ||||
| 	intel_pixel_read.c \ | ||||
| 	intel_pixel_draw.c \ | ||||
| 	intel_buffers.c \ | ||||
| 	intel_blit.c \ | ||||
| 	i915_tex.c \ | ||||
| 	i915_texstate.c \ | ||||
| 	i915_context.c \ | ||||
| 	i915_debug.c \ | ||||
| 	i915_fragprog.c \ | ||||
| 	i915_metaops.c \ | ||||
| 	i915_program.c \ | ||||
| 	i915_state.c \ | ||||
| 	i915_vtbl.c \ | ||||
| 	intel_context.c \ | ||||
| 	intel_ioctl.c \ | ||||
| 	intel_pixel.c \ | ||||
| 	intel_render.c \ | ||||
| 	intel_rotate.c \ | ||||
| 	intel_screen.c \ | ||||
| 	intel_span.c \ | ||||
| 	intel_state.c \ | ||||
| 	intel_tex.c \ | ||||
| 	intel_texmem.c \ | ||||
| 	intel_tris.c  | ||||
|  | ||||
| 	intel_tris.c \ | ||||
| 	intel_fbo.c \ | ||||
| 	intel_depthstencil.c \ | ||||
| 	intel_batchpool.c | ||||
| C_SOURCES = \ | ||||
| 	$(COMMON_SOURCES) \ | ||||
| 	$(DRIVER_SOURCES) | ||||
|   | ||||
| @@ -38,14 +38,14 @@ | ||||
|  * Mesa's Driver Functions | ||||
|  ***************************************/ | ||||
|  | ||||
| static const struct dri_extension i830_extensions[] = | ||||
| { | ||||
| static const struct dri_extension i830_extensions[] = { | ||||
|    {"GL_ARB_texture_env_crossbar", NULL}, | ||||
|    {NULL, NULL} | ||||
| }; | ||||
|  | ||||
|  | ||||
| static void i830InitDriverFunctions( struct dd_function_table *functions ) | ||||
| static void | ||||
| i830InitDriverFunctions(struct dd_function_table *functions) | ||||
| { | ||||
|    intelInitDriverFunctions(functions); | ||||
|    i830InitStateFuncs(functions); | ||||
| @@ -53,16 +53,17 @@ static void i830InitDriverFunctions( struct dd_function_table *functions ) | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean i830CreateContext( const __GLcontextModes *mesaVis, | ||||
| GLboolean | ||||
| i830CreateContext(const __GLcontextModes * mesaVis, | ||||
|                   __DRIcontextPrivate * driContextPriv, | ||||
|                   void *sharedContextPrivate) | ||||
| { | ||||
|    struct dd_function_table functions; | ||||
|    i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context); | ||||
|    intelContextPtr intel = &i830->intel; | ||||
|    struct i830_context *i830 = CALLOC_STRUCT(i830_context); | ||||
|    struct intel_context *intel = &i830->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLuint i; | ||||
|    if (!i830) return GL_FALSE; | ||||
|    if (!i830) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    i830InitVtbl(i830); | ||||
|    i830InitDriverFunctions(&functions); | ||||
| @@ -77,34 +78,14 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis, | ||||
|    intel->ctx.Const.MaxTextureImageUnits = I830_TEX_UNITS; | ||||
|    intel->ctx.Const.MaxTextureCoordUnits = I830_TEX_UNITS; | ||||
|  | ||||
|    intel->nr_heaps = 1; | ||||
|    intel->texture_heaps[0] =  | ||||
|       driCreateTextureHeap( 0, intel, | ||||
| 			    intel->intelScreen->tex.size, | ||||
| 			    12, | ||||
| 			    I830_NR_TEX_REGIONS, | ||||
| 			    intel->sarea->texList, | ||||
| 			    (unsigned *) & intel->sarea->texAge, | ||||
| 			    & intel->swapped, | ||||
| 			    sizeof( struct i830_texture_object ), | ||||
| 			    (destroy_texture_object_t *)intelDestroyTexObj ); | ||||
|  | ||||
|    /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly | ||||
|     * FIXME: packed, but they're not in Intel graphics hardware. | ||||
|    /* Advertise the full hardware capabilities.  The new memory | ||||
|     * manager should cope much better with overload situations: | ||||
|     */ | ||||
|    intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS; | ||||
|    i = driQueryOptioni( &intel->intelScreen->optionCache, "allow_large_textures"); | ||||
|    driCalculateMaxTextureLevels( intel->texture_heaps, | ||||
| 				 intel->nr_heaps, | ||||
| 				 &intel->ctx.Const, | ||||
| 				 4, | ||||
| 				 11, /* max 2D texture size is 2048x2048 */ | ||||
| 				 8,  /* max 3D texture size is 256^3 */ | ||||
| 				 10, /* max CUBE texture size is 1024x1024 */ | ||||
| 				 11, /* max RECT. supported */ | ||||
| 				 12, | ||||
| 				 GL_FALSE, | ||||
| 				 i ); | ||||
|    ctx->Const.MaxTextureLevels = 12; | ||||
|    ctx->Const.Max3DTextureLevels = 9; | ||||
|    ctx->Const.MaxCubeTextureLevels = 11; | ||||
|    ctx->Const.MaxTextureRectSize = (1 << 11); | ||||
|    ctx->Const.MaxTextureUnits = I830_TEX_UNITS; | ||||
|  | ||||
|    _tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12, | ||||
|                       18 * sizeof(GLfloat)); | ||||
| @@ -114,11 +95,10 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis, | ||||
|    driInitExtensions(ctx, i830_extensions, GL_FALSE); | ||||
|  | ||||
|    i830InitState(i830); | ||||
|  | ||||
|    i830InitMetaFuncs(i830); | ||||
|  | ||||
|    _tnl_allow_vertex_fog(ctx, 1); | ||||
|    _tnl_allow_pixel_fog(ctx, 0); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -39,6 +39,7 @@ | ||||
| #define I830_UPLOAD_CTX              0x1 | ||||
| #define I830_UPLOAD_BUFFERS          0x2 | ||||
| #define I830_UPLOAD_STIPPLE          0x4 | ||||
| #define I830_UPLOAD_INVARIENT        0x8 | ||||
| #define I830_UPLOAD_TEX(i)           (0x10<<(i)) | ||||
| #define I830_UPLOAD_TEXBLEND(i)      (0x100<<(i)) | ||||
| #define I830_UPLOAD_TEX_ALL          (0x0f0) | ||||
| @@ -48,17 +49,15 @@ | ||||
|  */ | ||||
| #define I830_DESTREG_CBUFADDR0 0 | ||||
| #define I830_DESTREG_CBUFADDR1 1 | ||||
| #define I830_DESTREG_CBUFADDR2 2 | ||||
| #define I830_DESTREG_DBUFADDR0 3 | ||||
| #define I830_DESTREG_DBUFADDR1 4 | ||||
| #define I830_DESTREG_DBUFADDR2 5 | ||||
| #define I830_DESTREG_DV0 6 | ||||
| #define I830_DESTREG_DV1 7 | ||||
| #define I830_DESTREG_SENABLE 8 | ||||
| #define I830_DESTREG_SR0 9 | ||||
| #define I830_DESTREG_SR1 10 | ||||
| #define I830_DESTREG_SR2 11 | ||||
| #define I830_DEST_SETUP_SIZE 12 | ||||
| #define I830_DESTREG_DBUFADDR0 2 | ||||
| #define I830_DESTREG_DBUFADDR1 3 | ||||
| #define I830_DESTREG_DV0 4 | ||||
| #define I830_DESTREG_DV1 5 | ||||
| #define I830_DESTREG_SENABLE 6 | ||||
| #define I830_DESTREG_SR0 7 | ||||
| #define I830_DESTREG_SR1 8 | ||||
| #define I830_DESTREG_SR2 9 | ||||
| #define I830_DEST_SETUP_SIZE 10 | ||||
|  | ||||
| #define I830_CTXREG_STATE1		0 | ||||
| #define I830_CTXREG_STATE2		1 | ||||
| @@ -84,14 +83,13 @@ | ||||
| #define I830_STP_SETUP_SIZE    2 | ||||
|  | ||||
| #define I830_TEXREG_TM0LI      0        /* load immediate 2 texture map n */ | ||||
| #define I830_TEXREG_TM0S0      1 | ||||
| #define I830_TEXREG_TM0S1      2 | ||||
| #define I830_TEXREG_TM0S2      3 | ||||
| #define I830_TEXREG_TM0S3      4 | ||||
| #define I830_TEXREG_TM0S4      5 | ||||
| #define I830_TEXREG_MCS	       6	/* _3DSTATE_MAP_COORD_SETS */ | ||||
| #define I830_TEXREG_CUBE       7	/* _3DSTATE_MAP_SUBE */ | ||||
| #define I830_TEX_SETUP_SIZE    8 | ||||
| #define I830_TEXREG_TM0S1      1 | ||||
| #define I830_TEXREG_TM0S2      2 | ||||
| #define I830_TEXREG_TM0S3      3 | ||||
| #define I830_TEXREG_TM0S4      4 | ||||
| #define I830_TEXREG_MCS	       5        /* _3DSTATE_MAP_COORD_SETS */ | ||||
| #define I830_TEXREG_CUBE       6        /* _3DSTATE_MAP_SUBE */ | ||||
| #define I830_TEX_SETUP_SIZE    7 | ||||
|  | ||||
| #define I830_TEXBLEND_SIZE	12      /* (4 args + op) * 2 + COLOR_FACTOR */ | ||||
|  | ||||
| @@ -103,13 +101,25 @@ struct i830_texture_object | ||||
|  | ||||
| #define I830_TEX_UNITS 4 | ||||
|  | ||||
| struct i830_hw_state { | ||||
| struct i830_hw_state | ||||
| { | ||||
|    GLuint Ctx[I830_CTX_SETUP_SIZE]; | ||||
|    GLuint Buffer[I830_DEST_SETUP_SIZE]; | ||||
|    GLuint Stipple[I830_STP_SETUP_SIZE]; | ||||
|    GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE]; | ||||
|    GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE]; | ||||
|    GLuint TexBlendWordsUsed[I830_TEX_UNITS]; | ||||
|  | ||||
|    struct intel_region *draw_region; | ||||
|    struct intel_region *depth_region; | ||||
|  | ||||
|    /* Regions aren't actually that appropriate here as the memory may | ||||
|     * be from a PBO or FBO.  Just use the buffer id.  Will have to do | ||||
|     * this for draw and depth for FBO's... | ||||
|     */ | ||||
|    struct _DriBufferObject *tex_buffer[I830_TEX_UNITS]; | ||||
|    GLuint tex_offset[I830_TEX_UNITS]; | ||||
|  | ||||
|    GLuint emitted;              /* I810_UPLOAD_* */ | ||||
|    GLuint active; | ||||
| }; | ||||
| @@ -118,15 +128,12 @@ struct i830_context | ||||
| { | ||||
|    struct intel_context intel; | ||||
|  | ||||
|    GLuint lodbias_tm0s3[MAX_TEXTURE_UNITS]; | ||||
|      DECLARE_RENDERINPUTS(last_index_bitset); | ||||
|  | ||||
|    struct i830_hw_state meta, initial, state, *current; | ||||
| }; | ||||
|  | ||||
| typedef struct i830_context *i830ContextPtr; | ||||
| typedef struct i830_texture_object *i830TextureObjectPtr; | ||||
|  | ||||
| #define I830_CONTEXT(ctx)	((i830ContextPtr)(ctx)) | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -147,8 +154,7 @@ do {						\ | ||||
|  | ||||
| /* i830_vtbl.c | ||||
|  */ | ||||
| extern void  | ||||
| i830InitVtbl( i830ContextPtr i830 ); | ||||
| extern void i830InitVtbl(struct i830_context *i830); | ||||
|  | ||||
| /* i830_context.c | ||||
|  */ | ||||
| @@ -159,59 +165,44 @@ i830CreateContext( const __GLcontextModes *mesaVis, | ||||
|  | ||||
| /* i830_tex.c, i830_texstate.c | ||||
|  */ | ||||
| extern void  | ||||
| i830UpdateTextureState( intelContextPtr intel ); | ||||
| extern void i830UpdateTextureState(struct intel_context *intel); | ||||
|  | ||||
| extern void  | ||||
| i830InitTextureFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| extern intelTextureObjectPtr | ||||
| i830AllocTexObj( struct gl_texture_object *tObj ); | ||||
| extern void i830InitTextureFuncs(struct dd_function_table *functions); | ||||
|  | ||||
| /* i830_texblend.c | ||||
|  */ | ||||
| extern GLuint i830SetTexEnvCombine(i830ContextPtr i830, | ||||
|     const struct gl_tex_env_combine_state * combine, GLint blendUnit, | ||||
|      GLuint texel_op, GLuint *state, const GLfloat *factor ); | ||||
| extern GLuint i830SetTexEnvCombine(struct i830_context *i830, | ||||
|                                    const struct gl_tex_env_combine_state | ||||
|                                    *combine, GLint blendUnit, GLuint texel_op, | ||||
|                                    GLuint * state, const GLfloat * factor); | ||||
|  | ||||
| extern void  | ||||
| i830EmitTextureBlend( i830ContextPtr i830 ); | ||||
| extern void i830EmitTextureBlend(struct i830_context *i830); | ||||
|  | ||||
|  | ||||
| /* i830_state.c | ||||
|  */ | ||||
| extern void  | ||||
| i830InitStateFuncs( struct dd_function_table *functions ); | ||||
| extern void i830InitStateFuncs(struct dd_function_table *functions); | ||||
|  | ||||
| extern void  | ||||
| i830EmitState( i830ContextPtr i830 ); | ||||
| extern void i830EmitState(struct i830_context *i830); | ||||
|  | ||||
| extern void  | ||||
| i830InitState( i830ContextPtr i830 ); | ||||
| extern void i830InitState(struct i830_context *i830); | ||||
|  | ||||
| /* i830_metaops.c | ||||
|  */ | ||||
| extern GLboolean | ||||
| i830TryTextureReadPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *pack, | ||||
| 			  GLvoid *pixels ); | ||||
|  | ||||
| extern GLboolean | ||||
| i830TryTextureDrawPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  const GLvoid *pixels ); | ||||
| extern void i830InitMetaFuncs(struct i830_context *i830); | ||||
|  | ||||
| extern void | ||||
| i830ClearWithTris( intelContextPtr intel, GLbitfield mask, | ||||
| 		   GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|  | ||||
| extern void | ||||
| i830RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, | ||||
| i830RotateWindow(struct intel_context *intel, __DRIdrawablePrivate * dPriv, | ||||
|                  GLuint srcBuf); | ||||
|  | ||||
| #endif | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.  These are better-typed than the | ||||
|  * macros used previously: | ||||
|  */ | ||||
| static INLINE struct i830_context * | ||||
| i830_context(GLcontext * ctx) | ||||
| { | ||||
|    return (struct i830_context *) ctx; | ||||
| } | ||||
|  | ||||
| #endif | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -407,7 +407,7 @@ | ||||
| #define LOGICOP_SET			0xf | ||||
| #define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00)) | ||||
| #define ENABLE_STENCIL_TEST_MASK	(1<<17) | ||||
| #define STENCIL_TEST_MASK(x)		((x)<<8) | ||||
| #define STENCIL_TEST_MASK(x)		(((x)&0xff)<<8) | ||||
| #define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff)) | ||||
| #define ENABLE_STENCIL_WRITE_MASK	(1<<16) | ||||
| #define STENCIL_WRITE_MASK(x)		((x)&0xff) | ||||
|   | ||||
| @@ -36,21 +36,23 @@ | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_fbo.h" | ||||
|  | ||||
| #include "i830_context.h" | ||||
| #include "i830_reg.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_STATE | ||||
|  | ||||
| static void | ||||
| i830StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, | ||||
|                         GLuint mask) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|  | ||||
|    mask = mask & 0xff; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, | ||||
|    DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(func), ref, mask); | ||||
|  | ||||
|  | ||||
| @@ -69,10 +71,9 @@ i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
| static void | ||||
| i830StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask); | ||||
|    DBG("%s : mask 0x%x\n", __FUNCTION__, mask); | ||||
|     | ||||
|    mask = mask & 0xff; | ||||
|  | ||||
| @@ -86,16 +87,17 @@ static void | ||||
| i830StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|                       GLenum zpass) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int fop, dfop, dpop; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, | ||||
|    DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(fail), | ||||
|        _mesa_lookup_enum_by_nr(zfail),  | ||||
|        _mesa_lookup_enum_by_nr(zpass)); | ||||
|  | ||||
|    fop = 0; dfop = 0; dpop = 0; | ||||
|    fop = 0; | ||||
|    dfop = 0; | ||||
|    dpop = 0; | ||||
|  | ||||
|    switch (fail) { | ||||
|    case GL_KEEP: | ||||
| @@ -187,13 +189,16 @@ i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|    i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK); | ||||
|    i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_PARMS | | ||||
|                                                STENCIL_FAIL_OP(fop) | | ||||
| 					    STENCIL_PASS_DEPTH_FAIL_OP(dfop) | | ||||
| 					    STENCIL_PASS_DEPTH_PASS_OP(dpop)); | ||||
|                                                STENCIL_PASS_DEPTH_FAIL_OP | ||||
|                                                (dfop) | | ||||
|                                                STENCIL_PASS_DEPTH_PASS_OP | ||||
|                                                (dpop)); | ||||
| } | ||||
|  | ||||
| static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
| static void | ||||
| i830AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|    GLubyte refByte; | ||||
|    GLuint refInt; | ||||
| @@ -219,9 +224,10 @@ static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
|  * This function is substantially different from the old i830-specific driver. | ||||
|  * I'm not sure which is correct. | ||||
|  */ | ||||
| static void i830EvalLogicOpBlendState(GLcontext *ctx) | ||||
| static void | ||||
| i830EvalLogicOpBlendState(GLcontext * ctx) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
| @@ -230,12 +236,14 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx) | ||||
|                                                   ENABLE_LOGIC_OP_MASK); | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | | ||||
|                                                  ENABLE_LOGIC_OP); | ||||
|    } else if (ctx->Color.BlendEnabled) { | ||||
|    } | ||||
|    else if (ctx->Color.BlendEnabled) { | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | | ||||
|                                                   ENABLE_LOGIC_OP_MASK); | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND | | ||||
|                                                  DISABLE_LOGIC_OP); | ||||
|    } else { | ||||
|    } | ||||
|    else { | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | | ||||
|                                                   ENABLE_LOGIC_OP_MASK); | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | | ||||
| @@ -243,13 +251,13 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i830BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| static void | ||||
| i830BlendColor(GLcontext * ctx, const GLfloat color[4]) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    GLubyte r, g, b, a; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); | ||||
|    UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); | ||||
| @@ -257,7 +265,8 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
|    UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|    i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] = (a<<24) | (r<<16) | (g<<8) | b; | ||||
|    i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] = | ||||
|       (a << 24) | (r << 16) | (g << 8) | b; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -266,9 +275,10 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
|  * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) | ||||
|  * change the interpretation of the blend function. | ||||
|  */ | ||||
| static void i830_set_blend_state( GLcontext * ctx ) | ||||
| static void | ||||
| i830_set_blend_state(GLcontext * ctx) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int funcA; | ||||
|    int funcRGB; | ||||
|    int eqnA; | ||||
| @@ -277,7 +287,8 @@ static void i830_set_blend_state( GLcontext * ctx ) | ||||
|    int s1; | ||||
|  | ||||
|  | ||||
|    funcRGB = SRC_BLND_FACT( intel_translate_blend_factor( ctx->Color.BlendSrcRGB ) ) | ||||
|    funcRGB = | ||||
|       SRC_BLND_FACT(intel_translate_blend_factor(ctx->Color.BlendSrcRGB)) | ||||
|       | DST_BLND_FACT(intel_translate_blend_factor(ctx->Color.BlendDstRGB)); | ||||
|  | ||||
|    switch (ctx->Color.BlendEquationRGB) { | ||||
| @@ -361,20 +372,19 @@ static void i830_set_blend_state( GLcontext * ctx ) | ||||
|    i830EvalLogicOpBlendState(ctx); | ||||
|  | ||||
|    if (0) { | ||||
|       fprintf(stderr, "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n", | ||||
| 	      __FUNCTION__, __LINE__, | ||||
| 	      i830->state.Ctx[I830_CTXREG_STATE1], | ||||
|       fprintf(stderr, | ||||
|               "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n", | ||||
|               __FUNCTION__, __LINE__, i830->state.Ctx[I830_CTXREG_STATE1], | ||||
|               i830->state.Ctx[I830_CTXREG_IALPHAB], | ||||
|               (ctx->Color.BlendEnabled) ? "en" : "dis"); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, | ||||
| 				      GLenum modeA)  | ||||
| static void | ||||
| i830BlendEquationSeparate(GLcontext * ctx, GLenum modeRGB, GLenum modeA) | ||||
| { | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|      fprintf(stderr, "%s -> %s, %s\n", __FUNCTION__, | ||||
|    DBG("%s -> %s, %s\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(modeRGB), | ||||
|        _mesa_lookup_enum_by_nr(modeA)); | ||||
|  | ||||
| @@ -384,12 +394,11 @@ static void i830BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,  | ||||
| 				  GLenum dfactorRGB, GLenum sfactorA, | ||||
| 				  GLenum dfactorA ) | ||||
| static void | ||||
| i830BlendFuncSeparate(GLcontext * ctx, GLenum sfactorRGB, | ||||
|                       GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA) | ||||
| { | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|      fprintf(stderr, "%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__, | ||||
|    DBG("%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(sfactorRGB), | ||||
|        _mesa_lookup_enum_by_nr(dfactorRGB), | ||||
|        _mesa_lookup_enum_by_nr(sfactorA), | ||||
| @@ -404,13 +413,13 @@ static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, | ||||
|  | ||||
|  | ||||
|  | ||||
| static void i830DepthFunc(GLcontext *ctx, GLenum func) | ||||
| static void | ||||
| i830DepthFunc(GLcontext * ctx, GLenum func) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|    i830->state.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK; | ||||
| @@ -418,12 +427,12 @@ static void i830DepthFunc(GLcontext *ctx, GLenum func) | ||||
|                                            DEPTH_TEST_FUNC(test)); | ||||
| } | ||||
|  | ||||
| static void i830DepthMask(GLcontext *ctx, GLboolean flag) | ||||
| static void | ||||
| i830DepthMask(GLcontext * ctx, GLboolean flag) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag); | ||||
|    DBG("%s flag (%d)\n", __FUNCTION__, flag); | ||||
|     | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
| @@ -441,9 +450,10 @@ static void i830DepthMask(GLcontext *ctx, GLboolean flag) | ||||
|  * The i830 supports a 4x4 stipple natively, GL wants 32x32. | ||||
|  * Fortunately stipple is usually a repeating pattern. | ||||
|  */ | ||||
| static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| static void | ||||
| i830PolygonStipple(GLcontext * ctx, const GLubyte * mask) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    const GLubyte *m = mask; | ||||
|    GLubyte p[4]; | ||||
|    int i, j, k; | ||||
| @@ -456,10 +466,14 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
|       i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE; | ||||
|    } | ||||
|  | ||||
|    p[0] = mask[12] & 0xf; p[0] |= p[0] << 4; | ||||
|    p[1] = mask[8] & 0xf; p[1] |= p[1] << 4; | ||||
|    p[2] = mask[4] & 0xf; p[2] |= p[2] << 4; | ||||
|    p[3] = mask[0] & 0xf; p[3] |= p[3] << 4; | ||||
|    p[0] = mask[12] & 0xf; | ||||
|    p[0] |= p[0] << 4; | ||||
|    p[1] = mask[8] & 0xf; | ||||
|    p[1] |= p[1] << 4; | ||||
|    p[2] = mask[4] & 0xf; | ||||
|    p[2] |= p[2] << 4; | ||||
|    p[3] = mask[0] & 0xf; | ||||
|    p[3] |= p[3] << 4; | ||||
|  | ||||
|    for (k = 0; k < 8; k++) | ||||
|       for (j = 3; j >= 0; j--) | ||||
| @@ -471,8 +485,7 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
|  | ||||
|    newMask = (((p[0] & 0xf) << 0) | | ||||
|               ((p[1] & 0xf) << 4) | | ||||
| 	      ((p[2] & 0xf) << 8) | | ||||
| 	      ((p[3] & 0xf) << 12)); | ||||
|               ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12)); | ||||
|  | ||||
|  | ||||
|    if (newMask == 0xffff || newMask == 0x0) { | ||||
| @@ -493,48 +506,40 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| /* ============================================================= | ||||
|  * Hardware clipping | ||||
|  */ | ||||
| static void i830Scissor(GLcontext *ctx, GLint x, GLint y,  | ||||
| 			GLsizei w, GLsizei h) | ||||
| static void | ||||
| i830Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = i830->intel.intelScreen; | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int x1, y1, x2, y2; | ||||
|  | ||||
|    if (!i830->intel.driDrawable) | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|  | ||||
|    x1 = x; | ||||
|    y1 = i830->intel.driDrawable->h - (y + h); | ||||
|    y1 = ctx->DrawBuffer->Height - (y + h); | ||||
|    x2 = x + w - 1; | ||||
|    y2 = y1 + h - 1; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__, | ||||
|    DBG("[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__, | ||||
|        x, y, w, h); | ||||
|  | ||||
|    if (x1 < 0) x1 = 0; | ||||
|    if (y1 < 0) y1 = 0; | ||||
|    if (x2 < 0) x2 = 0; | ||||
|    if (y2 < 0) y2 = 0; | ||||
|  | ||||
|    if (x2 >= screen->width) x2 = screen->width-1; | ||||
|    if (y2 >= screen->height) y2 = screen->height-1; | ||||
|    if (x1 >= screen->width) x1 = screen->width-1; | ||||
|    if (y1 >= screen->height) y1 = screen->height-1; | ||||
|  | ||||
|    x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); | ||||
|    x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); | ||||
|    i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); | ||||
|    i830->state.Buffer[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); | ||||
| } | ||||
|  | ||||
| static void i830LogicOp(GLcontext *ctx, GLenum opcode) | ||||
| static void | ||||
| i830LogicOp(GLcontext * ctx, GLenum opcode) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int tmp = intel_translate_logic_op(opcode); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|    i830->state.Ctx[I830_CTXREG_STATE4] &= ~LOGICOP_MASK; | ||||
| @@ -543,13 +548,13 @@ static void i830LogicOp(GLcontext *ctx, GLenum opcode) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
| static void | ||||
| i830CullFaceFrontFace(GLcontext * ctx, GLenum unused) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    GLuint mode; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    if (!ctx->Polygon.CullFlag) { | ||||
|       mode = CULLMODE_NONE; | ||||
| @@ -571,14 +576,14 @@ static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
|    i830->state.Ctx[I830_CTXREG_STATE3] |= ENABLE_CULL_MODE | mode; | ||||
| } | ||||
|  | ||||
| static void i830LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
| static void | ||||
| i830LineWidth(GLcontext * ctx, GLfloat widthf) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int width; | ||||
|    int state5; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    width = (int) (widthf * 2); | ||||
|    CLAMP_SELF(width, 1, 15); | ||||
| @@ -592,13 +597,13 @@ static void i830LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i830PointSize(GLcontext *ctx, GLfloat size) | ||||
| static void | ||||
| i830PointSize(GLcontext * ctx, GLfloat size) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    GLint point_size = (int) size; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|      fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    CLAMP_SELF(point_size, 1, 256); | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
| @@ -612,23 +617,21 @@ static void i830PointSize(GLcontext *ctx, GLfloat size) | ||||
|  * Color masks | ||||
|  */ | ||||
|  | ||||
| static void i830ColorMask(GLcontext *ctx, | ||||
| 			  GLboolean r, GLboolean g, | ||||
| 			  GLboolean b, GLboolean a) | ||||
| static void | ||||
| i830ColorMask(GLcontext * ctx, | ||||
|               GLboolean r, GLboolean g, GLboolean b, GLboolean a) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    GLuint tmp = 0; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); | ||||
|    DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); | ||||
|  | ||||
|    tmp = ((i830->state.Ctx[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) | | ||||
|           ENABLE_COLOR_MASK | | ||||
|           ENABLE_COLOR_WRITE | | ||||
|           ((!r) << WRITEMASK_RED_SHIFT) | | ||||
|           ((!g) << WRITEMASK_GREEN_SHIFT) | | ||||
| 	  ((!b) << WRITEMASK_BLUE_SHIFT) | | ||||
| 	  ((!a) << WRITEMASK_ALPHA_SHIFT)); | ||||
|           ((!b) << WRITEMASK_BLUE_SHIFT) | ((!a) << WRITEMASK_ALPHA_SHIFT)); | ||||
|  | ||||
|    if (tmp != i830->state.Ctx[I830_CTXREG_ENABLES_2]) { | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
| @@ -636,9 +639,10 @@ static void i830ColorMask(GLcontext *ctx, | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void update_specular( GLcontext *ctx ) | ||||
| static void | ||||
| update_specular(GLcontext * ctx) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|    i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK; | ||||
| @@ -649,11 +653,10 @@ static void update_specular( GLcontext *ctx ) | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_SPEC_ADD; | ||||
| } | ||||
|  | ||||
| static void i830LightModelfv(GLcontext *ctx, GLenum pname,  | ||||
| 			     const GLfloat *param) | ||||
| static void | ||||
| i830LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param) | ||||
| { | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { | ||||
|       update_specular(ctx); | ||||
| @@ -662,9 +665,10 @@ static void i830LightModelfv(GLcontext *ctx, GLenum pname, | ||||
|  | ||||
| /* In Mesa 3.5 we can reliably do native flatshading. | ||||
|  */ | ||||
| static void i830ShadeModel(GLcontext *ctx, GLenum mode) | ||||
| static void | ||||
| i830ShadeModel(GLcontext * ctx, GLenum mode) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
|  | ||||
| @@ -673,12 +677,14 @@ static void i830ShadeModel(GLcontext *ctx, GLenum mode) | ||||
|    i830->state.Ctx[I830_CTXREG_STATE3] &= ~SHADE_MODE_MASK; | ||||
|  | ||||
|    if (mode == GL_FLAT) { | ||||
|      i830->state.Ctx[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_FLAT) | | ||||
| 					  FOG_SHADE_MODE(SHADE_MODE_FLAT) | | ||||
| 					  SPEC_SHADE_MODE(SHADE_MODE_FLAT) | | ||||
|       i830->state.Ctx[I830_CTXREG_STATE3] |= | ||||
|          (ALPHA_SHADE_MODE(SHADE_MODE_FLAT) | FOG_SHADE_MODE(SHADE_MODE_FLAT) | ||||
|           | SPEC_SHADE_MODE(SHADE_MODE_FLAT) | | ||||
|           COLOR_SHADE_MODE(SHADE_MODE_FLAT)); | ||||
|    } else { | ||||
|      i830->state.Ctx[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
|    } | ||||
|    else { | ||||
|       i830->state.Ctx[I830_CTXREG_STATE3] |= | ||||
|          (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
|           FOG_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
|           SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
|           COLOR_SHADE_MODE(SHADE_MODE_LINEAR)); | ||||
| @@ -688,12 +694,12 @@ static void i830ShadeModel(GLcontext *ctx, GLenum mode) | ||||
| /* ============================================================= | ||||
|  * Fog | ||||
|  */ | ||||
| static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
| static void | ||||
| i830Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    if (pname == GL_FOG_COLOR) { | ||||
|       GLuint color = (((GLubyte) (ctx->Fog.Color[0] * 255.0F) << 16) | | ||||
| @@ -701,16 +707,18 @@ static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
|                       ((GLubyte) (ctx->Fog.Color[2] * 255.0F) << 0)); | ||||
|  | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|       i830->state.Ctx[I830_CTXREG_FOGCOLOR] = (_3DSTATE_FOG_COLOR_CMD | color); | ||||
|       i830->state.Ctx[I830_CTXREG_FOGCOLOR] = | ||||
|          (_3DSTATE_FOG_COLOR_CMD | color); | ||||
|    } | ||||
| } | ||||
|  | ||||
| /* ============================================================= | ||||
|  */ | ||||
|  | ||||
| static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| static void | ||||
| i830Enable(GLcontext * ctx, GLenum cap, GLboolean state) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    switch (cap) { | ||||
|    case GL_LIGHTING: | ||||
| @@ -770,12 +778,10 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|  | ||||
|       if (state) | ||||
|          i830->state.Buffer[I830_DESTREG_SENABLE] = | ||||
| 	    (_3DSTATE_SCISSOR_ENABLE_CMD | | ||||
| 	     ENABLE_SCISSOR_RECT); | ||||
|             (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); | ||||
|       else | ||||
|          i830->state.Buffer[I830_DESTREG_SENABLE] = | ||||
| 	    (_3DSTATE_SCISSOR_ENABLE_CMD | | ||||
| 	     DISABLE_SCISSOR_RECT); | ||||
|             (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); | ||||
|  | ||||
|       break; | ||||
|  | ||||
| @@ -806,21 +812,33 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|       break; | ||||
|  | ||||
|    case GL_STENCIL_TEST: | ||||
|       if (i830->intel.hw_stencil) { | ||||
|       { | ||||
|          GLboolean hw_stencil = GL_FALSE; | ||||
|          if (ctx->DrawBuffer) { | ||||
|             struct intel_renderbuffer *irbStencil | ||||
|                = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); | ||||
|             hw_stencil = (irbStencil && irbStencil->region); | ||||
|          } | ||||
|          if (hw_stencil) { | ||||
|             I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
|             if (state) { | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE; | ||||
| 	 } else { | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE; | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE; | ||||
|             } | ||||
|       } else { | ||||
|             else { | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_2] &= | ||||
|                   ~ENABLE_STENCIL_WRITE; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_2] |= | ||||
|                   DISABLE_STENCIL_WRITE; | ||||
|             } | ||||
|          } | ||||
|          else { | ||||
|             FALLBACK(&i830->intel, I830_FALLBACK_STENCIL, state); | ||||
|          } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|    case GL_POLYGON_STIPPLE: | ||||
| @@ -829,8 +847,7 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|        * supports it.  Disabled for now. | ||||
|        */ | ||||
|       if (i830->intel.hw_stipple && | ||||
| 	  i830->intel.reduced_primitive == GL_TRIANGLES) | ||||
|       { | ||||
|           i830->intel.reduced_primitive == GL_TRIANGLES) { | ||||
|          I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE); | ||||
|          i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE; | ||||
|          if (state) | ||||
| @@ -844,7 +861,8 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830_init_packets( i830ContextPtr i830 ) | ||||
| static void | ||||
| i830_init_packets(struct i830_context *i830) | ||||
| { | ||||
|    intelScreenPrivate *screen = i830->intel.intelScreen; | ||||
|  | ||||
| @@ -859,15 +877,13 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|                                  DISABLE_TEX_CNTRL_STAGE | | ||||
|                                  TEXOP_SCALE_1X | | ||||
|                                  TEXOP_MODIFY_PARMS | | ||||
| 				  TEXOP_LAST_STAGE | | ||||
| 				  TEXBLENDOP_ARG1); | ||||
|                                  TEXOP_LAST_STAGE | TEXBLENDOP_ARG1); | ||||
|    i830->state.TexBlend[0][1] = (_3DSTATE_MAP_BLEND_OP_CMD(0) | | ||||
|                                  TEXPIPE_ALPHA | | ||||
|                                  ENABLE_TEXOUTPUT_WRT_SEL | | ||||
|                                  TEXOP_OUTPUT_CURRENT | | ||||
|                                  TEXOP_SCALE_1X | | ||||
| 				  TEXOP_MODIFY_PARMS | | ||||
| 				  TEXBLENDOP_ARG1); | ||||
|                                  TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1); | ||||
|    i830->state.TexBlend[0][2] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) | | ||||
|                                  TEXPIPE_COLOR | | ||||
|                                  TEXBLEND_ARG1 | | ||||
| @@ -902,6 +918,7 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|                                              DISABLE_COLOR_BLEND | | ||||
|                                              DISABLE_DEPTH_TEST); | ||||
|  | ||||
| #if 000                         /* XXX all the stencil enable state is set in i830Enable(), right? */ | ||||
|    if (i830->intel.hw_stencil) { | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD | | ||||
|                                                 ENABLE_STENCIL_WRITE | | ||||
| @@ -911,7 +928,10 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|                                                 /* set no color comps disabled */ | ||||
|                                                 ENABLE_COLOR_WRITE | | ||||
|                                                 ENABLE_DEPTH_WRITE); | ||||
|    } else { | ||||
|    } | ||||
|    else | ||||
| #endif | ||||
|    { | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD | | ||||
|                                                 DISABLE_STENCIL_WRITE | | ||||
|                                                 ENABLE_TEX_CACHE | | ||||
| @@ -934,22 +954,21 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|                                           ENABLE_GLOBAL_DEPTH_BIAS | | ||||
|                                           GLOBAL_DEPTH_BIAS(0) | | ||||
|                                           ENABLE_ALPHA_TEST_FUNC | | ||||
| 					  ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) | | ||||
| 					  ALPHA_REF_VALUE(0) ); | ||||
|                                           ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) | ||||
|                                           | ALPHA_REF_VALUE(0)); | ||||
|  | ||||
|    i830->state.Ctx[I830_CTXREG_STATE3] = (_3DSTATE_MODES_3_CMD | | ||||
|                                           ENABLE_DEPTH_TEST_FUNC | | ||||
|                                           DEPTH_TEST_FUNC(COMPAREFUNC_LESS) | | ||||
|                                           ENABLE_ALPHA_SHADE_MODE | | ||||
| 					  ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
| 					  ENABLE_FOG_SHADE_MODE | | ||||
|                                           ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | ||||
|                                           | ENABLE_FOG_SHADE_MODE | | ||||
|                                           FOG_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
|                                           ENABLE_SPEC_SHADE_MODE | | ||||
|                                           SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
|                                           ENABLE_COLOR_SHADE_MODE | | ||||
| 					  COLOR_SHADE_MODE(SHADE_MODE_LINEAR) | | ||||
| 					  ENABLE_CULL_MODE | | ||||
| 					  CULLMODE_NONE); | ||||
|                                           COLOR_SHADE_MODE(SHADE_MODE_LINEAR) | ||||
|                                           | ENABLE_CULL_MODE | CULLMODE_NONE); | ||||
|  | ||||
|    i830->state.Ctx[I830_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD | | ||||
|                                           ENABLE_LOGIC_OP_FUNC | | ||||
| @@ -961,20 +980,19 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|  | ||||
|    i830->state.Ctx[I830_CTXREG_STENCILTST] = (_3DSTATE_STENCIL_TEST_CMD | | ||||
|                                               ENABLE_STENCIL_PARMS | | ||||
| 					      STENCIL_FAIL_OP(STENCILOP_KEEP) | | ||||
| 					      STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_KEEP) | | ||||
| 					      STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_KEEP) | | ||||
|                                               STENCIL_FAIL_OP(STENCILOP_KEEP) | ||||
|                                               | | ||||
|                                               STENCIL_PASS_DEPTH_FAIL_OP | ||||
|                                               (STENCILOP_KEEP) | | ||||
|                                               STENCIL_PASS_DEPTH_PASS_OP | ||||
|                                               (STENCILOP_KEEP) | | ||||
|                                               ENABLE_STENCIL_TEST_FUNC | | ||||
| 					      STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS) | | ||||
|                                               STENCIL_TEST_FUNC | ||||
|                                               (COMPAREFUNC_ALWAYS) | | ||||
|                                               ENABLE_STENCIL_REF_VALUE | | ||||
|                                               STENCIL_REF_VALUE(0)); | ||||
|  | ||||
|    i830->state.Ctx[I830_CTXREG_STATE5] = (_3DSTATE_MODES_5_CMD | | ||||
| 					  FLUSH_TEXTURE_CACHE | | ||||
| 					  ENABLE_SPRITE_POINT_TEX | | ||||
| 					  SPRITE_POINT_TEX_OFF | | ||||
| 					  ENABLE_FIXED_LINE_WIDTH | | ||||
| 					  FIXED_LINE_WIDTH(0x2) | /* 1.0 */ | ||||
|    i830->state.Ctx[I830_CTXREG_STATE5] = (_3DSTATE_MODES_5_CMD | FLUSH_TEXTURE_CACHE | ENABLE_SPRITE_POINT_TEX | SPRITE_POINT_TEX_OFF | ENABLE_FIXED_LINE_WIDTH | FIXED_LINE_WIDTH(0x2) |       /* 1.0 */ | ||||
|                                           ENABLE_FIXED_POINT_WIDTH | | ||||
|                                           FIXED_POINT_WIDTH(1)); | ||||
|  | ||||
| @@ -1001,24 +1019,17 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|    i830->state.Stipple[I830_STPREG_ST0] = _3DSTATE_STIPPLE; | ||||
|  | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR1] =  | ||||
|       (BUF_3D_ID_COLOR_BACK |  | ||||
|        BUF_3D_PITCH(screen->front.pitch) |  /* pitch in bytes */ | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(screen->front.pitch) |     /* pitch in bytes */ | ||||
|                                                  BUF_3D_USE_FENCE); | ||||
|  | ||||
|  | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR1] =  | ||||
|       (BUF_3D_ID_DEPTH | | ||||
|        BUF_3D_PITCH(screen->depth.pitch) |  /* pitch in bytes */ | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | BUF_3D_PITCH(screen->depth.pitch) |  /* pitch in bytes */ | ||||
|                                                  BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; | ||||
|  | ||||
|  | ||||
|    i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; | ||||
|  | ||||
|    switch (screen->fbFormat) { | ||||
|    case DV_PF_555: | ||||
|    case DV_PF_565: | ||||
|       i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) |   /* .5 */ | ||||
|                                               DSTORG_VERT_BIAS(0x8) |   /* .5 */ | ||||
| @@ -1043,7 +1054,8 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i830InitStateFuncs( struct dd_function_table *functions ) | ||||
| void | ||||
| i830InitStateFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|    functions->AlphaFunc = i830AlphaFunc; | ||||
|    functions->BlendColor = i830BlendColor; | ||||
| @@ -1068,7 +1080,8 @@ void i830InitStateFuncs( struct dd_function_table *functions ) | ||||
|    functions->StencilOpSeparate = i830StencilOpSeparate; | ||||
| } | ||||
|  | ||||
| void i830InitState( i830ContextPtr i830 ) | ||||
| void | ||||
| i830InitState(struct i830_context *i830) | ||||
| { | ||||
|    GLcontext *ctx = &i830->intel.ctx; | ||||
|  | ||||
| @@ -1080,13 +1093,8 @@ void i830InitState( i830ContextPtr i830 ) | ||||
|  | ||||
|    i830->current = &i830->state; | ||||
|    i830->state.emitted = 0; | ||||
|    i830->state.active = (I830_UPLOAD_TEXBLEND(0) | | ||||
|    i830->state.active = (I830_UPLOAD_INVARIENT | | ||||
|                          I830_UPLOAD_TEXBLEND(0) | | ||||
|                          I830_UPLOAD_STIPPLE | | ||||
| 			 I830_UPLOAD_CTX | | ||||
| 			 I830_UPLOAD_BUFFERS); | ||||
|                          I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -45,261 +45,13 @@ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Set the texture wrap modes. | ||||
|  *  | ||||
|  * The i830M (and related graphics cores) do not support GL_CLAMP.  The Intel | ||||
|  * drivers for "other operating systems" implement GL_CLAMP as | ||||
|  * GL_CLAMP_TO_EDGE, so the same is done here. | ||||
|  *  | ||||
|  * \param t Texture object whose wrap modes are to be set | ||||
|  * \param swrap Wrap mode for the \a s texture coordinate | ||||
|  * \param twrap Wrap mode for the \a t texture coordinate | ||||
|  */ | ||||
| static void i830SetTexWrapping(i830TextureObjectPtr tex, | ||||
| 			       GLenum swrap,  | ||||
| 			       GLenum twrap) | ||||
| { | ||||
|    tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK); | ||||
|  | ||||
|    switch( swrap ) { | ||||
|    case GL_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP); | ||||
|       break; | ||||
|    case GL_CLAMP: | ||||
|    case GL_CLAMP_TO_EDGE: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP); | ||||
|       break; | ||||
|    case GL_CLAMP_TO_BORDER: | ||||
|       tex->Setup[I830_TEXREG_MCS] |=  | ||||
| 			TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER); | ||||
|       break; | ||||
|    case GL_MIRRORED_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |=  | ||||
| 			TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR); | ||||
|       break; | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    switch( twrap ) { | ||||
|    case GL_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP); | ||||
|       break; | ||||
|    case GL_CLAMP: | ||||
|    case GL_CLAMP_TO_EDGE: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP); | ||||
|       break; | ||||
|    case GL_CLAMP_TO_BORDER: | ||||
|       tex->Setup[I830_TEXREG_MCS] |=  | ||||
| 			TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER); | ||||
|       break; | ||||
|    case GL_MIRRORED_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= | ||||
| 			TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR); | ||||
|       break; | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Set the texture magnification and minification modes. | ||||
|  *  | ||||
|  * \param t Texture whose filter modes are to be set | ||||
|  * \param minf Texture minification mode | ||||
|  * \param magf Texture magnification mode | ||||
|  * \param bias LOD bias for this texture unit. | ||||
|  */ | ||||
|  | ||||
| static void i830SetTexFilter( i830TextureObjectPtr t, GLenum minf, GLenum magf, | ||||
| 			      GLfloat maxanisotropy ) | ||||
| { | ||||
|    int minFilt = 0, mipFilt = 0, magFilt = 0; | ||||
|  | ||||
|    if(INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if ( maxanisotropy > 1.0 ) { | ||||
|       minFilt = FILTER_ANISOTROPIC; | ||||
|       magFilt = FILTER_ANISOTROPIC; | ||||
|    } | ||||
|    else { | ||||
|       switch (minf) { | ||||
|       case GL_NEAREST: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_NONE; | ||||
| 	 break; | ||||
|       case GL_LINEAR: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_NONE; | ||||
| 	 break; | ||||
|       case GL_NEAREST_MIPMAP_NEAREST: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_LINEAR_MIPMAP_NEAREST: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_NEAREST_MIPMAP_LINEAR: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_LINEAR; | ||||
| 	 break; | ||||
|       case GL_LINEAR_MIPMAP_LINEAR: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_LINEAR; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 break; | ||||
|       } | ||||
|  | ||||
|       switch (magf) { | ||||
|       case GL_NEAREST: | ||||
| 	 magFilt = FILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_LINEAR: | ||||
| 	 magFilt = FILTER_LINEAR; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 break; | ||||
|       }   | ||||
|    } | ||||
|  | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_FILTER_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIP_FILTER_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAG_FILTER_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | | ||||
| 				   (mipFilt << TM0S3_MIP_FILTER_SHIFT) | | ||||
| 				   (magFilt << TM0S3_MAG_FILTER_SHIFT)); | ||||
| } | ||||
|  | ||||
| static void i830SetTexBorderColor(i830TextureObjectPtr t, GLubyte color[4]) | ||||
| { | ||||
|    if(INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|     t->Setup[I830_TEXREG_TM0S4] =  | ||||
|         INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Allocate space for and load the mesa images into the texture memory block. | ||||
|  * This will happen before drawing with a new texture, or drawing with a | ||||
|  * texture after it was swapped out or teximaged again. | ||||
|  */ | ||||
|  | ||||
| intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj ) | ||||
| { | ||||
|    i830TextureObjectPtr t = CALLOC_STRUCT( i830_texture_object ); | ||||
|    if ( !t )  | ||||
|       return NULL; | ||||
|  | ||||
|    texObj->DriverData = t; | ||||
|    t->intel.base.tObj = texObj; | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
|    make_empty_list( &t->intel.base ); | ||||
|  | ||||
|    t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */ | ||||
|    t->Setup[I830_TEXREG_TM0S0] = 0; | ||||
|    t->Setup[I830_TEXREG_TM0S1] = 0; | ||||
|    t->Setup[I830_TEXREG_TM0S2] = 0; | ||||
|    t->Setup[I830_TEXREG_TM0S3] = 0; | ||||
|    t->Setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | | ||||
| 				MAP_UNIT(0) | | ||||
| 				ENABLE_TEXCOORD_PARAMS | | ||||
| 				TEXCOORDS_ARE_NORMAL | | ||||
| 				TEXCOORDTYPE_CARTESIAN | | ||||
| 				ENABLE_ADDR_V_CNTL | | ||||
| 				TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) | | ||||
| 				ENABLE_ADDR_U_CNTL | | ||||
| 				TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP)); | ||||
|  | ||||
|     | ||||
|    i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT ); | ||||
|    i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter,  | ||||
| 		     texObj->MaxAnisotropy ); | ||||
|    i830SetTexBorderColor( t, texObj->_BorderChan ); | ||||
|  | ||||
|    return &t->intel; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830TexParameter( GLcontext *ctx, GLenum target, | ||||
| 			      struct gl_texture_object *tObj, | ||||
| 			      GLenum pname, const GLfloat *params ) | ||||
| { | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData; | ||||
|    if (!t) | ||||
|       return; | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_MIN_FILTER: | ||||
|    case GL_TEXTURE_MAG_FILTER: | ||||
|    case GL_TEXTURE_MAX_ANISOTROPY_EXT: | ||||
|       i830SetTexFilter( t, tObj->MinFilter, tObj->MagFilter, | ||||
| 			tObj->MaxAnisotropy); | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_WRAP_S: | ||||
|    case GL_TEXTURE_WRAP_T: | ||||
|       i830SetTexWrapping( t, tObj->WrapS, tObj->WrapT ); | ||||
|       break; | ||||
|    | ||||
|    case GL_TEXTURE_BORDER_COLOR: | ||||
|       i830SetTexBorderColor( t, tObj->_BorderChan ); | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_BASE_LEVEL: | ||||
|    case GL_TEXTURE_MAX_LEVEL: | ||||
|    case GL_TEXTURE_MIN_LOD: | ||||
|    case GL_TEXTURE_MAX_LOD: | ||||
|       /* The i830 and its successors can do a lot of this without | ||||
|        * reloading the textures.  A project for someone? | ||||
|        */ | ||||
|       intelFlush( ctx ); | ||||
|       driSwapOutTextureObject( (driTextureObject *) t ); | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830TexEnv( GLcontext *ctx, GLenum target,  | ||||
| static void | ||||
| i830TexEnv(GLcontext * ctx, GLenum target, | ||||
|            GLenum pname, const GLfloat * param) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    GLuint unit = ctx->Texture.CurrentUnit; | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_ENV_COLOR: | ||||
| #if 0 | ||||
|    { | ||||
|       GLubyte r, g, b, a; | ||||
|       GLuint col; | ||||
|        | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(r, param[RCOMP]); | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(g, param[GCOMP]); | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(b, param[BCOMP]); | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(a, param[ACOMP]); | ||||
|  | ||||
|       col = ((a << 24) | (r << 16) | (g << 8) | b); | ||||
|  | ||||
|       if (col != i830->state.TexEnv[unit][I830_TEXENVREG_COL1]) { | ||||
| 	 I830_STATECHANGE(i830, I830_UPLOAD_TEXENV); | ||||
| 	 i830->state.TexEnv[unit][I830_TEXENVREG_COL1] = col; | ||||
|       } | ||||
|  | ||||
|       break; | ||||
|    } | ||||
| #endif | ||||
|    case GL_TEXTURE_ENV_MODE: | ||||
|    case GL_COMBINE_RGB: | ||||
|    case GL_COMBINE_ALPHA: | ||||
| @@ -320,12 +72,15 @@ static void i830TexEnv( GLcontext *ctx, GLenum target, | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_LOD_BIAS:{ | ||||
|          struct i830_context *i830 = i830_context(ctx); | ||||
|          GLuint unit = ctx->Texture.CurrentUnit; | ||||
|          int b = (int) ((*param) * 16.0); | ||||
|       if (b > 63) b = 63; | ||||
|       if (b < -64) b = -64; | ||||
|          if (b > 63) | ||||
|             b = 63; | ||||
|          if (b < -64) | ||||
|             b = -64; | ||||
|          I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK; | ||||
|       i830->state.Tex[unit][I830_TEXREG_TM0S3] |=  | ||||
|          i830->lodbias_tm0s3[unit] = | ||||
|             ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK); | ||||
|          break; | ||||
|       } | ||||
| @@ -335,22 +90,11 @@ static void i830TexEnv( GLcontext *ctx, GLenum target, | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i830BindTexture( GLcontext *ctx, GLenum target, | ||||
| 			    struct gl_texture_object *texObj ) | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| i830InitTextureFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|    i830TextureObjectPtr tex; | ||||
|     | ||||
|    if (!texObj->DriverData) | ||||
|       i830AllocTexObj( texObj ); | ||||
|     | ||||
|    tex = (i830TextureObjectPtr)texObj->DriverData; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void i830InitTextureFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->BindTexture 		= i830BindTexture; | ||||
|    functions->TexEnv = i830TexEnv; | ||||
|    functions->TexParameter              = i830TexParameter; | ||||
| } | ||||
|   | ||||
| @@ -46,38 +46,34 @@ | ||||
| /* ================================================================ | ||||
|  * Texture combine functions | ||||
|  */ | ||||
| static GLuint pass_through( GLuint *state, GLuint blendUnit ) | ||||
| static GLuint | ||||
| pass_through(GLuint * state, GLuint blendUnit) | ||||
| { | ||||
|    state[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) | | ||||
|                TEXPIPE_COLOR | | ||||
|                ENABLE_TEXOUTPUT_WRT_SEL | | ||||
|                TEXOP_OUTPUT_CURRENT | | ||||
|                DISABLE_TEX_CNTRL_STAGE | | ||||
| 	       TEXOP_SCALE_1X | | ||||
| 	       TEXOP_MODIFY_PARMS | | ||||
| 	       TEXBLENDOP_ARG1); | ||||
|                TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1); | ||||
|    state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) | | ||||
|                TEXPIPE_ALPHA | | ||||
|                ENABLE_TEXOUTPUT_WRT_SEL | | ||||
|                TEXOP_OUTPUT_CURRENT | | ||||
| 	       TEXOP_SCALE_1X | | ||||
| 	       TEXOP_MODIFY_PARMS | | ||||
| 	       TEXBLENDOP_ARG1); | ||||
|                TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1); | ||||
|    state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) | | ||||
|                TEXPIPE_COLOR | | ||||
|                TEXBLEND_ARG1 | | ||||
| 	       TEXBLENDARG_MODIFY_PARMS | | ||||
| 	       TEXBLENDARG_CURRENT); | ||||
|                TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT); | ||||
|    state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) | | ||||
|                TEXPIPE_ALPHA | | ||||
|                TEXBLEND_ARG1 | | ||||
| 	       TEXBLENDARG_MODIFY_PARMS | | ||||
| 	       TEXBLENDARG_CURRENT); | ||||
|                TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT); | ||||
|  | ||||
|    return 4; | ||||
| } | ||||
|  | ||||
| static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count,  | ||||
| static GLuint | ||||
| emit_factor(GLuint blendUnit, GLuint * state, GLuint count, | ||||
|             const GLfloat * factor) | ||||
| { | ||||
|    GLubyte r, g, b, a; | ||||
| @@ -101,14 +97,20 @@ static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ GLuint GetTexelOp(GLint unit) | ||||
| static INLINE GLuint | ||||
| GetTexelOp(GLint unit) | ||||
| { | ||||
|    switch (unit) { | ||||
|    case 0: return TEXBLENDARG_TEXEL0; | ||||
|    case 1: return TEXBLENDARG_TEXEL1; | ||||
|    case 2: return TEXBLENDARG_TEXEL2; | ||||
|    case 3: return TEXBLENDARG_TEXEL3; | ||||
|    default: return TEXBLENDARG_TEXEL0; | ||||
|    case 0: | ||||
|       return TEXBLENDARG_TEXEL0; | ||||
|    case 1: | ||||
|       return TEXBLENDARG_TEXEL1; | ||||
|    case 2: | ||||
|       return TEXBLENDARG_TEXEL2; | ||||
|    case 3: | ||||
|       return TEXBLENDARG_TEXEL3; | ||||
|    default: | ||||
|       return TEXBLENDARG_TEXEL0; | ||||
|    } | ||||
| } | ||||
|  | ||||
| @@ -132,12 +134,10 @@ static __inline__ GLuint GetTexelOp(GLint unit) | ||||
|  * partial support for the extension? | ||||
|  */ | ||||
| GLuint | ||||
| i830SetTexEnvCombine(i830ContextPtr i830, | ||||
| i830SetTexEnvCombine(struct i830_context * i830, | ||||
|                      const struct gl_tex_env_combine_state * combine, | ||||
|                      GLint blendUnit, | ||||
| 		     GLuint texel_op, | ||||
| 		     GLuint *state, | ||||
| 		     const GLfloat *factor ) | ||||
|                      GLuint texel_op, GLuint * state, const GLfloat * factor) | ||||
| { | ||||
|    const GLuint numColorArgs = combine->_NumArgsRGB; | ||||
|    const GLuint numAlphaArgs = combine->_NumArgsA; | ||||
| @@ -259,8 +259,7 @@ i830SetTexEnvCombine(i830ContextPtr i830, | ||||
|          args_RGB[i] |= TEXBLENDARG_REPLICATE_ALPHA; | ||||
|          break; | ||||
|       case GL_ONE_MINUS_SRC_ALPHA: | ||||
| 	 args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA |  | ||||
| 			 TEXBLENDARG_INV_ARG); | ||||
|          args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA | TEXBLENDARG_INV_ARG); | ||||
|          break; | ||||
|       default: | ||||
|          return pass_through(state, blendUnit); | ||||
| @@ -366,15 +365,11 @@ i830SetTexEnvCombine(i830ContextPtr i830, | ||||
|                     TEXPIPE_COLOR | | ||||
|                     ENABLE_TEXOUTPUT_WRT_SEL | | ||||
|                     TEXOP_OUTPUT_CURRENT | | ||||
| 		    DISABLE_TEX_CNTRL_STAGE | | ||||
| 		    TEXOP_MODIFY_PARMS | | ||||
| 		    blendop); | ||||
|                     DISABLE_TEX_CNTRL_STAGE | TEXOP_MODIFY_PARMS | blendop); | ||||
|    state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) | | ||||
|                     TEXPIPE_ALPHA | | ||||
|                     ENABLE_TEXOUTPUT_WRT_SEL | | ||||
| 		    TEXOP_OUTPUT_CURRENT | | ||||
| 		    TEXOP_MODIFY_PARMS | | ||||
| 		    ablendop); | ||||
|                     TEXOP_OUTPUT_CURRENT | TEXOP_MODIFY_PARMS | ablendop); | ||||
|  | ||||
|    for (i = 0; i < numColorArgs; i++) { | ||||
|       state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) | | ||||
| @@ -394,26 +389,28 @@ i830SetTexEnvCombine(i830ContextPtr i830, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit, | ||||
| static void | ||||
| emit_texblend(struct i830_context *i830, GLuint unit, GLuint blendUnit, | ||||
|               GLboolean last_stage) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit]; | ||||
|    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz; | ||||
|  | ||||
|  | ||||
|    if (0) fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit); | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit); | ||||
|  | ||||
|    /* Update i830->state.TexBlend | ||||
|     */ | ||||
|    tmp_sz = i830SetTexEnvCombine(i830, texUnit->_CurrentCombine, blendUnit, | ||||
| 				 GetTexelOp(unit), tmp, | ||||
| 				 texUnit->EnvColor ); | ||||
|                                  GetTexelOp(unit), tmp, texUnit->EnvColor); | ||||
|  | ||||
|    if (last_stage) | ||||
|       tmp[0] |= TEXOP_LAST_STAGE; | ||||
|  | ||||
|    if (tmp_sz != i830->state.TexBlendWordsUsed[blendUnit] || | ||||
|        memcmp( tmp, i830->state.TexBlend[blendUnit], tmp_sz * sizeof(GLuint))) { | ||||
|        memcmp(tmp, i830->state.TexBlend[blendUnit], | ||||
|               tmp_sz * sizeof(GLuint))) { | ||||
|  | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(blendUnit)); | ||||
|       memcpy(i830->state.TexBlend[blendUnit], tmp, tmp_sz * sizeof(GLuint)); | ||||
| @@ -423,7 +420,8 @@ static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit, | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), GL_TRUE); | ||||
| } | ||||
|  | ||||
| static void emit_passthrough( i830ContextPtr i830 ) | ||||
| static void | ||||
| emit_passthrough(struct i830_context *i830) | ||||
| { | ||||
|    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz; | ||||
|    GLuint unit = 0; | ||||
| @@ -442,7 +440,8 @@ static void emit_passthrough( i830ContextPtr i830 ) | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), GL_TRUE); | ||||
| } | ||||
|  | ||||
| void i830EmitTextureBlend( i830ContextPtr i830 ) | ||||
| void | ||||
| i830EmitTextureBlend(struct i830_context *i830) | ||||
| { | ||||
|    GLcontext *ctx = &i830->intel.ctx; | ||||
|    GLuint unit, last_stage = 0, blendunit = 0; | ||||
| @@ -462,4 +461,3 @@ void i830EmitTextureBlend( i830ContextPtr i830 ) | ||||
|       emit_passthrough(i830); | ||||
|    } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -38,446 +38,279 @@ | ||||
| #include "intel_screen.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i830_context.h" | ||||
| #include "i830_reg.h" | ||||
|  | ||||
| static const GLint initial_offsets[6][2] = { {0,0}, | ||||
| 				       {0,2}, | ||||
| 				       {1,0}, | ||||
| 				       {1,2}, | ||||
| 				       {1,1}, | ||||
| 				       {1,3} }; | ||||
|  | ||||
| static const GLint step_offsets[6][2] = { {0,2}, | ||||
| 				    {0,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,1}, | ||||
| 				    {-1,1} }; | ||||
|  | ||||
| #define I830_TEX_UNIT_ENABLED(unit)		(1<<unit) | ||||
|  | ||||
| static GLboolean i830SetTexImages( i830ContextPtr i830,  | ||||
| 				  struct gl_texture_object *tObj ) | ||||
| static GLuint | ||||
| translate_texture_format(GLuint mesa_format) | ||||
| { | ||||
|    GLuint total_height, pitch, i, textureFormat; | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData; | ||||
|    const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; | ||||
|    GLint firstLevel, lastLevel, numLevels; | ||||
|  | ||||
|    switch( baseImage->TexFormat->MesaFormat ) { | ||||
|    switch (mesa_format) { | ||||
|    case MESA_FORMAT_L8: | ||||
|       t->intel.texelBytes = 1; | ||||
|       textureFormat = MAPSURF_8BIT | MT_8BIT_L8; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_8BIT | MT_8BIT_L8; | ||||
|    case MESA_FORMAT_I8: | ||||
|       t->intel.texelBytes = 1; | ||||
|       textureFormat = MAPSURF_8BIT | MT_8BIT_I8; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_8BIT | MT_8BIT_I8; | ||||
|    case MESA_FORMAT_A8: | ||||
|       t->intel.texelBytes = 1; | ||||
|       textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */ | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */ | ||||
|    case MESA_FORMAT_AL88: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_AY88; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_AY88; | ||||
|    case MESA_FORMAT_RGB565: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|    case MESA_FORMAT_ARGB1555: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|    case MESA_FORMAT_ARGB4444: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_ARGB4444; | ||||
|    case MESA_FORMAT_ARGB8888: | ||||
|       t->intel.texelBytes = 4; | ||||
|       textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|    case MESA_FORMAT_YCBCR_REV: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL |  | ||||
| 		       TM0S1_COLORSPACE_CONVERSION); | ||||
|       break; | ||||
|  | ||||
|       return (MAPSURF_422 | MT_422_YCRCB_NORMAL); | ||||
|    case MESA_FORMAT_YCBCR: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */ | ||||
| 		       TM0S1_COLORSPACE_CONVERSION); | ||||
|       break; | ||||
|  | ||||
|       return (MAPSURF_422 | MT_422_YCRCB_SWAPY); | ||||
|    case MESA_FORMAT_RGB_FXT1: | ||||
|    case MESA_FORMAT_RGBA_FXT1: | ||||
|      t->intel.texelBytes = 2; | ||||
|      textureFormat = MAPSURF_COMPRESSED | MT_COMPRESS_FXT1; | ||||
|      break; | ||||
|  | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); | ||||
|    case MESA_FORMAT_RGBA_DXT1: | ||||
|    case MESA_FORMAT_RGB_DXT1: | ||||
|      /*  | ||||
|       * DXTn pitches are Width/4 * blocksize in bytes  | ||||
|       * for DXT1: blocksize=8 so Width/4*8 = Width * 2  | ||||
|       * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4 | ||||
|       */ | ||||
|      t->intel.texelBytes = 2; | ||||
|      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); | ||||
|      break; | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); | ||||
|    case MESA_FORMAT_RGBA_DXT3: | ||||
|      t->intel.texelBytes = 4; | ||||
|      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); | ||||
|      break; | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); | ||||
|    case MESA_FORMAT_RGBA_DXT5: | ||||
|      t->intel.texelBytes = 4; | ||||
|      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); | ||||
|      break; | ||||
|  | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); | ||||
|    default: | ||||
|       fprintf(stderr, "%s: bad image format\n", __FUNCTION__); | ||||
|       fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format); | ||||
|       abort(); | ||||
|       return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|    /* Compute which mipmap levels we really want to send to the hardware. | ||||
|     * This depends on the base image size, GL_TEXTURE_MIN_LOD, | ||||
|     * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. | ||||
|     * Yes, this looks overly complicated, but it's all needed. | ||||
|  | ||||
|  | ||||
|  | ||||
| /* The i915 (and related graphics cores) do not support GL_CLAMP.  The | ||||
|  * Intel drivers for "other operating systems" implement GL_CLAMP as | ||||
|  * GL_CLAMP_TO_EDGE, so the same is done here. | ||||
|  */ | ||||
|    driCalculateTextureFirstLastLevel( (driTextureObject *) t ); | ||||
|  | ||||
|  | ||||
|    /* Figure out the amount of memory required to hold all the mipmap | ||||
|     * levels.  Choose the smallest pitch to accomodate the largest | ||||
|     * mipmap: | ||||
|     */ | ||||
|    firstLevel = t->intel.base.firstLevel; | ||||
|    lastLevel = t->intel.base.lastLevel; | ||||
|    numLevels = lastLevel - firstLevel + 1; | ||||
|  | ||||
|  | ||||
|    /* All images must be loaded at this pitch.  Count the number of | ||||
|     * lines required: | ||||
|     */ | ||||
|    switch (tObj->Target) { | ||||
|    case GL_TEXTURE_CUBE_MAP: { | ||||
|       const GLuint dim = tObj->Image[0][firstLevel]->Width; | ||||
|       GLuint face; | ||||
|  | ||||
|       pitch = dim * t->intel.texelBytes; | ||||
|       pitch *= 2;		/* double pitch for cube layouts */ | ||||
|       pitch = (pitch + 3) & ~3; | ||||
|        | ||||
|       total_height = dim * 4; | ||||
|  | ||||
|       for ( face = 0 ; face < 6 ; face++) { | ||||
| 	 GLuint x = initial_offsets[face][0] * dim; | ||||
| 	 GLuint y = initial_offsets[face][1] * dim; | ||||
| 	 GLuint d = dim; | ||||
| 	  | ||||
| 	 t->intel.base.dirty_images[face] = ~0; | ||||
|  | ||||
| 	 assert(tObj->Image[face][firstLevel]->Width == dim); | ||||
| 	 assert(tObj->Image[face][firstLevel]->Height == dim); | ||||
|  | ||||
| 	 for (i = 0; i < numLevels; i++) { | ||||
| 	    t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; | ||||
| 	    if (!t->intel.image[face][i].image) { | ||||
| 	       fprintf(stderr, "no image %d %d\n", face, i); | ||||
| 	       break;		/* can't happen */ | ||||
| 	    } | ||||
| 	  | ||||
| 	    t->intel.image[face][i].offset =  | ||||
| 	       y * pitch + x * t->intel.texelBytes; | ||||
| 	    t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; | ||||
|  | ||||
| 	    d >>= 1; | ||||
| 	    x += step_offsets[face][0] * d; | ||||
| 	    y += step_offsets[face][1] * d; | ||||
| 	 } | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
| static GLuint | ||||
| translate_wrap_mode(GLenum wrap) | ||||
| { | ||||
|    switch (wrap) { | ||||
|    case GL_REPEAT: | ||||
|       return TEXCOORDMODE_WRAP; | ||||
|    case GL_CLAMP: | ||||
|    case GL_CLAMP_TO_EDGE: | ||||
|       return TEXCOORDMODE_CLAMP;        /* not really correct */ | ||||
|    case GL_CLAMP_TO_BORDER: | ||||
|       return TEXCOORDMODE_CLAMP_BORDER; | ||||
|    case GL_MIRRORED_REPEAT: | ||||
|       return TEXCOORDMODE_MIRROR; | ||||
|    default: | ||||
|       pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; | ||||
|       pitch = (pitch + 3) & ~3; | ||||
|       t->intel.base.dirty_images[0] = ~0; | ||||
|       return TEXCOORDMODE_WRAP; | ||||
|    } | ||||
| } | ||||
|  | ||||
|       for ( total_height = i = 0 ; i < numLevels ; i++ ) { | ||||
| 	 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; | ||||
| 	 if (!t->intel.image[0][i].image)  | ||||
| 	    break; | ||||
|  | ||||
| 	 t->intel.image[0][i].offset = total_height * pitch; | ||||
| 	 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; | ||||
| 	 if (t->intel.image[0][i].image->IsCompressed) | ||||
| /* Recalculate all state from scratch.  Perhaps not the most | ||||
|  * efficient, but this has gotten complex enough that we need | ||||
|  * something which is understandable and reliable. | ||||
|  */ | ||||
| static GLboolean | ||||
| i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) | ||||
| { | ||||
| 	   if (t->intel.image[0][i].image->Height > 4) | ||||
| 	     total_height += t->intel.image[0][i].image->Height/4; | ||||
| 	   else | ||||
| 	     total_height += 1; | ||||
| 	 } | ||||
| 	 else | ||||
| 	   total_height += MAX2(2, t->intel.image[0][i].image->Height); | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(tObj); | ||||
|    struct gl_texture_image *firstImage; | ||||
|    GLuint *state = i830->state.Tex[unit]; | ||||
|  | ||||
|    t->intel.Pitch = pitch; | ||||
|    t->intel.base.totalSize = total_height*pitch; | ||||
|    t->intel.max_level = i-1; | ||||
|    t->Setup[I830_TEXREG_TM0S1] =  | ||||
|       (((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) | | ||||
|        ((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) | | ||||
|        textureFormat); | ||||
|    t->Setup[I830_TEXREG_TM0S2] =  | ||||
|       (((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | | ||||
|       TM0S2_CUBE_FACE_ENA_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT; | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
|    memset(state, 0, sizeof(state)); | ||||
|  | ||||
|    return intelUploadTexImages( &i830->intel, &t->intel, 0 ); | ||||
| } | ||||
|    if (!intel_finalize_mipmap_tree(intel, unit)) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    /* Get first image here, since intelObj->firstLevel will get set in | ||||
|     * the intel_finalize_mipmap_tree() call above. | ||||
|     */ | ||||
|    firstImage = tObj->Image[0][intelObj->firstLevel]; | ||||
|  | ||||
|    i830->state.tex_buffer[unit] = intelObj->mt->region->buffer; | ||||
|    i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0, | ||||
|                                                              intelObj-> | ||||
|                                                              firstLevel); | ||||
|  | ||||
|  | ||||
| static void i830_import_tex_unit( i830ContextPtr i830,  | ||||
| 			   i830TextureObjectPtr t, | ||||
| 			   GLuint unit ) | ||||
| { | ||||
|    if(INTEL_DEBUG&DEBUG_TEXTURE) | ||||
|       fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); | ||||
|     | ||||
|    if (i830->intel.CurrentTexObj[unit])  | ||||
|       i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit); | ||||
|  | ||||
|    i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t; | ||||
|    t->intel.base.bound |= (1 << unit); | ||||
|  | ||||
|    I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) ); | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |  | ||||
|    state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | | ||||
|                                (LOAD_TEXTURE_MAP0 << unit) | 4); | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | | ||||
| 					       t->intel.TextureOffset); | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1]; | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2]; | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK; | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] & | ||||
| 						~TM0S3_LOD_BIAS_MASK); | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4]; | ||||
|    i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] &  | ||||
| 					     ~MAP_UNIT_MASK);    | ||||
|    i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE]; | ||||
|    i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit); | ||||
|  | ||||
|    t->intel.dirty &= ~I830_UPLOAD_TEX(unit); | ||||
| } | ||||
| /*    state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */ | ||||
| /* 			       t->intel.TextureOffset); */ | ||||
|  | ||||
|  | ||||
|    state[I830_TEXREG_TM0S1] = | ||||
|       (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) | | ||||
|        ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | | ||||
|        translate_texture_format(firstImage->TexFormat->MesaFormat)); | ||||
|  | ||||
|    state[I830_TEXREG_TM0S2] = | ||||
|       (((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) - | ||||
|          1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK); | ||||
|  | ||||
| static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) | ||||
|    { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; | ||||
|    struct gl_texture_object *tObj = texUnit->_Current; | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; | ||||
|       if (tObj->Target == GL_TEXTURE_CUBE_MAP) | ||||
|          state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) | | ||||
|                                     CUBE_NEGX_ENABLE | | ||||
|                                     CUBE_POSX_ENABLE | | ||||
|                                     CUBE_NEGY_ENABLE | | ||||
|                                     CUBE_POSY_ENABLE | | ||||
|                                     CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE); | ||||
|       else | ||||
|          state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit)); | ||||
|    } | ||||
|  | ||||
|    if (0) fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Fallback if there's a texture border */ | ||||
|    if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { | ||||
|       fprintf(stderr, "Texture border\n"); | ||||
|  | ||||
|  | ||||
|    { | ||||
|       GLuint minFilt, mipFilt, magFilt; | ||||
|  | ||||
|       switch (tObj->MinFilter) { | ||||
|       case GL_NEAREST: | ||||
|          minFilt = FILTER_NEAREST; | ||||
|          mipFilt = MIPFILTER_NONE; | ||||
|          break; | ||||
|       case GL_LINEAR: | ||||
|          minFilt = FILTER_LINEAR; | ||||
|          mipFilt = MIPFILTER_NONE; | ||||
|          break; | ||||
|       case GL_NEAREST_MIPMAP_NEAREST: | ||||
|          minFilt = FILTER_NEAREST; | ||||
|          mipFilt = MIPFILTER_NEAREST; | ||||
|          break; | ||||
|       case GL_LINEAR_MIPMAP_NEAREST: | ||||
|          minFilt = FILTER_LINEAR; | ||||
|          mipFilt = MIPFILTER_NEAREST; | ||||
|          break; | ||||
|       case GL_NEAREST_MIPMAP_LINEAR: | ||||
|          minFilt = FILTER_NEAREST; | ||||
|          mipFilt = MIPFILTER_LINEAR; | ||||
|          break; | ||||
|       case GL_LINEAR_MIPMAP_LINEAR: | ||||
|          minFilt = FILTER_LINEAR; | ||||
|          mipFilt = MIPFILTER_LINEAR; | ||||
|          break; | ||||
|       default: | ||||
|          return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|    /* Upload teximages (not pipelined) | ||||
|     */ | ||||
|    if (t->intel.base.dirty_images[0]) { | ||||
|       if (!i830SetTexImages( i830, tObj )) { | ||||
|       if (tObj->MaxAnisotropy > 1.0) { | ||||
|          minFilt = FILTER_ANISOTROPIC; | ||||
|          magFilt = FILTER_ANISOTROPIC; | ||||
|       } | ||||
|       else { | ||||
|          switch (tObj->MagFilter) { | ||||
|          case GL_NEAREST: | ||||
|             magFilt = FILTER_NEAREST; | ||||
|             break; | ||||
|          case GL_LINEAR: | ||||
|             magFilt = FILTER_LINEAR; | ||||
|             break; | ||||
|          default: | ||||
|             return GL_FALSE; | ||||
|          } | ||||
|       } | ||||
|  | ||||
|    /* Update state if this is a different texture object to last | ||||
|     * time. | ||||
|       state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit]; | ||||
|  | ||||
| #if 0 | ||||
|       /* YUV conversion: | ||||
|        */ | ||||
|    if (i830->intel.CurrentTexObj[unit] != &t->intel ||  | ||||
|        (t->intel.dirty & I830_UPLOAD_TEX(unit))) { | ||||
|       i830_import_tex_unit( i830, t, unit); | ||||
|       if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || | ||||
|           firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) | ||||
|          state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION; | ||||
| #endif | ||||
|  | ||||
|       state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel - | ||||
|                                     intelObj->firstLevel) * | ||||
|                                    4) << TM0S3_MIN_MIP_SHIFT; | ||||
|  | ||||
|       state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | | ||||
|                                    (mipFilt << TM0S3_MIP_FILTER_SHIFT) | | ||||
|                                    (magFilt << TM0S3_MAG_FILTER_SHIFT)); | ||||
|    } | ||||
|  | ||||
|    { | ||||
|       GLenum ws = tObj->WrapS; | ||||
|       GLenum wt = tObj->WrapT; | ||||
|  | ||||
|  | ||||
|       /* 3D textures not available on i830 | ||||
|        */ | ||||
|       if (tObj->Target == GL_TEXTURE_3D) | ||||
|          return GL_FALSE; | ||||
|  | ||||
|       state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | | ||||
|                                 MAP_UNIT(unit) | | ||||
|                                 ENABLE_TEXCOORD_PARAMS | | ||||
|                                 ss3 | | ||||
|                                 ENABLE_ADDR_V_CNTL | | ||||
|                                 TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt)) | ||||
|                                 | ENABLE_ADDR_U_CNTL | | ||||
|                                 TEXCOORD_ADDR_U_MODE(translate_wrap_mode | ||||
|                                                      (ws))); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0], | ||||
|                                                   tObj->_BorderChan[1], | ||||
|                                                   tObj->_BorderChan[2], | ||||
|                                                   tObj->_BorderChan[3]); | ||||
|  | ||||
|  | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS]; | ||||
|  | ||||
|    mcs &= ~TEXCOORDS_ARE_NORMAL; | ||||
|    mcs |= TEXCOORDS_ARE_IN_TEXELUNITS; | ||||
|  | ||||
|    if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) | ||||
|        || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) { | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_MCS] = mcs; | ||||
|       i830->state.Tex[unit][I830_TEXREG_CUBE] = 0; | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS]; | ||||
|  | ||||
|    mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS; | ||||
|    mcs |= TEXCOORDS_ARE_NORMAL; | ||||
|  | ||||
|    if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) | ||||
|        || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) { | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_MCS] = mcs; | ||||
|       i830->state.Tex[unit][I830_TEXREG_CUBE] = 0; | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|   | ||||
| static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; | ||||
|    struct gl_texture_object *tObj = texUnit->_Current; | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; | ||||
|    GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS]; | ||||
|    const GLuint cube = CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE | ||||
|      | CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE | ||||
|      | CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE; | ||||
|    GLuint face; | ||||
|  | ||||
|    mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS; | ||||
|    mcs |= TEXCOORDS_ARE_NORMAL; | ||||
|  | ||||
|    if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) | ||||
|        || (cube != i830->state.Tex[unit][I830_TEXREG_CUBE])) { | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_MCS] = mcs; | ||||
|       i830->state.Tex[unit][I830_TEXREG_CUBE] = cube; | ||||
|    } | ||||
|  | ||||
|    /* Upload teximages (not pipelined) | ||||
|    /* memcmp was already disabled, but definitely won't work as the | ||||
|     * region might now change and that wouldn't be detected: | ||||
|     */ | ||||
|    if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] || | ||||
|         t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] || | ||||
|         t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) { | ||||
|       i830SetTexImages( i830, tObj ); | ||||
|    } | ||||
|  | ||||
|    /* upload (per face) */ | ||||
|    for (face = 0; face < 6; face++) { | ||||
|       if (t->intel.base.dirty_images[face]) { | ||||
| 	 if (!intelUploadTexImages( &i830->intel, &t->intel, face )) { | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean disable_tex( GLcontext *ctx, GLuint unit ) | ||||
|  | ||||
|  | ||||
| void | ||||
| i830UpdateTextureState(struct intel_context *intel) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    GLboolean ok = GL_TRUE; | ||||
|    GLuint i; | ||||
|  | ||||
|    /* This is happening too often.  I need to conditionally send diffuse | ||||
|     * state to the card.  Perhaps a diffuse dirty flag of some kind. | ||||
|     * Will need to change this logic if more than 2 texture units are | ||||
|     * used.  We need to only do this up to the last unit enabled, or unit | ||||
|     * one if nothing is enabled. | ||||
|     */ | ||||
|  | ||||
|    if ( i830->intel.CurrentTexObj[unit] != NULL ) { | ||||
|       /* The old texture is no longer bound to this texture unit. | ||||
|        * Mark it as such. | ||||
|        */ | ||||
|  | ||||
|       i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0); | ||||
|       i830->intel.CurrentTexObj[unit] = NULL; | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; | ||||
|  | ||||
|    if (texUnit->_ReallyEnabled && | ||||
|        INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    switch(texUnit->_ReallyEnabled) { | ||||
|    for (i = 0; i < I830_TEX_UNITS && ok; i++) { | ||||
|       switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) { | ||||
|       case TEXTURE_1D_BIT: | ||||
|       case TEXTURE_2D_BIT: | ||||
|       return (enable_tex_common( ctx, unit ) && | ||||
| 	      enable_tex_2d( ctx, unit )); | ||||
|    case TEXTURE_RECT_BIT: | ||||
|       return (enable_tex_common( ctx, unit ) && | ||||
| 	      enable_tex_rect( ctx, unit )); | ||||
|       case TEXTURE_CUBE_BIT: | ||||
|       return (enable_tex_common( ctx, unit ) && | ||||
| 	      enable_tex_cube( ctx, unit )); | ||||
|          ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL); | ||||
|          break; | ||||
|       case TEXTURE_RECT_BIT: | ||||
|          ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS); | ||||
|          break; | ||||
|       case 0: | ||||
|       return disable_tex( ctx, unit ); | ||||
|          if (i830->state.active & I830_UPLOAD_TEX(i)) | ||||
|             I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE); | ||||
|          break; | ||||
|       case TEXTURE_3D_BIT: | ||||
|       default: | ||||
|       return GL_FALSE; | ||||
|          ok = GL_FALSE; | ||||
|          break; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
| void i830UpdateTextureState( intelContextPtr intel ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLboolean ok; | ||||
|  | ||||
|    if (0) fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE); | ||||
|  | ||||
|    ok = (i830UpdateTexUnit( ctx, 0 ) && | ||||
| 	 i830UpdateTexUnit( ctx, 1 ) && | ||||
| 	 i830UpdateTexUnit( ctx, 2 ) && | ||||
| 	 i830UpdateTexUnit( ctx, 3 )); | ||||
|  | ||||
|    FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok); | ||||
|  | ||||
|    if (ok) | ||||
|       i830EmitTextureBlend(i830); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -28,13 +28,14 @@ | ||||
|  | ||||
| #include "i830_context.h" | ||||
| #include "i830_reg.h" | ||||
|  | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| #include "intel_regions.h" | ||||
| #include "tnl/t_context.h" | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
| #define FILE_DEBUG_FLAG DEBUG_STATE | ||||
|  | ||||
| static GLboolean i830_check_vertex_size(struct intel_context *intel, | ||||
|                                         GLuint expected); | ||||
|  | ||||
| #define SZ_TO_HW(sz)  ((sz-2)&0x3) | ||||
| @@ -59,10 +60,11 @@ do {									\ | ||||
| #define VRTX_TEX_SET_FMT(n, x)          ((x)<<((n)*2)) | ||||
| #define TEXBIND_SET(n, x) 		((x)<<((n)*4)) | ||||
|  | ||||
| static void i830_render_start( intelContextPtr intel ) | ||||
| static void | ||||
| i830_render_start(struct intel_context *intel) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|    DECLARE_RENDERINPUTS(index_bitset); | ||||
| @@ -166,6 +168,7 @@ static void i830_render_start( intelContextPtr intel ) | ||||
|        v2 != i830->state.Ctx[I830_CTXREG_VF2] || | ||||
|        mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] || | ||||
|        !RENDERINPUTS_EQUAL(index_bitset, i830->last_index_bitset)) { | ||||
|       int k; | ||||
|  | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
| @@ -185,22 +188,22 @@ static void i830_render_start( intelContextPtr intel ) | ||||
|       i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1; | ||||
|       RENDERINPUTS_COPY(i830->last_index_bitset, index_bitset); | ||||
|  | ||||
|       assert(i830_check_vertex_size( intel, intel->vertex_size )); | ||||
|       k = i830_check_vertex_size(intel, intel->vertex_size); | ||||
|       assert(k); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i830_reduced_primitive_state( intelContextPtr intel, | ||||
| 					  GLenum rprim ) | ||||
| static void | ||||
| i830_reduced_primitive_state(struct intel_context *intel, GLenum rprim) | ||||
| { | ||||
|     i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    GLuint st1 = i830->state.Stipple[I830_STPREG_ST1]; | ||||
|  | ||||
|    st1 &= ~ST1_ENABLE; | ||||
|  | ||||
|    switch (rprim) { | ||||
|    case GL_TRIANGLES: | ||||
|        if (intel->ctx.Polygon.StippleFlag && | ||||
| 	   intel->hw_stipple) | ||||
|       if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple) | ||||
|          st1 |= ST1_ENABLE; | ||||
|       break; | ||||
|    case GL_LINES: | ||||
| @@ -212,6 +215,8 @@ static void i830_reduced_primitive_state( intelContextPtr intel, | ||||
|    i830->intel.reduced_primitive = rprim; | ||||
|  | ||||
|    if (st1 != i830->state.Stipple[I830_STPREG_ST1]) { | ||||
|       INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE); | ||||
|       i830->state.Stipple[I830_STPREG_ST1] = st1; | ||||
|    } | ||||
| @@ -220,36 +225,56 @@ static void i830_reduced_primitive_state( intelContextPtr intel, | ||||
| /* Pull apart the vertex format registers and figure out how large a | ||||
|  * vertex is supposed to be.  | ||||
|  */ | ||||
| static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
| 					 GLuint expected ) | ||||
| static GLboolean | ||||
| i830_check_vertex_size(struct intel_context *intel, GLuint expected) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    int vft0 = i830->current->Ctx[I830_CTXREG_VF]; | ||||
|    int vft1 = i830->current->Ctx[I830_CTXREG_VF2]; | ||||
|    int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT; | ||||
|    int i, sz = 0; | ||||
|  | ||||
|    switch (vft0 & VFT0_XYZW_MASK) { | ||||
|    case VFT0_XY: sz = 2; break; | ||||
|    case VFT0_XYZ: sz = 3; break; | ||||
|    case VFT0_XYW: sz = 3; break; | ||||
|    case VFT0_XYZW: sz = 4; break; | ||||
|    case VFT0_XY: | ||||
|       sz = 2; | ||||
|       break; | ||||
|    case VFT0_XYZ: | ||||
|       sz = 3; | ||||
|       break; | ||||
|    case VFT0_XYW: | ||||
|       sz = 3; | ||||
|       break; | ||||
|    case VFT0_XYZW: | ||||
|       sz = 4; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "no xyzw specified\n"); | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    if (vft0 & VFT0_SPEC) sz++; | ||||
|    if (vft0 & VFT0_DIFFUSE) sz++; | ||||
|    if (vft0 & VFT0_DEPTH_OFFSET) sz++; | ||||
|    if (vft0 & VFT0_POINT_WIDTH) sz++; | ||||
|    if (vft0 & VFT0_SPEC) | ||||
|       sz++; | ||||
|    if (vft0 & VFT0_DIFFUSE) | ||||
|       sz++; | ||||
|    if (vft0 & VFT0_DEPTH_OFFSET) | ||||
|       sz++; | ||||
|    if (vft0 & VFT0_POINT_WIDTH) | ||||
|       sz++; | ||||
|  | ||||
|    for (i = 0; i < nrtex; i++) { | ||||
|       switch (vft1 & VFT1_TEX0_MASK) { | ||||
|       case TEXCOORDFMT_2D: sz += 2; break; | ||||
|       case TEXCOORDFMT_3D: sz += 3; break; | ||||
|       case TEXCOORDFMT_4D: sz += 4; break; | ||||
|       case TEXCOORDFMT_1D: sz += 1; break; | ||||
|       case TEXCOORDFMT_2D: | ||||
|          sz += 2; | ||||
|          break; | ||||
|       case TEXCOORDFMT_3D: | ||||
|          sz += 3; | ||||
|          break; | ||||
|       case TEXCOORDFMT_4D: | ||||
|          sz += 4; | ||||
|          break; | ||||
|       case TEXCOORDFMT_1D: | ||||
|          sz += 1; | ||||
|          break; | ||||
|       } | ||||
|       vft1 >>= VFT1_TEX1_SHIFT; | ||||
|    } | ||||
| @@ -260,16 +285,12 @@ static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
|    return sz == expected; | ||||
| } | ||||
|  | ||||
| static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
| static void | ||||
| i830_emit_invarient_state(struct intel_context *intel) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH( 200 ); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0)); | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1)); | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2)); | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3)); | ||||
|    BEGIN_BATCH(40, 0); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); | ||||
|    OUT_BATCH(0); | ||||
| @@ -282,9 +303,7 @@ static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_FOG_MODE_CMD); | ||||
|    OUT_BATCH(FOGFUNC_ENABLE | | ||||
| 	     FOG_LINEAR_CONST |  | ||||
| 	     FOGSRC_INDEX_Z |  | ||||
| 	     ENABLE_FOG_DENSITY); | ||||
|              FOG_LINEAR_CONST | FOGSRC_INDEX_Z | ENABLE_FOG_DENSITY); | ||||
|    OUT_BATCH(0); | ||||
|    OUT_BATCH(0); | ||||
|  | ||||
| @@ -330,15 +349,7 @@ static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
|              ENABLE_TRI_FAN_PROVOKE_VRTX | | ||||
|              ENABLE_TRI_STRIP_PROVOKE_VRTX | | ||||
|              LINE_STRIP_PROVOKE_VRTX(1) | | ||||
| 	     TRI_FAN_PROVOKE_VRTX(2) |  | ||||
| 	     TRI_STRIP_PROVOKE_VRTX(2)); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |  | ||||
| 	     DISABLE_SCISSOR_RECT); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); | ||||
|    OUT_BATCH(0); | ||||
|    OUT_BATCH(0); | ||||
|              TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2)); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM); | ||||
|    OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE); | ||||
| @@ -358,18 +369,24 @@ static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
| #define emit( intel, state, size )			\ | ||||
| do {							\ | ||||
|    int k;						\ | ||||
|    BEGIN_BATCH( size / sizeof(GLuint));			\ | ||||
|    for (k = 0 ; k < size / sizeof(GLuint) ; k++)	\ | ||||
|    BEGIN_BATCH(size / sizeof(GLuint), 0);		\ | ||||
|    for (k = 0 ; k < size / sizeof(GLuint) ; k++) {	\ | ||||
|       if (0) _mesa_printf("  0x%08x\n", state[k]);		\ | ||||
|       OUT_BATCH(state[k]);				\ | ||||
|    }							\ | ||||
|    ADVANCE_BATCH();					\ | ||||
| } while (0); | ||||
| } while (0) | ||||
|  | ||||
| static GLuint get_state_size( struct i830_hw_state *state ) | ||||
| static GLuint | ||||
| get_state_size(struct i830_hw_state *state) | ||||
| { | ||||
|    GLuint dirty = state->active & ~state->emitted; | ||||
|    GLuint sz = 0; | ||||
|    GLuint i; | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_INVARIENT) | ||||
|       sz += 40 * sizeof(int); | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_CTX) | ||||
|       sz += sizeof(state->Ctx); | ||||
|  | ||||
| @@ -393,81 +410,139 @@ static GLuint get_state_size( struct i830_hw_state *state ) | ||||
|  | ||||
| /* Push the state into the sarea and/or texture memory. | ||||
|  */ | ||||
| static void i830_emit_state( intelContextPtr intel ) | ||||
| static void | ||||
| i830_emit_state(struct intel_context *intel) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    struct i830_hw_state *state = i830->current; | ||||
|    int i; | ||||
|    GLuint dirty = state->active & ~state->emitted; | ||||
|    GLuint counter = intel->batch.counter; | ||||
|    GLuint dirty; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    if (intel->batch.space < get_state_size(state)) { | ||||
|       intelFlushBatch(intel, GL_TRUE); | ||||
|    /* We don't hold the lock at this point, so want to make sure that | ||||
|     * there won't be a buffer wrap.   | ||||
|     * | ||||
|     * It might be better to talk about explicit places where | ||||
|     * scheduling is allowed, rather than assume that it is whenever a | ||||
|     * batchbuffer fills up. | ||||
|     */ | ||||
|    intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0); | ||||
|  | ||||
|    /* Do this here as we may have flushed the batchbuffer above, | ||||
|     * causing more state to be dirty! | ||||
|     */ | ||||
|    dirty = state->active & ~state->emitted; | ||||
|       counter = intel->batch.counter; | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_INVARIENT) { | ||||
|       DBG("I830_UPLOAD_INVARIENT:\n"); | ||||
|       i830_emit_invarient_state(intel); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_CTX) { | ||||
|       if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n");  | ||||
|       DBG("I830_UPLOAD_CTX:\n"); | ||||
|       emit(i830, state->Ctx, sizeof(state->Ctx)); | ||||
|  | ||||
|    } | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_BUFFERS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");  | ||||
|       emit( i830, state->Buffer, sizeof(state->Buffer) ); | ||||
|       DBG("I830_UPLOAD_BUFFERS:\n"); | ||||
|       BEGIN_BATCH(I830_DEST_SETUP_SIZE + 2, 0); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]); | ||||
|       OUT_RELOC(state->draw_region->buffer, | ||||
|                 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                 DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); | ||||
|  | ||||
|       if (state->depth_region) { | ||||
|          OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]); | ||||
|          OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]); | ||||
|          OUT_RELOC(state->depth_region->buffer, | ||||
|                    DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                    DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); | ||||
|       } | ||||
|  | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_DV0]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_DV1]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SENABLE]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SR0]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SR1]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SR2]); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_STIPPLE) { | ||||
|       if (VERBOSE) fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");  | ||||
|       DBG("I830_UPLOAD_STIPPLE:\n"); | ||||
|       emit(i830, state->Stipple, sizeof(state->Stipple)); | ||||
|    } | ||||
|  | ||||
|    for (i = 0; i < I830_TEX_UNITS; i++) { | ||||
|       if ((dirty & I830_UPLOAD_TEX(i))) { | ||||
|  	 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);  | ||||
| 	 emit( i830, state->Tex[i], sizeof(state->Tex[i]));  | ||||
|          DBG("I830_UPLOAD_TEX(%d):\n", i); | ||||
|  | ||||
|          BEGIN_BATCH(I830_TEX_SETUP_SIZE + 1, 0); | ||||
|          OUT_BATCH(state->Tex[i][I830_TEXREG_TM0LI]); | ||||
|  | ||||
|          if (state->tex_buffer[i]) { | ||||
|             OUT_RELOC(state->tex_buffer[i], | ||||
|                       DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, | ||||
|                       DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, | ||||
|                       state->tex_offset[i] | TM0S0_USE_FENCE); | ||||
|          } | ||||
|          else { | ||||
|             assert(i == 0); | ||||
|             assert(state == &i830->meta); | ||||
|             OUT_BATCH(0); | ||||
|          } | ||||
|  | ||||
|          OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S1]); | ||||
|          OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S2]); | ||||
|          OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S3]); | ||||
|          OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]); | ||||
|          OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]); | ||||
|          OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]); | ||||
|       } | ||||
|  | ||||
|       if (dirty & I830_UPLOAD_TEXBLEND(i)) { | ||||
| 	 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d):\n", i);  | ||||
| 	 emit( i830, state->TexBlend[i],  | ||||
| 	       state->TexBlendWordsUsed[i] * 4 ); | ||||
|          DBG("I830_UPLOAD_TEXBLEND(%d): %d words\n", i, | ||||
|              state->TexBlendWordsUsed[i]); | ||||
|          emit(i830, state->TexBlend[i], state->TexBlendWordsUsed[i] * 4); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    state->emitted |= dirty; | ||||
|    intel->batch.last_emit_state = counter; | ||||
|    assert(counter == intel->batch.counter); | ||||
| } | ||||
|  | ||||
| static void i830_destroy_context( intelContextPtr intel ) | ||||
| static void | ||||
| i830_destroy_context(struct intel_context *intel) | ||||
| { | ||||
|    _tnl_free_vertices(&intel->ctx); | ||||
| } | ||||
|  | ||||
| static void | ||||
| i830_set_color_region(intelContextPtr intel, const intelRegion *region) | ||||
| i830_set_draw_region(struct intel_context *intel, | ||||
|                      struct intel_region *draw_region, | ||||
|                      struct intel_region *depth_region) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    intel_region_release(intel->intelScreen, &i830->state.draw_region); | ||||
|    intel_region_release(intel->intelScreen, &i830->state.depth_region); | ||||
|    intel_region_reference(&i830->state.draw_region, draw_region); | ||||
|    intel_region_reference(&i830->state.depth_region, depth_region); | ||||
|  | ||||
|    /* XXX FBO: Need code from i915_set_draw_region() */ | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR1] = | ||||
|       (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR2] = region->offset; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| i830_set_z_region(intelContextPtr intel, const intelRegion *region) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS ); | ||||
|       (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(draw_region->pitch) | | ||||
|        BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR1] = | ||||
|       (BUF_3D_ID_DEPTH | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR2] = region->offset; | ||||
|       (BUF_3D_ID_DEPTH | BUF_3D_PITCH(depth_region->pitch) | | ||||
|        BUF_3D_USE_FENCE); | ||||
| } | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
| static void | ||||
| i830_update_color_z_regions(intelContextPtr intel, | ||||
|                             const intelRegion * colorRegion, | ||||
| @@ -476,52 +551,56 @@ i830_update_color_z_regions(intelContextPtr intel, | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|  | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR1] = | ||||
|       (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) | BUF_3D_USE_FENCE); | ||||
|       (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) | | ||||
|        BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR2] = colorRegion->offset; | ||||
|  | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR1] = | ||||
|       (BUF_3D_ID_DEPTH | BUF_3D_PITCH(depthRegion->pitch) | BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR2] = depthRegion->offset; | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* This isn't really handled at the moment. | ||||
|  */ | ||||
| static void i830_lost_hardware( intelContextPtr intel ) | ||||
| static void | ||||
| i830_lost_hardware(struct intel_context *intel) | ||||
| { | ||||
|    I830_CONTEXT(intel)->state.emitted = 0; | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    i830->state.emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void i830_emit_flush( intelContextPtr intel ) | ||||
| static GLuint | ||||
| i830_flush_cmd(void) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH(2); | ||||
|    OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
|    return MI_FLUSH | FLUSH_MAP_CACHE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void i830InitVtbl( i830ContextPtr i830 ) | ||||
| static void  | ||||
| i830_assert_not_dirty( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    struct i830_hw_state *state = i830->current; | ||||
|    GLuint dirty = state->active & ~state->emitted; | ||||
|    assert(!dirty); | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| i830InitVtbl(struct i830_context *i830) | ||||
| { | ||||
|    i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj; | ||||
|    i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; | ||||
|    i830->intel.vtbl.clear_with_tris = i830ClearWithTris; | ||||
|    i830->intel.vtbl.rotate_window = i830RotateWindow; | ||||
|    i830->intel.vtbl.destroy = i830_destroy_context; | ||||
|    i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state; | ||||
|    i830->intel.vtbl.emit_state = i830_emit_state; | ||||
|    i830->intel.vtbl.lost_hardware = i830_lost_hardware; | ||||
|    i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state; | ||||
|    i830->intel.vtbl.set_color_region = i830_set_color_region; | ||||
|    i830->intel.vtbl.set_z_region = i830_set_z_region; | ||||
|    i830->intel.vtbl.update_color_z_regions = i830_update_color_z_regions; | ||||
|    i830->intel.vtbl.set_draw_region = i830_set_draw_region; | ||||
|    i830->intel.vtbl.update_texture_state = i830UpdateTextureState; | ||||
|    i830->intel.vtbl.emit_flush = i830_emit_flush; | ||||
|    i830->intel.vtbl.flush_cmd = i830_flush_cmd; | ||||
|    i830->intel.vtbl.render_start = i830_render_start; | ||||
|    i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty; | ||||
| } | ||||
|   | ||||
| @@ -41,15 +41,19 @@ | ||||
| #include "utils.h" | ||||
| #include "i915_reg.h" | ||||
|  | ||||
| #include "intel_regions.h" | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| /*************************************** | ||||
|  * Mesa's Driver Functions | ||||
|  ***************************************/ | ||||
|  | ||||
| static const struct dri_extension i915_extensions[] = | ||||
| { | ||||
| static const struct dri_extension i915_extensions[] = { | ||||
|    {"GL_ARB_depth_texture", NULL}, | ||||
|    {"GL_ARB_fragment_program", NULL}, | ||||
|    {"GL_ARB_shadow", NULL}, | ||||
|    {"GL_ARB_texture_env_crossbar", NULL}, | ||||
|    {"GL_ARB_texture_non_power_of_two", NULL}, | ||||
|    {"GL_EXT_shadow_funcs", NULL}, | ||||
|    /* ARB extn won't work if not enabled */ | ||||
|    {"GL_SGIX_depth_texture", NULL}, | ||||
| @@ -58,14 +62,15 @@ static const struct dri_extension i915_extensions[] = | ||||
|  | ||||
| /* Override intel default. | ||||
|  */ | ||||
| static void i915InvalidateState( GLcontext *ctx, GLuint new_state ) | ||||
| static void | ||||
| i915InvalidateState(GLcontext * ctx, GLuint new_state) | ||||
| { | ||||
|    _swrast_InvalidateState(ctx, new_state); | ||||
|    _swsetup_InvalidateState(ctx, new_state); | ||||
|    _ac_InvalidateState(ctx, new_state); | ||||
|    _tnl_InvalidateState(ctx, new_state); | ||||
|    _tnl_invalidate_vertex_state(ctx, new_state); | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= new_state; | ||||
|    intel_context(ctx)->NewGLState |= new_state; | ||||
|  | ||||
|    /* Todo: gather state values under which tracked parameters become | ||||
|     * invalidated, add callbacks for things like | ||||
| @@ -83,7 +88,8 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915InitDriverFunctions( struct dd_function_table *functions ) | ||||
| static void | ||||
| i915InitDriverFunctions(struct dd_function_table *functions) | ||||
| { | ||||
|    intelInitDriverFunctions(functions); | ||||
|    i915InitStateFunctions(functions); | ||||
| @@ -94,19 +100,24 @@ static void i915InitDriverFunctions( struct dd_function_table *functions ) | ||||
|  | ||||
|  | ||||
|  | ||||
| GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
| GLboolean | ||||
| i915CreateContext(const __GLcontextModes * mesaVis, | ||||
|                   __DRIcontextPrivate * driContextPriv, | ||||
|                   void *sharedContextPrivate) | ||||
| { | ||||
|    struct dd_function_table functions; | ||||
|    i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context); | ||||
|    intelContextPtr intel = &i915->intel; | ||||
|    struct i915_context *i915 = | ||||
|       (struct i915_context *) CALLOC_STRUCT(i915_context); | ||||
|    struct intel_context *intel = &i915->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLuint i; | ||||
|  | ||||
|    if (!i915) return GL_FALSE; | ||||
|    if (!i915) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    _mesa_printf("\ntexmem-0-3 branch\n\n"); | ||||
|  | ||||
|    i915InitVtbl(i915); | ||||
|    i915InitMetaFuncs(i915); | ||||
|  | ||||
|    i915InitDriverFunctions(&functions); | ||||
|  | ||||
| @@ -120,42 +131,21 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
|    ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS; | ||||
|    ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS; | ||||
|  | ||||
|    intel->nr_heaps = 1; | ||||
|    intel->texture_heaps[0] =  | ||||
|       driCreateTextureHeap( 0, intel, | ||||
| 			    intel->intelScreen->tex.size, | ||||
| 			    12, | ||||
| 			    I830_NR_TEX_REGIONS, | ||||
| 			    intel->sarea->texList, | ||||
| 			    (unsigned *) & intel->sarea->texAge, | ||||
| 			    & intel->swapped, | ||||
| 			    sizeof( struct i915_texture_object ), | ||||
| 			    (destroy_texture_object_t *)intelDestroyTexObj ); | ||||
|  | ||||
|    /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are | ||||
|     * tightly packed, but they're not in Intel graphics | ||||
|     * hardware. | ||||
|    /* Advertise the full hardware capabilities.  The new memory | ||||
|     * manager should cope much better with overload situations: | ||||
|     */ | ||||
|    ctx->Const.MaxTextureLevels = 12; | ||||
|    ctx->Const.Max3DTextureLevels = 9; | ||||
|    ctx->Const.MaxCubeTextureLevels = 12; | ||||
|    ctx->Const.MaxTextureRectSize = (1 << 11); | ||||
|    ctx->Const.MaxTextureUnits = I915_TEX_UNITS; | ||||
|    i = driQueryOptioni( &intel->intelScreen->optionCache, "allow_large_textures"); | ||||
|    driCalculateMaxTextureLevels( intel->texture_heaps, | ||||
| 				 intel->nr_heaps, | ||||
| 				 &intel->ctx.Const, | ||||
| 				 4, | ||||
| 				 11, /* max 2D texture size is 2048x2048 */ | ||||
| 				 8,  /* 3D texture */ | ||||
| 				 11, /* cube texture. */ | ||||
| 				 11, /* rect texture */ | ||||
| 				 12, | ||||
| 				 GL_FALSE, | ||||
| 				 i ); | ||||
|  | ||||
|    /* GL_ARB_fragment_program limits - don't think Mesa actually | ||||
|     * validates programs against these, and in any case one ARB | ||||
|     * instruction can translate to more than one HW instruction, so | ||||
|     * we'll still have to check and fallback each time. | ||||
|     */ | ||||
|     | ||||
|    ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAttribs = 11;    /* 8 tex, 2 color, fog */ | ||||
|    ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT; | ||||
| @@ -163,9 +153,12 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
|    ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN; | ||||
|    ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN + | ||||
|                                                        I915_MAX_TEX_INSN); | ||||
|    ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT; | ||||
|    ctx->Const.FragmentProgram.MaxNativeTexIndirections = | ||||
|       I915_MAX_TEX_INDIRECT; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */ | ||||
|  | ||||
|    ctx->_MaintainTexEnvProgram = 1; | ||||
|    ctx->_UseTexEnvProgram = 1; | ||||
|  | ||||
|    driInitExtensions(ctx, i915_extensions, GL_FALSE); | ||||
|  | ||||
| @@ -179,4 +172,3 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -45,6 +45,8 @@ | ||||
| #define I915_UPLOAD_PROGRAM          0x8 | ||||
| #define I915_UPLOAD_CONSTANTS        0x10 | ||||
| #define I915_UPLOAD_FOG              0x20 | ||||
| #define I915_UPLOAD_INVARIENT        0x40 | ||||
| #define I915_UPLOAD_DEFAULTS         0x80 | ||||
| #define I915_UPLOAD_TEX(i)           (0x00010000<<(i)) | ||||
| #define I915_UPLOAD_TEX_ALL          (0x00ff0000) | ||||
| #define I915_UPLOAD_TEX_0_SHIFT      16 | ||||
| @@ -54,10 +56,8 @@ | ||||
|  */ | ||||
| #define I915_DESTREG_CBUFADDR0 0 | ||||
| #define I915_DESTREG_CBUFADDR1 1 | ||||
| #define I915_DESTREG_CBUFADDR2 2 | ||||
| #define I915_DESTREG_DBUFADDR0 3 | ||||
| #define I915_DESTREG_DBUFADDR1 4 | ||||
| #define I915_DESTREG_DBUFADDR2 5 | ||||
| #define I915_DESTREG_DV0 6 | ||||
| #define I915_DESTREG_DV1 7 | ||||
| #define I915_DESTREG_SENABLE 8 | ||||
| @@ -88,7 +88,6 @@ | ||||
| #define I915_STPREG_ST1        1 | ||||
| #define I915_STP_SETUP_SIZE    2 | ||||
|  | ||||
| #define I915_TEXREG_MS2        0 | ||||
| #define I915_TEXREG_MS3        1 | ||||
| #define I915_TEXREG_MS4        2 | ||||
| #define I915_TEXREG_SS2        3 | ||||
| @@ -96,6 +95,15 @@ | ||||
| #define I915_TEXREG_SS4        5 | ||||
| #define I915_TEX_SETUP_SIZE    6 | ||||
|  | ||||
| #define I915_DEFREG_C0    0 | ||||
| #define I915_DEFREG_C1    1 | ||||
| #define I915_DEFREG_S0    2 | ||||
| #define I915_DEFREG_S1    3 | ||||
| #define I915_DEFREG_Z0    4 | ||||
| #define I915_DEFREG_Z1    5 | ||||
| #define I915_DEF_SETUP_SIZE    6 | ||||
|  | ||||
|  | ||||
| #define I915_MAX_CONSTANT      32 | ||||
| #define I915_CONSTANT_SIZE     (2+(4*I915_MAX_CONSTANT)) | ||||
|  | ||||
| @@ -106,7 +114,8 @@ | ||||
| /* Hardware version of a parsed fragment program.  "Derived" from the | ||||
|  * mesa fragment_program struct. | ||||
|  */ | ||||
| struct i915_fragment_program { | ||||
| struct i915_fragment_program | ||||
| { | ||||
|    struct gl_fragment_program FragProg; | ||||
|  | ||||
|    GLboolean translated; | ||||
| @@ -158,15 +167,14 @@ struct i915_fragment_program { | ||||
|    GLuint wpos_tex; | ||||
|    GLboolean depth_written; | ||||
|  | ||||
|    struct {  | ||||
|    struct | ||||
|    { | ||||
|       GLuint reg;               /* Hardware constant idx */ | ||||
|       const GLfloat *values;    /* Pointer to tracked values */ | ||||
|    } param[I915_MAX_CONSTANT]; | ||||
|    GLuint nr_params; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|    /* Helpers for i915_texprog.c: | ||||
|     */ | ||||
|    GLuint src_texture;          /* Reg containing sampled texture color, | ||||
| @@ -187,27 +195,37 @@ struct i915_fragment_program { | ||||
|  | ||||
|  | ||||
|  | ||||
| struct i915_texture_object | ||||
| { | ||||
|    struct intel_texture_object intel; | ||||
|    GLenum lastTarget; | ||||
|    GLboolean refs_border_color; | ||||
|    GLuint Setup[I915_TEX_SETUP_SIZE]; | ||||
| }; | ||||
|  | ||||
| #define I915_TEX_UNITS 8 | ||||
|  | ||||
|  | ||||
| struct i915_hw_state { | ||||
| struct i915_hw_state | ||||
| { | ||||
|    GLuint Ctx[I915_CTX_SETUP_SIZE]; | ||||
|    GLuint Buffer[I915_DEST_SETUP_SIZE]; | ||||
|    GLuint Stipple[I915_STP_SETUP_SIZE]; | ||||
|    GLuint Fog[I915_FOG_SETUP_SIZE]; | ||||
|    GLuint Defaults[I915_DEF_SETUP_SIZE]; | ||||
|    GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE]; | ||||
|    GLuint Constant[I915_CONSTANT_SIZE]; | ||||
|    GLuint ConstantSize; | ||||
|    GLuint Program[I915_PROGRAM_SIZE]; | ||||
|    GLuint ProgramSize; | ||||
|  | ||||
|    /* Region pointers for relocation:  | ||||
|     */ | ||||
|    struct intel_region *draw_region; | ||||
|    struct intel_region *depth_region; | ||||
| /*    struct intel_region *tex_region[I915_TEX_UNITS]; */ | ||||
|  | ||||
|    /* Regions aren't actually that appropriate here as the memory may | ||||
|     * be from a PBO or FBO.  Just use the buffer id.  Will have to do | ||||
|     * this for draw and depth for FBO's... | ||||
|     */ | ||||
|    struct _DriBufferObject *tex_buffer[I915_TEX_UNITS]; | ||||
|    GLuint tex_offset[I915_TEX_UNITS]; | ||||
|  | ||||
|  | ||||
|    GLuint active;               /* I915_UPLOAD_* */ | ||||
|    GLuint emitted;              /* I915_UPLOAD_* */ | ||||
| }; | ||||
| @@ -222,6 +240,8 @@ struct i915_context | ||||
|  | ||||
|    GLuint last_ReallyEnabled; | ||||
|    GLuint vertex_fog; | ||||
|    GLuint lodbias_ss2[MAX_TEXTURE_UNITS]; | ||||
|  | ||||
|  | ||||
|    struct i915_fragment_program tex_program; | ||||
|    struct i915_fragment_program *current_program; | ||||
| @@ -230,24 +250,14 @@ struct i915_context | ||||
| }; | ||||
|  | ||||
|  | ||||
| typedef struct i915_context *i915ContextPtr; | ||||
| typedef struct i915_texture_object *i915TextureObjectPtr; | ||||
|  | ||||
| #define I915_CONTEXT(ctx)	((i915ContextPtr)(ctx)) | ||||
|  | ||||
|  | ||||
|  | ||||
| #define I915_STATECHANGE(i915, flag)					\ | ||||
| do {									\ | ||||
|    if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__);	\ | ||||
|    INTEL_FIREVERTICES( &(i915)->intel );					\ | ||||
|    (i915)->state.emitted &= ~(flag);					\ | ||||
| } while (0) | ||||
|  | ||||
| #define I915_ACTIVESTATE(i915, flag, mode)			\ | ||||
| do {								\ | ||||
|    if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n",	\ | ||||
| 		  flag, mode, __FUNCTION__);			\ | ||||
|    INTEL_FIREVERTICES( &(i915)->intel );				\ | ||||
|    if (mode)							\ | ||||
|       (i915)->state.active |= (flag);				\ | ||||
| @@ -259,7 +269,13 @@ do {								\ | ||||
| /*====================================================================== | ||||
|  * i915_vtbl.c | ||||
|  */ | ||||
| extern void i915InitVtbl( i915ContextPtr i915 ); | ||||
| extern void i915InitVtbl(struct i915_context *i915); | ||||
|  | ||||
| extern void | ||||
| i915_state_draw_region(struct intel_context *intel, | ||||
|                        struct i915_hw_state *state, | ||||
|                        struct intel_region *color_region, | ||||
|                        struct intel_region *depth_region); | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -296,7 +312,7 @@ extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
| /*====================================================================== | ||||
|  * i915_texprog.c | ||||
|  */ | ||||
| extern void i915ValidateTextureProgram( i915ContextPtr i915 ); | ||||
| extern void i915ValidateTextureProgram(struct i915_context *i915); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
| @@ -310,48 +326,42 @@ extern void i915_print_ureg( const char *msg, GLuint ureg ); | ||||
|  * i915_state.c | ||||
|  */ | ||||
| extern void i915InitStateFunctions(struct dd_function_table *functions); | ||||
| extern void i915InitState( i915ContextPtr i915 ); | ||||
| extern void i915_update_fog(GLcontext *ctxx); | ||||
| extern void i915InitState(struct i915_context *i915); | ||||
| extern void i915_update_fog(GLcontext * ctx); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_tex.c | ||||
|  */ | ||||
| extern void i915UpdateTextureState( intelContextPtr intel ); | ||||
| extern void i915UpdateTextureState(struct intel_context *intel); | ||||
| extern void i915InitTextureFuncs(struct dd_function_table *functions); | ||||
| extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ); | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_metaops.c | ||||
|  */ | ||||
| extern GLboolean | ||||
| i915TryTextureReadPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *pack, | ||||
| 			  GLvoid *pixels ); | ||||
| void i915InitMetaFuncs(struct i915_context *i915); | ||||
|  | ||||
| extern GLboolean | ||||
| i915TryTextureDrawPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  const GLvoid *pixels ); | ||||
|  | ||||
| extern void  | ||||
| i915ClearWithTris( intelContextPtr intel, GLbitfield mask, | ||||
| 		   GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|  | ||||
|  | ||||
| extern void | ||||
| i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, | ||||
|                  GLuint srcBuf); | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_fragprog.c | ||||
|  */ | ||||
| extern void i915ValidateFragmentProgram( i915ContextPtr i915 ); | ||||
| extern void i915ValidateFragmentProgram(struct i915_context *i915); | ||||
| extern void i915InitFragProgFuncs(struct dd_function_table *functions); | ||||
|  | ||||
| #endif | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.  These are better-typed than the | ||||
|  * macros used previously: | ||||
|  */ | ||||
| static INLINE struct i915_context * | ||||
| i915_context(GLcontext * ctx) | ||||
| { | ||||
|    return (struct i915_context *) ctx; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #define I915_CONTEXT(ctx)	i915_context(ctx) | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -113,15 +113,24 @@ static const char *regname[0x8] = { | ||||
|    "UNKNOWN", | ||||
| }; | ||||
|  | ||||
| static void print_reg_type_nr( GLuint type, GLuint nr ) | ||||
| static void | ||||
| print_reg_type_nr(GLuint type, GLuint nr) | ||||
| { | ||||
|    switch (type) { | ||||
|    case REG_TYPE_T: | ||||
|       switch (nr) { | ||||
|       case T_DIFFUSE: fprintf(stderr, "T_DIFFUSE"); return; | ||||
|       case T_SPECULAR: fprintf(stderr, "T_SPECULAR"); return; | ||||
|       case T_FOG_W: fprintf(stderr, "T_FOG_W"); return; | ||||
|       default: fprintf(stderr, "T_TEX%d", nr); return; | ||||
|       case T_DIFFUSE: | ||||
|          fprintf(stderr, "T_DIFFUSE"); | ||||
|          return; | ||||
|       case T_SPECULAR: | ||||
|          fprintf(stderr, "T_SPECULAR"); | ||||
|          return; | ||||
|       case T_FOG_W: | ||||
|          fprintf(stderr, "T_FOG_W"); | ||||
|          return; | ||||
|       default: | ||||
|          fprintf(stderr, "T_TEX%d", nr); | ||||
|          return; | ||||
|       } | ||||
|    case REG_TYPE_OC: | ||||
|       if (nr == 0) { | ||||
| @@ -151,7 +160,8 @@ static void print_reg_type_nr( GLuint type, GLuint nr ) | ||||
| 		      (SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) | ||||
|  | ||||
|  | ||||
| static void print_reg_neg_swizzle( GLuint reg ) | ||||
| static void | ||||
| print_reg_neg_swizzle(GLuint reg) | ||||
| { | ||||
|    int i; | ||||
|  | ||||
| @@ -166,19 +176,34 @@ static void print_reg_neg_swizzle( GLuint reg ) | ||||
|          fprintf(stderr, "-"); | ||||
|  | ||||
|       switch ((reg >> (i * 4)) & 0x7) { | ||||
|       case 0: fprintf(stderr, "x"); break; | ||||
|       case 1: fprintf(stderr, "y"); break; | ||||
|       case 2: fprintf(stderr, "z"); break; | ||||
|       case 3: fprintf(stderr, "w"); break; | ||||
|       case 4: fprintf(stderr, "0"); break; | ||||
|       case 5: fprintf(stderr, "1"); break; | ||||
|       default: fprintf(stderr, "?"); break; | ||||
|       case 0: | ||||
|          fprintf(stderr, "x"); | ||||
|          break; | ||||
|       case 1: | ||||
|          fprintf(stderr, "y"); | ||||
|          break; | ||||
|       case 2: | ||||
|          fprintf(stderr, "z"); | ||||
|          break; | ||||
|       case 3: | ||||
|          fprintf(stderr, "w"); | ||||
|          break; | ||||
|       case 4: | ||||
|          fprintf(stderr, "0"); | ||||
|          break; | ||||
|       case 5: | ||||
|          fprintf(stderr, "1"); | ||||
|          break; | ||||
|       default: | ||||
|          fprintf(stderr, "?"); | ||||
|          break; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void print_src_reg( GLuint dword ) | ||||
| static void | ||||
| print_src_reg(GLuint dword) | ||||
| { | ||||
|    GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; | ||||
|    GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; | ||||
| @@ -186,14 +211,16 @@ static void print_src_reg( GLuint dword ) | ||||
|    print_reg_neg_swizzle(dword); | ||||
| } | ||||
|  | ||||
| void i915_print_ureg( const char *msg, GLuint ureg ) | ||||
| void | ||||
| i915_print_ureg(const char *msg, GLuint ureg) | ||||
| { | ||||
|    fprintf(stderr, "%s: ", msg); | ||||
|    print_src_reg(ureg >> 8); | ||||
|    fprintf(stderr, "\n"); | ||||
| } | ||||
|  | ||||
| static void print_dest_reg( GLuint dword ) | ||||
| static void | ||||
| print_dest_reg(GLuint dword) | ||||
| { | ||||
|    GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; | ||||
|    GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; | ||||
| @@ -201,10 +228,14 @@ static void print_dest_reg( GLuint dword ) | ||||
|    if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) | ||||
|       return; | ||||
|    fprintf(stderr, "."); | ||||
|    if (dword & A0_DEST_CHANNEL_X) fprintf(stderr, "x"); | ||||
|    if (dword & A0_DEST_CHANNEL_Y) fprintf(stderr, "y"); | ||||
|    if (dword & A0_DEST_CHANNEL_Z) fprintf(stderr, "z"); | ||||
|    if (dword & A0_DEST_CHANNEL_W) fprintf(stderr, "w"); | ||||
|    if (dword & A0_DEST_CHANNEL_X) | ||||
|       fprintf(stderr, "x"); | ||||
|    if (dword & A0_DEST_CHANNEL_Y) | ||||
|       fprintf(stderr, "y"); | ||||
|    if (dword & A0_DEST_CHANNEL_Z) | ||||
|       fprintf(stderr, "z"); | ||||
|    if (dword & A0_DEST_CHANNEL_W) | ||||
|       fprintf(stderr, "w"); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -213,7 +244,8 @@ static void print_dest_reg( GLuint dword ) | ||||
| #define GET_SRC2_REG(r)      (r) | ||||
|  | ||||
|  | ||||
| static void print_arith_op( GLuint opcode, const GLuint *program ) | ||||
| static void | ||||
| print_arith_op(GLuint opcode, const GLuint * program) | ||||
| { | ||||
|    if (opcode != A0_NOP) { | ||||
|       print_dest_reg(program[0]); | ||||
| @@ -245,22 +277,24 @@ static void print_arith_op( GLuint opcode, const GLuint *program ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void print_tex_op( GLuint opcode, const GLuint *program ) | ||||
| static void | ||||
| print_tex_op(GLuint opcode, const GLuint * program) | ||||
| { | ||||
|    print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); | ||||
|    fprintf(stderr, " = "); | ||||
|  | ||||
|    fprintf(stderr, "%s ", opcodes[opcode]); | ||||
|  | ||||
|    fprintf(stderr, "S[%d],",  | ||||
| 	   program[0] & T0_SAMPLER_NR_MASK); | ||||
|    fprintf(stderr, "S[%d],", program[0] & T0_SAMPLER_NR_MASK); | ||||
|  | ||||
|    print_reg_type_nr( (program[1]>>T1_ADDRESS_REG_TYPE_SHIFT) & REG_TYPE_MASK, | ||||
|    print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & | ||||
|                      REG_TYPE_MASK, | ||||
|                      (program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); | ||||
|    fprintf(stderr, "\n"); | ||||
| } | ||||
|  | ||||
| static void print_dcl_op( GLuint opcode, const GLuint *program ) | ||||
| static void | ||||
| print_dcl_op(GLuint opcode, const GLuint * program) | ||||
| { | ||||
|    fprintf(stderr, "%s ", opcodes[opcode]); | ||||
|    print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); | ||||
| @@ -268,7 +302,8 @@ static void print_dcl_op( GLuint opcode, const GLuint *program ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915_disassemble_program( const GLuint *program, GLuint sz ) | ||||
| void | ||||
| i915_disassemble_program(const GLuint * program, GLuint sz) | ||||
| { | ||||
|    GLuint size = program[0] & 0x1ff; | ||||
|    GLint i; | ||||
|   | ||||
| @@ -45,19 +45,22 @@ | ||||
| static const GLfloat sin_constants[4] = { 1.0, | ||||
|    -1.0 / (3 * 2 * 1), | ||||
|    1.0 / (5 * 4 * 3 * 2 * 1), | ||||
| 					   -1.0/(7*6*5*4*3*2*1) }; | ||||
|    -1.0 / (7 * 6 * 5 * 4 * 3 * 2 * 1) | ||||
| }; | ||||
|  | ||||
| /* 1, -1/2!, 1/4!, -1/6! */ | ||||
| static const GLfloat cos_constants[4] = { 1.0, | ||||
|    -1.0 / (2 * 1), | ||||
|    1.0 / (4 * 3 * 2 * 1), | ||||
| 					   -1.0/(6*5*4*3*2*1) }; | ||||
|    -1.0 / (6 * 5 * 4 * 3 * 2 * 1) | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Retrieve a ureg for the given source register.  Will emit | ||||
|  * constants, apply swizzling and negation as needed. | ||||
|  */ | ||||
| static GLuint src_vector( struct i915_fragment_program *p, | ||||
| static GLuint | ||||
| src_vector(struct i915_fragment_program *p, | ||||
|            const struct prog_src_register *source, | ||||
|            const struct gl_fragment_program *program) | ||||
| { | ||||
| @@ -113,19 +116,22 @@ static GLuint src_vector( struct i915_fragment_program *p, | ||||
|        * hardware as program constants. | ||||
|        */ | ||||
|    case PROGRAM_LOCAL_PARAM: | ||||
|          src = i915_emit_param4fv(  | ||||
| 	    p, program->Base.LocalParams[source->Index]); | ||||
|       src = i915_emit_param4fv(p, program->Base.LocalParams[source->Index]); | ||||
|       break; | ||||
|  | ||||
|    case PROGRAM_ENV_PARAM: | ||||
|          src = i915_emit_param4fv(  | ||||
| 	    p, p->ctx->FragmentProgram.Parameters[source->Index]); | ||||
|       src = | ||||
|          i915_emit_param4fv(p, | ||||
|                             p->ctx->FragmentProgram.Parameters[source-> | ||||
|                                                                Index]); | ||||
|       break; | ||||
|  | ||||
|    case PROGRAM_STATE_VAR: | ||||
|    case PROGRAM_NAMED_PARAM: | ||||
|          src = i915_emit_param4fv(  | ||||
| 	    p, program->Base.Parameters->ParameterValues[source->Index] ); | ||||
|       src = | ||||
|          i915_emit_param4fv(p, | ||||
|                             program->Base.Parameters->ParameterValues[source-> | ||||
|                                                                       Index]); | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
| @@ -136,8 +142,7 @@ static GLuint src_vector( struct i915_fragment_program *p, | ||||
|    src = swizzle(src, | ||||
|                  GET_SWZ(source->Swizzle, 0), | ||||
|                  GET_SWZ(source->Swizzle, 1), | ||||
| 		 GET_SWZ(source->Swizzle, 2), | ||||
| 		 GET_SWZ(source->Swizzle, 3)); | ||||
|                  GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3)); | ||||
|  | ||||
|    if (source->NegateBase) | ||||
|       src = negate(src, | ||||
| @@ -150,7 +155,8 @@ static GLuint src_vector( struct i915_fragment_program *p, | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLuint get_result_vector( struct i915_fragment_program *p, | ||||
| static GLuint | ||||
| get_result_vector(struct i915_fragment_program *p, | ||||
|                   const struct prog_instruction *inst) | ||||
| { | ||||
|    switch (inst->DstReg.File) { | ||||
| @@ -173,29 +179,42 @@ static GLuint get_result_vector( struct i915_fragment_program *p, | ||||
|    } | ||||
| } | ||||
|  | ||||
| static GLuint get_result_flags( const struct prog_instruction *inst ) | ||||
| static GLuint | ||||
| get_result_flags(const struct prog_instruction *inst) | ||||
| { | ||||
|    GLuint flags = 0; | ||||
|  | ||||
|    if (inst->SaturateMode == SATURATE_ZERO_ONE) flags |= A0_DEST_SATURATE; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_X) flags |= A0_DEST_CHANNEL_X; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_Y) flags |= A0_DEST_CHANNEL_Y; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_Z) flags |= A0_DEST_CHANNEL_Z; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_W) flags |= A0_DEST_CHANNEL_W; | ||||
|    if (inst->SaturateMode == SATURATE_ZERO_ONE) | ||||
|       flags |= A0_DEST_SATURATE; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_X) | ||||
|       flags |= A0_DEST_CHANNEL_X; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_Y) | ||||
|       flags |= A0_DEST_CHANNEL_Y; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_Z) | ||||
|       flags |= A0_DEST_CHANNEL_Z; | ||||
|    if (inst->DstReg.WriteMask & WRITEMASK_W) | ||||
|       flags |= A0_DEST_CHANNEL_W; | ||||
|  | ||||
|    return flags; | ||||
| } | ||||
|  | ||||
| static GLuint translate_tex_src_target( struct i915_fragment_program *p, | ||||
| 				     GLubyte bit ) | ||||
| static GLuint | ||||
| translate_tex_src_target(struct i915_fragment_program *p, GLubyte bit) | ||||
| { | ||||
|    switch (bit) { | ||||
|    case TEXTURE_1D_INDEX:   return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_2D_INDEX:   return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_RECT_INDEX: return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_3D_INDEX:   return D0_SAMPLE_TYPE_VOLUME; | ||||
|    case TEXTURE_CUBE_INDEX: return D0_SAMPLE_TYPE_CUBE; | ||||
|    default: i915_program_error(p, "TexSrcBit"); return 0; | ||||
|    case TEXTURE_1D_INDEX: | ||||
|       return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_2D_INDEX: | ||||
|       return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_RECT_INDEX: | ||||
|       return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_3D_INDEX: | ||||
|       return D0_SAMPLE_TYPE_VOLUME; | ||||
|    case TEXTURE_CUBE_INDEX: | ||||
|       return D0_SAMPLE_TYPE_CUBE; | ||||
|    default: | ||||
|       i915_program_error(p, "TexSrcBit"); | ||||
|       return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
| @@ -242,9 +261,11 @@ do {									\ | ||||
|  * can lead to confusion -- hopefully we cope with it ok now. | ||||
|  * | ||||
|  */ | ||||
| static void upload_program( struct i915_fragment_program *p ) | ||||
| static void | ||||
| upload_program(struct i915_fragment_program *p) | ||||
| { | ||||
|    const struct gl_fragment_program *program = p->ctx->FragmentProgram._Current; | ||||
|    const struct gl_fragment_program *program = | ||||
|       p->ctx->FragmentProgram._Current; | ||||
|    const struct prog_instruction *inst = program->Base.Instructions; | ||||
|  | ||||
| /*    _mesa_debug_fp_inst(program->Base.NumInstructions, inst); */ | ||||
| @@ -285,11 +306,7 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|          src0 = src_vector(p, &inst->SrcReg[0], program); | ||||
|          src1 = src_vector(p, &inst->SrcReg[1], program); | ||||
|          src2 = src_vector(p, &inst->SrcReg[2], program); | ||||
| 	 i915_emit_arith( p,  | ||||
| 			 A0_CMP, | ||||
| 			 get_result_vector( p, inst ),  | ||||
| 			 get_result_flags( inst ), 0, | ||||
| 			 src0, src2, src1);	/* NOTE: order of src2, src1 */ | ||||
|          i915_emit_arith(p, A0_CMP, get_result_vector(p, inst), get_result_flags(inst), 0, src0, src2, src1);   /* NOTE: order of src2, src1 */ | ||||
|          break; | ||||
|  | ||||
|       case OPCODE_COS: | ||||
| @@ -299,24 +316,16 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|          i915_emit_arith(p, | ||||
|                          A0_MUL, | ||||
|                          tmp, A0_DEST_CHANNEL_X, 0, | ||||
| 			 src0,  | ||||
| 			 i915_emit_const1f(p, 1.0/(M_PI * 2)), | ||||
| 			 0); | ||||
|                          src0, i915_emit_const1f(p, 1.0 / (M_PI * 2)), 0); | ||||
|  | ||||
| 	 i915_emit_arith( p,  | ||||
| 			 A0_MOD, | ||||
| 			 tmp, A0_DEST_CHANNEL_X, 0, | ||||
| 			 tmp,  | ||||
| 			 0, 0 ); | ||||
|          i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); | ||||
|  | ||||
|          /* By choosing different taylor constants, could get rid of this mul: | ||||
|           */ | ||||
|          i915_emit_arith(p, | ||||
|                          A0_MUL, | ||||
|                          tmp, A0_DEST_CHANNEL_X, 0, | ||||
| 			 tmp,  | ||||
| 			 i915_emit_const1f(p, (M_PI * 2)), | ||||
| 			 0); | ||||
|                          tmp, i915_emit_const1f(p, (M_PI * 2)), 0); | ||||
|  | ||||
|          /*  | ||||
|           * t0.xy = MUL x.xx11, x.x1111  ; x^2, x, 1, 1 | ||||
| @@ -384,8 +393,7 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|                          get_result_vector(p, inst), | ||||
|                          get_result_flags(inst), 0, | ||||
|                          swizzle(src0, ONE, Y, Z, ONE), | ||||
| 			 swizzle(src1, ONE, Y, ONE, W  ), | ||||
| 			 0); | ||||
|                          swizzle(src1, ONE, Y, ONE, W), 0); | ||||
|          break; | ||||
|  | ||||
|       case OPCODE_EX2: | ||||
| @@ -410,11 +418,8 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|          src0 = src_vector(p, &inst->SrcReg[0], program); | ||||
|          tmp = i915_get_utemp(p); | ||||
|  | ||||
| 	 i915_emit_texld( p, | ||||
| 			 tmp, A0_DEST_CHANNEL_ALL, /* use a dummy dest reg */ | ||||
| 			 0, | ||||
| 			 src0, | ||||
| 			 T0_TEXKILL ); | ||||
|          i915_emit_texld(p, tmp, A0_DEST_CHANNEL_ALL,   /* use a dummy dest reg */ | ||||
|                          0, src0, T0_TEXKILL); | ||||
|          break; | ||||
|  | ||||
|       case OPCODE_LG2: | ||||
| @@ -475,13 +480,11 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|           * result = (-c)*a + tmp  | ||||
|           */ | ||||
|          i915_emit_arith(p, A0_MAD, tmp, | ||||
| 			 flags & A0_DEST_CHANNEL_ALL, 0, | ||||
| 			 src1, src0, src2 ); | ||||
|                          flags & A0_DEST_CHANNEL_ALL, 0, src1, src0, src2); | ||||
|  | ||||
|          i915_emit_arith(p, A0_MAD, | ||||
|                          get_result_vector(p, inst), | ||||
| 			 flags, 0,  | ||||
| 			 negate(src2, 1,1,1,1), src0, tmp ); | ||||
|                          flags, 0, negate(src2, 1, 1, 1, 1), src0, tmp); | ||||
|          break; | ||||
|  | ||||
|       case OPCODE_MAD: | ||||
| @@ -507,8 +510,7 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|          i915_emit_arith(p, | ||||
|                          A0_MOV, | ||||
|                          get_result_vector(p, inst), | ||||
| 			 flags, 0, | ||||
| 			 negate(tmp, 1,1,1,1), 0, 0); | ||||
|                          flags, 0, negate(tmp, 1, 1, 1, 1), 0, 0); | ||||
|          break; | ||||
|  | ||||
|       case OPCODE_MOV: | ||||
| @@ -532,17 +534,13 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|                          tmp, A0_DEST_CHANNEL_X, 0, | ||||
|                          swizzle(src0, X, X, X, X), 0, 0); | ||||
|  | ||||
| 	 i915_emit_arith( p, | ||||
| 			 A0_MUL, | ||||
| 			 tmp, A0_DEST_CHANNEL_X, 0, | ||||
| 			 tmp, src1, 0); | ||||
|          i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_X, 0, tmp, src1, 0); | ||||
|  | ||||
|  | ||||
|          i915_emit_arith(p, | ||||
|                          A0_EXP, | ||||
|                          get_result_vector(p, inst), | ||||
| 			 flags, 0, | ||||
| 			 swizzle(tmp,X,X,X,X), 0, 0); | ||||
|                          flags, 0, swizzle(tmp, X, X, X, X), 0, 0); | ||||
|  | ||||
|          break; | ||||
|  | ||||
| @@ -640,24 +638,16 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|          i915_emit_arith(p, | ||||
|                          A0_MUL, | ||||
|                          tmp, A0_DEST_CHANNEL_X, 0, | ||||
| 			 src0,  | ||||
| 			 i915_emit_const1f(p, 1.0/(M_PI * 2)), | ||||
| 			 0); | ||||
|                          src0, i915_emit_const1f(p, 1.0 / (M_PI * 2)), 0); | ||||
|  | ||||
| 	 i915_emit_arith( p,  | ||||
| 			 A0_MOD, | ||||
| 			 tmp, A0_DEST_CHANNEL_X, 0, | ||||
| 			 tmp,  | ||||
| 			 0, 0 ); | ||||
|          i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); | ||||
|  | ||||
|          /* By choosing different taylor constants, could get rid of this mul: | ||||
|           */ | ||||
|          i915_emit_arith(p, | ||||
|                          A0_MUL, | ||||
|                          tmp, A0_DEST_CHANNEL_X, 0, | ||||
| 			 tmp,  | ||||
| 			 i915_emit_const1f(p, (M_PI * 2)), | ||||
| 			 0); | ||||
|                          tmp, i915_emit_const1f(p, (M_PI * 2)), 0); | ||||
|  | ||||
|          /*  | ||||
|           * t0.xy = MUL x.xx11, x.x1111  ; x^2, x, 1, 1 | ||||
| @@ -765,7 +755,8 @@ static void upload_program( struct i915_fragment_program *p ) | ||||
|  * emit, just move the value into its correct position at the end of | ||||
|  * the program: | ||||
|  */ | ||||
| static void fixup_depth_write( struct i915_fragment_program *p ) | ||||
| static void | ||||
| fixup_depth_write(struct i915_fragment_program *p) | ||||
| { | ||||
|    if (p->depth_written) { | ||||
|       GLuint depth = UREG(REG_TYPE_OD, 0); | ||||
| @@ -773,8 +764,7 @@ static void fixup_depth_write( struct i915_fragment_program *p ) | ||||
|       i915_emit_arith(p, | ||||
|                       A0_MOV, | ||||
|                       depth, A0_DEST_CHANNEL_W, 0, | ||||
| 		      swizzle(depth,X,Y,Z,Z),  | ||||
| 		      0, 0); | ||||
|                       swizzle(depth, X, Y, Z, Z), 0, 0); | ||||
|    } | ||||
| } | ||||
|  | ||||
| @@ -782,7 +772,8 @@ static void fixup_depth_write( struct i915_fragment_program *p ) | ||||
| #define FRAG_BIT_TEX(n)  (FRAG_BIT_TEX0 << (n)) | ||||
|  | ||||
|  | ||||
| static void check_wpos( struct i915_fragment_program *p ) | ||||
| static void | ||||
| check_wpos(struct i915_fragment_program *p) | ||||
| { | ||||
|    GLuint inputs = p->FragProg.Base.InputsRead; | ||||
|    GLint i; | ||||
| @@ -804,9 +795,10 @@ static void check_wpos( struct i915_fragment_program *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void translate_program( struct i915_fragment_program *p ) | ||||
| static void | ||||
| translate_program(struct i915_fragment_program *p) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(p->ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(p->ctx); | ||||
|  | ||||
|    i915_init_program(i915, p); | ||||
|    check_wpos(p); | ||||
| @@ -818,7 +810,8 @@ static void translate_program( struct i915_fragment_program *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void track_params( struct i915_fragment_program *p ) | ||||
| static void | ||||
| track_params(struct i915_fragment_program *p) | ||||
| { | ||||
|    GLint i; | ||||
|  | ||||
| @@ -835,12 +828,11 @@ static void track_params( struct i915_fragment_program *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915BindProgram( GLcontext *ctx, | ||||
| 			    GLenum target,  | ||||
| 			    struct gl_program *prog ) | ||||
| static void | ||||
| i915BindProgram(GLcontext * ctx, GLenum target, struct gl_program *prog) | ||||
| { | ||||
|    if (target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *) prog; | ||||
|  | ||||
|       if (i915->current_program == p) | ||||
| @@ -864,9 +856,8 @@ static void i915BindProgram( GLcontext *ctx, | ||||
|    } | ||||
| } | ||||
|  | ||||
| static struct gl_program *i915NewProgram( GLcontext *ctx, | ||||
| 				      GLenum target,  | ||||
| 				      GLuint id ) | ||||
| static struct gl_program * | ||||
| i915NewProgram(GLcontext * ctx, GLenum target, GLuint id) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_VERTEX_PROGRAM_ARB: | ||||
| @@ -874,7 +865,8 @@ static struct gl_program *i915NewProgram( GLcontext *ctx, | ||||
|                                        target, id); | ||||
|  | ||||
|    case GL_FRAGMENT_PROGRAM_ARB:{ | ||||
|       struct i915_fragment_program *prog = CALLOC_STRUCT(i915_fragment_program); | ||||
|          struct i915_fragment_program *prog = | ||||
|             CALLOC_STRUCT(i915_fragment_program); | ||||
|          if (prog) { | ||||
|             i915_init_program(I915_CONTEXT(ctx), prog); | ||||
|  | ||||
| @@ -892,11 +884,11 @@ static struct gl_program *i915NewProgram( GLcontext *ctx, | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i915DeleteProgram( GLcontext *ctx, | ||||
| 			      struct gl_program *prog ) | ||||
| static void | ||||
| i915DeleteProgram(GLcontext * ctx, struct gl_program *prog) | ||||
| { | ||||
|    if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *) prog; | ||||
|  | ||||
|       if (i915->current_program == p) | ||||
| @@ -907,9 +899,8 @@ static void i915DeleteProgram( GLcontext *ctx, | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean i915IsProgramNative( GLcontext *ctx, | ||||
| 				     GLenum target,  | ||||
| 				     struct gl_program *prog ) | ||||
| static GLboolean | ||||
| i915IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog) | ||||
| { | ||||
|    if (target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *) prog; | ||||
| @@ -923,9 +914,9 @@ static GLboolean i915IsProgramNative( GLcontext *ctx, | ||||
|       return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static void i915ProgramStringNotify( GLcontext *ctx, | ||||
| 				    GLenum target, | ||||
| 				    struct gl_program *prog ) | ||||
| static void | ||||
| i915ProgramStringNotify(GLcontext * ctx, | ||||
|                         GLenum target, struct gl_program *prog) | ||||
| { | ||||
|    if (target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *) prog; | ||||
| @@ -940,10 +931,11 @@ static void i915ProgramStringNotify( GLcontext *ctx, | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
| void | ||||
| i915ValidateFragmentProgram(struct i915_context *i915) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|  | ||||
| @@ -955,6 +947,16 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
|    GLuint s2 = S2_TEXCOORD_NONE; | ||||
|    int i, offset = 0; | ||||
|  | ||||
|    if (i915->current_program != p) { | ||||
|       if (i915->current_program) { | ||||
|          i915->current_program->on_hardware = 0; | ||||
|          i915->current_program->params_uptodate = 0; | ||||
|       } | ||||
|  | ||||
|       i915->current_program = p; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* Important: | ||||
|     */ | ||||
|    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; | ||||
| @@ -1028,6 +1030,7 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
|  | ||||
|    if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || | ||||
|        s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { | ||||
|       int k; | ||||
|  | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
| @@ -1044,7 +1047,8 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
|       i915->state.Ctx[I915_CTXREG_LIS2] = s2; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] = s4; | ||||
|  | ||||
|       assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size )); | ||||
|       k = intel->vtbl.check_vertex_size(intel, intel->vertex_size); | ||||
|       assert(k); | ||||
|    } | ||||
|  | ||||
|    if (!p->params_uptodate) | ||||
| @@ -1054,7 +1058,8 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
|       i915_upload_program(i915, p); | ||||
| } | ||||
|  | ||||
| void i915InitFragProgFuncs( struct dd_function_table *functions ) | ||||
| void | ||||
| i915InitFragProgFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|    functions->BindProgram = i915BindProgram; | ||||
|    functions->NewProgram = i915NewProgram; | ||||
|   | ||||
| @@ -34,17 +34,20 @@ | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_rotate.h" | ||||
|  | ||||
| #include "i915_context.h" | ||||
| #include "i915_reg.h" | ||||
|  | ||||
| /* A large amount of state doesn't need to be uploaded. | ||||
| /* We touch almost everything: | ||||
|  */ | ||||
| #define ACTIVE (I915_UPLOAD_PROGRAM | 		\ | ||||
| 		I915_UPLOAD_STIPPLE |		\ | ||||
| #define ACTIVE (I915_UPLOAD_INVARIENT | 	\ | ||||
| 		I915_UPLOAD_CTX |		\ | ||||
| 		I915_UPLOAD_BUFFERS |		\ | ||||
| 		I915_UPLOAD_STIPPLE |		\ | ||||
|                 I915_UPLOAD_PROGRAM | 		\ | ||||
|                 I915_UPLOAD_FOG | 		\ | ||||
| 		I915_UPLOAD_TEX(0)) | ||||
|  | ||||
| #define SET_STATE( i915, STATE )		\ | ||||
| @@ -54,25 +57,25 @@ do {						\ | ||||
|    i915->current->emitted &= ~ACTIVE;		\ | ||||
| } while (0) | ||||
|  | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void set_initial_state( i915ContextPtr i915 ) | ||||
| { | ||||
|    memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) ); | ||||
|    i915->meta.active = ACTIVE; | ||||
|    i915->meta.emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_no_depth_stencil_write( i915ContextPtr i915 ) | ||||
| static void | ||||
| meta_no_stencil_write(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE | | ||||
|                                          S5_STENCIL_WRITE_ENABLE); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_no_depth_write(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE | | ||||
| @@ -81,12 +84,34 @@ static void set_no_depth_stencil_write( i915ContextPtr i915 ) | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_depth_replace(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_TRUE ) | ||||
|     * ctx->Driver.DepthMask( ctx, GL_TRUE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] |= (S6_DEPTH_TEST_ENABLE | | ||||
|                                         S6_DEPTH_WRITE_ENABLE); | ||||
|  | ||||
|    /* ctx->Driver.DepthFunc( ctx, GL_REPLACE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK; | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] |= | ||||
|       COMPAREFUNC_ALWAYS << S6_DEPTH_TEST_FUNC_SHIFT; | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Set stencil unit to replace always with the reference value. | ||||
|  */ | ||||
| static void set_stencil_replace( i915ContextPtr i915, | ||||
| 				 GLuint s_mask, | ||||
| 				 GLuint s_clear) | ||||
| static void | ||||
| meta_stencil_replace(struct intel_context *intel, | ||||
|                      GLuint s_mask, GLuint s_clear) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint op = STENCILOP_REPLACE; | ||||
|    GLuint func = COMPAREFUNC_ALWAYS; | ||||
|  | ||||
| @@ -95,13 +120,6 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | | ||||
|                                         S5_STENCIL_WRITE_ENABLE); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE | | ||||
| 				       S6_DEPTH_WRITE_ENABLE); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.StencilMask( ctx, s_mask ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; | ||||
| @@ -109,7 +127,6 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | | ||||
|                                           STENCIL_WRITE_MASK(s_mask)); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK | | ||||
| @@ -138,12 +155,13 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
| static void | ||||
| meta_color_mask(struct intel_context *intel, GLboolean state) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    const GLuint mask = (S5_WRITEDISABLE_RED | | ||||
|                         S5_WRITEDISABLE_GREEN | | ||||
| 			S5_WRITEDISABLE_BLUE | | ||||
| 			S5_WRITEDISABLE_ALPHA); | ||||
|                         S5_WRITEDISABLE_BLUE | S5_WRITEDISABLE_ALPHA); | ||||
|  | ||||
|    /* Copy colormask state from "regular" hw context. | ||||
|     */ | ||||
| @@ -160,6 +178,31 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| meta_import_pixel_state(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    memcpy(i915->meta.Fog, i915->state.Fog, I915_FOG_SETUP_SIZE * 4); | ||||
|  | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] = i915->state.Ctx[I915_CTXREG_LIS5]; | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] = i915->state.Ctx[I915_CTXREG_LIS6]; | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] = i915->state.Ctx[I915_CTXREG_STATE4]; | ||||
|    i915->meta.Ctx[I915_CTXREG_BLENDCOLOR1] = | ||||
|       i915->state.Ctx[I915_CTXREG_BLENDCOLOR1]; | ||||
|    i915->meta.Ctx[I915_CTXREG_IAB] = i915->state.Ctx[I915_CTXREG_IAB]; | ||||
|  | ||||
|    i915->meta.Buffer[I915_DESTREG_SENABLE] = | ||||
|       i915->state.Buffer[I915_DESTREG_SENABLE]; | ||||
|    i915->meta.Buffer[I915_DESTREG_SR1] = i915->state.Buffer[I915_DESTREG_SR1]; | ||||
|    i915->meta.Buffer[I915_DESTREG_SR2] = i915->state.Buffer[I915_DESTREG_SR2]; | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_FOG; | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #define REG( type, nr ) (((type)<<5)|(nr)) | ||||
|  | ||||
| @@ -211,16 +254,17 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void set_no_texture( i915ContextPtr i915 ) | ||||
| static void | ||||
| meta_no_texture(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    static const GLuint prog[] = { | ||||
|       _3DSTATE_PIXEL_SHADER_PROGRAM, | ||||
|  | ||||
|       /* Declare incoming diffuse color: | ||||
|        */ | ||||
|       (D0_DCL | | ||||
|        D0_DECL_REG( REG_T_DIFFUSE ) | | ||||
|        D0_CHANNEL_ALL), | ||||
|       (D0_DCL | D0_DECL_REG(REG_T_DIFFUSE) | D0_CHANNEL_ALL), | ||||
|       D1_MBZ, | ||||
|       D2_MBZ, | ||||
|  | ||||
| @@ -228,8 +272,7 @@ static void set_no_texture( i915ContextPtr i915 ) | ||||
|        */ | ||||
|       (A0_MOV | | ||||
|        A0_DEST_REG(REG_OC) | | ||||
|        A0_DEST_CHANNEL_ALL | | ||||
|        A0_SRC0_REG( REG_T_DIFFUSE )), | ||||
|        A0_DEST_CHANNEL_ALL | A0_SRC0_REG(REG_T_DIFFUSE)), | ||||
|       (A1_SRC0_XYZW), | ||||
|       0, | ||||
|    }; | ||||
| @@ -241,34 +284,29 @@ static void set_no_texture( i915ContextPtr i915 ) | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_PROGRAM; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void enable_texture_blend_replace( i915ContextPtr i915 ) | ||||
| static void | ||||
| meta_texture_blend_replace(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    static const GLuint prog[] = { | ||||
|       _3DSTATE_PIXEL_SHADER_PROGRAM, | ||||
|  | ||||
|       /* Declare the sampler: | ||||
|        */ | ||||
|       (D0_DCL | | ||||
|        D0_DECL_REG( REG_S(0) ) | | ||||
|        D0_SAMPLE_TYPE_2D | | ||||
|        D0_CHANNEL_NONE), | ||||
|       (D0_DCL | D0_DECL_REG(REG_S(0)) | D0_SAMPLE_TYPE_2D | D0_CHANNEL_NONE), | ||||
|       D1_MBZ, | ||||
|       D2_MBZ, | ||||
|  | ||||
|       /* Declare the interpolated texture coordinate: | ||||
|        */ | ||||
|       (D0_DCL | | ||||
|        D0_DECL_REG( REG_T_TEX(0) ) | | ||||
|        D0_CHANNEL_ALL), | ||||
|       (D0_DCL | D0_DECL_REG(REG_T_TEX(0)) | D0_CHANNEL_ALL), | ||||
|       D1_MBZ, | ||||
|       D2_MBZ, | ||||
|  | ||||
|       /* output-color = texld(sample0, texcoord0)  | ||||
|        */ | ||||
|       (T0_TEXLD |  | ||||
|        T0_DEST_REG( REG_OC ) | | ||||
|        T0_SAMPLER( 0 )), | ||||
|       (T0_TEXLD | T0_DEST_REG(REG_OC) | T0_SAMPLER(0)), | ||||
|       T1_ADDRESS_REG(REG_TYPE_T, 0), | ||||
|       T2_MBZ | ||||
|    }; | ||||
| @@ -286,36 +324,95 @@ static void enable_texture_blend_replace( i915ContextPtr i915 ) | ||||
| /* Set up an arbitary piece of memory as a rectangular texture | ||||
|  * (including the front or back buffer). | ||||
|  */ | ||||
| static void set_tex_rect_source( i915ContextPtr i915, | ||||
| static GLboolean | ||||
| meta_tex_rect_source(struct intel_context *intel, | ||||
|                      struct _DriBufferObject *buffer, | ||||
|                      GLuint offset, | ||||
| 				 GLuint width,  | ||||
| 				 GLuint height, | ||||
| 				 GLuint pitch, /* in bytes! */ | ||||
| 				 GLuint textureFormat ) | ||||
|                      GLuint pitch, GLuint height, GLenum format, GLenum type) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint unit = 0; | ||||
|    GLint numLevels = 1; | ||||
|    GLuint *state = i915->meta.Tex[0]; | ||||
|    GLuint textureFormat; | ||||
|    GLuint cpp; | ||||
|  | ||||
| #if 0 | ||||
|    printf("TexRect source offset 0x%x  pitch %d\n", offset, pitch); | ||||
| #endif | ||||
|    /* A full implementation of this would do the upload through | ||||
|     * glTexImage2d, and get all the conversion operations at that | ||||
|     * point.  We are restricted, but still at least have access to the | ||||
|     * fragment program swizzle. | ||||
|     */ | ||||
|    switch (format) { | ||||
|    case GL_BGRA: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       case GL_UNSIGNED_BYTE: | ||||
|          textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888); | ||||
|          cpp = 4; | ||||
|          break; | ||||
|       default: | ||||
|          return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_RGBA: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       case GL_UNSIGNED_BYTE: | ||||
|          textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888); | ||||
|          cpp = 4; | ||||
|          break; | ||||
|       default: | ||||
|          return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_BGR: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_SHORT_5_6_5_REV: | ||||
|          textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); | ||||
|          cpp = 2; | ||||
|          break; | ||||
|       default: | ||||
|          return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_RGB: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_SHORT_5_6_5: | ||||
|          textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); | ||||
|          cpp = 2; | ||||
|          break; | ||||
|       default: | ||||
|          return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
| /*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */ | ||||
| /* 	   __FUNCTION__, offset, width, height, pitch, textureFormat ); */ | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if ((pitch * cpp) & 3) { | ||||
|       _mesa_printf("%s: texture is not dword pitch\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
| /*    intel_region_release(intel, &i915->meta.tex_region[0]); */ | ||||
| /*    intel_region_reference(&i915->meta.tex_region[0], region); */ | ||||
|    i915->meta.tex_buffer[0] = buffer; | ||||
|    i915->meta.tex_offset[0] = offset; | ||||
|  | ||||
|    state[I915_TEXREG_MS2] = offset; | ||||
|    state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) | | ||||
| 			    ((width - 1) << MS3_WIDTH_SHIFT) | | ||||
| 			    textureFormat | | ||||
| 			    MS3_USE_FENCE_REGS); | ||||
|                              ((pitch - 1) << MS3_WIDTH_SHIFT) | | ||||
|                              textureFormat | MS3_USE_FENCE_REGS); | ||||
|  | ||||
|    state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |  | ||||
|    state[I915_TEXREG_MS4] = (((((pitch * cpp) / 4) - 1) << MS4_PITCH_SHIFT) | | ||||
|                              MS4_CUBE_FACE_ENA_MASK | | ||||
|                              ((((numLevels - 1) * 4)) << MS4_MAX_LOD_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) | | ||||
|                              (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | | ||||
|                              (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) | | ||||
|                              (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) | | ||||
|                              (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) | | ||||
| @@ -324,47 +421,28 @@ static void set_tex_rect_source( i915ContextPtr i915, | ||||
|    state[I915_TEXREG_SS4] = 0; | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_TEX(0); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Select between front and back draw buffers. | ||||
| /** | ||||
|  * Set the color and depth drawing region for meta ops. | ||||
|  */ | ||||
| static void set_draw_region( i915ContextPtr i915, const intelRegion *region ) | ||||
| static void | ||||
| meta_draw_region(struct intel_context *intel, | ||||
|                  struct intel_region *color_region, | ||||
|                  struct intel_region *depth_region) | ||||
| { | ||||
| #if 0 | ||||
|    printf("Rotate into region: offset 0x%x  pitch %d\n", | ||||
|           region->offset, region->pitch); | ||||
| #endif | ||||
|    i915->meta.Buffer[I915_DESTREG_CBUFADDR1] = | ||||
|       (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); | ||||
|    i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = region->offset; | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    i915_state_draw_region(intel, &i915->meta, color_region, depth_region); | ||||
| } | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
| /* Setup an arbitary draw format, useful for targeting texture or agp | ||||
|  * memory. | ||||
|  */ | ||||
| static void set_draw_format( i915ContextPtr i915, | ||||
| 			     GLuint format, | ||||
| 			     GLuint depth_format) | ||||
| static void | ||||
| set_vertex_format(struct intel_context *intel) | ||||
| { | ||||
|    i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
| 					DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
| 					format | | ||||
| 					LOD_PRECLAMP_OGL | | ||||
| 					TEX_DEFAULT_COLOR_OGL | | ||||
| 					depth_format); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
| /*    fprintf(stderr, "%s: DV1: %x\n",  */ | ||||
| /* 	   __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void set_vertex_format( i915ContextPtr i915 ) | ||||
| { | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS2] = | ||||
|       (S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) | | ||||
|        S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) | | ||||
| @@ -377,324 +455,55 @@ static void set_vertex_format( i915ContextPtr i915 ) | ||||
|  | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS4] &= ~S4_VFMT_MASK; | ||||
|  | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS4] |=  | ||||
|       (S4_VFMT_COLOR | | ||||
|        S4_VFMT_SPEC_FOG | | ||||
|        S4_VFMT_XYZW); | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS4] |= (S4_VFMT_COLOR | S4_VFMT_XYZ); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| static void draw_quad(i915ContextPtr i915,  | ||||
| 		      GLfloat x0, GLfloat x1, | ||||
| 		      GLfloat y0, GLfloat y1,  | ||||
| 		      GLubyte red, GLubyte green, | ||||
| 		      GLubyte blue, GLubyte alpha, | ||||
| 		      GLfloat s0, GLfloat s1, | ||||
| 		      GLfloat t0, GLfloat t1 ) | ||||
|  | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void | ||||
| install_meta_state(struct intel_context *intel) | ||||
| { | ||||
|    GLuint vertex_size = 8; | ||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,  | ||||
| 						PRIM3D_TRIFAN,  | ||||
| 						4 * vertex_size, | ||||
| 						vertex_size ); | ||||
|    intelVertex tmp; | ||||
|    int i; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", | ||||
| 	      __FUNCTION__, | ||||
| 	      x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); | ||||
|  | ||||
|  | ||||
|    /* initial vertex, left bottom */ | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.y = y0; | ||||
|    tmp.v.z = 1.0; | ||||
|    tmp.v.w = 1.0;  | ||||
|    tmp.v.color.red = red; | ||||
|    tmp.v.color.green = green; | ||||
|    tmp.v.color.blue = blue; | ||||
|    tmp.v.color.alpha = alpha; | ||||
|    tmp.v.specular.red = 0; | ||||
|    tmp.v.specular.green = 0; | ||||
|    tmp.v.specular.blue = 0; | ||||
|    tmp.v.specular.alpha = 0; | ||||
|    tmp.v.u0 = s0; | ||||
|    tmp.v.v0 = t0; | ||||
|  | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right bottom */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.x = x1; | ||||
|    tmp.v.u0 = s1; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right top */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.y = y1; | ||||
|    tmp.v.v0 = t1; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* left top */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.u0 = s0; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void draw_poly(i915ContextPtr i915,  | ||||
| 		      GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha, | ||||
|                       GLuint numVerts, | ||||
|                       /*const*/ GLfloat verts[][2], | ||||
|                       /*const*/ GLfloat texcoords[][2]) | ||||
| { | ||||
|    GLuint vertex_size = 8; | ||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,  | ||||
| 						PRIM3D_TRIFAN,  | ||||
| 						numVerts * vertex_size, | ||||
| 						vertex_size ); | ||||
|    intelVertex tmp; | ||||
|    int i, k; | ||||
|  | ||||
|    /* initial constant vertex fields */ | ||||
|    tmp.v.z = 1.0; | ||||
|    tmp.v.w = 1.0;  | ||||
|    tmp.v.color.red = red; | ||||
|    tmp.v.color.green = green; | ||||
|    tmp.v.color.blue = blue; | ||||
|    tmp.v.color.alpha = alpha; | ||||
|    tmp.v.specular.red = 0; | ||||
|    tmp.v.specular.green = 0; | ||||
|    tmp.v.specular.blue = 0; | ||||
|    tmp.v.specular.alpha = 0; | ||||
|  | ||||
|    for (k = 0; k < numVerts; k++) { | ||||
|       tmp.v.x = verts[k][0]; | ||||
|       tmp.v.y = verts[k][1]; | ||||
|       tmp.v.u0 = texcoords[k][0]; | ||||
|       tmp.v.v0 = texcoords[k][1]; | ||||
|  | ||||
|       for (i = 0 ; i < vertex_size ; i++) | ||||
|          vb[i] = tmp.ui[i]; | ||||
|  | ||||
|       vb += vertex_size; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void  | ||||
| i915ClearWithTris(intelContextPtr intel, GLbitfield mask, | ||||
| 		  GLboolean all, | ||||
| 		  GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( intel ); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    int x0, y0, x1, y1; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    memcpy(&i915->meta, &i915->initial, sizeof(i915->meta)); | ||||
|    i915->meta.active = ACTIVE; | ||||
|    i915->meta.emitted = 0; | ||||
|  | ||||
|    SET_STATE(i915, meta); | ||||
|    set_initial_state( i915 );  | ||||
|    set_no_texture( i915 );  | ||||
|    set_vertex_format( i915 );  | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (!all) { | ||||
|       x0 = cx; | ||||
|       y0 = cy; | ||||
|       x1 = x0 + cw; | ||||
|       y1 = y0 + ch; | ||||
|    } else { | ||||
|       x0 = 0; | ||||
|       y0 = 0; | ||||
|       x1 = x0 + dPriv->w; | ||||
|       y1 = y0 + dPriv->h; | ||||
|    set_vertex_format(intel); | ||||
|    meta_no_texture(intel); | ||||
| } | ||||
|  | ||||
|    /* Don't do any clipping to screen - these are window coordinates. | ||||
|     * The active cliprects will be applied as for any other geometry. | ||||
|     */ | ||||
|  | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) {  | ||||
|       set_no_depth_stencil_write( i915 ); | ||||
|       set_color_mask( i915, GL_TRUE ); | ||||
|       set_draw_region( i915, &screen->front ); | ||||
|  | ||||
|       draw_quad(i915, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green,  | ||||
|  		intel->clear_blue, intel->clear_alpha,  | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       set_no_depth_stencil_write( i915 ); | ||||
|       set_color_mask( i915, GL_TRUE ); | ||||
|       set_draw_region( i915, &screen->back ); | ||||
|  | ||||
|       draw_quad(i915, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green, | ||||
| 		intel->clear_blue, intel->clear_alpha, | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       set_stencil_replace( i915,  | ||||
| 			   intel->ctx.Stencil.WriteMask[0],  | ||||
| 			   intel->ctx.Stencil.Clear); | ||||
|        | ||||
|       set_color_mask( i915, GL_FALSE ); | ||||
|       set_draw_region( i915, &screen->front ); /* could be either? */ | ||||
|  | ||||
|       draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 ); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
| static void | ||||
| leave_meta_state(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    intel_region_release(intel->intelScreen, &i915->meta.draw_region); | ||||
|    intel_region_release(intel->intelScreen, &i915->meta.depth_region); | ||||
| /*    intel_region_release(intel, &i915->meta.tex_region[0]); */ | ||||
|    SET_STATE(i915, state); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Copy the window contents named by dPriv to the rotated (or reflected) | ||||
|  * color buffer. | ||||
|  * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source. | ||||
|  */ | ||||
|  | ||||
| void | ||||
| i915RotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, | ||||
|                  GLuint srcBuf) | ||||
| i915InitMetaFuncs(struct i915_context *i915) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( intel ); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    const GLuint cpp = screen->cpp; | ||||
|    drm_clip_rect_t fullRect; | ||||
|    GLuint textureFormat, srcOffset, srcPitch; | ||||
|    const drm_clip_rect_t *clipRects; | ||||
|    int numClipRects; | ||||
|    int i; | ||||
|  | ||||
|    int xOrig, yOrig; | ||||
|    int origNumClipRects; | ||||
|    drm_clip_rect_t *origRects; | ||||
|  | ||||
|    /* | ||||
|     * set up hardware state | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|  | ||||
|    SET_STATE( i915, meta );  | ||||
|    set_initial_state( i915 );  | ||||
|    set_no_texture( i915 );  | ||||
|    set_vertex_format( i915 );  | ||||
|    set_no_depth_stencil_write( i915 ); | ||||
|    set_color_mask( i915, GL_TRUE ); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* save current drawing origin and cliprects (restored at end) */ | ||||
|    xOrig = intel->drawX; | ||||
|    yOrig = intel->drawY; | ||||
|    origNumClipRects = intel->numClipRects; | ||||
|    origRects = intel->pClipRects; | ||||
|  | ||||
|    if (!intel->numClipRects) | ||||
|       goto done; | ||||
|  | ||||
|    /* | ||||
|     * set drawing origin, cliprects for full-screen access to rotated screen | ||||
|     */ | ||||
|    fullRect.x1 = 0; | ||||
|    fullRect.y1 = 0; | ||||
|    fullRect.x2 = screen->rotatedWidth; | ||||
|    fullRect.y2 = screen->rotatedHeight; | ||||
|    intel->drawX = 0; | ||||
|    intel->drawY = 0; | ||||
|    intel->numClipRects = 1; | ||||
|    intel->pClipRects = &fullRect; | ||||
|  | ||||
|    set_draw_region( i915, &screen->rotated ); | ||||
|  | ||||
|    if (cpp == 4) | ||||
|       textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|    else | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|  | ||||
|    if (srcBuf == BUFFER_BIT_FRONT_LEFT) { | ||||
|       srcPitch = screen->front.pitch;   /* in bytes */ | ||||
|       srcOffset = screen->front.offset; /* bytes */ | ||||
|       clipRects = dPriv->pClipRects; | ||||
|       numClipRects = dPriv->numClipRects; | ||||
|    i915->intel.vtbl.install_meta_state = install_meta_state; | ||||
|    i915->intel.vtbl.leave_meta_state = leave_meta_state; | ||||
|    i915->intel.vtbl.meta_no_depth_write = meta_no_depth_write; | ||||
|    i915->intel.vtbl.meta_no_stencil_write = meta_no_stencil_write; | ||||
|    i915->intel.vtbl.meta_stencil_replace = meta_stencil_replace; | ||||
|    i915->intel.vtbl.meta_depth_replace = meta_depth_replace; | ||||
|    i915->intel.vtbl.meta_color_mask = meta_color_mask; | ||||
|    i915->intel.vtbl.meta_no_texture = meta_no_texture; | ||||
|    i915->intel.vtbl.meta_texture_blend_replace = meta_texture_blend_replace; | ||||
|    i915->intel.vtbl.meta_tex_rect_source = meta_tex_rect_source; | ||||
|    i915->intel.vtbl.meta_draw_region = meta_draw_region; | ||||
|    i915->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state; | ||||
| } | ||||
|    else { | ||||
|       srcPitch = screen->back.pitch;   /* in bytes */ | ||||
|       srcOffset = screen->back.offset; /* bytes */ | ||||
|       clipRects = dPriv->pBackClipRects; | ||||
|       numClipRects = dPriv->numBackClipRects; | ||||
|    } | ||||
|  | ||||
|    /* set the whole screen up as a texture to avoid alignment issues */ | ||||
|    set_tex_rect_source(i915, | ||||
|                        srcOffset, | ||||
|                        screen->width, | ||||
| 		       screen->height, | ||||
|                        srcPitch, | ||||
|                        textureFormat); | ||||
|  | ||||
|    enable_texture_blend_replace(i915); | ||||
|  | ||||
|    /* | ||||
|     * loop over the source window's cliprects | ||||
|     */ | ||||
|    for (i = 0; i < numClipRects; i++) { | ||||
|       int srcX0 = clipRects[i].x1; | ||||
|       int srcY0 = clipRects[i].y1; | ||||
|       int srcX1 = clipRects[i].x2; | ||||
|       int srcY1 = clipRects[i].y2; | ||||
|       GLfloat verts[4][2], tex[4][2]; | ||||
|       int j; | ||||
|  | ||||
|       /* build vertices for four corners of clip rect */ | ||||
|       verts[0][0] = srcX0;  verts[0][1] = srcY0; | ||||
|       verts[1][0] = srcX1;  verts[1][1] = srcY0; | ||||
|       verts[2][0] = srcX1;  verts[2][1] = srcY1; | ||||
|       verts[3][0] = srcX0;  verts[3][1] = srcY1; | ||||
|  | ||||
|       /* .. and texcoords */ | ||||
|       tex[0][0] = srcX0;  tex[0][1] = srcY0; | ||||
|       tex[1][0] = srcX1;  tex[1][1] = srcY0; | ||||
|       tex[2][0] = srcX1;  tex[2][1] = srcY1; | ||||
|       tex[3][0] = srcX0;  tex[3][1] = srcY1; | ||||
|  | ||||
|       /* transform coords to rotated screen coords */ | ||||
|       for (j = 0; j < 4; j++) { | ||||
|          matrix23TransformCoordf(&screen->rotMatrix, | ||||
|                                  &verts[j][0], &verts[j][1]); | ||||
|       } | ||||
|  | ||||
|       /* draw polygon to map source image to dest region */ | ||||
|       draw_poly(i915, 255, 255, 255, 255, 4, verts, tex); | ||||
|  | ||||
|    } /* cliprect loop */ | ||||
|  | ||||
|    intelFlushBatchLocked( intel, GL_FALSE, GL_FALSE, GL_FALSE ); | ||||
|  | ||||
|  done: | ||||
|    /* restore original drawing origin and cliprects */ | ||||
|    intel->drawX = xOrig; | ||||
|    intel->drawY = yOrig; | ||||
|    intel->numClipRects = origNumClipRects; | ||||
|    intel->pClipRects = origRects; | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    SET_STATE( i915, state ); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -72,7 +72,8 @@ | ||||
|  | ||||
| #define I915_CONSTFLAG_PARAM 0x1f | ||||
|  | ||||
| GLuint i915_get_temp( struct i915_fragment_program *p ) | ||||
| GLuint | ||||
| i915_get_temp(struct i915_fragment_program *p) | ||||
| { | ||||
|    int bit = ffs(~p->temp_flag); | ||||
|    if (!bit) { | ||||
| @@ -85,7 +86,8 @@ GLuint i915_get_temp( struct i915_fragment_program *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint i915_get_utemp( struct i915_fragment_program *p ) | ||||
| GLuint | ||||
| i915_get_utemp(struct i915_fragment_program * p) | ||||
| { | ||||
|    int bit = ffs(~p->utemp_flag); | ||||
|    if (!bit) { | ||||
| @@ -97,13 +99,15 @@ GLuint i915_get_utemp( struct i915_fragment_program *p ) | ||||
|    return UREG(REG_TYPE_U, (bit - 1)); | ||||
| } | ||||
|  | ||||
| void i915_release_utemps( struct i915_fragment_program *p ) | ||||
| void | ||||
| i915_release_utemps(struct i915_fragment_program *p) | ||||
| { | ||||
|    p->utemp_flag = ~0x7; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint i915_emit_decl( struct i915_fragment_program *p, | ||||
| GLuint | ||||
| i915_emit_decl(struct i915_fragment_program *p, | ||||
|                GLuint type, GLuint nr, GLuint d0_flags) | ||||
| { | ||||
|    GLuint reg = UREG(type, nr); | ||||
| @@ -131,24 +135,26 @@ GLuint i915_emit_decl( struct i915_fragment_program *p, | ||||
|    return reg; | ||||
| } | ||||
|  | ||||
| GLuint i915_emit_arith( struct i915_fragment_program *p, | ||||
| GLuint | ||||
| i915_emit_arith(struct i915_fragment_program * p, | ||||
|                 GLuint op, | ||||
|                 GLuint dest, | ||||
|                 GLuint mask, | ||||
| 		       GLuint saturate, | ||||
| 		       GLuint src0, | ||||
| 		       GLuint src1, | ||||
| 		       GLuint src2 ) | ||||
|                 GLuint saturate, GLuint src0, GLuint src1, GLuint src2) | ||||
| { | ||||
|    GLuint c[3]; | ||||
|    GLuint nr_const = 0; | ||||
|  | ||||
|    assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); | ||||
|    assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); | ||||
|    dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); | ||||
|    assert(dest); | ||||
|  | ||||
|    if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) c[nr_const++] = 0; | ||||
|    if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) c[nr_const++] = 1; | ||||
|    if (GET_UREG_TYPE(src2) == REG_TYPE_CONST) c[nr_const++] = 2; | ||||
|    if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) | ||||
|       c[nr_const++] = 0; | ||||
|    if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) | ||||
|       c[nr_const++] = 1; | ||||
|    if (GET_UREG_TYPE(src2) == REG_TYPE_CONST) | ||||
|       c[nr_const++] = 2; | ||||
|  | ||||
|    /* Recursively call this function to MOV additional const values | ||||
|     * into temporary registers.  Use utemp registers for this - | ||||
| @@ -180,15 +186,9 @@ GLuint i915_emit_arith( struct i915_fragment_program *p, | ||||
|       p->utemp_flag = old_utemp_flag;   /* restore */ | ||||
|    } | ||||
|  | ||||
|    *(p->csr++) = (op |  | ||||
| 		  A0_DEST( dest ) | | ||||
| 		  mask |  | ||||
| 		  saturate | | ||||
| 		  A0_SRC0( src0 )); | ||||
|    *(p->csr++) = (A1_SRC0( src0 ) | | ||||
| 		  A1_SRC1( src1 )); | ||||
|    *(p->csr++) = (A2_SRC1( src1 ) | | ||||
| 		  A2_SRC2( src2 )); | ||||
|    *(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); | ||||
|    *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1)); | ||||
|    *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2)); | ||||
|  | ||||
|    p->nr_alu_insn++; | ||||
|    return dest; | ||||
| @@ -201,6 +201,24 @@ GLuint i915_emit_texld( struct i915_fragment_program *p, | ||||
| 			GLuint coord, | ||||
| 			GLuint op ) | ||||
| { | ||||
|    if (coord != UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord))) { | ||||
|       /* No real way to work around this in the general case - need to | ||||
|        * allocate and declare a new temporary register (a utemp won't | ||||
|        * do).  Will fallback for now. | ||||
|        */ | ||||
|       i915_program_error(p, "Can't (yet) swizzle TEX arguments"); | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    /* Don't worry about saturate as we only support   | ||||
|     */ | ||||
|    if (destmask != A0_DEST_CHANNEL_ALL) { | ||||
|       GLuint tmp = i915_get_utemp(p); | ||||
|       i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, op ); | ||||
|       i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 ); | ||||
|       return dest; | ||||
|    } | ||||
|    else { | ||||
|       assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); | ||||
|       assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); | ||||
|  | ||||
| @@ -210,7 +228,6 @@ GLuint i915_emit_texld( struct i915_fragment_program *p, | ||||
|  | ||||
|       *(p->csr++) = (op |  | ||||
| 		     T0_DEST( dest ) | | ||||
| 		  destmask | | ||||
| 		     T0_SAMPLER( sampler )); | ||||
|  | ||||
|       *(p->csr++) = T1_ADDRESS_REG( coord ); | ||||
| @@ -219,14 +236,18 @@ GLuint i915_emit_texld( struct i915_fragment_program *p, | ||||
|       p->nr_tex_insn++; | ||||
|       return dest; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint i915_emit_const1f( struct i915_fragment_program *p, GLfloat c0 ) | ||||
| GLuint | ||||
| i915_emit_const1f(struct i915_fragment_program * p, GLfloat c0) | ||||
| { | ||||
|    GLint reg, idx; | ||||
|  | ||||
|    if (c0 == 0.0) return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO); | ||||
|    if (c0 == 1.0) return swizzle(UREG(REG_TYPE_R, 0), ONE,  ONE,  ONE,  ONE ); | ||||
|    if (c0 == 0.0) | ||||
|       return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO); | ||||
|    if (c0 == 1.0) | ||||
|       return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE); | ||||
|  | ||||
|    for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { | ||||
|       if (p->constant_flags[reg] == I915_CONSTFLAG_PARAM) | ||||
| @@ -236,7 +257,8 @@ GLuint i915_emit_const1f( struct i915_fragment_program *p, GLfloat c0 ) | ||||
|              p->constant[reg][idx] == c0) { | ||||
|             p->constant[reg][idx] = c0; | ||||
|             p->constant_flags[reg] |= 1 << idx; | ||||
| 	    if (reg+1 > p->nr_constants) p->nr_constants = reg+1; | ||||
|             if (reg + 1 > p->nr_constants) | ||||
|                p->nr_constants = reg + 1; | ||||
|             return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE); | ||||
|          } | ||||
|       } | ||||
| @@ -247,16 +269,20 @@ GLuint i915_emit_const1f( struct i915_fragment_program *p, GLfloat c0 ) | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| GLuint i915_emit_const2f( struct i915_fragment_program *p,  | ||||
| 			 GLfloat c0, GLfloat c1 ) | ||||
| GLuint | ||||
| i915_emit_const2f(struct i915_fragment_program * p, GLfloat c0, GLfloat c1) | ||||
| { | ||||
|    GLint reg, idx; | ||||
|  | ||||
|    if (c0 == 0.0) return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W); | ||||
|    if (c0 == 1.0) return swizzle(i915_emit_const1f(p, c1), ONE,  X, Z, W);  | ||||
|    if (c0 == 0.0) | ||||
|       return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W); | ||||
|    if (c0 == 1.0) | ||||
|       return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W); | ||||
|  | ||||
|    if (c1 == 0.0) return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W); | ||||
|    if (c1 == 1.0) return swizzle(i915_emit_const1f(p, c0), X, ONE,  Z, W); | ||||
|    if (c1 == 0.0) | ||||
|       return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W); | ||||
|    if (c1 == 1.0) | ||||
|       return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W); | ||||
|  | ||||
|    for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { | ||||
|       if (p->constant_flags[reg] == 0xf || | ||||
| @@ -267,8 +293,10 @@ GLuint i915_emit_const2f( struct i915_fragment_program *p, | ||||
|             p->constant[reg][idx] = c0; | ||||
|             p->constant[reg][idx + 1] = c1; | ||||
|             p->constant_flags[reg] |= 3 << idx; | ||||
| 	    if (reg+1 > p->nr_constants) p->nr_constants = reg+1; | ||||
| 	    return swizzle(UREG(REG_TYPE_CONST, reg),idx,idx+1,ZERO,ONE); | ||||
|             if (reg + 1 > p->nr_constants) | ||||
|                p->nr_constants = reg + 1; | ||||
|             return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO, | ||||
|                            ONE); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| @@ -280,7 +308,8 @@ GLuint i915_emit_const2f( struct i915_fragment_program *p, | ||||
|  | ||||
|  | ||||
|  | ||||
| GLuint i915_emit_const4f( struct i915_fragment_program *p,  | ||||
| GLuint | ||||
| i915_emit_const4f(struct i915_fragment_program * p, | ||||
|                   GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3) | ||||
| { | ||||
|    GLint reg; | ||||
| @@ -289,8 +318,7 @@ GLuint i915_emit_const4f( struct i915_fragment_program *p, | ||||
|       if (p->constant_flags[reg] == 0xf && | ||||
|           p->constant[reg][0] == c0 && | ||||
|           p->constant[reg][1] == c1 && | ||||
| 	  p->constant[reg][2] == c2 && | ||||
| 	  p->constant[reg][3] == c3) { | ||||
|           p->constant[reg][2] == c2 && p->constant[reg][3] == c3) { | ||||
|          return UREG(REG_TYPE_CONST, reg); | ||||
|       } | ||||
|       else if (p->constant_flags[reg] == 0) { | ||||
| @@ -299,7 +327,8 @@ GLuint i915_emit_const4f( struct i915_fragment_program *p, | ||||
|          p->constant[reg][2] = c2; | ||||
|          p->constant[reg][3] = c3; | ||||
|          p->constant_flags[reg] = 0xf; | ||||
| 	 if (reg+1 > p->nr_constants) p->nr_constants = reg+1; | ||||
|          if (reg + 1 > p->nr_constants) | ||||
|             p->nr_constants = reg + 1; | ||||
|          return UREG(REG_TYPE_CONST, reg); | ||||
|       } | ||||
|    } | ||||
| @@ -310,14 +339,15 @@ GLuint i915_emit_const4f( struct i915_fragment_program *p, | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint i915_emit_const4fv( struct i915_fragment_program *p, const GLfloat *c ) | ||||
| GLuint | ||||
| i915_emit_const4fv(struct i915_fragment_program * p, const GLfloat * c) | ||||
| { | ||||
|    return i915_emit_const4f(p, c[0], c[1], c[2], c[3]); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint i915_emit_param4fv( struct i915_fragment_program *p,  | ||||
| 			  const GLfloat *values ) | ||||
| GLuint | ||||
| i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values) | ||||
| { | ||||
|    GLint reg, i; | ||||
|  | ||||
| @@ -336,7 +366,8 @@ GLuint i915_emit_param4fv( struct i915_fragment_program *p, | ||||
|          p->param[i].reg = reg; | ||||
|          p->params_uptodate = 0; | ||||
|  | ||||
| 	 if (reg+1 > p->nr_constants) p->nr_constants = reg+1; | ||||
|          if (reg + 1 > p->nr_constants) | ||||
|             p->nr_constants = reg + 1; | ||||
|          return UREG(REG_TYPE_CONST, reg); | ||||
|       } | ||||
|    } | ||||
| @@ -349,7 +380,8 @@ GLuint i915_emit_param4fv( struct i915_fragment_program *p, | ||||
|  | ||||
|  | ||||
|  | ||||
| void i915_program_error( struct i915_fragment_program *p, const char *msg ) | ||||
| void | ||||
| i915_program_error(struct i915_fragment_program *p, const char *msg) | ||||
| { | ||||
|    /* XXX we shouldn't print anything to stdout, record GL error or | ||||
|     * call _mesa_problem() | ||||
| @@ -358,7 +390,8 @@ void i915_program_error( struct i915_fragment_program *p, const char *msg ) | ||||
|    p->error = 1; | ||||
| } | ||||
|  | ||||
| void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
| void | ||||
| i915_init_program(struct i915_context *i915, struct i915_fragment_program *p) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
| @@ -396,7 +429,8 @@ void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915_fini_program( struct i915_fragment_program *p ) | ||||
| void | ||||
| i915_fini_program(struct i915_fragment_program *p) | ||||
| { | ||||
|    GLuint program_size = p->csr - p->program; | ||||
|    GLuint decl_size = p->decl - p->declarations; | ||||
| @@ -431,7 +465,9 @@ void i915_fini_program( struct i915_fragment_program *p ) | ||||
|    p->declarations[0] |= program_size + decl_size - 2; | ||||
| } | ||||
|  | ||||
| void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
| void | ||||
| i915_upload_program(struct i915_context *i915, | ||||
|                     struct i915_fragment_program *p) | ||||
| { | ||||
|    GLuint program_size = p->csr - p->program; | ||||
|    GLuint decl_size = p->decl - p->declarations; | ||||
| @@ -470,9 +506,7 @@ void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
|          for (i = 0; i < nr; i++) { | ||||
|             fprintf(stderr, "const[%d]: %f %f %f %f\n", i, | ||||
|                     p->constant[i][0], | ||||
| 		    p->constant[i][1], | ||||
| 		    p->constant[i][2], | ||||
| 		    p->constant[i][3]); | ||||
|                     p->constant[i][1], p->constant[i][2], p->constant[i][3]); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|   | ||||
| @@ -84,7 +84,8 @@ | ||||
|  | ||||
| /* One neat thing about the UREG representation:   | ||||
|  */ | ||||
| static __inline int swizzle( int reg, int x, int y, int z, int w ) | ||||
| static INLINE int | ||||
| swizzle(int reg, int x, int y, int z, int w) | ||||
| { | ||||
|    return ((reg & ~UREG_XYZW_CHANNEL_MASK) | | ||||
|            CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) | | ||||
| @@ -95,7 +96,8 @@ static __inline int swizzle( int reg, int x, int y, int z, int w ) | ||||
|  | ||||
| /* Another neat thing about the UREG representation:   | ||||
|  */ | ||||
| static __inline int negate( int reg, int x, int y, int z, int w ) | ||||
| static INLINE int | ||||
| negate(int reg, int x, int y, int z, int w) | ||||
| { | ||||
|    return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) | | ||||
|                  ((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) | | ||||
| @@ -112,25 +114,20 @@ extern void i915_release_utemps( struct i915_fragment_program *p ); | ||||
| extern GLuint i915_emit_texld(struct i915_fragment_program *p, | ||||
|                               GLuint dest, | ||||
|                               GLuint destmask, | ||||
| 			      GLuint sampler, | ||||
| 			      GLuint coord, | ||||
| 			      GLuint op ); | ||||
|                               GLuint sampler, GLuint coord, GLuint op); | ||||
|  | ||||
| extern GLuint i915_emit_arith(struct i915_fragment_program *p, | ||||
|                               GLuint op, | ||||
|                               GLuint dest, | ||||
|                               GLuint mask, | ||||
|                               GLuint saturate, | ||||
| 			      GLuint src0, | ||||
| 			      GLuint src1, | ||||
| 			      GLuint src2 ); | ||||
|                               GLuint src0, GLuint src1, GLuint src2); | ||||
|  | ||||
| extern GLuint i915_emit_decl(struct i915_fragment_program *p, | ||||
|                              GLuint type, GLuint nr, GLuint d0_flags); | ||||
|  | ||||
|  | ||||
| extern GLuint i915_emit_const1f( struct i915_fragment_program *p,  | ||||
| 				GLfloat c0 ); | ||||
| extern GLuint i915_emit_const1f(struct i915_fragment_program *p, GLfloat c0); | ||||
|  | ||||
| extern GLuint i915_emit_const2f(struct i915_fragment_program *p, | ||||
|                                 GLfloat c0, GLfloat c1); | ||||
| @@ -149,10 +146,10 @@ extern GLuint i915_emit_param4fv( struct i915_fragment_program *p, | ||||
| extern void i915_program_error(struct i915_fragment_program *p, | ||||
|                                const char *msg); | ||||
|  | ||||
| extern void i915_init_program( i915ContextPtr i915, | ||||
| extern void i915_init_program(struct i915_context *i915, | ||||
|                               struct i915_fragment_program *p); | ||||
|  | ||||
| extern void i915_upload_program( i915ContextPtr i915,  | ||||
| extern void i915_upload_program(struct i915_context *i915, | ||||
|                                 struct i915_fragment_program *p); | ||||
|  | ||||
| extern void i915_fini_program(struct i915_fragment_program *p); | ||||
|   | ||||
| @@ -425,8 +425,10 @@ | ||||
| #define S7_DEPTH_OFFSET_CONST_MASK     ~0 | ||||
|  | ||||
| /* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */ | ||||
| /* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */ | ||||
|  | ||||
| /* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */ | ||||
| #define _3DSTATE_MAP_PALETTE_LOAD_32    (CMD_3D|(0x1d<<24)|(0x8f<<16)) | ||||
| /* subsequent dwords up to length (max 16) are ARGB8888 color values */ | ||||
|  | ||||
| /* _3DSTATE_MODES_4, p218 */ | ||||
| #define _3DSTATE_MODES_4_CMD		(CMD_3D|(0x0d<<24)) | ||||
| @@ -435,7 +437,7 @@ | ||||
| #define LOGICOP_MASK			(0xf<<18) | ||||
| #define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00)) | ||||
| #define ENABLE_STENCIL_TEST_MASK	(1<<17) | ||||
| #define STENCIL_TEST_MASK(x)		((x)<<8) | ||||
| #define STENCIL_TEST_MASK(x)		(((x)&0xff)<<8) | ||||
| #define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff)) | ||||
| #define ENABLE_STENCIL_WRITE_MASK	(1<<16) | ||||
| #define STENCIL_WRITE_MASK(x)		((x)&0xff) | ||||
| @@ -826,10 +828,14 @@ | ||||
| #define ST1_ENABLE               (1<<16) | ||||
| #define ST1_MASK                 (0xffff) | ||||
|  | ||||
| #define _3DSTATE_DEFAULT_Z          ((0x3<<29)|(0x1d<<24)|(0x98<<16)) | ||||
| #define _3DSTATE_DEFAULT_DIFFUSE    ((0x3<<29)|(0x1d<<24)|(0x99<<16)) | ||||
| #define _3DSTATE_DEFAULT_SPECULAR   ((0x3<<29)|(0x1d<<24)|(0x9a<<16)) | ||||
|  | ||||
|  | ||||
| #define MI_FLUSH                   ((0<<29)|(4<<23)) | ||||
| #define FLUSH_MAP_CACHE            (1<<0) | ||||
| #define FLUSH_RENDER_CACHE (1<<1) | ||||
| #define INHIBIT_FLUSH_RENDER_CACHE (1<<2) | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -36,25 +36,25 @@ | ||||
|  | ||||
| #include "texmem.h" | ||||
|  | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| #include "i915_context.h" | ||||
| #include "i915_reg.h" | ||||
|  | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_STATE | ||||
|  | ||||
| static void | ||||
| i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, | ||||
|                         GLuint mask) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|  | ||||
|    mask = mask & 0xff; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, | ||||
|    DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(func), ref, mask); | ||||
|  | ||||
|  | ||||
| @@ -67,16 +67,16 @@ i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
|                                           S5_STENCIL_TEST_FUNC_MASK); | ||||
|  | ||||
|    i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) | | ||||
|  				       (test << S5_STENCIL_TEST_FUNC_SHIFT));  | ||||
|                                          (test << | ||||
|                                           S5_STENCIL_TEST_FUNC_SHIFT)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| i915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask); | ||||
|    DBG("%s : mask 0x%x\n", __FUNCTION__, mask); | ||||
|     | ||||
|    mask = mask & 0xff; | ||||
|  | ||||
| @@ -91,17 +91,15 @@ static void | ||||
| i915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|                       GLenum zpass) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int fop = intel_translate_stencil_op(fail); | ||||
|    int dfop = intel_translate_stencil_op(zfail); | ||||
|    int dpop = intel_translate_stencil_op(zpass); | ||||
|  | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, | ||||
|    DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(fail), | ||||
| 	      _mesa_lookup_enum_by_nr(zfail), | ||||
| 	      _mesa_lookup_enum_by_nr(zpass)); | ||||
|        _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass)); | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
| @@ -110,13 +108,16 @@ i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|                                           S5_STENCIL_PASS_Z_PASS_MASK); | ||||
|  | ||||
|    i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) | | ||||
| 				       (dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) | | ||||
| 				       (dpop << S5_STENCIL_PASS_Z_PASS_SHIFT)); | ||||
|                                          (dfop << | ||||
|                                           S5_STENCIL_PASS_Z_FAIL_SHIFT) | | ||||
|                                          (dpop << | ||||
|                                           S5_STENCIL_PASS_Z_PASS_SHIFT)); | ||||
| } | ||||
|  | ||||
| static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
| static void | ||||
| i915AlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|    GLubyte refByte; | ||||
|  | ||||
| @@ -126,7 +127,8 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
|    i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK | | ||||
|                                           S6_ALPHA_REF_MASK); | ||||
|    i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | | ||||
| 				       (((GLuint)refByte) << S6_ALPHA_REF_SHIFT)); | ||||
|                                          (((GLuint) refByte) << | ||||
|                                           S6_ALPHA_REF_SHIFT)); | ||||
| } | ||||
|  | ||||
| /* This function makes sure that the proper enables are | ||||
| @@ -135,33 +137,36 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
|  * could change the LogicOp or Independant Alpha Blend without subsequent | ||||
|  * calls to glEnable. | ||||
|  */ | ||||
| static void i915EvalLogicOpBlendState(GLcontext *ctx) | ||||
| static void | ||||
| i915EvalLogicOpBlendState(GLcontext * ctx) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
|    if (ctx->Color._LogicOpEnabled) { | ||||
|       i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; | ||||
|    } else { | ||||
|    } | ||||
|    else { | ||||
|       i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE; | ||||
|  | ||||
|       if (ctx->Color.BlendEnabled) { | ||||
|          i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE; | ||||
|       } else { | ||||
|       } | ||||
|       else { | ||||
|          i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i915BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| static void | ||||
| i915BlendColor(GLcontext * ctx, const GLfloat color[4]) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLubyte r, g, b, a; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); | ||||
|    UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); | ||||
| @@ -169,7 +174,8 @@ static void i915BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
|    UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|    i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = (a<<24) | (r<<16) | (g<<8) | b; | ||||
|    i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = | ||||
|       (a << 24) | (r << 16) | (g << 8) | b; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -180,31 +186,37 @@ static void i915BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLuint translate_blend_equation( GLenum mode ) | ||||
| static GLuint | ||||
| translate_blend_equation(GLenum mode) | ||||
| { | ||||
|    switch (mode) { | ||||
|    case GL_FUNC_ADD: return BLENDFUNC_ADD;  | ||||
|    case GL_MIN: return BLENDFUNC_MIN;  | ||||
|    case GL_MAX: return BLENDFUNC_MAX;  | ||||
|    case GL_FUNC_SUBTRACT: return BLENDFUNC_SUBTRACT;  | ||||
|    case GL_FUNC_REVERSE_SUBTRACT: return BLENDFUNC_REVERSE_SUBTRACT;  | ||||
|    default: return 0; | ||||
|    case GL_FUNC_ADD: | ||||
|       return BLENDFUNC_ADD; | ||||
|    case GL_MIN: | ||||
|       return BLENDFUNC_MIN; | ||||
|    case GL_MAX: | ||||
|       return BLENDFUNC_MAX; | ||||
|    case GL_FUNC_SUBTRACT: | ||||
|       return BLENDFUNC_SUBTRACT; | ||||
|    case GL_FUNC_REVERSE_SUBTRACT: | ||||
|       return BLENDFUNC_REVERSE_SUBTRACT; | ||||
|    default: | ||||
|       return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i915UpdateBlendState( GLcontext *ctx ) | ||||
| static void | ||||
| i915UpdateBlendState(GLcontext * ctx) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] & | ||||
|                  ~(IAB_SRC_FACTOR_MASK | | ||||
|                    IAB_DST_FACTOR_MASK | | ||||
| 		   (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | | ||||
| 		   IAB_ENABLE)); | ||||
|                    (BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE)); | ||||
|  | ||||
|    GLuint lis6 = (i915->state.Ctx[I915_CTXREG_LIS6] & | ||||
|                   ~(S6_CBUF_SRC_BLEND_FACT_MASK | | ||||
| 		    S6_CBUF_DST_BLEND_FACT_MASK | | ||||
| 		    S6_CBUF_BLEND_FUNC_MASK)); | ||||
|                     S6_CBUF_DST_BLEND_FACT_MASK | S6_CBUF_BLEND_FUNC_MASK)); | ||||
|  | ||||
|    GLuint eqRGB = ctx->Color.BlendEquationRGB; | ||||
|    GLuint eqA = ctx->Color.BlendEquationA; | ||||
| @@ -244,40 +256,40 @@ static void i915UpdateBlendState( GLcontext *ctx ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915BlendFuncSeparate(GLcontext *ctx, GLenum srcRGB,  | ||||
| 				 GLenum dstRGB, GLenum srcA, | ||||
| 				 GLenum dstA ) | ||||
| static void | ||||
| i915BlendFuncSeparate(GLcontext * ctx, GLenum srcRGB, | ||||
|                       GLenum dstRGB, GLenum srcA, GLenum dstA) | ||||
| { | ||||
|    i915UpdateBlendState(ctx); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB, | ||||
| 				     GLenum eqA)  | ||||
| static void | ||||
| i915BlendEquationSeparate(GLcontext * ctx, GLenum eqRGB, GLenum eqA) | ||||
| { | ||||
|    i915UpdateBlendState(ctx); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915DepthFunc(GLcontext *ctx, GLenum func) | ||||
| static void | ||||
| i915DepthFunc(GLcontext * ctx, GLenum func) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|    i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK; | ||||
|    i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT; | ||||
| } | ||||
|  | ||||
| static void i915DepthMask(GLcontext *ctx, GLboolean flag) | ||||
| static void | ||||
| i915DepthMask(GLcontext * ctx, GLboolean flag) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag); | ||||
|    DBG("%s flag (%d)\n", __FUNCTION__, flag); | ||||
|     | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
| @@ -293,9 +305,10 @@ static void i915DepthMask(GLcontext *ctx, GLboolean flag) | ||||
|  * The i915 supports a 4x4 stipple natively, GL wants 32x32. | ||||
|  * Fortunately stipple is usually a repeating pattern. | ||||
|  */ | ||||
| static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| static void | ||||
| i915PolygonStipple(GLcontext * ctx, const GLubyte * mask) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    const GLubyte *m = mask; | ||||
|    GLubyte p[4]; | ||||
|    int i, j, k; | ||||
| @@ -308,10 +321,14 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
|       i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE; | ||||
|    } | ||||
|  | ||||
|    p[0] = mask[12] & 0xf; p[0] |= p[0] << 4; | ||||
|    p[1] = mask[8] & 0xf; p[1] |= p[1] << 4; | ||||
|    p[2] = mask[4] & 0xf; p[2] |= p[2] << 4; | ||||
|    p[3] = mask[0] & 0xf; p[3] |= p[3] << 4; | ||||
|    p[0] = mask[12] & 0xf; | ||||
|    p[0] |= p[0] << 4; | ||||
|    p[1] = mask[8] & 0xf; | ||||
|    p[1] |= p[1] << 4; | ||||
|    p[2] = mask[4] & 0xf; | ||||
|    p[2] |= p[2] << 4; | ||||
|    p[3] = mask[0] & 0xf; | ||||
|    p[3] |= p[3] << 4; | ||||
|  | ||||
|    for (k = 0; k < 8; k++) | ||||
|       for (j = 3; j >= 0; j--) | ||||
| @@ -323,8 +340,7 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
|  | ||||
|    newMask = (((p[0] & 0xf) << 0) | | ||||
|               ((p[1] & 0xf) << 4) | | ||||
| 	      ((p[2] & 0xf) << 8) | | ||||
| 	      ((p[3] & 0xf) << 12)); | ||||
|               ((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12)); | ||||
|  | ||||
|  | ||||
|    if (newMask == 0xffff || newMask == 0x0) { | ||||
| @@ -345,48 +361,40 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| /* ============================================================= | ||||
|  * Hardware clipping | ||||
|  */ | ||||
| static void i915Scissor(GLcontext *ctx, GLint x, GLint y,  | ||||
| 			GLsizei w, GLsizei h) | ||||
| static void | ||||
| i915Scissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = i915->intel.intelScreen; | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int x1, y1, x2, y2; | ||||
|  | ||||
|    if (!i915->intel.driDrawable) | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|  | ||||
|    x1 = x; | ||||
|    y1 = i915->intel.driDrawable->h - (y + h); | ||||
|    y1 = ctx->DrawBuffer->Height - (y + h); | ||||
|    x2 = x + w - 1; | ||||
|    y2 = y1 + h - 1; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__, | ||||
|    DBG("[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__, | ||||
|        x, y, w, h); | ||||
|  | ||||
|    if (x1 < 0) x1 = 0; | ||||
|    if (y1 < 0) y1 = 0; | ||||
|    if (x2 < 0) x2 = 0; | ||||
|    if (y2 < 0) y2 = 0; | ||||
|  | ||||
|    if (x2 >= screen->width) x2 = screen->width-1; | ||||
|    if (y2 >= screen->height) y2 = screen->height-1; | ||||
|    if (x1 >= screen->width) x1 = screen->width-1; | ||||
|    if (y1 >= screen->height) y1 = screen->height-1; | ||||
|  | ||||
|    x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); | ||||
|    x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); | ||||
|    i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); | ||||
|    i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); | ||||
| } | ||||
|  | ||||
| static void i915LogicOp(GLcontext *ctx, GLenum opcode) | ||||
| static void | ||||
| i915LogicOp(GLcontext * ctx, GLenum opcode) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int tmp = intel_translate_logic_op(opcode); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|    i915->state.Ctx[I915_CTXREG_STATE4] &= ~LOGICOP_MASK; | ||||
| @@ -395,13 +403,14 @@ static void i915LogicOp(GLcontext *ctx, GLenum opcode) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
| static void | ||||
| i915CullFaceFrontFace(GLcontext * ctx, GLenum unused) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLuint mode; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s %d\n", __FUNCTION__, | ||||
|        ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0); | ||||
|  | ||||
|    if (!ctx->Polygon.CullFlag) { | ||||
|       mode = S4_CULLMODE_NONE; | ||||
| @@ -409,6 +418,8 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
|    else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { | ||||
|       mode = S4_CULLMODE_CW; | ||||
|  | ||||
|       if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) | ||||
|          mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); | ||||
|       if (ctx->Polygon.CullFaceMode == GL_FRONT) | ||||
|          mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); | ||||
|       if (ctx->Polygon.FrontFace != GL_CCW) | ||||
| @@ -423,14 +434,14 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
|    i915->state.Ctx[I915_CTXREG_LIS4] |= mode; | ||||
| } | ||||
|  | ||||
| static void i915LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
| static void | ||||
| i915LineWidth(GLcontext * ctx, GLfloat widthf) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK; | ||||
|    int width; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    width = (int) (widthf * 2); | ||||
|    CLAMP_SELF(width, 1, 0xf); | ||||
| @@ -442,14 +453,14 @@ static void i915LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i915PointSize(GLcontext *ctx, GLfloat size) | ||||
| static void | ||||
| i915PointSize(GLcontext * ctx, GLfloat size) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK; | ||||
|    GLint point_size = (int) size; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|      fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    CLAMP_SELF(point_size, 1, 255); | ||||
|    lis4 |= point_size << S4_POINT_WIDTH_SHIFT; | ||||
| @@ -465,20 +476,24 @@ static void i915PointSize(GLcontext *ctx, GLfloat size) | ||||
|  * Color masks | ||||
|  */ | ||||
|  | ||||
| static void i915ColorMask(GLcontext *ctx, | ||||
| 			 GLboolean r, GLboolean g, | ||||
| 			 GLboolean b, GLboolean a) | ||||
| static void | ||||
| i915ColorMask(GLcontext * ctx, | ||||
|               GLboolean r, GLboolean g, GLboolean b, GLboolean a) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); | ||||
|    DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, | ||||
|        a); | ||||
|  | ||||
|    if (!r) tmp |= S5_WRITEDISABLE_RED; | ||||
|    if (!g) tmp |= S5_WRITEDISABLE_GREEN; | ||||
|    if (!b) tmp |= S5_WRITEDISABLE_BLUE; | ||||
|    if (!a) tmp |= S5_WRITEDISABLE_ALPHA; | ||||
|    if (!r) | ||||
|       tmp |= S5_WRITEDISABLE_RED; | ||||
|    if (!g) | ||||
|       tmp |= S5_WRITEDISABLE_GREEN; | ||||
|    if (!b) | ||||
|       tmp |= S5_WRITEDISABLE_BLUE; | ||||
|    if (!a) | ||||
|       tmp |= S5_WRITEDISABLE_ALPHA; | ||||
|  | ||||
|    if (tmp != i915->state.Ctx[I915_CTXREG_LIS5]) { | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
| @@ -486,35 +501,37 @@ static void i915ColorMask(GLcontext *ctx, | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void update_specular( GLcontext *ctx ) | ||||
| static void | ||||
| update_specular(GLcontext * ctx) | ||||
| { | ||||
|    /* A hack to trigger the rebuild of the fragment program. | ||||
|     */ | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= _NEW_TEXTURE; | ||||
|    intel_context(ctx)->NewGLState |= _NEW_TEXTURE; | ||||
|    I915_CONTEXT(ctx)->tex_program.translated = 0; | ||||
| } | ||||
|  | ||||
| static void i915LightModelfv(GLcontext *ctx, GLenum pname,  | ||||
| 			     const GLfloat *param) | ||||
| static void | ||||
| i915LightModelfv(GLcontext * ctx, GLenum pname, const GLfloat * param) | ||||
| { | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { | ||||
|       update_specular(ctx); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i915ShadeModel(GLcontext *ctx, GLenum mode) | ||||
| static void | ||||
| i915ShadeModel(GLcontext * ctx, GLenum mode) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
|    if (mode == GL_SMOOTH) { | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] &= ~(S4_FLATSHADE_ALPHA | | ||||
|                                              S4_FLATSHADE_COLOR | | ||||
|                                              S4_FLATSHADE_SPECULAR); | ||||
|    } else { | ||||
|    } | ||||
|    else { | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] |= (S4_FLATSHADE_ALPHA | | ||||
|                                             S4_FLATSHADE_COLOR | | ||||
|                                             S4_FLATSHADE_SPECULAR); | ||||
| @@ -524,9 +541,10 @@ static void i915ShadeModel(GLcontext *ctx, GLenum mode) | ||||
| /* ============================================================= | ||||
|  * Fog | ||||
|  */ | ||||
| void i915_update_fog( GLcontext *ctx ) | ||||
| void | ||||
| i915_update_fog(GLcontext * ctx) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLenum mode; | ||||
|    GLboolean enabled; | ||||
|    GLboolean try_pixel_fog; | ||||
| @@ -542,9 +560,7 @@ void i915_update_fog( GLcontext *ctx ) | ||||
|       enabled = ctx->Fog.Enabled; | ||||
|       mode = ctx->Fog.Mode; | ||||
|  | ||||
|       try_pixel_fog = (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && | ||||
| 		       ctx->Hint.Fog == GL_NICEST &&  | ||||
| 		       0);	/* XXX - DISABLE -- Need ortho fallback */ | ||||
|       try_pixel_fog = (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && ctx->Hint.Fog == GL_NICEST && 0);       /* XXX - DISABLE -- Need ortho fallback */ | ||||
|    } | ||||
|  | ||||
|    if (!enabled) { | ||||
| @@ -576,10 +592,15 @@ void i915_update_fog( GLcontext *ctx ) | ||||
|                ((GLuint) (c1 * FMC1_C1_ONE)) & FMC1_C1_MASK; | ||||
|  | ||||
|             if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) { | ||||
| 	       i915->state.Fog[I915_FOGREG_MODE2] = (GLuint)(c2 * FMC2_C2_ONE); | ||||
|                i915->state.Fog[I915_FOGREG_MODE2] = | ||||
|                   (GLuint) (c2 * FMC2_C2_ONE); | ||||
|             } | ||||
|             else { | ||||
| 	       union { float f; int i; } fi; | ||||
|                union | ||||
|                { | ||||
|                   float f; | ||||
|                   int i; | ||||
|                } fi; | ||||
|                fi.f = c2; | ||||
|                i915->state.Fog[I915_FOGREG_MODE2] = fi.i; | ||||
|             } | ||||
| @@ -595,7 +616,8 @@ void i915_update_fog( GLcontext *ctx ) | ||||
|          break; | ||||
|       } | ||||
|    } | ||||
|    else /* if (i915->vertex_fog != I915_FOG_VERTEX) */ {       | ||||
|    else {                       /* if (i915->vertex_fog != I915_FOG_VERTEX) */ | ||||
|  | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_FOG); | ||||
|       i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK; | ||||
|       i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX; | ||||
| @@ -617,9 +639,10 @@ void i915_update_fog( GLcontext *ctx ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
| static void | ||||
| i915Fogfv(GLcontext * ctx, GLenum pname, const GLfloat * param) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_FOG_COORDINATE_SOURCE_EXT: | ||||
| @@ -636,7 +659,11 @@ static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
|                                                         FMC3_D_ONE); | ||||
|       } | ||||
|       else { | ||||
| 	 union { float f; int i; } fi; | ||||
|          union | ||||
|          { | ||||
|             float f; | ||||
|             int i; | ||||
|          } fi; | ||||
|          fi.f = ctx->Fog.Density; | ||||
|          i915->state.Fog[I915_FOGREG_MODE3] = fi.i; | ||||
|       } | ||||
| @@ -656,7 +683,8 @@ static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i915Hint(GLcontext *ctx, GLenum target, GLenum state) | ||||
| static void | ||||
| i915Hint(GLcontext * ctx, GLenum target, GLenum state) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_FOG_HINT: | ||||
| @@ -669,9 +697,10 @@ static void i915Hint(GLcontext *ctx, GLenum target, GLenum state) | ||||
| /* ============================================================= | ||||
|  */ | ||||
|  | ||||
| static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| static void | ||||
| i915Enable(GLcontext * ctx, GLenum cap, GLboolean state) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    switch (cap) { | ||||
|    case GL_TEXTURE_2D: | ||||
| @@ -699,7 +728,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|  | ||||
|       /* Logicop doesn't seem to work at 16bpp: | ||||
|        */ | ||||
|       if (i915->intel.intelScreen->cpp == 2) | ||||
|       if (i915->intel.intelScreen->cpp == 2)    /* XXX FBO fix */ | ||||
|          FALLBACK(&i915->intel, I915_FALLBACK_LOGICOP, state); | ||||
|       break; | ||||
|  | ||||
| @@ -727,11 +756,11 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|    case GL_SCISSOR_TEST: | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); | ||||
|       if (state) | ||||
| 	 i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | | ||||
| 						   ENABLE_SCISSOR_RECT); | ||||
|          i915->state.Buffer[I915_DESTREG_SENABLE] = | ||||
|             (_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); | ||||
|       else | ||||
| 	 i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | | ||||
| 						   DISABLE_SCISSOR_RECT); | ||||
|          i915->state.Buffer[I915_DESTREG_SENABLE] = | ||||
|             (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); | ||||
|       break; | ||||
|  | ||||
|    case GL_LINE_SMOOTH: | ||||
| @@ -750,7 +779,14 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|       break; | ||||
|  | ||||
|    case GL_STENCIL_TEST: | ||||
|       if (i915->intel.hw_stencil) { | ||||
|       { | ||||
|          GLboolean hw_stencil = GL_FALSE; | ||||
|          if (ctx->DrawBuffer) { | ||||
|             struct intel_renderbuffer *irbStencil | ||||
|                = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); | ||||
|             hw_stencil = (irbStencil && irbStencil->region); | ||||
|          } | ||||
|          if (hw_stencil) { | ||||
|             I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|             if (state) | ||||
|                i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | | ||||
| @@ -758,9 +794,11 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|             else | ||||
|                i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE | | ||||
|                                                       S5_STENCIL_WRITE_ENABLE); | ||||
|       } else { | ||||
|          } | ||||
|          else { | ||||
|             FALLBACK(&i915->intel, I915_FALLBACK_STENCIL, state); | ||||
|          } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|    case GL_POLYGON_STIPPLE: | ||||
| @@ -769,8 +807,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|        * supports it.  Disabled for now. | ||||
|        */ | ||||
|       if (i915->intel.hw_stipple && | ||||
| 	  i915->intel.reduced_primitive == GL_TRIANGLES) | ||||
|       { | ||||
|           i915->intel.reduced_primitive == GL_TRIANGLES) { | ||||
|          I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); | ||||
|          if (state) | ||||
|             i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE; | ||||
| @@ -780,11 +817,9 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|       break; | ||||
|  | ||||
|    case GL_POLYGON_SMOOTH: | ||||
|       FALLBACK( &i915->intel, I915_FALLBACK_POLYGON_SMOOTH, state ); | ||||
|       break; | ||||
|  | ||||
|    case GL_POINT_SMOOTH: | ||||
|       FALLBACK( &i915->intel, I915_FALLBACK_POINT_SMOOTH, state ); | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
| @@ -793,7 +828,8 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_init_packets( i915ContextPtr i915 ) | ||||
| static void | ||||
| i915_init_packets(struct i915_context *i915) | ||||
| { | ||||
|    intelScreenPrivate *screen = i915->intel.intelScreen; | ||||
|  | ||||
| @@ -809,14 +845,12 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|       i915->state.Ctx[I915_CTXREG_LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | | ||||
|                                          I1_LOAD_S(2) | | ||||
|                                          I1_LOAD_S(4) | | ||||
| 				       I1_LOAD_S(5) | | ||||
| 				       I1_LOAD_S(6) |  | ||||
| 				       (4)); | ||||
|                                          I1_LOAD_S(5) | I1_LOAD_S(6) | (4)); | ||||
|       i915->state.Ctx[I915_CTXREG_LIS2] = 0; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] = 0; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS5] = 0; | ||||
|  | ||||
|       if (screen->cpp == 2) | ||||
|       if (screen->cpp == 2)     /* XXX FBO fix */ | ||||
|          i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; | ||||
|  | ||||
|  | ||||
| @@ -831,14 +865,12 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|                                              ENABLE_STENCIL_WRITE_MASK | | ||||
|                                              STENCIL_WRITE_MASK(0xff)); | ||||
|  | ||||
|       i915->state.Ctx[I915_CTXREG_IAB] = | ||||
|          (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE | | ||||
|           IAB_MODIFY_FUNC | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR); | ||||
|  | ||||
|       i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | | ||||
| 					IAB_MODIFY_ENABLE | | ||||
| 					IAB_MODIFY_FUNC | | ||||
| 					IAB_MODIFY_SRC_FACTOR | | ||||
| 					IAB_MODIFY_DST_FACTOR); | ||||
|  | ||||
|       i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] = _3DSTATE_CONST_BLEND_COLOR_CMD; | ||||
|       i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] = | ||||
|          _3DSTATE_CONST_BLEND_COLOR_CMD; | ||||
|       i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0; | ||||
|  | ||||
|    } | ||||
| @@ -866,27 +898,20 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); | ||||
|       /* color buffer offset/stride */ | ||||
|       i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       i915->state.Buffer[I915_DESTREG_CBUFADDR1] =  | ||||
| 	 (BUF_3D_ID_COLOR_BACK |  | ||||
| 	  BUF_3D_PITCH(screen->front.pitch) |  /* pitch in bytes */ | ||||
|       /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */ | ||||
|       i915->state.Buffer[I915_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(screen->front.pitch) |  /* pitch in bytes */ | ||||
|                                                     BUF_3D_USE_FENCE); | ||||
|       /*i915->state.Buffer[I915_DESTREG_CBUFADDR2] is the offset */ | ||||
|  | ||||
|  | ||||
|       /* depth/Z buffer offset/stride */ | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR1] =  | ||||
| 	 (BUF_3D_ID_DEPTH | | ||||
| 	  BUF_3D_PITCH(screen->depth.pitch) |  /* pitch in bytes */ | ||||
|       /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */ | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | BUF_3D_PITCH(screen->depth.pitch) |       /* pitch in bytes */ | ||||
|                                                     BUF_3D_USE_FENCE); | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset; | ||||
|  | ||||
|  | ||||
|       i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; | ||||
|  | ||||
|       /* color/depth pixel format */ | ||||
|       /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */ | ||||
| #if 0                           /* seems we don't need this */ | ||||
|       switch (screen->fbFormat) { | ||||
|       case DV_PF_555: | ||||
|       case DV_PF_565: | ||||
|          i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) |        /* .5 */ | ||||
|                                                  DSTORG_VERT_BIAS(0x8) |        /* .5 */ | ||||
| @@ -905,26 +930,42 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|                                                  DEPTH_FRMT_24_FIXED_8_OTHER); | ||||
|          break; | ||||
|       } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|       /* scissor */ | ||||
|       i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | | ||||
| 						DISABLE_SCISSOR_RECT); | ||||
|       i915->state.Buffer[I915_DESTREG_SENABLE] = | ||||
|          (_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); | ||||
|       i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD; | ||||
|       i915->state.Buffer[I915_DESTREG_SR1] = 0; | ||||
|       i915->state.Buffer[I915_DESTREG_SR2] = 0; | ||||
|    } | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
|    { | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_DEFAULTS); | ||||
|       i915->state.Default[I915_DEFREG_C0] = _3DSTATE_DEFAULT_DIFFUSE; | ||||
|       i915->state.Default[I915_DEFREG_C1] = 0; | ||||
|       i915->state.Default[I915_DEFREG_S0] = _3DSTATE_DEFAULT_SPECULAR; | ||||
|       i915->state.Default[I915_DEFREG_S1] = 0; | ||||
|       i915->state.Default[I915_DEFREG_Z0] = _3DSTATE_DEFAULT_Z; | ||||
|       i915->state.Default[I915_DEFREG_Z1] = 0; | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|    /* These will be emitted every at the head of every buffer, unless | ||||
|     * we get hardware contexts working. | ||||
|     */ | ||||
|    i915->state.active = (I915_UPLOAD_PROGRAM | | ||||
|                          I915_UPLOAD_STIPPLE | | ||||
|                          I915_UPLOAD_CTX | | ||||
| 			I915_UPLOAD_BUFFERS); | ||||
|                          I915_UPLOAD_BUFFERS | I915_UPLOAD_INVARIENT); | ||||
| } | ||||
|  | ||||
| void i915InitStateFunctions( struct dd_function_table *functions ) | ||||
| void | ||||
| i915InitStateFunctions(struct dd_function_table *functions) | ||||
| { | ||||
|    functions->AlphaFunc = i915AlphaFunc; | ||||
|    functions->BlendColor = i915BlendColor; | ||||
| @@ -951,7 +992,8 @@ void i915InitStateFunctions( struct dd_function_table *functions ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915InitState( i915ContextPtr i915 ) | ||||
| void | ||||
| i915InitState(struct i915_context *i915) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|  | ||||
| @@ -962,10 +1004,3 @@ void i915InitState( i915ContextPtr i915 ) | ||||
|    memcpy(&i915->initial, &i915->state, sizeof(i915->state)); | ||||
|    i915->current = &i915->state; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -45,76 +45,11 @@ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Allocate space for and load the mesa images into the texture memory block. | ||||
|  * This will happen before drawing with a new texture, or drawing with a | ||||
|  * texture after it was swapped out or teximaged again. | ||||
|  */ | ||||
|  | ||||
| intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ) | ||||
| { | ||||
|    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) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    GLuint unit = ctx->Texture.CurrentUnit; | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_ENV_COLOR:  /* Should be a tracked param */ | ||||
| @@ -139,12 +74,14 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_LOD_BIAS:{ | ||||
|       int b = (int) ((*param) * 16.0); | ||||
|       if (b > 255) b = 255; | ||||
|       if (b < -256) b = -256; | ||||
|          GLuint unit = ctx->Texture.CurrentUnit; | ||||
|          GLint b = (int) ((*param) * 16.0); | ||||
|          if (b > 255) | ||||
|             b = 255; | ||||
|          if (b < -256) | ||||
|             b = -256; | ||||
|          I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); | ||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK; | ||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] |=  | ||||
|          i915->lodbias_ss2[unit] = | ||||
|             ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); | ||||
|          break; | ||||
|       } | ||||
| @@ -155,21 +92,10 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915BindTexture( GLcontext *ctx, GLenum target, | ||||
| 			    struct gl_texture_object *texObj ) | ||||
| static void | ||||
| i915BindTexture(GLcontext * ctx, GLenum target, | ||||
|                 struct gl_texture_object *texobj) | ||||
| { | ||||
|    i915TextureObjectPtr tex; | ||||
|     | ||||
|    if (!texObj->DriverData) | ||||
|       i915AllocTexObj( texObj ); | ||||
|     | ||||
|    tex = (i915TextureObjectPtr)texObj->DriverData; | ||||
|  | ||||
|    if (tex->lastTarget != texObj->Target) { | ||||
|       tex->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       tex->lastTarget = texObj->Target; | ||||
|    } | ||||
|  | ||||
|    /* Need this if image format changes between bound textures. | ||||
|     * Could try and shortcircuit by checking for differences in | ||||
|     * state between incoming and outgoing textures: | ||||
| @@ -179,9 +105,9 @@ static void i915BindTexture( GLcontext *ctx, GLenum target, | ||||
|  | ||||
|  | ||||
|  | ||||
| void i915InitTextureFuncs( struct dd_function_table *functions ) | ||||
| void | ||||
| i915InitTextureFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|    functions->BindTexture = i915BindTexture; | ||||
|    functions->TexEnv = i915TexEnv; | ||||
|    functions->TexParameter = i915TexParameter; | ||||
| } | ||||
|   | ||||
							
								
								
									
										380
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,380 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| /* Code to layout images in a mipmap tree for i915 and i945 | ||||
|  * respectively. | ||||
|  */ | ||||
|  | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "macros.h" | ||||
| #include "intel_context.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_TEXTURE | ||||
|  | ||||
| static GLint initial_offsets[6][2] = { {0, 0}, | ||||
| {0, 2}, | ||||
| {1, 0}, | ||||
| {1, 2}, | ||||
| {1, 1}, | ||||
| {1, 3} | ||||
| }; | ||||
|  | ||||
|  | ||||
| static GLint step_offsets[6][2] = { {0, 2}, | ||||
| {0, 2}, | ||||
| {-1, 2}, | ||||
| {-1, 2}, | ||||
| {-1, 1}, | ||||
| {-1, 1} | ||||
| }; | ||||
|  | ||||
| static GLuint | ||||
| minify(GLuint d) | ||||
| { | ||||
|    return MAX2(1, d >> 1); | ||||
| } | ||||
|  | ||||
| GLboolean | ||||
| i915_miptree_layout(struct intel_mipmap_tree * mt) | ||||
| { | ||||
|    GLint level; | ||||
|  | ||||
|    switch (mt->target) { | ||||
|    case GL_TEXTURE_CUBE_MAP:{ | ||||
|          const GLuint dim = mt->width0; | ||||
|          GLuint face; | ||||
|  | ||||
|          /* double pitch for cube layouts */ | ||||
|          mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp; | ||||
|          mt->total_height = dim * 4; | ||||
|  | ||||
|          for (level = mt->first_level; level <= mt->last_level; level++) | ||||
|             intel_miptree_set_level_info(mt, level, 6, | ||||
|                                          0, 0, | ||||
|                                          mt->pitch, mt->total_height, 1); | ||||
|  | ||||
|          for (face = 0; face < 6; face++) { | ||||
|             GLuint x = initial_offsets[face][0] * dim; | ||||
|             GLuint y = initial_offsets[face][1] * dim; | ||||
|             GLuint d = dim; | ||||
|  | ||||
|             for (level = mt->first_level; level <= mt->last_level; level++) { | ||||
|                intel_miptree_set_image_offset(mt, level, face, x, y); | ||||
|  | ||||
|                if (d == 0) | ||||
|                   _mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n", | ||||
|                                face, level, mt->first_level, mt->last_level); | ||||
|  | ||||
|                d >>= 1; | ||||
|                x += step_offsets[face][0] * d; | ||||
|                y += step_offsets[face][1] * d; | ||||
|             } | ||||
|          } | ||||
|          break; | ||||
|       } | ||||
|    case GL_TEXTURE_3D:{ | ||||
|          GLuint width = mt->width0; | ||||
|          GLuint height = mt->height0; | ||||
|          GLuint depth = mt->depth0; | ||||
|          GLuint stack_height = 0; | ||||
|  | ||||
|          /* Calculate the size of a single slice.  | ||||
|           */ | ||||
|          mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|  | ||||
|          /* XXX: hardware expects/requires 9 levels at minimum. | ||||
|           */ | ||||
|          for (level = mt->first_level; level <= MAX2(8, mt->last_level); | ||||
|               level++) { | ||||
|             intel_miptree_set_level_info(mt, level, 1, 0, mt->total_height, | ||||
|                                          width, height, depth); | ||||
|  | ||||
|  | ||||
|             stack_height += MAX2(2, height); | ||||
|  | ||||
|             width = minify(width); | ||||
|             height = minify(height); | ||||
|             depth = minify(depth); | ||||
|          } | ||||
|  | ||||
|          /* Fixup depth image_offsets:  | ||||
|           */ | ||||
|          depth = mt->depth0; | ||||
|          for (level = mt->first_level; level <= mt->last_level; level++) { | ||||
|             GLuint i; | ||||
|             for (i = 0; i < depth; i++)  | ||||
|                intel_miptree_set_image_offset(mt, level, i, | ||||
|                                               0, i * stack_height); | ||||
|  | ||||
|             depth = minify(depth); | ||||
|          } | ||||
|  | ||||
|  | ||||
|          /* Multiply slice size by texture depth for total size.  It's | ||||
|           * remarkable how wasteful of memory the i915 texture layouts | ||||
|           * are.  They are largely fixed in the i945. | ||||
|           */ | ||||
|          mt->total_height = stack_height * mt->depth0; | ||||
|          break; | ||||
|       } | ||||
|  | ||||
|    default:{ | ||||
|          GLuint width = mt->width0; | ||||
|          GLuint height = mt->height0; | ||||
| 	 GLuint img_height; | ||||
|  | ||||
|          mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|          mt->total_height = 0; | ||||
|  | ||||
|          for (level = mt->first_level; level <= mt->last_level; level++) { | ||||
|             intel_miptree_set_level_info(mt, level, 1, | ||||
|                                          0, mt->total_height, | ||||
|                                          width, height, 1); | ||||
|  | ||||
|             if (mt->compressed) | ||||
|                img_height = MAX2(1, height / 4); | ||||
|             else | ||||
|                img_height = MAX2(2, height); | ||||
|  | ||||
| 	    mt->total_height += img_height; | ||||
| 	    mt->total_height += 1; | ||||
| 	    mt->total_height &= ~1; | ||||
|  | ||||
|             width = minify(width); | ||||
|             height = minify(height); | ||||
|          } | ||||
|          break; | ||||
|       } | ||||
|    } | ||||
|    DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__, | ||||
|        mt->pitch, | ||||
|        mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean | ||||
| i945_miptree_layout(struct intel_mipmap_tree * mt) | ||||
| { | ||||
|    GLint level; | ||||
|  | ||||
|    switch (mt->target) { | ||||
|    case GL_TEXTURE_CUBE_MAP:{ | ||||
|          const GLuint dim = mt->width0; | ||||
|          GLuint face; | ||||
|  | ||||
|          /* Depending on the size of the largest images, pitch can be | ||||
|           * determined either by the old-style packing of cubemap faces, | ||||
|           * or the final row of 4x4, 2x2 and 1x1 faces below this.  | ||||
|           */ | ||||
|          if (dim > 32) | ||||
|             mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp; | ||||
|          else | ||||
|             mt->pitch = 14 * 8; | ||||
|  | ||||
|          mt->total_height = dim * 4 + 4; | ||||
|  | ||||
|          /* Set all the levels to effectively occupy the whole rectangular region.  | ||||
|           */ | ||||
|          for (level = mt->first_level; level <= mt->last_level; level++) | ||||
|             intel_miptree_set_level_info(mt, level, 6, | ||||
|                                          0, 0, | ||||
|                                          mt->pitch, mt->total_height, 1); | ||||
|  | ||||
|  | ||||
|  | ||||
|          for (face = 0; face < 6; face++) { | ||||
|             GLuint x = initial_offsets[face][0] * dim; | ||||
|             GLuint y = initial_offsets[face][1] * dim; | ||||
|             GLuint d = dim; | ||||
|  | ||||
|             if (dim == 4 && face >= 4) { | ||||
|                y = mt->total_height - 4; | ||||
|                x = (face - 4) * 8; | ||||
|             } | ||||
|             else if (dim < 4) { | ||||
|                y = mt->total_height - 4; | ||||
|                x = face * 8; | ||||
|             } | ||||
|  | ||||
|             for (level = mt->first_level; level <= mt->last_level; level++) { | ||||
|                intel_miptree_set_image_offset(mt, level, face, x, y); | ||||
|  | ||||
|                d >>= 1; | ||||
|  | ||||
|                switch (d) { | ||||
|                case 4: | ||||
|                   switch (face) { | ||||
|                   case FACE_POS_X: | ||||
|                   case FACE_NEG_X: | ||||
|                      x += step_offsets[face][0] * d; | ||||
|                      y += step_offsets[face][1] * d; | ||||
|                      break; | ||||
|                   case FACE_POS_Y: | ||||
|                   case FACE_NEG_Y: | ||||
|                      y += 12; | ||||
|                      x -= 8; | ||||
|                      break; | ||||
|                   case FACE_POS_Z: | ||||
|                   case FACE_NEG_Z: | ||||
|                      y = mt->total_height - 4; | ||||
|                      x = (face - 4) * 8; | ||||
|                      break; | ||||
|                   } | ||||
|  | ||||
|                case 2: | ||||
|                   y = mt->total_height - 4; | ||||
|                   x = 16 + face * 8; | ||||
|                   break; | ||||
|  | ||||
|                case 1: | ||||
|                   x += 48; | ||||
|                   break; | ||||
|  | ||||
|                default: | ||||
|                   x += step_offsets[face][0] * d; | ||||
|                   y += step_offsets[face][1] * d; | ||||
|                   break; | ||||
|                } | ||||
|             } | ||||
|          } | ||||
|          break; | ||||
|       } | ||||
|    case GL_TEXTURE_3D:{ | ||||
|          GLuint width = mt->width0; | ||||
|          GLuint height = mt->height0; | ||||
|          GLuint depth = mt->depth0; | ||||
|          GLuint pack_x_pitch, pack_x_nr; | ||||
|          GLuint pack_y_pitch; | ||||
|          GLuint level; | ||||
|  | ||||
|          mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|          mt->total_height = 0; | ||||
|  | ||||
|          pack_y_pitch = MAX2(mt->height0, 2); | ||||
|          pack_x_pitch = mt->pitch; | ||||
|          pack_x_nr = 1; | ||||
|  | ||||
|          for (level = mt->first_level; level <= mt->last_level; level++) { | ||||
|             GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6; | ||||
|             GLint x = 0; | ||||
|             GLint y = 0; | ||||
|             GLint q, j; | ||||
|  | ||||
|             intel_miptree_set_level_info(mt, level, nr_images, | ||||
|                                          0, mt->total_height, | ||||
|                                          width, height, depth); | ||||
|  | ||||
|             for (q = 0; q < nr_images;) { | ||||
|                for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) { | ||||
|                   intel_miptree_set_image_offset(mt, level, q, x, y); | ||||
|                   x += pack_x_pitch; | ||||
|                } | ||||
|  | ||||
|                x = 0; | ||||
|                y += pack_y_pitch; | ||||
|             } | ||||
|  | ||||
|  | ||||
|             mt->total_height += y; | ||||
|  | ||||
|             if (pack_x_pitch > 4) { | ||||
|                pack_x_pitch >>= 1; | ||||
|                pack_x_nr <<= 1; | ||||
|                assert(pack_x_pitch * pack_x_nr <= mt->pitch); | ||||
|             } | ||||
|  | ||||
|             if (pack_y_pitch > 2) { | ||||
|                pack_y_pitch >>= 1; | ||||
|             } | ||||
|  | ||||
|             width = minify(width); | ||||
|             height = minify(height); | ||||
|             depth = minify(depth); | ||||
|          } | ||||
|          break; | ||||
|       } | ||||
|  | ||||
|    case GL_TEXTURE_1D: | ||||
|    case GL_TEXTURE_2D: | ||||
|    case GL_TEXTURE_RECTANGLE_ARB:{ | ||||
|          GLuint x = 0; | ||||
|          GLuint y = 0; | ||||
|          GLuint width = mt->width0; | ||||
|          GLuint height = mt->height0; | ||||
| 	 GLint align_h = 2; | ||||
|  | ||||
|          mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|          mt->total_height = 0; | ||||
|  | ||||
|          for (level = mt->first_level; level <= mt->last_level; level++) { | ||||
| 	    GLuint img_height; | ||||
|  | ||||
|             intel_miptree_set_level_info(mt, level, 1, | ||||
|                                          x, y,  | ||||
| 					 width,  | ||||
| 					 mt->compressed ? height/4 : height, 1); | ||||
|  | ||||
|  | ||||
| 	    if (mt->compressed) | ||||
|                img_height = MAX2(1, height / 4); | ||||
|             else | ||||
|                img_height = MAX2(align_h, height); | ||||
|  | ||||
|             /* LPT change: step right after second mipmap. | ||||
|              */ | ||||
|             if (level == mt->first_level + 1) { | ||||
|                x += mt->pitch / 2; | ||||
| 	       x = (x + 3) & ~3; | ||||
| 	    } | ||||
|             else { | ||||
| 	       y += img_height; | ||||
| 	       y += align_h - 1; | ||||
| 	       y &= ~(align_h - 1); | ||||
| 	    } | ||||
|  | ||||
|             /* Because the images are packed better, the final offset | ||||
|              * might not be the maximal one: | ||||
|              */ | ||||
|             mt->total_height = MAX2(mt->total_height, y); | ||||
|  | ||||
|             width = minify(width); | ||||
|             height = minify(height); | ||||
|          } | ||||
|          break; | ||||
|       } | ||||
|    default: | ||||
|       _mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()"); | ||||
|    } | ||||
|  | ||||
|    DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__, | ||||
|        mt->pitch, | ||||
|        mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
| @@ -1,671 +0,0 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include <strings.h> | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "macros.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "tnl/t_context.h" | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| #include "i915_reg.h" | ||||
| #include "i915_context.h" | ||||
| #include "i915_program.h" | ||||
|  | ||||
| static GLuint translate_tex_src_bit( struct i915_fragment_program *p, | ||||
| 				     GLubyte bit ) | ||||
| { | ||||
|    switch (bit) { | ||||
|    case TEXTURE_1D_BIT:   return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_2D_BIT:   return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_RECT_BIT: return D0_SAMPLE_TYPE_2D; | ||||
|    case TEXTURE_3D_BIT:   return D0_SAMPLE_TYPE_VOLUME; | ||||
|    case TEXTURE_CUBE_BIT: return D0_SAMPLE_TYPE_CUBE; | ||||
|    default: i915_program_error(p, "TexSrcBit"); return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static GLuint get_source( struct i915_fragment_program *p,  | ||||
| 			  GLenum src, GLuint unit ) | ||||
| { | ||||
|    switch (src) { | ||||
|    case GL_TEXTURE:  | ||||
|       if (p->src_texture == UREG_BAD) { | ||||
|  | ||||
| 	 /* TODO: Use D0_CHANNEL_XY where possible. | ||||
| 	  */ | ||||
| 	 GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled); | ||||
| 	 GLuint sampler = i915_emit_decl(p, REG_TYPE_S, unit, dim); | ||||
| 	 GLuint texcoord = i915_emit_decl(p, REG_TYPE_T, unit, D0_CHANNEL_ALL); | ||||
| 	 GLuint tmp = i915_get_temp( p ); | ||||
| 	 GLuint op = T0_TEXLD; | ||||
|  | ||||
| 	 if (p->VB->TexCoordPtr[unit]->size == 4) | ||||
| 	    op = T0_TEXLDP; | ||||
|  | ||||
| 	 p->src_texture = i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL,  | ||||
| 					  sampler, texcoord, op ); | ||||
|       } | ||||
|  | ||||
|       return p->src_texture; | ||||
|  | ||||
|       /* Crossbar: */ | ||||
|    case GL_TEXTURE0: | ||||
|    case GL_TEXTURE1: | ||||
|    case GL_TEXTURE2: | ||||
|    case GL_TEXTURE3: | ||||
|    case GL_TEXTURE4: | ||||
|    case GL_TEXTURE5: | ||||
|    case GL_TEXTURE6: | ||||
|    case GL_TEXTURE7: { | ||||
|       return UREG_BAD; | ||||
|    } | ||||
|  | ||||
|    case GL_CONSTANT: | ||||
|       return i915_emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor ); | ||||
|    case GL_PRIMARY_COLOR: | ||||
|       return i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); | ||||
|    case GL_PREVIOUS: | ||||
|    default:  | ||||
|       i915_emit_decl(p,  | ||||
| 		GET_UREG_TYPE(p->src_previous), | ||||
| 		GET_UREG_NR(p->src_previous), D0_CHANNEL_ALL);  | ||||
|       return p->src_previous; | ||||
|    } | ||||
| } | ||||
| 			 | ||||
|  | ||||
| static GLuint emit_combine_source( struct i915_fragment_program *p,  | ||||
| 				   GLuint mask, | ||||
| 				   GLuint unit, | ||||
| 				   GLenum source,  | ||||
| 				   GLenum operand ) | ||||
| { | ||||
|    GLuint arg, src; | ||||
|  | ||||
|    src = get_source(p, source, unit); | ||||
|  | ||||
|    switch (operand) { | ||||
|    case GL_ONE_MINUS_SRC_COLOR:  | ||||
|       /* Get unused tmp, | ||||
|        * Emit tmp = 1.0 + arg.-x-y-z-w | ||||
|        */ | ||||
|       arg = i915_get_temp( p ); | ||||
|       return i915_emit_arith( p, A0_ADD, arg, mask, 0, | ||||
| 		  swizzle(src, ONE, ONE, ONE, ONE ), | ||||
| 		  negate(src, 1,1,1,1), 0); | ||||
|  | ||||
|    case GL_SRC_ALPHA:  | ||||
|       if (mask == A0_DEST_CHANNEL_W) | ||||
| 	 return src; | ||||
|       else | ||||
| 	 return swizzle( src, W, W, W, W ); | ||||
|    case GL_ONE_MINUS_SRC_ALPHA:  | ||||
|       /* Get unused tmp, | ||||
|        * Emit tmp = 1.0 + arg.-w-w-w-w | ||||
|        */ | ||||
|       arg = i915_get_temp( p ); | ||||
|       return i915_emit_arith( p, A0_ADD, arg, mask, 0, | ||||
| 			 swizzle(src, ONE, ONE, ONE, ONE ), | ||||
| 			 negate( swizzle(src,W,W,W,W), 1,1,1,1), 0); | ||||
|    case GL_SRC_COLOR:  | ||||
|    default: | ||||
|       return src; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static int nr_args( GLenum mode ) | ||||
| { | ||||
|    switch (mode) { | ||||
|    case GL_REPLACE: return 1;  | ||||
|    case GL_MODULATE: return 2; | ||||
|    case GL_ADD: return 2; | ||||
|    case GL_ADD_SIGNED: return 2; | ||||
|    case GL_INTERPOLATE:	return 3; | ||||
|    case GL_SUBTRACT: return 2; | ||||
|    case GL_DOT3_RGB_EXT: return 2; | ||||
|    case GL_DOT3_RGBA_EXT: return 2; | ||||
|    case GL_DOT3_RGB: return 2; | ||||
|    case GL_DOT3_RGBA: return 2; | ||||
|    default: return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean args_match( struct gl_texture_unit *texUnit ) | ||||
| { | ||||
|    int i, nr = nr_args(texUnit->Combine.ModeRGB); | ||||
|  | ||||
|    for (i = 0 ; i < nr ; i++) { | ||||
|       if (texUnit->Combine.SourceA[i] != texUnit->Combine.SourceRGB[i])  | ||||
| 	 return GL_FALSE; | ||||
|  | ||||
|       switch(texUnit->Combine.OperandA[i]) { | ||||
|       case GL_SRC_ALPHA:  | ||||
| 	 switch(texUnit->Combine.OperandRGB[i]) { | ||||
| 	 case GL_SRC_COLOR:  | ||||
| 	 case GL_SRC_ALPHA:  | ||||
| 	    break; | ||||
| 	 default: | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
| 	 break; | ||||
|       case GL_ONE_MINUS_SRC_ALPHA:  | ||||
| 	 switch(texUnit->Combine.OperandRGB[i]) { | ||||
| 	 case GL_ONE_MINUS_SRC_COLOR:  | ||||
| 	 case GL_ONE_MINUS_SRC_ALPHA:  | ||||
| 	    break; | ||||
| 	 default: | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
| 	 break; | ||||
|       default:  | ||||
| 	 return GL_FALSE;	/* impossible */ | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLuint emit_combine( struct i915_fragment_program *p, | ||||
| 			    GLuint dest, | ||||
| 			    GLuint mask, | ||||
| 			    GLuint saturate, | ||||
| 			    GLuint unit, | ||||
| 			    GLenum mode, | ||||
| 			    const GLenum *source, | ||||
| 			    const GLenum *operand) | ||||
| { | ||||
|    int tmp, src[3], nr = nr_args(mode); | ||||
|    int i; | ||||
|  | ||||
|    for (i = 0; i < nr; i++) | ||||
|       src[i] = emit_combine_source( p, mask, unit, source[i], operand[i] ); | ||||
|  | ||||
|    switch (mode) { | ||||
|    case GL_REPLACE:  | ||||
|       if (mask == A0_DEST_CHANNEL_ALL && !saturate) | ||||
| 	 return src[0]; | ||||
|       else | ||||
| 	 return i915_emit_arith( p, A0_MOV, dest, mask, saturate, src[0], 0, 0 ); | ||||
|    case GL_MODULATE:  | ||||
|       return i915_emit_arith( p, A0_MUL, dest, mask, saturate, | ||||
| 			     src[0], src[1], 0 ); | ||||
|    case GL_ADD:  | ||||
|       return i915_emit_arith( p, A0_ADD, dest, mask, saturate,  | ||||
| 			     src[0], src[1], 0 ); | ||||
|    case GL_ADD_SIGNED: | ||||
|       /* tmp = arg0 + arg1 | ||||
|        * result = tmp + -.5 | ||||
|        */ | ||||
|       tmp = i915_emit_const1f(p, .5); | ||||
|       tmp = negate(swizzle(tmp,X,X,X,X),1,1,1,1); | ||||
|       i915_emit_arith( p, A0_ADD, dest, mask, 0, src[0], src[1], 0 ); | ||||
|       i915_emit_arith( p, A0_ADD, dest, mask, saturate, dest, tmp, 0 ); | ||||
|       return dest; | ||||
|    case GL_INTERPOLATE:		/* TWO INSTRUCTIONS */ | ||||
|       /* Arg0 * (Arg2) + Arg1 * (1-Arg2) | ||||
|        * | ||||
|        * Arg0*Arg2 + Arg1 - Arg1Arg2  | ||||
|        * | ||||
|        * tmp = Arg0*Arg2 + Arg1,  | ||||
|        * result = (-Arg1)Arg2 + tmp  | ||||
|        */ | ||||
|       tmp = i915_get_temp( p ); | ||||
|       i915_emit_arith( p, A0_MAD, tmp, mask, 0, src[0], src[2], src[1] ); | ||||
|       i915_emit_arith( p, A0_MAD, dest, mask, saturate,  | ||||
| 		      negate(src[1], 1,1,1,1), src[2], tmp ); | ||||
|       return dest; | ||||
|    case GL_SUBTRACT:  | ||||
|       /* negate src[1] */ | ||||
|       return i915_emit_arith( p, A0_ADD, dest, mask, saturate, src[0], | ||||
| 			 negate(src[1],1,1,1,1), 0 ); | ||||
|  | ||||
|    case GL_DOT3_RGBA: | ||||
|    case GL_DOT3_RGBA_EXT:  | ||||
|    case GL_DOT3_RGB_EXT: | ||||
|    case GL_DOT3_RGB: { | ||||
|       GLuint tmp0 = i915_get_temp( p ); | ||||
|       GLuint tmp1 = i915_get_temp( p ); | ||||
|       GLuint neg1 = negate(swizzle(i915_emit_const1f(p, 1),X,X,X,X), 1,1,1,1); | ||||
|       GLuint two = swizzle(i915_emit_const1f(p, 2),X,X,X,X); | ||||
|       i915_emit_arith( p, A0_MAD, tmp0, A0_DEST_CHANNEL_ALL, 0,  | ||||
| 		      two, src[0], neg1); | ||||
|       if (src[0] == src[1]) | ||||
| 	 tmp1 = tmp0; | ||||
|       else | ||||
| 	 i915_emit_arith( p, A0_MAD, tmp1, A0_DEST_CHANNEL_ALL, 0,  | ||||
| 			 two, src[1], neg1); | ||||
|       i915_emit_arith( p, A0_DP3, dest, mask, saturate, tmp0, tmp1, 0); | ||||
|       return dest; | ||||
|    } | ||||
|  | ||||
|    default:  | ||||
|       return src[0]; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static GLuint get_dest( struct i915_fragment_program *p, int unit ) | ||||
| { | ||||
|    if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) | ||||
|       return i915_get_temp( p ); | ||||
|    else if (unit != p->last_tex_stage) | ||||
|       return i915_get_temp( p ); | ||||
|    else | ||||
|       return UREG(REG_TYPE_OC, 0); | ||||
| } | ||||
|        | ||||
|  | ||||
|  | ||||
| static GLuint emit_texenv( struct i915_fragment_program *p, int unit ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &p->ctx->Texture.Unit[unit]; | ||||
|    GLenum envMode = texUnit->EnvMode; | ||||
|    struct gl_texture_object *tObj = texUnit->_Current; | ||||
|    GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; | ||||
|    GLuint saturate = unit < p->last_tex_stage ? A0_DEST_SATURATE : 0; | ||||
|  | ||||
|    switch(envMode) { | ||||
|    case GL_BLEND: { | ||||
|       const int cf = get_source(p, GL_PREVIOUS, unit); | ||||
|       const int cc = get_source(p, GL_CONSTANT, unit); | ||||
|       const int cs = get_source(p, GL_TEXTURE, unit); | ||||
|       const int out = get_dest(p, unit); | ||||
|  | ||||
|       if (format == GL_INTENSITY) { | ||||
| 	 /* cv = cf(1 - cs) + cc.cs | ||||
| 	  * cv = cf - cf.cs + cc.cs | ||||
| 	  */ | ||||
| 	 /* u[2] = MAD( -cf * cs + cf ) | ||||
| 	  * cv   = MAD( cc * cs + u[2] ) | ||||
| 	  */ | ||||
| 	  | ||||
| 	 i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0,  | ||||
| 			 negate(cf,1,1,1,1), cs, cf ); | ||||
|  | ||||
| 	 i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate,  | ||||
| 			 cc, cs, out ); | ||||
|  | ||||
| 	 return out; | ||||
|       } else { | ||||
| 	 /* cv = cf(1 - cs) + cc.cs | ||||
| 	  * cv = cf - cf.cs + cc.cs | ||||
| 	  * av =      af.as | ||||
| 	  */ | ||||
| 	 /* u[2] = MAD( cf.-x-y-zw * cs.xyzw + cf.xyz0 ) | ||||
| 	  * oC   = MAD( cc.xyz0 * cs.xyz0 + u[2].xyzw ) | ||||
| 	  */ | ||||
| 	 i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0, | ||||
| 			 negate(cf,1,1,1,0),   | ||||
| 			 cs, | ||||
| 			 swizzle(cf,X,Y,Z,ZERO) ); | ||||
|  | ||||
|  | ||||
| 	 i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate, | ||||
| 			 swizzle(cc,X,Y,Z,ZERO),   | ||||
| 			 swizzle(cs,X,Y,Z,ZERO), | ||||
| 			 out ); | ||||
|  | ||||
| 	 return out; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    case GL_DECAL: { | ||||
|       if (format == GL_RGB || | ||||
| 	  format == GL_RGBA) { | ||||
| 	 int cf = get_source( p, GL_PREVIOUS, unit ); | ||||
| 	 int cs = get_source( p, GL_TEXTURE, unit ); | ||||
| 	 int out = get_dest(p, unit); | ||||
| 	  | ||||
| 	 /* cv = cf(1-as) + cs.as | ||||
| 	  * cv = cf.(-as) + cf + cs.as | ||||
| 	  * av = af | ||||
| 	  */  | ||||
| 	  | ||||
| 	 /* u[2] = mad( cf.xyzw * cs.-w-w-w1 + cf.xyz0 ) | ||||
| 	  * oc = mad( cs.xyz0 * cs.www0 + u[2].xyzw ) | ||||
| 	  */ | ||||
| 	 i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, 0, | ||||
| 			 cf,   | ||||
| 			 negate(swizzle(cs,W,W,W,ONE),1,1,1,0), | ||||
| 			 swizzle(cf,X,Y,Z,ZERO) ); | ||||
| 	  | ||||
| 	 i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate, | ||||
| 			 swizzle(cs,X,Y,Z,ZERO),   | ||||
| 			 swizzle(cs,W,W,W,ZERO), | ||||
| 			 out ); | ||||
| 	 return out; | ||||
|       } | ||||
|       else { | ||||
| 	 return get_source( p, GL_PREVIOUS, unit ); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    case GL_REPLACE: { | ||||
|       const int cs = get_source( p, GL_TEXTURE, unit );	/* saturated */ | ||||
|       switch (format) { | ||||
|       case GL_ALPHA: { | ||||
| 	 const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */ | ||||
| 	 i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_XYZ, 0, cf, 0, 0 ); | ||||
| 	 return cs; | ||||
|       } | ||||
|       case GL_RGB: | ||||
|       case GL_LUMINANCE: { | ||||
| 	 const int cf = get_source( p, GL_PREVIOUS, unit ); /* saturated */ | ||||
| 	 i915_emit_arith( p, A0_MOV, cs, A0_DEST_CHANNEL_W, 0, cf, 0, 0 ); | ||||
| 	 return cs; | ||||
|       } | ||||
|       default: | ||||
| 	 return cs; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    case GL_MODULATE: { | ||||
|       const int cf = get_source( p, GL_PREVIOUS, unit ); | ||||
|       const int cs = get_source( p, GL_TEXTURE, unit ); | ||||
|       const int out = get_dest(p, unit); | ||||
|       switch (format) { | ||||
|       case GL_ALPHA:  | ||||
| 	 i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate, | ||||
| 			 swizzle(cs, ONE, ONE, ONE, W), cf, 0 ); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 i915_emit_arith( p, A0_MUL, out, A0_DEST_CHANNEL_ALL, saturate,  | ||||
| 			 cs, cf, 0 ); | ||||
| 	 break; | ||||
|       } | ||||
|       return out; | ||||
|    } | ||||
|    case GL_ADD: { | ||||
|       int cf = get_source( p, GL_PREVIOUS, unit ); | ||||
|       int cs = get_source( p, GL_TEXTURE, unit ); | ||||
|       const int out = get_dest( p, unit ); | ||||
|  | ||||
|       if (format == GL_INTENSITY) { | ||||
| 	 /* output-color.rgba = add( incoming, u[1] ) | ||||
| 	  */ | ||||
| 	 i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, saturate,  | ||||
| 			 cs, cf, 0 ); | ||||
| 	 return out; | ||||
|       } | ||||
|       else { | ||||
| 	 /* cv.xyz = cf.xyz + cs.xyz | ||||
| 	  * cv.w   = cf.w * cs.w | ||||
| 	  * | ||||
| 	  * cv.xyzw = MAD( cf.111w * cs.xyzw + cf.xyz0 ) | ||||
| 	  */ | ||||
|  	 i915_emit_arith( p, A0_MAD, out, A0_DEST_CHANNEL_ALL, saturate, | ||||
| 			 swizzle(cf,ONE,ONE,ONE,W),  | ||||
| 			 cs,   | ||||
| 			 swizzle(cf,X,Y,Z,ZERO) );  | ||||
| 	 return out; | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    case GL_COMBINE: { | ||||
|       GLuint rgb_shift, alpha_shift, out, shift; | ||||
|       GLuint dest = get_dest(p, unit); | ||||
|  | ||||
|       /* The EXT version of the DOT3 extension does not support the | ||||
|        * scale factor, but the ARB version (and the version in OpenGL | ||||
|        * 1.3) does. | ||||
|        */ | ||||
|       switch (texUnit->Combine.ModeRGB) { | ||||
|       case GL_DOT3_RGB_EXT: | ||||
| 	 alpha_shift = texUnit->Combine.ScaleShiftA; | ||||
| 	 rgb_shift = 0; | ||||
| 	 break; | ||||
|  | ||||
|       case GL_DOT3_RGBA_EXT: | ||||
| 	 alpha_shift = 0; | ||||
| 	 rgb_shift = 0; | ||||
| 	 break; | ||||
|  | ||||
|       default: | ||||
| 	 rgb_shift = texUnit->Combine.ScaleShiftRGB; | ||||
| 	 alpha_shift = texUnit->Combine.ScaleShiftA; | ||||
| 	 break; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* Emit the RGB and A combine ops | ||||
|        */ | ||||
|       if (texUnit->Combine.ModeRGB == texUnit->Combine.ModeA &&  | ||||
| 	  args_match( texUnit )) { | ||||
| 	 out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate, | ||||
| 			     unit, | ||||
| 			     texUnit->Combine.ModeRGB, | ||||
| 			     texUnit->Combine.SourceRGB, | ||||
| 			     texUnit->Combine.OperandRGB ); | ||||
|       } | ||||
|       else if (texUnit->Combine.ModeRGB == GL_DOT3_RGBA_EXT || | ||||
| 	       texUnit->Combine.ModeRGB == GL_DOT3_RGBA) { | ||||
|  | ||||
| 	 out = emit_combine( p, dest, A0_DEST_CHANNEL_ALL, saturate, | ||||
| 			     unit, | ||||
| 			     texUnit->Combine.ModeRGB, | ||||
| 			     texUnit->Combine.SourceRGB, | ||||
| 			     texUnit->Combine.OperandRGB ); | ||||
|       } | ||||
|       else { | ||||
| 	 /* Need to do something to stop from re-emitting identical | ||||
| 	  * argument calculations here: | ||||
| 	  */ | ||||
| 	 out = emit_combine( p, dest, A0_DEST_CHANNEL_XYZ, saturate, | ||||
| 			     unit, | ||||
| 			     texUnit->Combine.ModeRGB, | ||||
| 			     texUnit->Combine.SourceRGB, | ||||
| 			     texUnit->Combine.OperandRGB ); | ||||
| 	 out = emit_combine( p, dest, A0_DEST_CHANNEL_W, saturate, | ||||
| 			     unit, | ||||
| 			     texUnit->Combine.ModeA, | ||||
| 			     texUnit->Combine.SourceA, | ||||
| 			     texUnit->Combine.OperandA ); | ||||
|       } | ||||
|  | ||||
|       /* Deal with the final shift: | ||||
|        */ | ||||
|       if (alpha_shift || rgb_shift) { | ||||
| 	 if (rgb_shift == alpha_shift) { | ||||
| 	    shift = i915_emit_const1f(p, 1<<rgb_shift); | ||||
| 	    shift = swizzle(shift,X,X,X,X); | ||||
| 	 } | ||||
| 	 else { | ||||
| 	    shift = i915_emit_const2f(p, 1<<rgb_shift, 1<<alpha_shift); | ||||
| 	    shift = swizzle(shift,X,X,X,Y); | ||||
| 	 } | ||||
| 	 return i915_emit_arith( p, A0_MUL, dest, A0_DEST_CHANNEL_ALL,  | ||||
| 				saturate, out, shift, 0 ); | ||||
|       } | ||||
|  | ||||
|       return out; | ||||
|    } | ||||
|  | ||||
|    default: | ||||
|       return get_source(p, GL_PREVIOUS, 0); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void emit_program_fini( struct i915_fragment_program *p ) | ||||
| { | ||||
|    int cf = get_source( p, GL_PREVIOUS, 0 ); | ||||
|    int out = UREG( REG_TYPE_OC, 0 ); | ||||
|  | ||||
|    if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { | ||||
|       /* Emit specular add. | ||||
|        */ | ||||
|       GLuint s = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_ALL); | ||||
|       i915_emit_arith( p, A0_ADD, out, A0_DEST_CHANNEL_ALL, 0, cf,  | ||||
| 		  swizzle(s, X,Y,Z,ZERO), 0 ); | ||||
|    } | ||||
|    else if (cf != out) { | ||||
|       /* Will wind up in here if no texture enabled or a couple of | ||||
|        * other scenarios (GL_REPLACE for instance). | ||||
|        */ | ||||
|       i915_emit_arith( p, A0_MOV, out, A0_DEST_CHANNEL_ALL, 0, cf, 0, 0 ); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915EmitTextureProgram( i915ContextPtr i915 ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    struct i915_fragment_program *p = &i915->tex_program; | ||||
|    GLuint unit; | ||||
|  | ||||
|    if (0) fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    i915_init_program( i915, p ); | ||||
|  | ||||
|    if (ctx->Texture._EnabledUnits) { | ||||
|       for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++) | ||||
| 	 if (ctx->Texture.Unit[unit]._ReallyEnabled) { | ||||
| 	    p->last_tex_stage = unit; | ||||
| 	 } | ||||
|  | ||||
|       for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) | ||||
| 	 if (ctx->Texture.Unit[unit]._ReallyEnabled) { | ||||
| 	    p->src_previous = emit_texenv( p, unit ); | ||||
| 	    p->src_texture = UREG_BAD; | ||||
| 	    p->temp_flag = 0xffff000; | ||||
| 	    p->temp_flag |= 1 << GET_UREG_NR(p->src_previous); | ||||
| 	 } | ||||
|    } | ||||
|  | ||||
|    emit_program_fini( p ); | ||||
|  | ||||
|    i915_fini_program( p ); | ||||
|    i915_upload_program( i915, p ); | ||||
|  | ||||
|    p->translated = 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915ValidateTextureProgram( i915ContextPtr i915 ) | ||||
| { | ||||
|    intelContextPtr intel = &i915->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|    DECLARE_RENDERINPUTS(index_bitset); | ||||
|    int i, offset; | ||||
|    GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; | ||||
|    GLuint s2 = S2_TEXCOORD_NONE; | ||||
|  | ||||
|    RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); | ||||
|  | ||||
|    /* Important: | ||||
|     */ | ||||
|    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; | ||||
|    intel->vertex_attr_count = 0; | ||||
|    intel->coloroffset = 0; | ||||
|    intel->specoffset = 0; | ||||
|    offset = 0; | ||||
|  | ||||
|    if (i915->vertex_fog == I915_FOG_PIXEL) { | ||||
|       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 ); | ||||
|       RENDERINPUTS_CLEAR( index_bitset, _TNL_ATTRIB_FOG ); | ||||
|    } | ||||
|    else if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { | ||||
|       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 ); | ||||
|    } | ||||
|    else { | ||||
|       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12 ); | ||||
|    } | ||||
|  | ||||
|    /* How undefined is undefined? */ | ||||
|    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) { | ||||
|       EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4 ); | ||||
|    } | ||||
|        | ||||
|    intel->coloroffset = offset / 4; | ||||
|    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4 ); | ||||
|              | ||||
|    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || | ||||
|        RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { | ||||
|       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { | ||||
| 	 intel->specoffset = offset / 4; | ||||
| 	 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3 ); | ||||
|       } else  | ||||
| 	 EMIT_PAD( 3 ); | ||||
|        | ||||
|       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) | ||||
| 	 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1 ); | ||||
|       else | ||||
| 	 EMIT_PAD( 1 ); | ||||
|    } | ||||
|  | ||||
|    if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { | ||||
|       for (i = 0; i < 8; i++) { | ||||
| 	 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) { | ||||
| 	    int sz = VB->TexCoordPtr[i]->size; | ||||
| 	     | ||||
| 	    s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); | ||||
| 	    s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); | ||||
|  | ||||
| 	    EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_SZ(sz), 0, sz * 4 ); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Only need to change the vertex emit code if there has been a | ||||
|     * statechange to a new hardware vertex format: | ||||
|     */ | ||||
|    if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || | ||||
|        s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { | ||||
|      | ||||
|       I915_STATECHANGE( i915, I915_UPLOAD_CTX ); | ||||
|  | ||||
|       i915->tex_program.translated = 0; | ||||
|  | ||||
|       /* Must do this *after* statechange, so as not to affect | ||||
|        * buffered vertices reliant on the old state: | ||||
|        */ | ||||
|       intel->vertex_size = _tnl_install_attrs( ctx,  | ||||
| 					       intel->vertex_attrs,  | ||||
| 					       intel->vertex_attr_count, | ||||
| 					       intel->ViewportMatrix.m, 0 );  | ||||
|  | ||||
|       intel->vertex_size >>= 2; | ||||
|  | ||||
|       i915->state.Ctx[I915_CTXREG_LIS2] = s2; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] = s4; | ||||
|  | ||||
|       assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size )); | ||||
|    } | ||||
|  | ||||
|    if (!i915->tex_program.translated || | ||||
|        i915->last_ReallyEnabled != ctx->Texture._EnabledUnits) { | ||||
|       i915EmitTextureProgram( i915 );       | ||||
|       i915->last_ReallyEnabled = ctx->Texture._EnabledUnits; | ||||
|    } | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -37,34 +37,32 @@ | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i915_reg.h" | ||||
| #include "i915_context.h" | ||||
|  | ||||
| static void i915_render_start( intelContextPtr intel ) | ||||
| static void | ||||
| i915_render_start(struct intel_context *intel) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    if (ctx->FragmentProgram._Active)  | ||||
|    i915ValidateFragmentProgram(i915); | ||||
|    else  | ||||
|       i915ValidateTextureProgram( i915 ); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_reduced_primitive_state( intelContextPtr intel, | ||||
| 					  GLenum rprim ) | ||||
| static void | ||||
| i915_reduced_primitive_state(struct intel_context *intel, GLenum rprim) | ||||
| { | ||||
|     i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; | ||||
|  | ||||
|    st1 &= ~ST1_ENABLE; | ||||
|  | ||||
|    switch (rprim) { | ||||
|    case GL_TRIANGLES: | ||||
|        if (intel->ctx.Polygon.StippleFlag && | ||||
| 	   intel->hw_stipple) | ||||
|       if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple) | ||||
|          st1 |= ST1_ENABLE; | ||||
|       break; | ||||
|    case GL_LINES: | ||||
| @@ -76,6 +74,8 @@ static void i915_reduced_primitive_state( intelContextPtr intel, | ||||
|    i915->intel.reduced_primitive = rprim; | ||||
|  | ||||
|    if (st1 != i915->state.Stipple[I915_STPREG_ST1]) { | ||||
|       INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); | ||||
|       i915->state.Stipple[I915_STPREG_ST1] = st1; | ||||
|    } | ||||
| @@ -85,39 +85,65 @@ static void i915_reduced_primitive_state( intelContextPtr intel, | ||||
| /* Pull apart the vertex format registers and figure out how large a | ||||
|  * vertex is supposed to be.  | ||||
|  */ | ||||
| static GLboolean i915_check_vertex_size( intelContextPtr intel, | ||||
| 					 GLuint expected ) | ||||
| static GLboolean | ||||
| i915_check_vertex_size(struct intel_context *intel, GLuint expected) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    int lis2 = i915->current->Ctx[I915_CTXREG_LIS2]; | ||||
|    int lis4 = i915->current->Ctx[I915_CTXREG_LIS4]; | ||||
|    int i, sz = 0; | ||||
|  | ||||
|    switch (lis4 & S4_VFMT_XYZW_MASK) { | ||||
|    case S4_VFMT_XY: sz = 2; break; | ||||
|    case S4_VFMT_XYZ: sz = 3; break; | ||||
|    case S4_VFMT_XYW: sz = 3; break; | ||||
|    case S4_VFMT_XYZW: sz = 4; break; | ||||
|    case S4_VFMT_XY: | ||||
|       sz = 2; | ||||
|       break; | ||||
|    case S4_VFMT_XYZ: | ||||
|       sz = 3; | ||||
|       break; | ||||
|    case S4_VFMT_XYW: | ||||
|       sz = 3; | ||||
|       break; | ||||
|    case S4_VFMT_XYZW: | ||||
|       sz = 4; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "no xyzw specified\n"); | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    if (lis4 & S4_VFMT_SPEC_FOG) sz++; | ||||
|    if (lis4 & S4_VFMT_COLOR) sz++; | ||||
|    if (lis4 & S4_VFMT_DEPTH_OFFSET) sz++; | ||||
|    if (lis4 & S4_VFMT_POINT_WIDTH) sz++; | ||||
|    if (lis4 & S4_VFMT_FOG_PARAM) sz++; | ||||
|    if (lis4 & S4_VFMT_SPEC_FOG) | ||||
|       sz++; | ||||
|    if (lis4 & S4_VFMT_COLOR) | ||||
|       sz++; | ||||
|    if (lis4 & S4_VFMT_DEPTH_OFFSET) | ||||
|       sz++; | ||||
|    if (lis4 & S4_VFMT_POINT_WIDTH) | ||||
|       sz++; | ||||
|    if (lis4 & S4_VFMT_FOG_PARAM) | ||||
|       sz++; | ||||
|  | ||||
|    for (i = 0; i < 8; i++) { | ||||
|       switch (lis2 & S2_TEXCOORD_FMT0_MASK) { | ||||
|       case TEXCOORDFMT_2D: sz += 2; break; | ||||
|       case TEXCOORDFMT_3D: sz += 3; break; | ||||
|       case TEXCOORDFMT_4D: sz += 4; break; | ||||
|       case TEXCOORDFMT_1D: sz += 1; break; | ||||
|       case TEXCOORDFMT_2D_16: sz += 1; break; | ||||
|       case TEXCOORDFMT_4D_16: sz += 2; break; | ||||
|       case TEXCOORDFMT_NOT_PRESENT: break; | ||||
|       case TEXCOORDFMT_2D: | ||||
|          sz += 2; | ||||
|          break; | ||||
|       case TEXCOORDFMT_3D: | ||||
|          sz += 3; | ||||
|          break; | ||||
|       case TEXCOORDFMT_4D: | ||||
|          sz += 4; | ||||
|          break; | ||||
|       case TEXCOORDFMT_1D: | ||||
|          sz += 1; | ||||
|          break; | ||||
|       case TEXCOORDFMT_2D_16: | ||||
|          sz += 1; | ||||
|          break; | ||||
|       case TEXCOORDFMT_4D_16: | ||||
|          sz += 2; | ||||
|          break; | ||||
|       case TEXCOORDFMT_NOT_PRESENT: | ||||
|          break; | ||||
|       default: | ||||
|          fprintf(stderr, "bad texcoord fmt %d\n", i); | ||||
|          return GL_FALSE; | ||||
| @@ -132,17 +158,17 @@ static GLboolean i915_check_vertex_size( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
| static void | ||||
| i915_emit_invarient_state(struct intel_context *intel) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH( 200 ); | ||||
|    BEGIN_BATCH(200, 0); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_AA_CMD | | ||||
|              AA_LINE_ECAAR_WIDTH_ENABLE | | ||||
|              AA_LINE_ECAAR_WIDTH_1_0 | | ||||
| 	     AA_LINE_REGION_WIDTH_ENABLE | | ||||
| 	     AA_LINE_REGION_WIDTH_1_0); | ||||
|              AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); | ||||
|    OUT_BATCH(0); | ||||
| @@ -159,10 +185,7 @@ static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
|              CSB_TCB(1, 1) | | ||||
|              CSB_TCB(2, 2) | | ||||
|              CSB_TCB(3, 3) | | ||||
| 	     CSB_TCB(4, 4) | | ||||
| 	     CSB_TCB(5, 5) | | ||||
| 	     CSB_TCB(6, 6) | | ||||
| 	     CSB_TCB(7, 7)); | ||||
|              CSB_TCB(4, 4) | CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7)); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_RASTER_RULES_CMD | | ||||
|              ENABLE_POINT_RASTER_RULE | | ||||
| @@ -170,20 +193,15 @@ static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
|              ENABLE_LINE_STRIP_PROVOKE_VRTX | | ||||
|              ENABLE_TRI_FAN_PROVOKE_VRTX | | ||||
|              LINE_STRIP_PROVOKE_VRTX(1) | | ||||
| 	     TRI_FAN_PROVOKE_VRTX(2) |  | ||||
| 	     ENABLE_TEXKILL_3D_4D | | ||||
| 	     TEXKILL_4D); | ||||
|              TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D); | ||||
|  | ||||
|    /* Need to initialize this to zero. | ||||
|     */ | ||||
|    OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |  | ||||
| 	     I1_LOAD_S(3) | | ||||
| 	     (1)); | ||||
|    OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (1)); | ||||
|    OUT_BATCH(0); | ||||
|  | ||||
|    /* XXX: Use this */ | ||||
|    OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |  | ||||
| 	     DISABLE_SCISSOR_RECT); | ||||
|    OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); | ||||
|    OUT_BATCH(0); | ||||
| @@ -196,24 +214,17 @@ static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
|  | ||||
|  | ||||
|    /* Don't support twosided stencil yet */ | ||||
|    OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | | ||||
| 	     BFO_ENABLE_STENCIL_TWO_SIDE | | ||||
| 	     0 ); | ||||
|    OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0); | ||||
|  | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| #define emit(intel, state, size )		     \ | ||||
| do {							\ | ||||
|    int k;						\ | ||||
|    BEGIN_BATCH( (size) / sizeof(GLuint));		\ | ||||
|    for (k = 0 ; k < (size) / sizeof(GLuint) ; k++)	\ | ||||
|       OUT_BATCH((state)[k]);				\ | ||||
|    ADVANCE_BATCH();					\ | ||||
| } while (0); | ||||
|    intel_batchbuffer_data(intel->batch, state, size, 0 ) | ||||
|  | ||||
| static GLuint get_dirty( struct i915_hw_state *state ) | ||||
| static GLuint | ||||
| get_dirty(struct i915_hw_state *state) | ||||
| { | ||||
|    GLuint dirty; | ||||
|  | ||||
| @@ -224,12 +235,12 @@ static GLuint get_dirty( struct i915_hw_state *state ) | ||||
|    if (dirty & I915_UPLOAD_TEX_ALL) | ||||
|       state->emitted &= ~I915_UPLOAD_TEX_ALL; | ||||
|    dirty = state->active & ~state->emitted; | ||||
|  | ||||
|    return dirty; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLuint get_state_size( struct i915_hw_state *state ) | ||||
| static GLuint | ||||
| get_state_size(struct i915_hw_state *state) | ||||
| { | ||||
|    GLuint dirty = get_dirty(state); | ||||
|    GLuint i; | ||||
| @@ -268,42 +279,83 @@ static GLuint get_state_size( struct i915_hw_state *state ) | ||||
|  | ||||
| /* Push the state into the sarea and/or texture memory. | ||||
|  */ | ||||
| static void i915_emit_state( intelContextPtr intel ) | ||||
| static void | ||||
| i915_emit_state(struct intel_context *intel) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    struct i915_hw_state *state = i915->current; | ||||
|    int i; | ||||
|    GLuint dirty = get_dirty(state); | ||||
|    GLuint counter = intel->batch.counter; | ||||
|    GLuint dirty; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    if (intel->batch.space < get_state_size(state)) { | ||||
|       intelFlushBatch(intel, GL_TRUE); | ||||
|       dirty = get_dirty(state); | ||||
|       counter = intel->batch.counter; | ||||
|    } | ||||
|    /* We don't hold the lock at this point, so want to make sure that | ||||
|     * there won't be a buffer wrap.   | ||||
|     * | ||||
|     * It might be better to talk about explicit places where | ||||
|     * scheduling is allowed, rather than assume that it is whenever a | ||||
|     * batchbuffer fills up. | ||||
|     */ | ||||
|    intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0); | ||||
|  | ||||
|    if (VERBOSE)  | ||||
|    /* Do this here as we may have flushed the batchbuffer above, | ||||
|     * causing more state to be dirty! | ||||
|     */ | ||||
|    dirty = get_dirty(state); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_STATE) | ||||
|       fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_INVARIENT) { | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          fprintf(stderr, "I915_UPLOAD_INVARIENT:\n"); | ||||
|       i915_emit_invarient_state(intel); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_CTX) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");  | ||||
|       emit( i915, state->Ctx, sizeof(state->Ctx) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          fprintf(stderr, "I915_UPLOAD_CTX:\n"); | ||||
|       emit(intel, state->Ctx, sizeof(state->Ctx)); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_BUFFERS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");  | ||||
|       emit( i915, state->Buffer, sizeof(state->Buffer) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); | ||||
|       BEGIN_BATCH(I915_DEST_SETUP_SIZE + 2, 0); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); | ||||
|       OUT_RELOC(state->draw_region->buffer, | ||||
|                 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                 DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, | ||||
|                 state->draw_region->draw_offset); | ||||
|  | ||||
|       if (state->depth_region) { | ||||
|          OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); | ||||
|          OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); | ||||
|          OUT_RELOC(state->depth_region->buffer, | ||||
|                    DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                    DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, | ||||
|                    state->depth_region->draw_offset); | ||||
|       } | ||||
|  | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_STIPPLE) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");  | ||||
|       emit( i915, state->Stipple, sizeof(state->Stipple) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          fprintf(stderr, "I915_UPLOAD_STIPPLE:\n"); | ||||
|       emit(intel, state->Stipple, sizeof(state->Stipple)); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_FOG) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n");  | ||||
|       emit( i915, state->Fog, sizeof(state->Fog) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          fprintf(stderr, "I915_UPLOAD_FOG:\n"); | ||||
|       emit(intel, state->Fog, sizeof(state->Fog)); | ||||
|    } | ||||
|  | ||||
|    /* Combine all the dirty texture state into a single command to | ||||
| @@ -316,18 +368,30 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
|          if (dirty & I915_UPLOAD_TEX(i)) | ||||
|             nr++; | ||||
|  | ||||
|       BEGIN_BATCH(2+nr*3); | ||||
|       BEGIN_BATCH(2 + nr * 3, 0); | ||||
|       OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); | ||||
|       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); | ||||
|       for (i = 0; i < I915_TEX_UNITS; i++) | ||||
|          if (dirty & I915_UPLOAD_TEX(i)) { | ||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]); | ||||
|  | ||||
|             if (state->tex_buffer[i]) { | ||||
|                OUT_RELOC(state->tex_buffer[i], | ||||
|                          DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, | ||||
|                          DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, | ||||
|                          state->tex_offset[i]); | ||||
|             } | ||||
|             else { | ||||
|                assert(i == 0); | ||||
|                assert(state == &i915->meta); | ||||
|                OUT_BATCH(0); | ||||
|             } | ||||
|  | ||||
|             OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); | ||||
|             OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); | ||||
|          } | ||||
|       ADVANCE_BATCH(); | ||||
|  | ||||
|       BEGIN_BATCH(2+nr*3); | ||||
|       BEGIN_BATCH(2 + nr * 3, 0); | ||||
|       OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); | ||||
|       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); | ||||
|       for (i = 0; i < I915_TEX_UNITS; i++) | ||||
| @@ -340,114 +404,146 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_CONSTANTS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");  | ||||
|       emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n"); | ||||
|       emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint)); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_PROGRAM) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");  | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          fprintf(stderr, "I915_UPLOAD_PROGRAM:\n"); | ||||
|  | ||||
|       assert((state->Program[0] & 0x1ff) + 2 == state->ProgramSize); | ||||
|  | ||||
|       emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) ); | ||||
|       if (VERBOSE) | ||||
|       emit(intel, state->Program, state->ProgramSize * sizeof(GLuint)); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
|          i915_disassemble_program(state->Program, state->ProgramSize); | ||||
|    } | ||||
|  | ||||
|    state->emitted |= dirty; | ||||
|    intel->batch.last_emit_state = counter; | ||||
|    assert(counter == intel->batch.counter); | ||||
| } | ||||
|  | ||||
| static void i915_destroy_context( intelContextPtr intel ) | ||||
| static void | ||||
| i915_destroy_context(struct intel_context *intel) | ||||
| { | ||||
|    _tnl_free_vertices(&intel->ctx); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Set the color buffer drawing region. | ||||
|  * Set the drawing regions for the color and depth/stencil buffers. | ||||
|  * This involves setting the pitch, cpp and buffer ID/location. | ||||
|  * Also set pixel format for color and Z rendering | ||||
|  * Used for setting both regular and meta state. | ||||
|  */ | ||||
| static void | ||||
| i915_set_color_region( intelContextPtr intel, const intelRegion *region) | ||||
| void | ||||
| i915_state_draw_region(struct intel_context *intel, | ||||
|                        struct i915_hw_state *state, | ||||
|                        struct intel_region *color_region, | ||||
|                        struct intel_region *depth_region) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); | ||||
|    i915->state.Buffer[I915_DESTREG_CBUFADDR1] = | ||||
|       (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); | ||||
|    i915->state.Buffer[I915_DESTREG_CBUFADDR2] = region->offset; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint value; | ||||
|  | ||||
|    ASSERT(state == &i915->state || state == &i915->meta); | ||||
|  | ||||
|    if (state->draw_region != color_region) { | ||||
|       intel_region_release(intel->intelScreen, &state->draw_region); | ||||
|       intel_region_reference(&state->draw_region, color_region); | ||||
|    } | ||||
|    if (state->depth_region != depth_region) { | ||||
|       intel_region_release(intel->intelScreen, &state->depth_region); | ||||
|       intel_region_reference(&state->depth_region, depth_region); | ||||
|    } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * specify the z-buffer/stencil region | ||||
|    /* | ||||
|     * Set stride/cpp values | ||||
|     */ | ||||
| static void | ||||
| i915_set_z_region( intelContextPtr intel, const intelRegion *region) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); | ||||
|    i915->state.Buffer[I915_DESTREG_DBUFADDR1] = | ||||
|       (BUF_3D_ID_DEPTH | BUF_3D_PITCH(region->pitch) | BUF_3D_USE_FENCE); | ||||
|    i915->state.Buffer[I915_DESTREG_DBUFADDR2] = region->offset; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Set both the color and Z/stencil drawing regions. | ||||
|  * Similar to two previous functions, but don't use I915_STATECHANGE() | ||||
|  */ | ||||
| static void | ||||
| i915_update_color_z_regions(intelContextPtr intel, | ||||
|                             const intelRegion *colorRegion, | ||||
|                             const intelRegion *depthRegion) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|  | ||||
|    i915->state.Buffer[I915_DESTREG_CBUFADDR1] = | ||||
|       (BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(colorRegion->pitch) | BUF_3D_USE_FENCE); | ||||
|    i915->state.Buffer[I915_DESTREG_CBUFADDR2] = colorRegion->offset; | ||||
|  | ||||
|    i915->state.Buffer[I915_DESTREG_DBUFADDR1] = | ||||
|       (BUF_3D_ID_DEPTH | | ||||
|        BUF_3D_PITCH(depthRegion->pitch) |  /* pitch in bytes */ | ||||
|    if (color_region) { | ||||
|       state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       state->Buffer[I915_DESTREG_CBUFADDR1] = | ||||
|          (BUF_3D_ID_COLOR_BACK | | ||||
|           BUF_3D_PITCH(color_region->pitch * color_region->cpp) | | ||||
|           BUF_3D_USE_FENCE); | ||||
|    i915->state.Buffer[I915_DESTREG_DBUFADDR2] = depthRegion->offset; | ||||
|    } | ||||
|  | ||||
|    if (depth_region) { | ||||
|       state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       state->Buffer[I915_DESTREG_DBUFADDR1] = | ||||
|          (BUF_3D_ID_DEPTH | | ||||
|           BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) | | ||||
|           BUF_3D_USE_FENCE); | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * Compute/set I915_DESTREG_DV1 value | ||||
|     */ | ||||
|    value = (DSTORG_HORT_BIAS(0x8) |     /* .5 */ | ||||
|             DSTORG_VERT_BIAS(0x8) |     /* .5 */ | ||||
|             LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL); | ||||
|    if (color_region && color_region->cpp == 4) { | ||||
|       value |= DV_PF_8888; | ||||
|    } | ||||
|    else { | ||||
|       value |= (DITHER_FULL_ALWAYS | DV_PF_565); | ||||
|    } | ||||
|    if (depth_region && depth_region->cpp == 4) { | ||||
|       value |= DEPTH_FRMT_24_FIXED_8_OTHER; | ||||
|    } | ||||
|    else { | ||||
|       value |= DEPTH_FRMT_16_FIXED; | ||||
|    } | ||||
|    state->Buffer[I915_DESTREG_DV1] = value; | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_lost_hardware( intelContextPtr intel ) | ||||
| static void | ||||
| i915_set_draw_region(struct intel_context *intel, | ||||
|                      struct intel_region *color_region, | ||||
|                      struct intel_region *depth_region) | ||||
| { | ||||
|    I915_CONTEXT(intel)->state.emitted = 0; | ||||
| } | ||||
|  | ||||
| static void i915_emit_flush( intelContextPtr intel ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH(2); | ||||
|    OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE );  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    i915_state_draw_region(intel, &i915->state, color_region, depth_region); | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915InitVtbl( i915ContextPtr i915 ) | ||||
|  | ||||
| static void | ||||
| i915_lost_hardware(struct intel_context *intel) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    i915->state.emitted = 0; | ||||
| } | ||||
|  | ||||
| static GLuint | ||||
| i915_flush_cmd(void) | ||||
| { | ||||
|    return MI_FLUSH | FLUSH_MAP_CACHE; | ||||
| } | ||||
|  | ||||
| static void  | ||||
| i915_assert_not_dirty( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    struct i915_hw_state *state = i915->current; | ||||
|    GLuint dirty = get_dirty(state); | ||||
|    assert(!dirty); | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| i915InitVtbl(struct i915_context *i915) | ||||
| { | ||||
|    i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj; | ||||
|    i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; | ||||
|    i915->intel.vtbl.clear_with_tris = i915ClearWithTris; | ||||
|    i915->intel.vtbl.rotate_window = i915RotateWindow; | ||||
|    i915->intel.vtbl.destroy = i915_destroy_context; | ||||
|    i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state; | ||||
|    i915->intel.vtbl.emit_state = i915_emit_state; | ||||
|    i915->intel.vtbl.lost_hardware = i915_lost_hardware; | ||||
|    i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state; | ||||
|    i915->intel.vtbl.render_start = i915_render_start; | ||||
|    i915->intel.vtbl.set_color_region = i915_set_color_region; | ||||
|    i915->intel.vtbl.set_z_region = i915_set_z_region; | ||||
|    i915->intel.vtbl.update_color_z_regions = i915_update_color_z_regions; | ||||
|    i915->intel.vtbl.set_draw_region = i915_set_draw_region; | ||||
|    i915->intel.vtbl.update_texture_state = i915UpdateTextureState; | ||||
|    i915->intel.vtbl.emit_flush = i915_emit_flush; | ||||
|    i915->intel.vtbl.flush_cmd = i915_flush_cmd; | ||||
|    i915->intel.vtbl.assert_not_dirty = i915_assert_not_dirty; | ||||
| } | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,126 +1,123 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BATCHBUFFER_H | ||||
| #define INTEL_BATCHBUFFER_H | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "mtypes.h" | ||||
| #include "dri_bufmgr.h" | ||||
|  | ||||
| struct intel_context; | ||||
|  | ||||
| #define BATCH_LOCALS	GLubyte *batch_ptr; | ||||
| #define BATCH_SZ 4096 | ||||
| #define BATCH_RESERVED 16 | ||||
|  | ||||
| /* #define VERBOSE 0 */ | ||||
| #ifndef VERBOSE | ||||
| extern int VERBOSE; | ||||
| #endif | ||||
| #define MAX_RELOCS 100 | ||||
|  | ||||
| #define INTEL_BATCH_NO_CLIPRECTS 0x1 | ||||
| #define INTEL_BATCH_CLIPRECTS    0x2 | ||||
|  | ||||
| #define BEGIN_BATCH(n)							\ | ||||
| do {									\ | ||||
|    if (VERBOSE) fprintf(stderr, 					\ | ||||
| 			"BEGIN_BATCH(%ld) in %s, %d dwords free\n",	\ | ||||
| 			((unsigned long)n), __FUNCTION__,		\ | ||||
| 			intel->batch.space/4);				\ | ||||
|    if (intel->batch.space < (n)*4)					\ | ||||
|       intelFlushBatch(intel, GL_TRUE);					\ | ||||
|    if (intel->batch.space == intel->batch.size)	intel->batch.func = __FUNCTION__;			\ | ||||
|    batch_ptr = intel->batch.ptr;					\ | ||||
| } while (0) | ||||
|  | ||||
| #define OUT_BATCH(n)					\ | ||||
| do {							\ | ||||
|    *(GLuint *)batch_ptr = (n);				\ | ||||
|    if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__);	\ | ||||
|    batch_ptr += 4;					\ | ||||
| } while (0) | ||||
|  | ||||
| #define ADVANCE_BATCH()						\ | ||||
| do {								\ | ||||
|    if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n");		\ | ||||
|    intel->batch.space -= (batch_ptr - intel->batch.ptr);	\ | ||||
|    intel->batch.ptr = batch_ptr;				\ | ||||
|    assert(intel->batch.space >= 0);				\ | ||||
| } while(0) | ||||
|  | ||||
| extern void intelInitBatchBuffer( GLcontext *ctx ); | ||||
| extern void intelDestroyBatchBuffer( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ); | ||||
| extern void intelWrapInlinePrimitive( intelContextPtr intel ); | ||||
| extern void intelRestartInlinePrimitive( intelContextPtr intel ); | ||||
| extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  | ||||
| 					      int primitive, int dwords, | ||||
| 					      int vertex_size); | ||||
| extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv, | ||||
| 			     const drm_clip_rect_t	*rect); | ||||
| extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 			     GLint cx1, GLint cy1, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelEmitCopyBlitLocked( intelContextPtr intel, | ||||
| 				     GLuint cpp, | ||||
| 				     GLshort src_pitch, | ||||
| 				     GLuint  src_offset, | ||||
| 				     GLshort dst_pitch, | ||||
| 				     GLuint  dst_offset, | ||||
| 				     GLshort srcx, GLshort srcy, | ||||
| 				     GLshort dstx, GLshort dsty, | ||||
| 				     GLshort w, GLshort h ); | ||||
|  | ||||
| extern void intelEmitFillBlitLocked( intelContextPtr intel, | ||||
| 				     GLuint cpp, | ||||
| 				     GLshort dst_pitch, | ||||
| 				     GLuint dst_offset, | ||||
| 				     GLshort x, GLshort y,  | ||||
| 				     GLshort w, GLshort h, | ||||
| 				     GLuint color ); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,  | ||||
| 						GLuint dwords ) | ||||
| struct buffer_reloc | ||||
| { | ||||
|    GLuint sz = dwords * sizeof(GLuint); | ||||
|    GLuint *ptr; | ||||
|    struct _DriBufferObject *buf; | ||||
|    GLuint offset; | ||||
|    GLuint delta;                /* not needed? */ | ||||
| }; | ||||
|  | ||||
|    if (intel->batch.space < sz) { | ||||
|       intelWrapInlinePrimitive( intel ); | ||||
| /*       assert(intel->batch.space >= sz); */ | ||||
| struct intel_batchbuffer | ||||
| { | ||||
|    struct bufmgr *bm; | ||||
|    struct intel_context *intel; | ||||
|  | ||||
|    struct _DriBufferObject *buffer; | ||||
|    struct _DriFenceObject *last_fence; | ||||
|    GLuint flags; | ||||
|  | ||||
|    drmBOList list; | ||||
|    GLuint list_count; | ||||
|    GLubyte *map; | ||||
|    GLubyte *ptr; | ||||
|  | ||||
|    struct buffer_reloc reloc[MAX_RELOCS]; | ||||
|    GLuint nr_relocs; | ||||
| }; | ||||
|  | ||||
| struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context | ||||
|                                                   *intel); | ||||
|  | ||||
| void intel_batchbuffer_free(struct intel_batchbuffer *batch); | ||||
|  | ||||
|  | ||||
| void intel_batchbuffer_finish(struct intel_batchbuffer *batch); | ||||
|  | ||||
| struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer | ||||
|                                                 *batch); | ||||
|  | ||||
| void intel_batchbuffer_reset(struct intel_batchbuffer *batch); | ||||
|  | ||||
|  | ||||
| /* Unlike bmBufferData, this currently requires the buffer be mapped. | ||||
|  * Consider it a convenience function wrapping multple | ||||
|  * intel_buffer_dword() calls. | ||||
|  */ | ||||
| void intel_batchbuffer_data(struct intel_batchbuffer *batch, | ||||
|                             const void *data, GLuint bytes, GLuint flags); | ||||
|  | ||||
| void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, | ||||
|                                      GLuint bytes); | ||||
|  | ||||
| GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, | ||||
|                                        struct _DriBufferObject *buffer, | ||||
|                                        GLuint flags, | ||||
|                                        GLuint mask, GLuint offset); | ||||
|  | ||||
| /* Inline functions - might actually be better off with these | ||||
|  * non-inlined.  Certainly better off switching all command packets to | ||||
|  * be passed as structs rather than dwords, but that's a little bit of | ||||
|  * work... | ||||
|  */ | ||||
| static INLINE GLuint | ||||
| intel_batchbuffer_space(struct intel_batchbuffer *batch) | ||||
| { | ||||
|    return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->map); | ||||
| } | ||||
|  | ||||
| /*    assert(intel->prim.primitive != ~0); */ | ||||
|    ptr = (GLuint *)intel->batch.ptr; | ||||
|    intel->batch.ptr += sz; | ||||
|    intel->batch.space -= sz; | ||||
|  | ||||
|    return ptr; | ||||
| static INLINE void | ||||
| intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword) | ||||
| { | ||||
|    assert(batch->map); | ||||
|    assert(intel_batchbuffer_space(batch) >= 4); | ||||
|    *(GLuint *) (batch->ptr) = dword; | ||||
|    batch->ptr += 4; | ||||
| } | ||||
|  | ||||
| static INLINE void | ||||
| intel_batchbuffer_require_space(struct intel_batchbuffer *batch, | ||||
|                                 GLuint sz, GLuint flags) | ||||
| { | ||||
|    assert(sz < BATCH_SZ - 8); | ||||
|    if (intel_batchbuffer_space(batch) < sz || | ||||
|        (batch->flags != 0 && flags != 0 && batch->flags != flags)) | ||||
|       intel_batchbuffer_flush(batch); | ||||
|  | ||||
|    batch->flags |= flags; | ||||
| } | ||||
|  | ||||
| /* Here are the crusty old macros, to be removed: | ||||
|  */ | ||||
| #define BATCH_LOCALS | ||||
|  | ||||
| #define BEGIN_BATCH(n, flags) do {				\ | ||||
|    assert(!intel->prim.flush);					\ | ||||
|    intel_batchbuffer_require_space(intel->batch, (n)*4, flags);	\ | ||||
| } while (0) | ||||
|  | ||||
| #define OUT_BATCH(d)  intel_batchbuffer_emit_dword(intel->batch, d) | ||||
|  | ||||
| #define OUT_RELOC(buf,flags,mask,delta) do { 				\ | ||||
|    assert((delta) >= 0);							\ | ||||
|    intel_batchbuffer_emit_reloc(intel->batch, buf, flags, mask, delta);	\ | ||||
| } while (0) | ||||
|  | ||||
| #define ADVANCE_BATCH() do { } while(0) | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										416
									
								
								src/mesa/drivers/dri/i915/intel_batchpool.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										416
									
								
								src/mesa/drivers/dri/i915/intel_batchpool.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,416 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||||
|  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  | ||||
|  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  | ||||
|  * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
| /* | ||||
|  * Authors: Thomas Hellstr<74>m <thomas-at-tungstengraphics-dot-com> | ||||
|  */ | ||||
|  | ||||
| #include <xf86drm.h> | ||||
| #include <stdlib.h> | ||||
| #include <errno.h> | ||||
| #include "imports.h" | ||||
| #include "glthread.h" | ||||
| #include "dri_bufpool.h" | ||||
| #include "dri_bufmgr.h" | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|    drmMMListHead head; | ||||
|    struct _BPool *parent; | ||||
|    struct _DriFenceObject *fence; | ||||
|    unsigned long start; | ||||
|    int unfenced; | ||||
|    int mapped; | ||||
| } BBuf; | ||||
|  | ||||
| typedef struct _BPool | ||||
| { | ||||
|    _glthread_Mutex mutex; | ||||
|    unsigned long bufSize; | ||||
|    unsigned poolSize; | ||||
|    unsigned numFree; | ||||
|    unsigned numTot; | ||||
|    unsigned numDelayed; | ||||
|    unsigned checkDelayed; | ||||
|    drmMMListHead free; | ||||
|    drmMMListHead delayed; | ||||
|    drmMMListHead head; | ||||
|    drmBO kernelBO; | ||||
|    void *virtual; | ||||
|    BBuf *bufs; | ||||
| } BPool; | ||||
|  | ||||
|  | ||||
| static BPool * | ||||
| createBPool(int fd, unsigned long bufSize, unsigned numBufs, unsigned flags, | ||||
|             unsigned checkDelayed) | ||||
| { | ||||
|    BPool *p = (BPool *) malloc(sizeof(*p)); | ||||
|    BBuf *buf; | ||||
|    int i; | ||||
|  | ||||
|    if (!p) | ||||
|       return NULL; | ||||
|  | ||||
|    p->bufs = (BBuf *) malloc(numBufs * sizeof(*p->bufs)); | ||||
|    if (!p->bufs) { | ||||
|       free(p); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    DRMINITLISTHEAD(&p->free); | ||||
|    DRMINITLISTHEAD(&p->head); | ||||
|    DRMINITLISTHEAD(&p->delayed); | ||||
|  | ||||
|    p->numTot = numBufs; | ||||
|    p->numFree = numBufs; | ||||
|    p->bufSize = bufSize; | ||||
|    p->numDelayed = 0; | ||||
|    p->checkDelayed = checkDelayed; | ||||
|  | ||||
|    _glthread_INIT_MUTEX(p->mutex); | ||||
|  | ||||
|    if (drmBOCreate(fd, NULL, 0, numBufs * bufSize, NULL, drm_bo_type_dc, | ||||
|                    flags, 0, &p->kernelBO)) { | ||||
|       free(p->bufs); | ||||
|       free(p); | ||||
|       return NULL; | ||||
|    } | ||||
|    if (drmBOMap(fd, &p->kernelBO, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, | ||||
|                 &p->virtual)) { | ||||
|       drmBODestroy(fd, &p->kernelBO); | ||||
|       free(p->bufs); | ||||
|       free(p); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * We unmap the buffer so that we can validate it later. Note that this is | ||||
|     * just a synchronizing operation. The buffer will have a virtual mapping | ||||
|     * until it is destroyed. | ||||
|     */ | ||||
|  | ||||
|    drmBOUnmap(fd, &p->kernelBO); | ||||
|  | ||||
|    buf = p->bufs; | ||||
|    for (i = 0; i < numBufs; ++i) { | ||||
|       buf->parent = p; | ||||
|       buf->fence = NULL; | ||||
|       buf->start = i * bufSize; | ||||
|       buf->mapped = 0; | ||||
|       buf->unfenced = 0; | ||||
|       DRMLISTADDTAIL(&buf->head, &p->free); | ||||
|       buf++; | ||||
|    } | ||||
|  | ||||
|    return p; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| pool_checkFree(BPool * p, int wait) | ||||
| { | ||||
|    drmMMListHead *list, *prev; | ||||
|    BBuf *buf; | ||||
|    int signaled = 0; | ||||
|    int i; | ||||
|  | ||||
|    list = p->delayed.next; | ||||
|  | ||||
|    if (p->numDelayed > 3) { | ||||
|       for (i = 0; i < p->numDelayed; i += 3) { | ||||
|          list = list->next; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    prev = list->prev; | ||||
|    for (; list != &p->delayed; list = prev, prev = list->prev) { | ||||
|  | ||||
|       buf = DRMLISTENTRY(BBuf, list, head); | ||||
|  | ||||
|       if (!signaled) { | ||||
|          if (wait) { | ||||
|             driFenceFinish(buf->fence, DRM_FENCE_TYPE_EXE, 1); | ||||
|             signaled = 1; | ||||
|          } | ||||
|          else { | ||||
|             signaled = driFenceSignaled(buf->fence, DRM_FENCE_TYPE_EXE); | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       if (!signaled) | ||||
|          break; | ||||
|  | ||||
|       driFenceUnReference(buf->fence); | ||||
|       buf->fence = NULL; | ||||
|       DRMLISTDEL(list); | ||||
|       p->numDelayed--; | ||||
|       DRMLISTADD(list, &p->free); | ||||
|       p->numFree++; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void * | ||||
| pool_create(struct _DriBufferPool *pool, | ||||
|             unsigned long size, unsigned flags, unsigned hint, | ||||
|             unsigned alignment) | ||||
| { | ||||
|    BPool *p = (BPool *) pool->data; | ||||
|  | ||||
|    drmMMListHead *item; | ||||
|  | ||||
|    if (alignment && (alignment != 4096)) | ||||
|       return NULL; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(p->mutex); | ||||
|  | ||||
|    if (p->numFree == 0) | ||||
|       pool_checkFree(p, GL_TRUE); | ||||
|  | ||||
|    if (p->numFree == 0) { | ||||
|       fprintf(stderr, "Out of fixed size buffer objects\n"); | ||||
|       BM_CKFATAL(-ENOMEM); | ||||
|    } | ||||
|  | ||||
|    item = p->free.next; | ||||
|  | ||||
|    if (item == &p->free) { | ||||
|       fprintf(stderr, "Fixed size buffer pool corruption\n"); | ||||
|    } | ||||
|  | ||||
|    DRMLISTDEL(item); | ||||
|    --p->numFree; | ||||
|  | ||||
|    _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|    return (void *) DRMLISTENTRY(BBuf, item, head); | ||||
| } | ||||
|  | ||||
|  | ||||
| static int | ||||
| pool_destroy(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|    BPool *p = buf->parent; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(p->mutex); | ||||
|  | ||||
|    if (buf->fence) { | ||||
|       DRMLISTADDTAIL(&buf->head, &p->delayed); | ||||
|       p->numDelayed++; | ||||
|    } | ||||
|    else { | ||||
|       buf->unfenced = 0; | ||||
|       DRMLISTADD(&buf->head, &p->free); | ||||
|       p->numFree++; | ||||
|    } | ||||
|  | ||||
|    if ((p->numDelayed % p->checkDelayed) == 0) | ||||
|       pool_checkFree(p, 0); | ||||
|  | ||||
|    _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int | ||||
| pool_map(struct _DriBufferPool *pool, void *private, unsigned flags, | ||||
|          int hint, void **virtual) | ||||
| { | ||||
|  | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|    BPool *p = buf->parent; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(p->mutex); | ||||
|  | ||||
|    /* | ||||
|     * Currently Mesa doesn't have any condition variables to resolve this | ||||
|     * cleanly in a multithreading environment. | ||||
|     * We bail out instead. | ||||
|     */ | ||||
|  | ||||
|    if (buf->mapped) { | ||||
|       fprintf(stderr, "Trying to map already mapped buffer object\n"); | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|    } | ||||
|  | ||||
| #if 0 | ||||
|    if (buf->unfenced && !(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) { | ||||
|       fprintf(stderr, "Trying to map an unfenced buffer object 0x%08x" | ||||
|               " 0x%08x %d\n", hint, flags, buf->start); | ||||
|       BM_CKFATAL(-EINVAL); | ||||
|    } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|    if (buf->fence) { | ||||
|       _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|       return -EBUSY; | ||||
|    } | ||||
|  | ||||
|    buf->mapped = GL_TRUE; | ||||
|    *virtual = (unsigned char *) p->virtual + buf->start; | ||||
|    _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy) | ||||
| { | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|    driFenceFinish(buf->fence, 0, lazy); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_unmap(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|  | ||||
|    buf->mapped = 0; | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| static unsigned long | ||||
| pool_offset(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|    BPool *p = buf->parent; | ||||
|  | ||||
|    return p->kernelBO.offset + buf->start; | ||||
| } | ||||
|  | ||||
| static unsigned | ||||
| pool_flags(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    BPool *p = (BPool *) pool->data; | ||||
|  | ||||
|    return p->kernelBO.flags; | ||||
| } | ||||
|  | ||||
| static unsigned long | ||||
| pool_size(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    BPool *p = (BPool *) pool->data; | ||||
|  | ||||
|    return p->bufSize; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int | ||||
| pool_fence(struct _DriBufferPool *pool, void *private, | ||||
|            struct _DriFenceObject *fence) | ||||
| { | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|    BPool *p = buf->parent; | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(p->mutex); | ||||
|    if (buf->fence) { | ||||
|       driFenceUnReference(buf->fence); | ||||
|    } | ||||
|    buf->fence = fence; | ||||
|    buf->unfenced = 0; | ||||
|    driFenceReference(buf->fence); | ||||
|    _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|  | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| static drmBO * | ||||
| pool_kernel(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|    BPool *p = buf->parent; | ||||
|  | ||||
|    return &p->kernelBO; | ||||
| } | ||||
|  | ||||
| static int | ||||
| pool_validate(struct _DriBufferPool *pool, void *private) | ||||
| { | ||||
|    BBuf *buf = (BBuf *) private; | ||||
|    BPool *p = buf->parent; | ||||
|    _glthread_LOCK_MUTEX(p->mutex); | ||||
|    buf->unfenced = GL_TRUE; | ||||
|    _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| pool_takedown(struct _DriBufferPool *pool) | ||||
| { | ||||
|    BPool *p = (BPool *) pool->data; | ||||
|  | ||||
|    /* | ||||
|     * Wait on outstanding fences.  | ||||
|     */ | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(p->mutex); | ||||
|    while ((p->numFree < p->numTot) && p->numDelayed) { | ||||
|       _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|       sched_yield(); | ||||
|       pool_checkFree(p, GL_TRUE); | ||||
|       _glthread_LOCK_MUTEX(p->mutex); | ||||
|    } | ||||
|  | ||||
|    drmBODestroy(pool->fd, &p->kernelBO); | ||||
|    free(p->bufs); | ||||
|    _glthread_UNLOCK_MUTEX(p->mutex); | ||||
|    free(p); | ||||
|    free(pool); | ||||
| } | ||||
|  | ||||
|  | ||||
| struct _DriBufferPool * | ||||
| driBatchPoolInit(int fd, unsigned flags, | ||||
|                  unsigned long bufSize, | ||||
|                  unsigned numBufs, unsigned checkDelayed) | ||||
| { | ||||
|    struct _DriBufferPool *pool; | ||||
|  | ||||
|    pool = (struct _DriBufferPool *) malloc(sizeof(*pool)); | ||||
|    if (!pool) | ||||
|       return NULL; | ||||
|  | ||||
|    pool->data = createBPool(fd, bufSize, numBufs, flags, checkDelayed); | ||||
|  | ||||
|    pool->fd = fd; | ||||
|    pool->map = &pool_map; | ||||
|    pool->unmap = &pool_unmap; | ||||
|    pool->destroy = &pool_destroy; | ||||
|    pool->offset = &pool_offset; | ||||
|    pool->flags = &pool_flags; | ||||
|    pool->size = &pool_size; | ||||
|    pool->create = &pool_create; | ||||
|    pool->fence = &pool_fence; | ||||
|    pool->kernel = &pool_kernel; | ||||
|    pool->validate = &pool_validate; | ||||
|    pool->waitIdle = &pool_waitIdle; | ||||
|    pool->setstatic = NULL; | ||||
|    pool->takeDown = &pool_takedown; | ||||
|    return pool; | ||||
| } | ||||
							
								
								
									
										516
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										516
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,516 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "context.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_reg.h" | ||||
| #include "intel_regions.h" | ||||
| #include "vblank.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_BLIT | ||||
|  | ||||
| /** | ||||
|  * Copy the back color buffer to the front color buffer.  | ||||
|  * Used for SwapBuffers(). | ||||
|  */ | ||||
| void | ||||
| intelCopyBuffer(const __DRIdrawablePrivate * dPriv, | ||||
|                 const drm_clip_rect_t * rect) | ||||
| { | ||||
|  | ||||
|    struct intel_context *intel; | ||||
|    GLboolean missed_target; | ||||
|    int64_t ust; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|  | ||||
|    intel = intelScreenContext(dPriv->driScreenPriv->private); | ||||
|    if (!intel) | ||||
|       return; | ||||
|  | ||||
|    if (intel->last_swap_fence) { | ||||
|       driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); | ||||
|       driFenceUnReference(intel->last_swap_fence); | ||||
|       intel->last_swap_fence = NULL; | ||||
|    } | ||||
|    intel->last_swap_fence = intel->first_swap_fence; | ||||
|    intel->first_swap_fence = NULL; | ||||
|  | ||||
|    if (!rect) { | ||||
|       driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags, | ||||
|                        &missed_target); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets | ||||
|     * should work regardless. | ||||
|     */ | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable && intel->driDrawable->numClipRects) { | ||||
|       const intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|       struct gl_framebuffer *fb | ||||
|          = (struct gl_framebuffer *) dPriv->driverPrivate; | ||||
|       const struct intel_region *frontRegion | ||||
|          = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); | ||||
|       const struct intel_region *backRegion | ||||
|          = intel_get_rb_region(fb, BUFFER_BACK_LEFT); | ||||
|       const int nbox = dPriv->numClipRects; | ||||
|       const drm_clip_rect_t *pbox = dPriv->pClipRects; | ||||
|       const int pitch = frontRegion->pitch; | ||||
|       const int cpp = frontRegion->cpp; | ||||
|       int BR13, CMD; | ||||
|       int i; | ||||
|  | ||||
|       ASSERT(fb); | ||||
|       ASSERT(fb->Name == 0);    /* Not a user-created FBO */ | ||||
|       ASSERT(frontRegion); | ||||
|       ASSERT(backRegion); | ||||
|       ASSERT(frontRegion->pitch == backRegion->pitch); | ||||
|       ASSERT(frontRegion->cpp == backRegion->cpp); | ||||
|  | ||||
|       if (cpp == 2) { | ||||
|          BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); | ||||
|          CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       } | ||||
|       else { | ||||
|          BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); | ||||
|          CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
|                 XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       } | ||||
|  | ||||
|       for (i = 0; i < nbox; i++, pbox++) { | ||||
|          drm_clip_rect_t box; | ||||
|  | ||||
|          if (pbox->x1 > pbox->x2 || | ||||
|              pbox->y1 > pbox->y2 || | ||||
|              pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height) | ||||
|             continue; | ||||
|  | ||||
|          box = *pbox; | ||||
|  | ||||
|          if (rect) { | ||||
|             if (rect->x1 > box.x1) | ||||
|                box.x1 = rect->x1; | ||||
|             if (rect->y1 > box.y1) | ||||
|                box.y1 = rect->y1; | ||||
|             if (rect->x2 < box.x2) | ||||
|                box.x2 = rect->x2; | ||||
|             if (rect->y2 < box.y2) | ||||
|                box.y2 = rect->y2; | ||||
|  | ||||
|             if (box.x1 > box.x2 || box.y1 > box.y2) | ||||
|                continue; | ||||
|          } | ||||
|  | ||||
|          BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); | ||||
|          OUT_BATCH(CMD); | ||||
|          OUT_BATCH(BR13); | ||||
|          OUT_BATCH((pbox->y1 << 16) | pbox->x1); | ||||
|          OUT_BATCH((pbox->y2 << 16) | pbox->x2); | ||||
|  | ||||
|          if (intel->sarea->pf_current_page == 0) | ||||
|             OUT_RELOC(frontRegion->buffer, | ||||
|                       DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                       DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); | ||||
|          else | ||||
|             OUT_RELOC(backRegion->buffer, | ||||
|                       DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                       DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); | ||||
|          OUT_BATCH((pbox->y1 << 16) | pbox->x1); | ||||
|          OUT_BATCH(BR13 & 0xffff); | ||||
|  | ||||
|          if (intel->sarea->pf_current_page == 0) | ||||
|             OUT_RELOC(backRegion->buffer, | ||||
|                       DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, | ||||
|                       DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); | ||||
|          else | ||||
|             OUT_RELOC(frontRegion->buffer, | ||||
|                       DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, | ||||
|                       DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); | ||||
|  | ||||
|          ADVANCE_BATCH(); | ||||
|       } | ||||
|  | ||||
|       if (intel->first_swap_fence) | ||||
|          driFenceUnReference(intel->first_swap_fence); | ||||
|       intel->first_swap_fence = intel_batchbuffer_flush(intel->batch); | ||||
|       driFenceReference(intel->first_swap_fence); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (!rect) { | ||||
|       intel->swap_count++; | ||||
|       (*dri_interface->getUST) (&ust); | ||||
|       if (missed_target) { | ||||
|          intel->swap_missed_count++; | ||||
|          intel->swap_missed_ust = ust - intel->swap_ust; | ||||
|       } | ||||
|  | ||||
|       intel->swap_ust = ust; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intelEmitFillBlit(struct intel_context *intel, | ||||
|                   GLuint cpp, | ||||
|                   GLshort dst_pitch, | ||||
|                   struct _DriBufferObject *dst_buffer, | ||||
|                   GLuint dst_offset, | ||||
|                   GLshort x, GLshort y, GLshort w, GLshort h, GLuint color) | ||||
| { | ||||
|    GLuint BR13, CMD; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch (cpp) { | ||||
|    case 1: | ||||
|    case 2: | ||||
|    case 3: | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1 << 24); | ||||
|       CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1 << 24) | (1 << 25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | | ||||
|              XY_COLOR_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", | ||||
|        __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h); | ||||
|  | ||||
|  | ||||
|    BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); | ||||
|    OUT_BATCH(CMD); | ||||
|    OUT_BATCH(BR13); | ||||
|    OUT_BATCH((y << 16) | x); | ||||
|    OUT_BATCH(((y + h) << 16) | (x + w)); | ||||
|    OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|              DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset); | ||||
|    OUT_BATCH(color); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Copy BitBlt | ||||
|  */ | ||||
| void | ||||
| intelEmitCopyBlit(struct intel_context *intel, | ||||
|                   GLuint cpp, | ||||
|                   GLshort src_pitch, | ||||
|                   struct _DriBufferObject *src_buffer, | ||||
|                   GLuint src_offset, | ||||
|                   GLshort dst_pitch, | ||||
|                   struct _DriBufferObject *dst_buffer, | ||||
|                   GLuint dst_offset, | ||||
|                   GLshort src_x, GLshort src_y, | ||||
|                   GLshort dst_x, GLshort dst_y, GLshort w, GLshort h) | ||||
| { | ||||
|    GLuint CMD, BR13; | ||||
|    int dst_y2 = dst_y + h; | ||||
|    int dst_x2 = dst_x + w; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|  | ||||
|    DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", | ||||
|        __FUNCTION__, | ||||
|        src_buffer, src_pitch, src_offset, src_x, src_y, | ||||
|        dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); | ||||
|  | ||||
|    src_pitch *= cpp; | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch (cpp) { | ||||
|    case 1: | ||||
|    case 2: | ||||
|    case 3: | ||||
|       BR13 = (((GLint) dst_pitch) & 0xffff) | (0xCC << 16) | (1 << 24); | ||||
|       CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = | ||||
|          (((GLint) dst_pitch) & 0xffff) | (0xCC << 16) | (1 << 24) | (1 << | ||||
|                                                                       25); | ||||
|       CMD = | ||||
|          (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
|           XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (dst_y2 < dst_y || dst_x2 < dst_x) { | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* Initial y values don't seem to work with negative pitches.  If | ||||
|     * we adjust the offsets manually (below), it seems to work fine. | ||||
|     * | ||||
|     * On the other hand, if we always adjust, the hardware doesn't | ||||
|     * know which blit directions to use, so overlapping copypixels get | ||||
|     * the wrong result. | ||||
|     */ | ||||
|    if (dst_pitch > 0 && src_pitch > 0) { | ||||
|       BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); | ||||
|       OUT_BATCH(CMD); | ||||
|       OUT_BATCH(BR13); | ||||
|       OUT_BATCH((dst_y << 16) | dst_x); | ||||
|       OUT_BATCH((dst_y2 << 16) | dst_x2); | ||||
|       OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                 DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset); | ||||
|       OUT_BATCH((src_y << 16) | src_x); | ||||
|       OUT_BATCH(((GLint) src_pitch & 0xffff)); | ||||
|       OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, | ||||
|                 DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, src_offset); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|    else { | ||||
|       BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); | ||||
|       OUT_BATCH(CMD); | ||||
|       OUT_BATCH(BR13); | ||||
|       OUT_BATCH((0 << 16) | dst_x); | ||||
|       OUT_BATCH((h << 16) | dst_x2); | ||||
|       OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                 DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, | ||||
|                 dst_offset + dst_y * dst_pitch); | ||||
|       OUT_BATCH((0 << 16) | src_x); | ||||
|       OUT_BATCH(((GLint) src_pitch & 0xffff)); | ||||
|       OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, | ||||
|                 DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, | ||||
|                 src_offset + src_y * src_pitch); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Use blitting to clear the renderbuffers named by 'flags'. | ||||
|  * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferMask field | ||||
|  * since that might include software renderbuffers or renderbuffers | ||||
|  * which we're clearing with triangles. | ||||
|  * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear | ||||
|  */ | ||||
| void | ||||
| intelClearWithBlit(GLcontext * ctx, GLbitfield mask, GLboolean all, | ||||
|                    GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint clear_depth; | ||||
|    GLbitfield skipBuffers = 0; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    DBG("%s %x\n", __FUNCTION__, mask); | ||||
|  | ||||
|    /* | ||||
|     * Compute values for clearing the buffers. | ||||
|     */ | ||||
|    clear_depth = 0; | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear); | ||||
|    } | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; | ||||
|    } | ||||
|  | ||||
|    /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in | ||||
|     * the loop below. | ||||
|     */ | ||||
|    if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) { | ||||
|       skipBuffers = BUFFER_BIT_STENCIL; | ||||
|    } | ||||
|  | ||||
|    /* XXX Move this flush/lock into the following conditional? */ | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->numClipRects) { | ||||
|       drm_clip_rect_t clear; | ||||
|       int i; | ||||
|  | ||||
|       /* Refresh the cx/y/w/h values as they may have been invalidated | ||||
|        * by a new window position or size picked up when we did | ||||
|        * LOCK_HARDWARE above.  The values passed by mesa are not | ||||
|        * reliable. | ||||
|        */ | ||||
|       { | ||||
|          cx = ctx->DrawBuffer->_Xmin; | ||||
|          cy = ctx->DrawBuffer->_Ymin; | ||||
|          ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; | ||||
|          cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; | ||||
|       } | ||||
|  | ||||
|       if (intel->ctx.DrawBuffer->Name == 0) { | ||||
|          /* clearing a window */ | ||||
|  | ||||
|          /* flip top to bottom */ | ||||
|          clear.x1 = cx + intel->drawX; | ||||
|          clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch; | ||||
|          clear.x2 = clear.x1 + cw; | ||||
|          clear.y2 = clear.y1 + ch; | ||||
|  | ||||
|          /* adjust for page flipping */ | ||||
|          if (intel->sarea->pf_current_page == 1) { | ||||
|             const GLuint tmp = mask; | ||||
|             mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); | ||||
|             if (tmp & BUFFER_BIT_FRONT_LEFT) | ||||
|                mask |= BUFFER_BIT_BACK_LEFT; | ||||
|             if (tmp & BUFFER_BIT_BACK_LEFT) | ||||
|                mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|          } | ||||
|       } | ||||
|       else { | ||||
|          /* clearing FBO */ | ||||
|          ASSERT(intel->numClipRects == 1); | ||||
|          ASSERT(intel->pClipRects == &intel->fboRect); | ||||
|          clear.x1 = cx; | ||||
|          clear.y1 = intel->ctx.DrawBuffer->Height - cy - ch; | ||||
|          clear.x2 = clear.y1 + cw; | ||||
|          clear.y2 = clear.y1 + ch; | ||||
|          /* no change to mask */ | ||||
|       } | ||||
|  | ||||
|       for (i = 0; i < intel->numClipRects; i++) { | ||||
|          const drm_clip_rect_t *box = &intel->pClipRects[i]; | ||||
|          drm_clip_rect_t b; | ||||
|          GLuint buf; | ||||
|          GLuint clearMask = mask;       /* use copy, since we modify it below */ | ||||
|  | ||||
|          if (!all) { | ||||
|             intel_intersect_cliprects(&b, &clear, box); | ||||
|          } | ||||
|          else { | ||||
|             b = *box; | ||||
|          } | ||||
|  | ||||
|          if (0) | ||||
|             _mesa_printf("clear %d,%d..%d,%d, mask %x\n", | ||||
|                          b.x1, b.y1, b.x2, b.y2, mask); | ||||
|  | ||||
|          /* Loop over all renderbuffers */ | ||||
|          for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) { | ||||
|             const GLbitfield bufBit = 1 << buf; | ||||
|             if ((clearMask & bufBit) && !(bufBit & skipBuffers)) { | ||||
|                /* OK, clear this renderbuffer */ | ||||
|                const struct intel_renderbuffer *irb | ||||
|                   = intel_renderbuffer(ctx->DrawBuffer-> | ||||
|                                        Attachment[buf].Renderbuffer); | ||||
|                struct _DriBufferObject *write_buffer = | ||||
|                   intel_region_buffer(intel->intelScreen, irb->region, | ||||
|                                       all ? INTEL_WRITE_FULL : | ||||
|                                       INTEL_WRITE_PART); | ||||
|  | ||||
|                GLuint clearVal; | ||||
|                GLint pitch, cpp; | ||||
|                GLuint BR13, CMD; | ||||
|  | ||||
|                ASSERT(irb); | ||||
|                ASSERT(irb->region); | ||||
|  | ||||
|                pitch = irb->region->pitch; | ||||
|                cpp = irb->region->cpp; | ||||
|  | ||||
|                DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", | ||||
|                    __FUNCTION__, | ||||
|                    irb->region->buffer, (pitch * cpp), | ||||
|                    irb->region->draw_offset, | ||||
|                    b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1); | ||||
|  | ||||
|  | ||||
|                /* Setup the blit command */ | ||||
|                if (cpp == 4) { | ||||
|                   BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25); | ||||
|                   if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) { | ||||
|                      CMD = XY_COLOR_BLT_CMD; | ||||
|                      if (clearMask & BUFFER_BIT_DEPTH) | ||||
|                         CMD |= XY_COLOR_BLT_WRITE_RGB; | ||||
|                      if (clearMask & BUFFER_BIT_STENCIL) | ||||
|                         CMD |= XY_COLOR_BLT_WRITE_ALPHA; | ||||
|                   } | ||||
|                   else { | ||||
|                      /* clearing RGBA */ | ||||
|                      CMD = (XY_COLOR_BLT_CMD | | ||||
|                             XY_COLOR_BLT_WRITE_ALPHA | | ||||
|                             XY_COLOR_BLT_WRITE_RGB); | ||||
|                   } | ||||
|                } | ||||
|                else { | ||||
|                   ASSERT(cpp == 2 || cpp == 0); | ||||
|                   BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24); | ||||
|                   CMD = XY_COLOR_BLT_CMD; | ||||
|                } | ||||
|  | ||||
|                if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) { | ||||
|                   clearVal = clear_depth; | ||||
|                } | ||||
|                else { | ||||
|                   clearVal = (cpp == 4) | ||||
|                      ? intel->ClearColor8888 : intel->ClearColor565; | ||||
|                } | ||||
|                /* | ||||
|                   _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n", | ||||
|                   buf, irb->Base.Name); | ||||
|                 */ | ||||
|                BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); | ||||
|                OUT_BATCH(CMD); | ||||
|                OUT_BATCH(BR13); | ||||
|                OUT_BATCH((b.y1 << 16) | b.x1); | ||||
|                OUT_BATCH((b.y2 << 16) | b.x2); | ||||
|                OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, | ||||
|                          DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, | ||||
|                          irb->region->draw_offset); | ||||
|                OUT_BATCH(clearVal); | ||||
|                ADVANCE_BATCH(); | ||||
|                clearMask &= ~bufBit;    /* turn off bit, for faster loop exit */ | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
							
								
								
									
										63
									
								
								src/mesa/drivers/dri/i915/intel_blit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/mesa/drivers/dri/i915/intel_blit.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BLIT_H | ||||
| #define INTEL_BLIT_H | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "dri_bufmgr.h" | ||||
|  | ||||
| extern void intelCopyBuffer(const __DRIdrawablePrivate * dpriv, | ||||
|                             const drm_clip_rect_t * rect); | ||||
|  | ||||
| extern void intelClearWithBlit(GLcontext * ctx, GLbitfield mask, | ||||
|                                GLboolean all, GLint cx1, GLint cy1, GLint cw, | ||||
|                                GLint ch); | ||||
|  | ||||
| extern void intelEmitCopyBlit(struct intel_context *intel, | ||||
|                               GLuint cpp, | ||||
|                               GLshort src_pitch, | ||||
|                               struct _DriBufferObject *src_buffer, | ||||
|                               GLuint src_offset, | ||||
|                               GLshort dst_pitch, | ||||
|                               struct _DriBufferObject *dst_buffer, | ||||
|                               GLuint dst_offset, | ||||
|                               GLshort srcx, GLshort srcy, | ||||
|                               GLshort dstx, GLshort dsty, | ||||
|                               GLshort w, GLshort h); | ||||
|  | ||||
| extern void intelEmitFillBlit(struct intel_context *intel, | ||||
|                               GLuint cpp, | ||||
|                               GLshort dst_pitch, | ||||
|                               struct _DriBufferObject *dst_buffer, | ||||
|                               GLuint dst_offset, | ||||
|                               GLshort x, GLshort y, | ||||
|                               GLshort w, GLshort h, GLuint color); | ||||
|  | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										250
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,250 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include "imports.h" | ||||
| #include "mtypes.h" | ||||
| #include "bufferobj.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "intel_regions.h" | ||||
| #include "dri_bufmgr.h" | ||||
|  | ||||
| /** | ||||
|  * There is some duplication between mesa's bufferobjects and our | ||||
|  * bufmgr buffers.  Both have an integer handle and a hashtable to | ||||
|  * lookup an opaque structure.  It would be nice if the handles and | ||||
|  * internal structure where somehow shared. | ||||
|  */ | ||||
| static struct gl_buffer_object * | ||||
| intel_bufferobj_alloc(GLcontext * ctx, GLuint name, GLenum target) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object); | ||||
|  | ||||
|    _mesa_initialize_buffer_object(&obj->Base, name, target); | ||||
|  | ||||
|    driGenBuffers(intel->intelScreen->regionPool, | ||||
|                  "bufferobj", 1, &obj->buffer, 64, 0, 0); | ||||
|  | ||||
|    return &obj->Base; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Break the COW tie to the region.  The region gets to keep the data. | ||||
|  */ | ||||
| void | ||||
| intel_bufferobj_release_region(struct intel_context *intel, | ||||
|                                struct intel_buffer_object *intel_obj) | ||||
| { | ||||
|    assert(intel_obj->region->buffer == intel_obj->buffer); | ||||
|    intel_obj->region->pbo = NULL; | ||||
|    intel_obj->region = NULL; | ||||
|    driBOUnReference(intel_obj->buffer); | ||||
|    intel_obj->buffer = NULL; | ||||
|  | ||||
|    /* This leads to a large number of buffer deletion/creation events. | ||||
|     * Currently the drm doesn't like that: | ||||
|     */ | ||||
|    driGenBuffers(intel->intelScreen->regionPool, | ||||
|                  "buffer object", 1, &intel_obj->buffer, 64, 0, 0); | ||||
|    driBOData(intel_obj->buffer, intel_obj->Base.Size, NULL, 0); | ||||
| } | ||||
|  | ||||
| /* Break the COW tie to the region.  Both the pbo and the region end | ||||
|  * up with a copy of the data. | ||||
|  */ | ||||
| void | ||||
| intel_bufferobj_cow(struct intel_context *intel, | ||||
|                     struct intel_buffer_object *intel_obj) | ||||
| { | ||||
|    assert(intel_obj->region); | ||||
|    intel_region_cow(intel->intelScreen, intel_obj->region); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Deallocate/free a vertex/pixel buffer object. | ||||
|  * Called via glDeleteBuffersARB(). | ||||
|  */ | ||||
| static void | ||||
| intel_bufferobj_free(GLcontext * ctx, struct gl_buffer_object *obj) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|  | ||||
|    if (intel_obj->region) { | ||||
|       intel_bufferobj_release_region(intel, intel_obj); | ||||
|    } | ||||
|    else if (intel_obj->buffer) { | ||||
|       driDeleteBuffers(1, &intel_obj->buffer); | ||||
|    } | ||||
|  | ||||
|    _mesa_free(intel_obj); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Allocate space for and store data in a buffer object.  Any data that was | ||||
|  * previously stored in the buffer object is lost.  If data is NULL, | ||||
|  * memory will be allocated, but no copy will occur. | ||||
|  * Called via glBufferDataARB(). | ||||
|  */ | ||||
| static void | ||||
| intel_bufferobj_data(GLcontext * ctx, | ||||
|                      GLenum target, | ||||
|                      GLsizeiptrARB size, | ||||
|                      const GLvoid * data, | ||||
|                      GLenum usage, struct gl_buffer_object *obj) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    intel_obj->Base.Size = size; | ||||
|    intel_obj->Base.Usage = usage; | ||||
|  | ||||
|    if (intel_obj->region) | ||||
|       intel_bufferobj_release_region(intel, intel_obj); | ||||
|  | ||||
|    driBOData(intel_obj->buffer, size, data, 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Replace data in a subrange of buffer object.  If the data range | ||||
|  * specified by size + offset extends beyond the end of the buffer or | ||||
|  * if data is NULL, no copy is performed. | ||||
|  * Called via glBufferSubDataARB(). | ||||
|  */ | ||||
| static void | ||||
| intel_bufferobj_subdata(GLcontext * ctx, | ||||
|                         GLenum target, | ||||
|                         GLintptrARB offset, | ||||
|                         GLsizeiptrARB size, | ||||
|                         const GLvoid * data, struct gl_buffer_object *obj) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|  | ||||
|    if (intel_obj->region) | ||||
|       intel_bufferobj_cow(intel, intel_obj); | ||||
|  | ||||
|    driBOSubData(intel_obj->buffer, offset, size, data); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glGetBufferSubDataARB(). | ||||
|  */ | ||||
| static void | ||||
| intel_bufferobj_get_subdata(GLcontext * ctx, | ||||
|                             GLenum target, | ||||
|                             GLintptrARB offset, | ||||
|                             GLsizeiptrARB size, | ||||
|                             GLvoid * data, struct gl_buffer_object *obj) | ||||
| { | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|    driBOGetSubData(intel_obj->buffer, offset, size, data); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glMapBufferARB(). | ||||
|  */ | ||||
| static void * | ||||
| intel_bufferobj_map(GLcontext * ctx, | ||||
|                     GLenum target, | ||||
|                     GLenum access, struct gl_buffer_object *obj) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    /* XXX: Translate access to flags arg below: | ||||
|     */ | ||||
|    assert(intel_obj); | ||||
|  | ||||
|    if (intel_obj->region) | ||||
|       intel_bufferobj_cow(intel, intel_obj); | ||||
|  | ||||
|    obj->Pointer = driBOMap(intel_obj->buffer, | ||||
|                            DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0); | ||||
|    return obj->Pointer; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glMapBufferARB(). | ||||
|  */ | ||||
| static GLboolean | ||||
| intel_bufferobj_unmap(GLcontext * ctx, | ||||
|                       GLenum target, struct gl_buffer_object *obj) | ||||
| { | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|    assert(obj->Pointer); | ||||
|    driBOUnmap(intel_obj->buffer); | ||||
|    obj->Pointer = NULL; | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| struct _DriBufferObject * | ||||
| intel_bufferobj_buffer(struct intel_context *intel, | ||||
|                        struct intel_buffer_object *intel_obj, GLuint flag) | ||||
| { | ||||
|    if (intel_obj->region) { | ||||
|       if (flag == INTEL_WRITE_PART) | ||||
|          intel_bufferobj_cow(intel, intel_obj); | ||||
|       else if (flag == INTEL_WRITE_FULL) | ||||
|          intel_bufferobj_release_region(intel, intel_obj); | ||||
|    } | ||||
|  | ||||
|    return intel_obj->buffer; | ||||
| } | ||||
|  | ||||
| void | ||||
| intel_bufferobj_init(struct intel_context *intel) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|    ctx->Driver.NewBufferObject = intel_bufferobj_alloc; | ||||
|    ctx->Driver.DeleteBuffer = intel_bufferobj_free; | ||||
|    ctx->Driver.BufferData = intel_bufferobj_data; | ||||
|    ctx->Driver.BufferSubData = intel_bufferobj_subdata; | ||||
|    ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata; | ||||
|    ctx->Driver.MapBuffer = intel_bufferobj_map; | ||||
|    ctx->Driver.UnmapBuffer = intel_bufferobj_unmap; | ||||
| } | ||||
							
								
								
									
										86
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
|  /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BUFFEROBJ_H | ||||
| #define INTEL_BUFFEROBJ_H | ||||
|  | ||||
| #include "mtypes.h" | ||||
|  | ||||
| struct intel_context; | ||||
| struct intel_region; | ||||
| struct gl_buffer_object; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object. | ||||
|  */ | ||||
| struct intel_buffer_object | ||||
| { | ||||
|    struct gl_buffer_object Base; | ||||
|    struct _DriBufferObject *buffer;     /* the low-level buffer manager's buffer handle */ | ||||
|  | ||||
|    struct intel_region *region; /* Is there a zero-copy texture | ||||
|                                    associated with this (pixel) | ||||
|                                    buffer object? */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* Get the bm buffer associated with a GL bufferobject: | ||||
|  */ | ||||
| struct _DriBufferObject *intel_bufferobj_buffer(struct intel_context *intel, | ||||
|                                                 struct intel_buffer_object | ||||
|                                                 *obj, GLuint flag); | ||||
|  | ||||
| /* Hook the bufferobject implementation into mesa:  | ||||
|  */ | ||||
| void intel_bufferobj_init(struct intel_context *intel); | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Are the obj->Name tests necessary?  Unfortunately yes, mesa | ||||
|  * allocates a couple of gl_buffer_object structs statically, and | ||||
|  * the Name == 0 test is the only way to identify them and avoid | ||||
|  * casting them erroneously to our structs. | ||||
|  */ | ||||
| static INLINE struct intel_buffer_object * | ||||
| intel_buffer_object(struct gl_buffer_object *obj) | ||||
| { | ||||
|    if (obj->Name) | ||||
|       return (struct intel_buffer_object *) obj; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
| /* Helpers for zerocopy image uploads.  See also intel_regions.h: | ||||
|  */ | ||||
| void intel_bufferobj_cow(struct intel_context *intel, | ||||
|                          struct intel_buffer_object *intel_obj); | ||||
| void intel_bufferobj_release_region(struct intel_context *intel, | ||||
|                                     struct intel_buffer_object *intel_obj); | ||||
|  | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										968
									
								
								src/mesa/drivers/dri/i915/intel_buffers.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										968
									
								
								src/mesa/drivers/dri/i915/intel_buffers.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,968 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_depthstencil.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "context.h" | ||||
| #include "framebuffer.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * XXX move this into a new dri/common/cliprects.c file. | ||||
|  */ | ||||
| GLboolean | ||||
| intel_intersect_cliprects(drm_clip_rect_t * dst, | ||||
|                           const drm_clip_rect_t * a, | ||||
|                           const drm_clip_rect_t * b) | ||||
| { | ||||
|    GLint bx = b->x1; | ||||
|    GLint by = b->y1; | ||||
|    GLint bw = b->x2 - bx; | ||||
|    GLint bh = b->y2 - by; | ||||
|  | ||||
|    if (bx < a->x1) | ||||
|       bw -= a->x1 - bx, bx = a->x1; | ||||
|    if (by < a->y1) | ||||
|       bh -= a->y1 - by, by = a->y1; | ||||
|    if (bx + bw > a->x2) | ||||
|       bw = a->x2 - bx; | ||||
|    if (by + bh > a->y2) | ||||
|       bh = a->y2 - by; | ||||
|    if (bw <= 0) | ||||
|       return GL_FALSE; | ||||
|    if (bh <= 0) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    dst->x1 = bx; | ||||
|    dst->y1 = by; | ||||
|    dst->x2 = bx + bw; | ||||
|    dst->y2 = by + bh; | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Return pointer to current color drawing region, or NULL. | ||||
|  */ | ||||
| struct intel_region * | ||||
| intel_drawbuf_region(struct intel_context *intel) | ||||
| { | ||||
|    struct intel_renderbuffer *irbColor = | ||||
|       intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]); | ||||
|    if (irbColor) | ||||
|       return irbColor->region; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Return pointer to current color reading region, or NULL. | ||||
|  */ | ||||
| struct intel_region * | ||||
| intel_readbuf_region(struct intel_context *intel) | ||||
| { | ||||
|    struct intel_renderbuffer *irb | ||||
|       = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); | ||||
|    if (irb) | ||||
|       return irb->region; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelBufferSize(GLframebuffer * buffer, GLuint * width, GLuint * height) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    /* Need to lock to make sure the driDrawable is uptodate.  This | ||||
|     * information is used to resize Mesa's software buffers, so it has | ||||
|     * to be correct. | ||||
|     */ | ||||
|    /* XXX This isn't 100% correct, the given buffer might not be | ||||
|     * bound to the current context! | ||||
|     */ | ||||
|    LOCK_HARDWARE(intel); | ||||
|    if (intel->driDrawable) { | ||||
|       *width = intel->driDrawable->w; | ||||
|       *height = intel->driDrawable->h; | ||||
|    } | ||||
|    else { | ||||
|       *width = 0; | ||||
|       *height = 0; | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Update the following fields for rendering to a user-created FBO: | ||||
|  *   intel->numClipRects | ||||
|  *   intel->pClipRects | ||||
|  *   intel->drawX | ||||
|  *   intel->drawY | ||||
|  */ | ||||
| static void | ||||
| intelSetRenderbufferClipRects(struct intel_context *intel) | ||||
| { | ||||
|    assert(intel->ctx.DrawBuffer->Width > 0); | ||||
|    assert(intel->ctx.DrawBuffer->Height > 0); | ||||
|    intel->fboRect.x1 = 0; | ||||
|    intel->fboRect.y1 = 0; | ||||
|    intel->fboRect.x2 = intel->ctx.DrawBuffer->Width; | ||||
|    intel->fboRect.y2 = intel->ctx.DrawBuffer->Height; | ||||
|    intel->numClipRects = 1; | ||||
|    intel->pClipRects = &intel->fboRect; | ||||
|    intel->drawX = 0; | ||||
|    intel->drawY = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * As above, but for rendering to front buffer of a window. | ||||
|  * \sa intelSetRenderbufferClipRects | ||||
|  */ | ||||
| static void | ||||
| intelSetFrontClipRects(struct intel_context *intel) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) | ||||
|       return; | ||||
|  | ||||
|    intel->numClipRects = dPriv->numClipRects; | ||||
|    intel->pClipRects = dPriv->pClipRects; | ||||
|    intel->drawX = dPriv->x; | ||||
|    intel->drawY = dPriv->y; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * As above, but for rendering to back buffer of a window. | ||||
|  */ | ||||
| static void | ||||
| intelSetBackClipRects(struct intel_context *intel) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) | ||||
|       return; | ||||
|  | ||||
|    if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { | ||||
|       /* use the front clip rects */ | ||||
|       intel->numClipRects = dPriv->numClipRects; | ||||
|       intel->pClipRects = dPriv->pClipRects; | ||||
|       intel->drawX = dPriv->x; | ||||
|       intel->drawY = dPriv->y; | ||||
|    } | ||||
|    else { | ||||
|       /* use the back clip rects */ | ||||
|       intel->numClipRects = dPriv->numBackClipRects; | ||||
|       intel->pClipRects = dPriv->pBackClipRects; | ||||
|       intel->drawX = dPriv->backX; | ||||
|       intel->drawY = dPriv->backY; | ||||
|  | ||||
|       if (dPriv->numBackClipRects == 1 && | ||||
|           dPriv->x == dPriv->backX && dPriv->y == dPriv->backY) { | ||||
|  | ||||
|          /* Repeat the calculation of the back cliprect dimensions here | ||||
|           * as early versions of dri.a in the Xserver are incorrect.  Try | ||||
|           * very hard not to restrict future versions of dri.a which | ||||
|           * might eg. allocate truly private back buffers. | ||||
|           */ | ||||
|          int x1, y1; | ||||
|          int x2, y2; | ||||
|  | ||||
|          x1 = dPriv->x; | ||||
|          y1 = dPriv->y; | ||||
|          x2 = dPriv->x + dPriv->w; | ||||
|          y2 = dPriv->y + dPriv->h; | ||||
|  | ||||
|          if (x1 < 0) | ||||
|             x1 = 0; | ||||
|          if (y1 < 0) | ||||
|             y1 = 0; | ||||
|          if (x2 > intel->intelScreen->width) | ||||
|             x2 = intel->intelScreen->width; | ||||
|          if (y2 > intel->intelScreen->height) | ||||
|             y2 = intel->intelScreen->height; | ||||
|  | ||||
|          if (x1 == dPriv->pBackClipRects[0].x1 && | ||||
|              y1 == dPriv->pBackClipRects[0].y1) { | ||||
|  | ||||
|             dPriv->pBackClipRects[0].x2 = x2; | ||||
|             dPriv->pBackClipRects[0].y2 = y2; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * This will be called whenever the currently bound window is moved/resized. | ||||
|  * XXX: actually, it seems to NOT be called when the window is only moved (BP). | ||||
|  */ | ||||
| void | ||||
| intelWindowMoved(struct intel_context *intel) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|    if (!intel->ctx.DrawBuffer) { | ||||
|       /* when would this happen? -BP */ | ||||
|       intelSetFrontClipRects(intel); | ||||
|    } | ||||
|    else if (intel->ctx.DrawBuffer->Name != 0) { | ||||
|       /* drawing to user-created FBO - do nothing */ | ||||
|       /* Cliprects would be set from intelDrawBuffer() */ | ||||
|    } | ||||
|    else { | ||||
|       /* drawing to a window */ | ||||
|       switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) { | ||||
|       case BUFFER_BIT_FRONT_LEFT: | ||||
|          intelSetFrontClipRects(intel); | ||||
|          break; | ||||
|       case BUFFER_BIT_BACK_LEFT: | ||||
|          intelSetBackClipRects(intel); | ||||
|          break; | ||||
|       default: | ||||
|          /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ | ||||
|          intelSetFrontClipRects(intel); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* this update Mesa's notion of window size */ | ||||
|    if (ctx->WinSysDrawBuffer) { | ||||
|       _mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer, | ||||
|                                intel->driDrawable->w, intel->driDrawable->h); | ||||
|    } | ||||
|  | ||||
|    /* Update hardware scissor */ | ||||
|    ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
|                        ctx->Scissor.Width, ctx->Scissor.Height); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* A true meta version of this would be very simple and additionally | ||||
|  * machine independent.  Maybe we'll get there one day. | ||||
|  */ | ||||
| static void | ||||
| intelClearWithTris(struct intel_context *intel, | ||||
|                    GLbitfield mask, | ||||
|                    GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    drm_clip_rect_t clear; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_BLIT) | ||||
|       _mesa_printf("%s 0x%x\n", __FUNCTION__, mask); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* XXX FBO: was: intel->driDrawable->numClipRects */ | ||||
|    if (intel->numClipRects) { | ||||
|       GLuint buf; | ||||
|  | ||||
|       intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|  | ||||
|       /* Refresh the cx/y/w/h values as they may have been invalidated | ||||
|        * by a new window position or size picked up when we did | ||||
|        * LOCK_HARDWARE above.  The values passed by mesa are not | ||||
|        * reliable. | ||||
|        */ | ||||
|       { | ||||
|          cx = ctx->DrawBuffer->_Xmin; | ||||
|          cy = ctx->DrawBuffer->_Ymin; | ||||
|          ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; | ||||
|          cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; | ||||
|       } | ||||
|  | ||||
|       /* note: regardless of 'all', cx, cy, cw, ch are now correct */ | ||||
|       clear.x1 = cx; | ||||
|       clear.y1 = cy; | ||||
|       clear.x2 = cx + cw; | ||||
|       clear.y2 = cy + ch; | ||||
|  | ||||
|       /* Back and stencil cliprects are the same.  Try and do both | ||||
|        * buffers at once: | ||||
|        */ | ||||
|       if (mask & | ||||
|           (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) { | ||||
|          struct intel_region *backRegion = | ||||
|             intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT); | ||||
|          struct intel_region *depthRegion = | ||||
|             intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH); | ||||
|          const GLuint clearColor = (backRegion && backRegion->cpp == 4) | ||||
|             ? intel->ClearColor8888 : intel->ClearColor565; | ||||
|  | ||||
|          intel->vtbl.meta_draw_region(intel, backRegion, depthRegion); | ||||
|  | ||||
|          if (mask & BUFFER_BIT_BACK_LEFT) | ||||
|             intel->vtbl.meta_color_mask(intel, GL_TRUE); | ||||
|          else | ||||
|             intel->vtbl.meta_color_mask(intel, GL_FALSE); | ||||
|  | ||||
|          if (mask & BUFFER_BIT_STENCIL) | ||||
|             intel->vtbl.meta_stencil_replace(intel, | ||||
|                                              intel->ctx.Stencil.WriteMask[0], | ||||
|                                              intel->ctx.Stencil.Clear); | ||||
|          else | ||||
|             intel->vtbl.meta_no_stencil_write(intel); | ||||
|  | ||||
|          if (mask & BUFFER_BIT_DEPTH) | ||||
|             intel->vtbl.meta_depth_replace(intel); | ||||
|          else | ||||
|             intel->vtbl.meta_no_depth_write(intel); | ||||
|  | ||||
|          /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the | ||||
|           * drawing origin may not be correctly emitted. | ||||
|           */ | ||||
|          intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, intel->ctx.Depth.Clear, clearColor, 0, 0, 0, 0);   /* texcoords */ | ||||
|  | ||||
|          mask &= | ||||
|             ~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH); | ||||
|       } | ||||
|  | ||||
|       /* clear the remaining (color) renderbuffers */ | ||||
|       for (buf = 0; buf < BUFFER_COUNT && mask; buf++) { | ||||
|          const GLuint bufBit = 1 << buf; | ||||
|          if (mask & bufBit) { | ||||
|             struct intel_renderbuffer *irbColor = | ||||
|                intel_renderbuffer(ctx->DrawBuffer-> | ||||
|                                   Attachment[buf].Renderbuffer); | ||||
|             GLuint color = (irbColor->region->cpp == 4) | ||||
|                ? intel->ClearColor8888 : intel->ClearColor565; | ||||
|  | ||||
|             ASSERT(irbColor); | ||||
|  | ||||
|             intel->vtbl.meta_no_depth_write(intel); | ||||
|             intel->vtbl.meta_no_stencil_write(intel); | ||||
|             intel->vtbl.meta_color_mask(intel, GL_TRUE); | ||||
|             intel->vtbl.meta_draw_region(intel, irbColor->region, NULL); | ||||
|  | ||||
|             /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the | ||||
|              * drawing origin may not be correctly emitted. | ||||
|              */ | ||||
|             intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, 0,      /* depth clear val */ | ||||
|                                  color, 0, 0, 0, 0);    /* texcoords */ | ||||
|  | ||||
|             mask &= ~bufBit; | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Copy the window contents named by dPriv to the rotated (or reflected) | ||||
|  * color buffer. | ||||
|  * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source. | ||||
|  */ | ||||
| void | ||||
| intelRotateWindow(struct intel_context *intel, | ||||
|                   __DRIdrawablePrivate * dPriv, GLuint srcBuf) | ||||
| { | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    drm_clip_rect_t fullRect; | ||||
|    struct intel_region *src; | ||||
|    const drm_clip_rect_t *clipRects; | ||||
|    int numClipRects; | ||||
|    int i; | ||||
|    GLenum format, type; | ||||
|  | ||||
|    int xOrig, yOrig; | ||||
|    int origNumClipRects; | ||||
|    drm_clip_rect_t *origRects; | ||||
|  | ||||
|    /* | ||||
|     * set up hardware state | ||||
|     */ | ||||
|    intelFlush(&intel->ctx); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (!intel->numClipRects) { | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|    intel->vtbl.meta_no_depth_write(intel); | ||||
|    intel->vtbl.meta_no_stencil_write(intel); | ||||
|    intel->vtbl.meta_color_mask(intel, GL_FALSE); | ||||
|  | ||||
|  | ||||
|    /* save current drawing origin and cliprects (restored at end) */ | ||||
|    xOrig = intel->drawX; | ||||
|    yOrig = intel->drawY; | ||||
|    origNumClipRects = intel->numClipRects; | ||||
|    origRects = intel->pClipRects; | ||||
|  | ||||
|    /* | ||||
|     * set drawing origin, cliprects for full-screen access to rotated screen | ||||
|     */ | ||||
|    fullRect.x1 = 0; | ||||
|    fullRect.y1 = 0; | ||||
|    fullRect.x2 = screen->rotatedWidth; | ||||
|    fullRect.y2 = screen->rotatedHeight; | ||||
|    intel->drawX = 0; | ||||
|    intel->drawY = 0; | ||||
|    intel->numClipRects = 1; | ||||
|    intel->pClipRects = &fullRect; | ||||
|  | ||||
|    intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL);    /* ? */ | ||||
|  | ||||
|    if (srcBuf == BUFFER_BIT_FRONT_LEFT) { | ||||
|       src = intel->intelScreen->front_region; | ||||
|       clipRects = dPriv->pClipRects; | ||||
|       numClipRects = dPriv->numClipRects; | ||||
|    } | ||||
|    else { | ||||
|       src = intel->intelScreen->back_region; | ||||
|       clipRects = dPriv->pBackClipRects; | ||||
|       numClipRects = dPriv->numBackClipRects; | ||||
|    } | ||||
|  | ||||
|    if (src->cpp == 4) { | ||||
|       format = GL_BGRA; | ||||
|       type = GL_UNSIGNED_BYTE; | ||||
|    } | ||||
|    else { | ||||
|       format = GL_BGR; | ||||
|       type = GL_UNSIGNED_SHORT_5_6_5_REV; | ||||
|    } | ||||
|  | ||||
|    /* set the whole screen up as a texture to avoid alignment issues */ | ||||
|    intel->vtbl.meta_tex_rect_source(intel, | ||||
|                                     src->buffer, | ||||
|                                     screen->width, | ||||
|                                     screen->height, src->pitch, format, type); | ||||
|  | ||||
|    intel->vtbl.meta_texture_blend_replace(intel); | ||||
|  | ||||
|    /* | ||||
|     * loop over the source window's cliprects | ||||
|     */ | ||||
|    for (i = 0; i < numClipRects; i++) { | ||||
|       int srcX0 = clipRects[i].x1; | ||||
|       int srcY0 = clipRects[i].y1; | ||||
|       int srcX1 = clipRects[i].x2; | ||||
|       int srcY1 = clipRects[i].y2; | ||||
|       GLfloat verts[4][2], tex[4][2]; | ||||
|       int j; | ||||
|  | ||||
|       /* build vertices for four corners of clip rect */ | ||||
|       verts[0][0] = srcX0; | ||||
|       verts[0][1] = srcY0; | ||||
|       verts[1][0] = srcX1; | ||||
|       verts[1][1] = srcY0; | ||||
|       verts[2][0] = srcX1; | ||||
|       verts[2][1] = srcY1; | ||||
|       verts[3][0] = srcX0; | ||||
|       verts[3][1] = srcY1; | ||||
|  | ||||
|       /* .. and texcoords */ | ||||
|       tex[0][0] = srcX0; | ||||
|       tex[0][1] = srcY0; | ||||
|       tex[1][0] = srcX1; | ||||
|       tex[1][1] = srcY0; | ||||
|       tex[2][0] = srcX1; | ||||
|       tex[2][1] = srcY1; | ||||
|       tex[3][0] = srcX0; | ||||
|       tex[3][1] = srcY1; | ||||
|  | ||||
|       /* transform coords to rotated screen coords */ | ||||
|  | ||||
|       for (j = 0; j < 4; j++) { | ||||
|          matrix23TransformCoordf(&screen->rotMatrix, | ||||
|                                  &verts[j][0], &verts[j][1]); | ||||
|       } | ||||
|  | ||||
|       /* draw polygon to map source image to dest region */ | ||||
|       intel_meta_draw_poly(intel, 4, verts, 0, 0, tex); | ||||
|  | ||||
|    }                            /* cliprect loop */ | ||||
|  | ||||
|    intel->vtbl.leave_meta_state(intel); | ||||
|    intel_batchbuffer_flush(intel->batch); | ||||
|  | ||||
|    /* restore original drawing origin and cliprects */ | ||||
|    intel->drawX = xOrig; | ||||
|    intel->drawY = yOrig; | ||||
|    intel->numClipRects = origNumClipRects; | ||||
|    intel->pClipRects = origRects; | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called by ctx->Driver.Clear. | ||||
|  */ | ||||
| static void | ||||
| intelClear(GLcontext * ctx, | ||||
|            GLbitfield mask, | ||||
|            GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask); | ||||
|    GLbitfield tri_mask = 0; | ||||
|    GLbitfield blit_mask = 0; | ||||
|    GLbitfield swrast_mask = 0; | ||||
|    GLuint i; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* HW color buffers (front, back, aux, generic FBO, etc) */ | ||||
|    if (colorMask == ~0) { | ||||
|       /* clear all R,G,B,A */ | ||||
|       /* XXX FBO: need to check if colorbuffers are software RBOs! */ | ||||
|       blit_mask |= (mask & BUFFER_BITS_COLOR); | ||||
|    } | ||||
|    else { | ||||
|       /* glColorMask in effect */ | ||||
|       tri_mask |= (mask & BUFFER_BITS_COLOR); | ||||
|    } | ||||
|  | ||||
|    /* HW stencil */ | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       const struct intel_region *stencilRegion | ||||
|          = intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL); | ||||
|       if (stencilRegion) { | ||||
|          /* have hw stencil */ | ||||
|          if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { | ||||
|             /* not clearing all stencil bits, so use triangle clearing */ | ||||
|             tri_mask |= BUFFER_BIT_STENCIL; | ||||
|          } | ||||
|          else { | ||||
|             /* clearing all stencil bits, use blitting */ | ||||
|             blit_mask |= BUFFER_BIT_STENCIL; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* HW depth */ | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       /* clear depth with whatever method is used for stencil (see above) */ | ||||
|       if (tri_mask & BUFFER_BIT_STENCIL) | ||||
|          tri_mask |= BUFFER_BIT_DEPTH; | ||||
|       else | ||||
|          blit_mask |= BUFFER_BIT_DEPTH; | ||||
|    } | ||||
|  | ||||
|    /* SW fallback clearing */ | ||||
|    swrast_mask = mask & ~tri_mask & ~blit_mask; | ||||
|  | ||||
|    for (i = 0; i < BUFFER_COUNT; i++) { | ||||
|       GLuint bufBit = 1 << i; | ||||
|       if ((blit_mask | tri_mask) & bufBit) { | ||||
|          if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) { | ||||
|             blit_mask &= ~bufBit; | ||||
|             tri_mask &= ~bufBit; | ||||
|             swrast_mask |= bufBit; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    intelFlush(ctx);             /* XXX intelClearWithBlit also does this */ | ||||
|  | ||||
|    if (blit_mask) | ||||
|       intelClearWithBlit(ctx, blit_mask, all, cx, cy, cw, ch); | ||||
|  | ||||
|    if (tri_mask) | ||||
|       intelClearWithTris(intel, tri_mask, all, cx, cy, cw, ch); | ||||
|  | ||||
|    if (swrast_mask) | ||||
|       _swrast_Clear(ctx, swrast_mask, all, cx, cy, cw, ch); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Flip the front & back buffers | ||||
|  */ | ||||
| static void | ||||
| intelPageFlip(const __DRIdrawablePrivate * dPriv) | ||||
| { | ||||
| #if 0 | ||||
|    struct intel_context *intel; | ||||
|    int tmp, ret; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|  | ||||
|    intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (dPriv->pClipRects) { | ||||
|       *(drm_clip_rect_t *) intel->sarea->boxes = dPriv->pClipRects[0]; | ||||
|       intel->sarea->nbox = 1; | ||||
|    } | ||||
|  | ||||
|    ret = drmCommandNone(intel->driFd, DRM_I830_FLIP); | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    tmp = intel->sarea->last_enqueue; | ||||
|    intelRefillBatchLocked(intel); | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|  | ||||
|    intelSetDrawBuffer(&intel->ctx, intel->ctx.Color.DriverDrawBuffer); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| void | ||||
| intelSwapBuffers(__DRIdrawablePrivate * dPriv) | ||||
| { | ||||
|    if (dPriv->driverPrivate) { | ||||
|       const struct gl_framebuffer *fb | ||||
|          = (struct gl_framebuffer *) dPriv->driverPrivate; | ||||
|       if (fb->Visual.doubleBufferMode) { | ||||
|          GET_CURRENT_CONTEXT(ctx); | ||||
|          if (ctx && ctx->DrawBuffer == fb) { | ||||
|             _mesa_notifySwapBuffers(ctx);       /* flush pending rendering */ | ||||
|          } | ||||
|          if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */ | ||||
|             intelPageFlip(dPriv); | ||||
|          } | ||||
|          else { | ||||
|             intelCopyBuffer(dPriv); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       _mesa_problem(NULL, | ||||
|                     "dPriv has no gl_framebuffer pointer in intelSwapBuffers"); | ||||
|    } | ||||
| } | ||||
| #else | ||||
| /* Trunk version: | ||||
|  */ | ||||
| void | ||||
| intelSwapBuffers(__DRIdrawablePrivate * dPriv) | ||||
| { | ||||
|    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | ||||
|       GET_CURRENT_CONTEXT(ctx); | ||||
|       struct intel_context *intel; | ||||
|  | ||||
|       if (ctx == NULL) | ||||
| 	 return; | ||||
|  | ||||
|       intel = intel_context(ctx); | ||||
|  | ||||
|       if (ctx->Visual.doubleBufferMode) { | ||||
|          intelScreenPrivate *screen = intel->intelScreen; | ||||
|          _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */ | ||||
|          if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */ | ||||
|             intelPageFlip(dPriv); | ||||
|          } | ||||
|          else { | ||||
|             intelCopyBuffer(dPriv, NULL); | ||||
|          } | ||||
|          if (screen->current_rotation != 0) { | ||||
|             intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* XXX this shouldn't be an error but we can't handle it for now */ | ||||
|       fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); | ||||
|    } | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void | ||||
| intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) | ||||
| { | ||||
|    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | ||||
|       struct intel_context *intel = | ||||
|          (struct intel_context *) dPriv->driContextPriv->driverPrivate; | ||||
|       GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|       if (ctx->Visual.doubleBufferMode) { | ||||
|          drm_clip_rect_t rect; | ||||
|          rect.x1 = x + dPriv->x; | ||||
|          rect.y1 = (dPriv->h - y - h) + dPriv->y; | ||||
|          rect.x2 = rect.x1 + w; | ||||
|          rect.y2 = rect.y1 + h; | ||||
|          _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */ | ||||
|          intelCopyBuffer(dPriv, &rect); | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* XXX this shouldn't be an error but we can't handle it for now */ | ||||
|       fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Update the hardware state for drawing into a window or framebuffer object. | ||||
|  * | ||||
|  * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other | ||||
|  * places within the driver. | ||||
|  * | ||||
|  * Basically, this needs to be called any time the current framebuffer | ||||
|  * changes, the renderbuffers change, or we need to draw into different | ||||
|  * color buffers. | ||||
|  */ | ||||
| void | ||||
| intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *colorRegion, *depthRegion = NULL; | ||||
|    struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; | ||||
|    int front = 0;               /* drawing to front color buffer? */ | ||||
|  | ||||
|    if (!fb) { | ||||
|       /* this can happen during the initial context initialization */ | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* Do this here, note core Mesa, since this function is called from | ||||
|     * many places within the driver. | ||||
|     */ | ||||
|    if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { | ||||
|       /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ | ||||
|       _mesa_update_framebuffer(ctx); | ||||
|       /* this updates the DrawBuffer's Width/Height if it's a FBO */ | ||||
|       _mesa_update_draw_buffer_bounds(ctx); | ||||
|    } | ||||
|  | ||||
|    if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { | ||||
|       /* this may occur when we're called by glBindFrameBuffer() during | ||||
|        * the process of someone setting up renderbuffers, etc. | ||||
|        */ | ||||
|       /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (fb->Name) | ||||
|       intel_validate_paired_depth_stencil(ctx, fb); | ||||
|  | ||||
|    /* | ||||
|     * How many color buffers are we drawing into? | ||||
|     */ | ||||
|    if (fb->_NumColorDrawBuffers[0] != 1 | ||||
| #if 0 | ||||
|        /* XXX FBO temporary - always use software rendering */ | ||||
|        || 1 | ||||
| #endif | ||||
|       ) { | ||||
|       /* writing to 0 or 2 or 4 color buffers */ | ||||
|       /*_mesa_debug(ctx, "Software rendering\n");*/ | ||||
|       FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); | ||||
|       front = 1;                /* might not have back color buffer */ | ||||
|    } | ||||
|    else { | ||||
|       /* draw to exactly one color buffer */ | ||||
|       /*_mesa_debug(ctx, "Hardware rendering\n");*/ | ||||
|       FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); | ||||
|       if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) { | ||||
|          front = 1; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * Get the intel_renderbuffer for the colorbuffer we're drawing into. | ||||
|     * And set up cliprects. | ||||
|     */ | ||||
|    if (fb->Name == 0) { | ||||
|       /* drawing to window system buffer */ | ||||
|       if (intel->sarea->pf_current_page == 1) { | ||||
|          /* page flipped back/front */ | ||||
|          front ^= 1; | ||||
|       } | ||||
|       if (front) { | ||||
|          intelSetFrontClipRects(intel); | ||||
|          colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); | ||||
|       } | ||||
|       else { | ||||
|          intelSetBackClipRects(intel); | ||||
|          colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT); | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* drawing to user-created FBO */ | ||||
|       struct intel_renderbuffer *irb; | ||||
|       intelSetRenderbufferClipRects(intel); | ||||
|       irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]); | ||||
|       colorRegion = (irb && irb->region) ? irb->region : NULL; | ||||
|    } | ||||
|  | ||||
|    /* Update culling direction which changes depending on the | ||||
|     * orientation of the buffer: | ||||
|     */ | ||||
|    if (ctx->Driver.FrontFace) | ||||
|       ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); | ||||
|    else | ||||
|       ctx->NewState |= _NEW_POLYGON; | ||||
|  | ||||
|    if (!colorRegion) { | ||||
|       FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); | ||||
|    } | ||||
|    else { | ||||
|       FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); | ||||
|    } | ||||
|  | ||||
|    /*** | ||||
|     *** Get depth buffer region and check if we need a software fallback. | ||||
|     *** Note that the depth buffer is usually a DEPTH_STENCIL buffer. | ||||
|     ***/ | ||||
|    if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) { | ||||
|       irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped); | ||||
|       if (irbDepth->region) { | ||||
|          FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); | ||||
|          depthRegion = irbDepth->region; | ||||
|       } | ||||
|       else { | ||||
|          FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE); | ||||
|          depthRegion = NULL; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* not using depth buffer */ | ||||
|       FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); | ||||
|       depthRegion = NULL; | ||||
|    } | ||||
|  | ||||
|    /*** | ||||
|     *** Stencil buffer | ||||
|     *** This can only be hardware accelerated if we're using a | ||||
|     *** combined DEPTH_STENCIL buffer (for now anyway). | ||||
|     ***/ | ||||
|    if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) { | ||||
|       irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped); | ||||
|       if (irbStencil && irbStencil->region) { | ||||
|          ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|          FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); | ||||
|          /* need to re-compute stencil hw state */ | ||||
|          ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); | ||||
|          if (!depthRegion) | ||||
|             depthRegion = irbStencil->region; | ||||
|       } | ||||
|       else { | ||||
|          FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE); | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */ | ||||
|       FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); | ||||
|       /* need to re-compute stencil hw state */ | ||||
|       ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /** | ||||
|     ** Release old regions, reference new regions | ||||
|     **/ | ||||
| #if 0                           /* XXX FBO: this seems to be redundant with i915_state_draw_region() */ | ||||
|    if (intel->draw_region != colorRegion) { | ||||
|       intel_region_release(intel, &intel->draw_region); | ||||
|       intel_region_reference(&intel->draw_region, colorRegion); | ||||
|    } | ||||
|    if (intel->intelScreen->depth_region != depthRegion) { | ||||
|       intel_region_release(intel, &intel->intelScreen->depth_region); | ||||
|       intel_region_reference(&intel->intelScreen->depth_region, depthRegion); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    intel->vtbl.set_draw_region(intel, colorRegion, depthRegion); | ||||
|  | ||||
|    /* update viewport since it depends on window size */ | ||||
|    ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, | ||||
|                         ctx->Viewport.Width, ctx->Viewport.Height); | ||||
|  | ||||
|    /* Update hardware scissor */ | ||||
|    ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
|                        ctx->Scissor.Width, ctx->Scissor.Height); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelDrawBuffer(GLcontext * ctx, GLenum mode) | ||||
| { | ||||
|    intel_draw_buffer(ctx, ctx->DrawBuffer); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelReadBuffer(GLcontext * ctx, GLenum mode) | ||||
| { | ||||
|    if (ctx->ReadBuffer == ctx->DrawBuffer) { | ||||
|       /* This will update FBO completeness status. | ||||
|        * A framebuffer will be incomplete if the GL_READ_BUFFER setting | ||||
|        * refers to a missing renderbuffer.  Calling glReadBuffer can set | ||||
|        * that straight and can make the drawing buffer complete. | ||||
|        */ | ||||
|       intel_draw_buffer(ctx, ctx->DrawBuffer); | ||||
|    } | ||||
|    /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc) | ||||
|     * reference ctx->ReadBuffer and do appropriate state checks. | ||||
|     */ | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelInitBufferFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|    functions->Clear = intelClear; | ||||
|    functions->GetBufferSize = intelBufferSize; | ||||
|    functions->ResizeBuffers = _mesa_resize_framebuffer; | ||||
|    functions->DrawBuffer = intelDrawBuffer; | ||||
|    functions->ReadBuffer = intelReadBuffer; | ||||
| } | ||||
							
								
								
									
										56
									
								
								src/mesa/drivers/dri/i915/intel_buffers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/mesa/drivers/dri/i915/intel_buffers.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BUFFERS_H | ||||
| #define INTEL_BUFFERS_H | ||||
|  | ||||
|  | ||||
| struct intel_context; | ||||
|  | ||||
|  | ||||
| extern GLboolean | ||||
| intel_intersect_cliprects(drm_clip_rect_t * dest, | ||||
|                           const drm_clip_rect_t * a, | ||||
|                           const drm_clip_rect_t * b); | ||||
|  | ||||
| extern struct intel_region *intel_readbuf_region(struct intel_context *intel); | ||||
|  | ||||
| extern struct intel_region *intel_drawbuf_region(struct intel_context *intel); | ||||
|  | ||||
| extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); | ||||
|  | ||||
| extern void intelWindowMoved(struct intel_context *intel); | ||||
|  | ||||
| extern void intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb); | ||||
|  | ||||
| extern void intelInitBufferFuncs(struct dd_function_table *functions); | ||||
|  | ||||
| extern void | ||||
| intelRotateWindow(struct intel_context *intel, | ||||
|                   __DRIdrawablePrivate * dPriv, GLuint srcBuf); | ||||
|  | ||||
| #endif /* INTEL_BUFFERS_H */ | ||||
| @@ -47,13 +47,18 @@ | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| #include "i830_dri.h" | ||||
| #include "i830_common.h" | ||||
|  | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_span.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "intel_fbo.h" | ||||
|  | ||||
| #include "vblank.h" | ||||
| #include "utils.h" | ||||
| @@ -74,27 +79,21 @@ int INTEL_DEBUG = (0); | ||||
| #define need_GL_EXT_blend_minmax | ||||
| #define need_GL_EXT_cull_vertex | ||||
| #define need_GL_EXT_fog_coord | ||||
| #define need_GL_EXT_framebuffer_object | ||||
| #define need_GL_EXT_multi_draw_arrays | ||||
| #define need_GL_EXT_secondary_color | ||||
| #define need_GL_NV_vertex_program | ||||
| #include "extension_helper.h" | ||||
|  | ||||
| #ifndef VERBOSE | ||||
| int VERBOSE = 0; | ||||
| #endif | ||||
|  | ||||
| #if DEBUG_LOCKING | ||||
| char *prevLockFile; | ||||
| int prevLockLine; | ||||
| #endif | ||||
| #define DRIVER_DATE                     "20060928" | ||||
|  | ||||
| /*************************************** | ||||
|  * Mesa's Driver Functions | ||||
|  ***************************************/ | ||||
| _glthread_Mutex lockMutex; | ||||
| static GLboolean lockMutexInit = GL_FALSE; | ||||
|  | ||||
| #define DRIVER_DATE                     "20050225" | ||||
|  | ||||
| const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
| static const GLubyte * | ||||
| intelGetString(GLcontext * ctx, GLenum name) | ||||
| { | ||||
|    const char *chipset; | ||||
|    static char buffer[128]; | ||||
| @@ -105,25 +104,34 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
|       break; | ||||
|  | ||||
|    case GL_RENDERER: | ||||
|       switch (INTEL_CONTEXT(ctx)->intelScreen->deviceID) { | ||||
|       switch (intel_context(ctx)->intelScreen->deviceID) { | ||||
|       case PCI_CHIP_845_G: | ||||
| 	 chipset = "Intel(R) 845G"; break; | ||||
|          chipset = "Intel(R) 845G"; | ||||
|          break; | ||||
|       case PCI_CHIP_I830_M: | ||||
| 	 chipset = "Intel(R) 830M"; break; | ||||
|          chipset = "Intel(R) 830M"; | ||||
|          break; | ||||
|       case PCI_CHIP_I855_GM: | ||||
| 	 chipset = "Intel(R) 852GM/855GM"; break; | ||||
|          chipset = "Intel(R) 852GM/855GM"; | ||||
|          break; | ||||
|       case PCI_CHIP_I865_G: | ||||
| 	 chipset = "Intel(R) 865G"; break; | ||||
|          chipset = "Intel(R) 865G"; | ||||
|          break; | ||||
|       case PCI_CHIP_I915_G: | ||||
| 	 chipset = "Intel(R) 915G"; break; | ||||
|          chipset = "Intel(R) 915G"; | ||||
|          break; | ||||
|       case PCI_CHIP_I915_GM: | ||||
| 	 chipset = "Intel(R) 915GM"; break; | ||||
|          chipset = "Intel(R) 915GM"; | ||||
|          break; | ||||
|       case PCI_CHIP_I945_G: | ||||
| 	 chipset = "Intel(R) 945G"; break; | ||||
|          chipset = "Intel(R) 945G"; | ||||
|          break; | ||||
|       case PCI_CHIP_I945_GM: | ||||
| 	 chipset = "Intel(R) 945GM"; break; | ||||
|          chipset = "Intel(R) 945GM"; | ||||
|          break; | ||||
|       default: | ||||
| 	 chipset = "Unknown Intel Chipset"; break; | ||||
|          chipset = "Unknown Intel Chipset"; | ||||
|          break; | ||||
|       } | ||||
|  | ||||
|       (void) driGetRendererString(buffer, chipset, DRIVER_DATE, 0); | ||||
| @@ -134,27 +142,6 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelBufferSize(GLframebuffer *buffer, | ||||
| 			   GLuint *width, GLuint *height) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    /* Need to lock to make sure the driDrawable is uptodate.  This | ||||
|     * information is used to resize Mesa's software buffers, so it has | ||||
|     * to be correct. | ||||
|     */ | ||||
|    LOCK_HARDWARE(intel); | ||||
|    if (intel->driDrawable) { | ||||
|       *width = intel->driDrawable->w; | ||||
|       *height = intel->driDrawable->h; | ||||
|    } | ||||
|    else { | ||||
|       *width = 0; | ||||
|       *height = 0; | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Extension strings exported by the intel driver. | ||||
| @@ -163,8 +150,7 @@ static void intelBufferSize(GLframebuffer *buffer, | ||||
|  * It appears that ARB_texture_env_crossbar has "disappeared" compared to the | ||||
|  * old i830-specific driver. | ||||
|  */ | ||||
| const struct dri_extension card_extensions[] = | ||||
| { | ||||
| const struct dri_extension card_extensions[] = { | ||||
|    {"GL_ARB_multisample", GL_ARB_multisample_functions}, | ||||
|    {"GL_ARB_multitexture", NULL}, | ||||
|    {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, | ||||
| @@ -177,16 +163,22 @@ const struct dri_extension card_extensions[] = | ||||
|    {"GL_ARB_texture_mirrored_repeat", NULL}, | ||||
|    {"GL_ARB_texture_rectangle", NULL}, | ||||
|    {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, | ||||
|    {"GL_ARB_pixel_buffer_object", NULL}, | ||||
|    {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, | ||||
|    {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, | ||||
|    {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, | ||||
|     { "GL_EXT_blend_equation_separate",    GL_EXT_blend_equation_separate_functions }, | ||||
|    {"GL_EXT_blend_equation_separate", | ||||
|     GL_EXT_blend_equation_separate_functions}, | ||||
|    {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, | ||||
|    {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, | ||||
|    {"GL_EXT_blend_subtract", NULL}, | ||||
|    {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, | ||||
|    {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, | ||||
|    {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, | ||||
|    {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, | ||||
| #if 1                           /* XXX FBO temporary? */ | ||||
|    {"GL_EXT_packed_depth_stencil", NULL}, | ||||
| #endif | ||||
|    {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, | ||||
|    {"GL_EXT_stencil_wrap", NULL}, | ||||
|    {"GL_EXT_texture_edge_clamp", NULL}, | ||||
| @@ -201,7 +193,7 @@ const struct dri_extension card_extensions[] = | ||||
|    {"GL_NV_blend_square", NULL}, | ||||
|    {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, | ||||
|    {"GL_NV_vertex_program1_1", NULL}, | ||||
|     { "GL_SGIS_generate_mipmap",           NULL }, | ||||
| /*     { "GL_SGIS_generate_mipmap",           NULL }, */ | ||||
|    {NULL, NULL} | ||||
| }; | ||||
|  | ||||
| @@ -226,45 +218,106 @@ static const struct tnl_pipeline_stage *intel_pipeline[] = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| static const struct dri_debug_control debug_control[] = | ||||
| { | ||||
|     { "fall",  DEBUG_FALLBACKS }, | ||||
| static const struct dri_debug_control debug_control[] = { | ||||
|    {"tex", DEBUG_TEXTURE}, | ||||
|     { "ioctl", DEBUG_IOCTL }, | ||||
|     { "prim",  DEBUG_PRIMS }, | ||||
|     { "vert",  DEBUG_VERTS }, | ||||
|    {"state", DEBUG_STATE}, | ||||
|    {"ioctl", DEBUG_IOCTL}, | ||||
|    {"blit", DEBUG_BLIT}, | ||||
|    {"mip", DEBUG_MIPTREE}, | ||||
|    {"fall", DEBUG_FALLBACKS}, | ||||
|    {"verb", DEBUG_VERBOSE}, | ||||
|     { "dri",   DEBUG_DRI }, | ||||
|     { "dma",   DEBUG_DMA }, | ||||
|     { "san",   DEBUG_SANITY }, | ||||
|     { "sync",  DEBUG_SYNC }, | ||||
|     { "sleep", DEBUG_SLEEP }, | ||||
|    {"bat", DEBUG_BATCH}, | ||||
|    {"pix", DEBUG_PIXEL}, | ||||
|    {"buf", DEBUG_BUFMGR}, | ||||
|    {"reg", DEBUG_REGION}, | ||||
|    {"fbo", DEBUG_FBO}, | ||||
|    {"lock", DEBUG_LOCK}, | ||||
|    {NULL, 0} | ||||
| }; | ||||
|  | ||||
|  | ||||
| static void intelInvalidateState( GLcontext *ctx, GLuint new_state ) | ||||
| static void | ||||
| intelInvalidateState(GLcontext * ctx, GLuint new_state) | ||||
| { | ||||
|    _swrast_InvalidateState(ctx, new_state); | ||||
|    _swsetup_InvalidateState(ctx, new_state); | ||||
|    _ac_InvalidateState(ctx, new_state); | ||||
|    _tnl_InvalidateState(ctx, new_state); | ||||
|    _tnl_invalidate_vertex_state(ctx, new_state); | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= new_state; | ||||
|    intel_context(ctx)->NewGLState |= new_state; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitDriverFunctions( struct dd_function_table *functions ) | ||||
| void | ||||
| intelFlush(GLcontext * ctx) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (intel->Fallback) | ||||
|       _swrast_flush(ctx); | ||||
|  | ||||
|    INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|    if (intel->batch->map != intel->batch->ptr) | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|  | ||||
|    /* XXX: Need to do an MI_FLUSH here. | ||||
|     */ | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Check if we need to rotate/warp the front color buffer to the | ||||
|  * rotated screen.  We generally need to do this when we get a glFlush | ||||
|  * or glFinish after drawing to the front color buffer. | ||||
|  */ | ||||
| static void | ||||
| intelCheckFrontRotate(GLcontext * ctx) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == | ||||
|        BUFFER_BIT_FRONT_LEFT) { | ||||
|       intelScreenPrivate *screen = intel->intelScreen; | ||||
|       if (screen->current_rotation != 0) { | ||||
|          __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|          intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glFlush. | ||||
|  */ | ||||
| static void | ||||
| intelglFlush(GLcontext * ctx) | ||||
| { | ||||
|    intelFlush(ctx); | ||||
|    intelCheckFrontRotate(ctx); | ||||
| } | ||||
|  | ||||
| void | ||||
| intelFinish(GLcontext * ctx) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    intelFlush(ctx); | ||||
|    if (intel->batch->last_fence) { | ||||
|       driFenceFinish(intel->batch->last_fence, | ||||
|                      0, GL_FALSE); | ||||
|       driFenceUnReference(intel->batch->last_fence); | ||||
|       intel->batch->last_fence = NULL; | ||||
|    } | ||||
|    intelCheckFrontRotate(ctx); | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelInitDriverFunctions(struct dd_function_table *functions) | ||||
| { | ||||
|    _mesa_init_driver_functions(functions); | ||||
|  | ||||
|    functions->Clear = intelClear; | ||||
|    functions->Flush = intelglFlush; | ||||
|    functions->Finish = intelFinish; | ||||
|    functions->GetBufferSize = intelBufferSize; | ||||
|    functions->ResizeBuffers = _mesa_resize_framebuffer; | ||||
|    functions->GetString = intelGetString; | ||||
|    functions->UpdateState = intelInvalidateState; | ||||
|    functions->CopyColorTable = _swrast_CopyColorTable; | ||||
| @@ -275,25 +328,12 @@ void intelInitDriverFunctions( struct dd_function_table *functions ) | ||||
|    intelInitTextureFuncs(functions); | ||||
|    intelInitPixelFuncs(functions); | ||||
|    intelInitStateFuncs(functions); | ||||
| } | ||||
|  | ||||
| static void intel_emit_invarient_state( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    intel->vtbl.emit_invarient_state( intel ); | ||||
|    intel->prim.flush = 0; | ||||
|  | ||||
|    /* 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 ); | ||||
|    intelInitBufferFuncs(functions); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| GLboolean intelInitContext( intelContextPtr intel, | ||||
| GLboolean | ||||
| intelInitContext(struct intel_context *intel, | ||||
|                  const __GLcontextModes * mesaVis, | ||||
|                  __DRIcontextPrivate * driContextPriv, | ||||
|                  void *sharedContextPrivate, | ||||
| @@ -309,8 +349,7 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|  | ||||
|    if (!_mesa_initialize_context(&intel->ctx, | ||||
|                                  mesaVis, shareCtx, | ||||
| 				 functions, | ||||
| 				 (void*) intel)) | ||||
|                                  functions, (void *) intel)) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    driContextPriv->driverPrivate = intel; | ||||
| @@ -318,15 +357,23 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    intel->driScreen = sPriv; | ||||
|    intel->sarea = saPriv; | ||||
|  | ||||
|  | ||||
|    (void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) ); | ||||
|    make_empty_list( & intel->swapped ); | ||||
|    if (!lockMutexInit) { | ||||
|       lockMutexInit = GL_TRUE; | ||||
|       _glthread_INIT_MUTEX(lockMutex); | ||||
|    } | ||||
|  | ||||
|    driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, | ||||
|                        intel->driScreen->myNum, "i915"); | ||||
|  | ||||
|    ctx->Const.MaxTextureMaxAnisotropy = 2.0; | ||||
|  | ||||
|    /* This doesn't yet catch all non-conformant rendering, but it's a | ||||
|     * start. | ||||
|     */ | ||||
|    if (getenv("INTEL_STRICT_CONFORMANCE")) { | ||||
|       intel->strict_conformance = 1; | ||||
|    } | ||||
|  | ||||
|    ctx->Const.MinLineWidth = 1.0; | ||||
|    ctx->Const.MinLineWidthAA = 1.0; | ||||
|    ctx->Const.MaxLineWidth = 3.0; | ||||
| @@ -339,6 +386,8 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    ctx->Const.MaxPointSizeAA = 3.0; | ||||
|    ctx->Const.PointSizeGranularity = 1.0; | ||||
|  | ||||
|    ctx->Const.MaxColorAttachments = 4;  /* XXX FBO: review this */ | ||||
|  | ||||
|    /* Initialize the software rasterizer and helper modules. */ | ||||
|    _swrast_CreateContext(ctx); | ||||
|    _ac_CreateContext(ctx); | ||||
| @@ -358,23 +407,16 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    intel->driFd = sPriv->fd; | ||||
|    intel->driHwLock = (drmLock *) & sPriv->pSAREA->lock; | ||||
|  | ||||
|    intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; | ||||
|    intel->hw_stipple = 1; | ||||
|  | ||||
|    /* XXX FBO: this doesn't seem to be used anywhere */ | ||||
|    switch (mesaVis->depthBits) { | ||||
|    case 0:                     /* what to do in this case? */ | ||||
|    case 16: | ||||
|       intel->depth_scale = 1.0/0xffff; | ||||
|       intel->polygon_offset_scale = 1.0 / 0xffff; | ||||
|       intel->depth_clear_mask = ~0; | ||||
|       intel->ClearDepth = 0xffff; | ||||
|       break; | ||||
|    case 24: | ||||
|       intel->depth_scale = 1.0/0xffffff; | ||||
|       intel->polygon_offset_scale = 2.0 / 0xffffff;     /* req'd to pass glean */ | ||||
|       intel->depth_clear_mask = 0x00ffffff; | ||||
|       intel->stencil_clear_mask = 0xff000000; | ||||
|       intel->ClearDepth = 0x00ffffff; | ||||
|       break; | ||||
|    default: | ||||
|       assert(0); | ||||
| @@ -398,12 +440,26 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    intel->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS); | ||||
|  | ||||
|    intel->vblank_flags = (intel->intelScreen->irq_active != 0) | ||||
|        ? driGetDefaultVBlankFlags(&intelScreen->optionCache) : VBLANK_FLAG_NO_IRQ; | ||||
|       ? driGetDefaultVBlankFlags(&intelScreen-> | ||||
|                                  optionCache) : VBLANK_FLAG_NO_IRQ; | ||||
|  | ||||
|    (*dri_interface->getUST) (&intel->swap_ust); | ||||
|    _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); | ||||
|  | ||||
|  | ||||
|    intel->batch = intel_batchbuffer_alloc(intel); | ||||
|    intel->last_swap_fence = NULL; | ||||
|    intel->first_swap_fence = NULL; | ||||
|  | ||||
|    intel_bufferobj_init(intel); | ||||
|    intel_fbo_init(intel); | ||||
|  | ||||
|    if (intel->ctx.Mesa_DXTn) { | ||||
|       _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc"); | ||||
| @@ -413,31 +469,14 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|       _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc"); | ||||
|    } | ||||
|  | ||||
| /*    driInitTextureObjects( ctx, & intel->swapped, */ | ||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_1D | */ | ||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_2D |  */ | ||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_RECT ); */ | ||||
|  | ||||
|  | ||||
|    intelInitBatchBuffer(&intel->ctx); | ||||
|    intel->prim.flush = intel_emit_invarient_state; | ||||
|    intel->prim.primitive = ~0; | ||||
|  | ||||
|  | ||||
| #if DO_DEBUG | ||||
|    INTEL_DEBUG  = driParseDebugString( getenv( "INTEL_DEBUG" ), | ||||
| 				       debug_control ); | ||||
|    INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ), | ||||
| 				       debug_control ); | ||||
|    INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); | ||||
| #endif | ||||
|  | ||||
| #ifndef VERBOSE | ||||
|    if (getenv("INTEL_VERBOSE")) | ||||
|       VERBOSE=1; | ||||
| #endif | ||||
|  | ||||
|    if (getenv("INTEL_NO_RAST") ||  | ||||
|        getenv("INTEL_NO_RAST")) { | ||||
|    if (getenv("INTEL_NO_RAST")) { | ||||
|       fprintf(stderr, "disabling 3D rasterization\n"); | ||||
|       FALLBACK(intel, INTEL_FALLBACK_USER, 1); | ||||
|    } | ||||
| @@ -445,9 +484,11 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | ||||
| void | ||||
| intelDestroyContext(__DRIcontextPrivate * driContextPriv) | ||||
| { | ||||
|    intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate; | ||||
|    struct intel_context *intel = | ||||
|       (struct intel_context *) driContextPriv->driverPrivate; | ||||
|  | ||||
|    assert(intel);               /* should never be null */ | ||||
|    if (intel) { | ||||
| @@ -465,144 +506,50 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | ||||
|       _swrast_DestroyContext(&intel->ctx); | ||||
|       intel->Fallback = 0;      /* don't call _swrast_Flush later */ | ||||
|  | ||||
|       intelDestroyBatchBuffer(&intel->ctx); | ||||
|       intel_batchbuffer_free(intel->batch); | ||||
|  | ||||
|       if (intel->last_swap_fence) { | ||||
| 	 driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); | ||||
| 	 driFenceUnReference(intel->last_swap_fence); | ||||
| 	 intel->last_swap_fence = NULL; | ||||
|       } | ||||
|       if (intel->first_swap_fence) { | ||||
| 	 driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE); | ||||
| 	 driFenceUnReference(intel->first_swap_fence); | ||||
| 	 intel->first_swap_fence = NULL; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       if (release_texture_heaps) { | ||||
|          /* This share group is about to go away, free our private | ||||
|           * texture object data. | ||||
|           */ | ||||
|          int i; | ||||
|  | ||||
|          for ( i = 0 ; i < intel->nr_heaps ; i++ ) { | ||||
| 	    driDestroyTextureHeap( intel->texture_heaps[ i ] ); | ||||
| 	    intel->texture_heaps[ i ] = NULL; | ||||
|          } | ||||
|  | ||||
| 	 assert( is_empty_list( & intel->swapped ) ); | ||||
|          if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
|             fprintf(stderr, "do something to free texture heaps\n"); | ||||
|       } | ||||
|  | ||||
|       /* free the Mesa context */ | ||||
|       _mesa_destroy_context(&intel->ctx); | ||||
|       _mesa_free_context_data(&intel->ctx); | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelSetFrontClipRects( intelContextPtr intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    intel->numClipRects = dPriv->numClipRects; | ||||
|    intel->pClipRects = dPriv->pClipRects; | ||||
|    intel->drawX = dPriv->x; | ||||
|    intel->drawY = dPriv->y; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelSetBackClipRects( intelContextPtr intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { | ||||
|       intel->numClipRects = dPriv->numClipRects; | ||||
|       intel->pClipRects = dPriv->pClipRects; | ||||
|       intel->drawX = dPriv->x; | ||||
|       intel->drawY = dPriv->y; | ||||
|    } else { | ||||
|       intel->numClipRects = dPriv->numBackClipRects; | ||||
|       intel->pClipRects = dPriv->pBackClipRects; | ||||
|       intel->drawX = dPriv->backX; | ||||
|       intel->drawY = dPriv->backY; | ||||
|        | ||||
|       if (dPriv->numBackClipRects == 1 && | ||||
| 	  dPriv->x == dPriv->backX && | ||||
| 	  dPriv->y == dPriv->backY) { | ||||
|        | ||||
| 	 /* Repeat the calculation of the back cliprect dimensions here | ||||
| 	  * as early versions of dri.a in the Xserver are incorrect.  Try | ||||
| 	  * very hard not to restrict future versions of dri.a which | ||||
| 	  * might eg. allocate truly private back buffers. | ||||
| 	  */ | ||||
| 	 int x1, y1; | ||||
| 	 int x2, y2; | ||||
| 	  | ||||
| 	 x1 = dPriv->x; | ||||
| 	 y1 = dPriv->y;       | ||||
| 	 x2 = dPriv->x + dPriv->w; | ||||
| 	 y2 = dPriv->y + dPriv->h; | ||||
| 	  | ||||
| 	 if (x1 < 0) x1 = 0; | ||||
| 	 if (y1 < 0) y1 = 0; | ||||
| 	 if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width; | ||||
| 	 if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height; | ||||
|  | ||||
| 	 if (x1 == dPriv->pBackClipRects[0].x1 && | ||||
| 	     y1 == dPriv->pBackClipRects[0].y1) { | ||||
|  | ||||
| 	    dPriv->pBackClipRects[0].x2 = x2; | ||||
| 	    dPriv->pBackClipRects[0].y2 = y2; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelWindowMoved( intelContextPtr intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!intel->ctx.DrawBuffer) { | ||||
|       intelSetFrontClipRects( intel ); | ||||
|    } | ||||
|    else { | ||||
|       driUpdateFramebufferSize(&intel->ctx, intel->driDrawable); | ||||
|      | ||||
|       switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) { | ||||
|       case BUFFER_BIT_FRONT_LEFT: | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
| 	 break; | ||||
|       case BUFFER_BIT_BACK_LEFT: | ||||
| 	 intelSetBackClipRects( intel ); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    _mesa_resize_framebuffer(&intel->ctx, | ||||
| 			    (GLframebuffer*)dPriv->driverPrivate, | ||||
| 			    dPriv->w, dPriv->h); | ||||
|     | ||||
|    /* Set state we know depends on drawable parameters: | ||||
|     */ | ||||
|    { | ||||
|       GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|       ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			   ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|        | ||||
|       ctx->Driver.DepthRange( ctx,  | ||||
| 			      ctx->Viewport.Near, | ||||
| 			      ctx->Viewport.Far ); | ||||
|    } | ||||
| } | ||||
|  | ||||
| GLboolean intelUnbindContext(__DRIcontextPrivate *driContextPriv) | ||||
| GLboolean | ||||
| intelUnbindContext(__DRIcontextPrivate * driContextPriv) | ||||
| { | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, | ||||
| GLboolean | ||||
| intelMakeCurrent(__DRIcontextPrivate * driContextPriv, | ||||
|                  __DRIdrawablePrivate * driDrawPriv, | ||||
|                  __DRIdrawablePrivate * driReadPriv) | ||||
| { | ||||
|  | ||||
|    if (driContextPriv) { | ||||
|       intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate; | ||||
|       struct intel_context *intel = | ||||
|          (struct intel_context *) driContextPriv->driverPrivate; | ||||
|       GLframebuffer *drawFb = (GLframebuffer *) driDrawPriv->driverPrivate; | ||||
|       GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate; | ||||
|  | ||||
|       if (intel->driDrawable != driDrawPriv) { | ||||
|          /* Shouldn't the readbuffer be stored also? */ | ||||
| @@ -612,56 +559,56 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, | ||||
|          intelWindowMoved(intel); | ||||
|       } | ||||
|  | ||||
|       _mesa_make_current(&intel->ctx, | ||||
| 			 (GLframebuffer *) driDrawPriv->driverPrivate, | ||||
| 			 (GLframebuffer *) driReadPriv->driverPrivate); | ||||
|       /* XXX FBO temporary fix-ups! */ | ||||
|       /* if the renderbuffers don't have regions, init them from the context */ | ||||
|       { | ||||
|          struct intel_renderbuffer *irbFront | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_FRONT_LEFT); | ||||
|          struct intel_renderbuffer *irbBack | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_BACK_LEFT); | ||||
|          struct intel_renderbuffer *irbDepth | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_DEPTH); | ||||
|          struct intel_renderbuffer *irbStencil | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_STENCIL); | ||||
|  | ||||
|       intel->ctx.Driver.DrawBuffer( &intel->ctx, intel->ctx.Color.DrawBuffer[0] ); | ||||
|    } else { | ||||
|          if (irbFront && !irbFront->region) { | ||||
|             intel_region_reference(&irbFront->region, intel->intelScreen->front_region); | ||||
|          } | ||||
|          if (irbBack && !irbBack->region) { | ||||
|             intel_region_reference(&irbBack->region, intel->intelScreen->back_region); | ||||
|          } | ||||
|          if (irbDepth && !irbDepth->region) { | ||||
|             intel_region_reference(&irbDepth->region, intel->intelScreen->depth_region); | ||||
|          } | ||||
|          if (irbStencil && !irbStencil->region) { | ||||
|             intel_region_reference(&irbStencil->region, intel->intelScreen->depth_region); | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       _mesa_make_current(&intel->ctx, drawFb, readFb); | ||||
|  | ||||
|       intel_draw_buffer(&intel->ctx, drawFb); | ||||
|    } | ||||
|    else { | ||||
|       _mesa_make_current(NULL, NULL, NULL); | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Use the information in the sarea to update the screen parameters | ||||
|  * related to screen rotation. | ||||
|  */ | ||||
| static void | ||||
| intelUpdateScreenRotation(intelContextPtr intel, | ||||
|                           __DRIscreenPrivate *sPriv, | ||||
|                           drmI830Sarea *sarea) | ||||
| { | ||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; | ||||
|    intelRegion *colorBuf; | ||||
|  | ||||
|    intelUnmapScreenRegions(intelScreen); | ||||
|  | ||||
|    intelUpdateScreenFromSAREA(intelScreen, sarea); | ||||
|  | ||||
|    /* update the current hw offsets for the color and depth buffers */ | ||||
|    if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) | ||||
|       colorBuf = &intelScreen->back; | ||||
|    else | ||||
|       colorBuf = &intelScreen->front; | ||||
|    intel->vtbl.update_color_z_regions(intel, colorBuf, &intelScreen->depth); | ||||
|  | ||||
|    if (!intelMapScreenRegions(sPriv)) { | ||||
|       fprintf(stderr, "ERROR Remapping screen regions!!!\n"); | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelGetLock( intelContextPtr intel, GLuint flags ) | ||||
| intelContendedLock(struct intel_context *intel, GLuint flags) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    __DRIscreenPrivate *sPriv = intel->driScreen; | ||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; | ||||
|    drmI830Sarea *sarea = intel->sarea; | ||||
|    unsigned   i; | ||||
|  | ||||
|    drmGetLock(intel->driFd, intel->hHWContext, flags); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_LOCK) | ||||
|       _mesa_printf("%s - got contended lock\n", __progname); | ||||
|  | ||||
|    /* If the window moved, may need to set a new cliprect now. | ||||
|     * | ||||
|     * NOTE: This releases and regains the hw lock, so all state | ||||
| @@ -670,194 +617,77 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) | ||||
|    if (dPriv) | ||||
|       DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); | ||||
|  | ||||
|    if (dPriv && intel->lastStamp != dPriv->lastStamp) { | ||||
|       intelWindowMoved( intel ); | ||||
|       intel->lastStamp = dPriv->lastStamp; | ||||
|    } | ||||
|  | ||||
|    /* If we lost context, need to dump all registers to hardware. | ||||
|     * Note that we don't care about 2d contexts, even if they perform | ||||
|     * accelerated commands, so the DRI locking in the X server is even | ||||
|     * more broken than usual. | ||||
|     */ | ||||
|  | ||||
|    if (sarea->width != intelScreen->width || | ||||
|        sarea->height != intelScreen->height || | ||||
|        sarea->rotation != intelScreen->current_rotation) { | ||||
|       intelUpdateScreenRotation(intel, sPriv, sarea); | ||||
|  | ||||
|       /* This will drop the outstanding batchbuffer on the floor */ | ||||
|       intel->batch.ptr -= (intel->batch.size - intel->batch.space); | ||||
|       intel->batch.space = intel->batch.size; | ||||
|       intelUpdateScreenRotation(sPriv, sarea); | ||||
|  | ||||
|       /*  | ||||
|        * This will drop the outstanding batchbuffer on the floor | ||||
|        * FIXME: This should be done for all contexts? | ||||
|        */ | ||||
|  | ||||
|       intel_batchbuffer_reset(intel->batch); | ||||
|  | ||||
|       /* lose all primitives */ | ||||
|       intel->prim.primitive = ~0; | ||||
|       intel->prim.start_ptr = 0; | ||||
|       intel->prim.flush = 0; | ||||
|  | ||||
|       /* re-emit all state */ | ||||
|       intel->vtbl.lost_hardware(intel); | ||||
|  | ||||
|       intel->lastStamp = 0; /* force window update */ | ||||
|       /* force window update */ | ||||
|       intel->lastStamp = 0; | ||||
|    } | ||||
|  | ||||
|       /* Release batch buffer | ||||
|  | ||||
|    /* Drawable changed? | ||||
|     */ | ||||
|       intelDestroyBatchBuffer(&intel->ctx); | ||||
|       intelInitBatchBuffer(&intel->ctx); | ||||
|       intel->prim.flush = intel_emit_invarient_state; | ||||
|    if (dPriv && intel->lastStamp != dPriv->lastStamp) { | ||||
|       intelWindowMoved(intel); | ||||
|       intel->lastStamp = dPriv->lastStamp; | ||||
|    } | ||||
| } | ||||
|  | ||||
|       /* Still need to reset the global LRU? | ||||
|  | ||||
| extern _glthread_Mutex lockMutex; | ||||
|  | ||||
|  | ||||
| /* Lock the hardware and validate our state.   | ||||
|  */ | ||||
|       intel_driReinitTextureHeap( intel->texture_heaps[0], intel->intelScreen->tex.size ); | ||||
| void LOCK_HARDWARE( struct intel_context *intel ) | ||||
| { | ||||
|     char __ret=0; | ||||
|  | ||||
|     _glthread_LOCK_MUTEX(lockMutex); | ||||
|     assert(!intel->locked); | ||||
|  | ||||
|     DRM_CAS(intel->driHwLock, intel->hHWContext, | ||||
|         (DRM_LOCK_HELD|intel->hHWContext), __ret); | ||||
|  | ||||
|     if (__ret) | ||||
|         intelContendedLock( intel, 0 ); | ||||
|  | ||||
|     if (INTEL_DEBUG & DEBUG_LOCK) | ||||
|       _mesa_printf("%s - locked\n", __progname); | ||||
|  | ||||
|     intel->locked = 1; | ||||
| } | ||||
|  | ||||
|    /* 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. | ||||
|  | ||||
|   /* Unlock the hardware using the global current context  | ||||
|    */ | ||||
|    for ( i = 0 ; i < intel->nr_heaps ; i++ ) { | ||||
|       DRI_AGE_TEXTURES( intel->texture_heaps[ i ] ); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelSwapBuffers( __DRIdrawablePrivate *dPriv ) | ||||
| void UNLOCK_HARDWARE( struct intel_context *intel ) | ||||
| { | ||||
|    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | ||||
|       intelContextPtr intel; | ||||
|       GLcontext *ctx; | ||||
|       intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|       ctx = &intel->ctx; | ||||
|       if (ctx->Visual.doubleBufferMode) { | ||||
|          intelScreenPrivate *screen = intel->intelScreen; | ||||
| 	 _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */ | ||||
| 	 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */ | ||||
| 	    intelPageFlip( dPriv ); | ||||
| 	 } else { | ||||
| 	     intelCopyBuffer( dPriv, NULL ); | ||||
| 	 } | ||||
|          if (screen->current_rotation != 0) { | ||||
|             intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); | ||||
|          } | ||||
|       } | ||||
|    } else { | ||||
|       /* XXX this shouldn't be an error but we can't handle it for now */ | ||||
|       fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); | ||||
|    } | ||||
|    intel->locked = 0; | ||||
|  | ||||
|    DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext); | ||||
|  | ||||
|    _glthread_UNLOCK_MUTEX(lockMutex); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_LOCK) | ||||
|       _mesa_printf("%s - unlocked\n", __progname); | ||||
| }  | ||||
|  | ||||
| void intelCopySubBuffer( __DRIdrawablePrivate *dPriv, | ||||
| 			 int x, int y, int w, int h ) | ||||
| { | ||||
|    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | ||||
|       intelContextPtr intel; | ||||
|       GLcontext *ctx; | ||||
|       intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|       ctx = &intel->ctx; | ||||
|       if (ctx->Visual.doubleBufferMode) { | ||||
|          intelScreenPrivate *screen = intel->intelScreen; | ||||
| 	 drm_clip_rect_t rect; | ||||
| 	 rect.x1 = x + dPriv->x; | ||||
| 	 rect.y1 = (dPriv->h - y - h) + dPriv->y; | ||||
| 	 rect.x2 = rect.x1 + w; | ||||
| 	 rect.y2 = rect.y1 + h; | ||||
| 	 _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */ | ||||
| 	 intelCopyBuffer( dPriv, &rect ); | ||||
|       } | ||||
|    } else { | ||||
|       /* XXX this shouldn't be an error but we can't handle it for now */ | ||||
|       fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelInitState( GLcontext *ctx ) | ||||
| { | ||||
|    /* Mesa should do this for us: | ||||
|     */ | ||||
|    ctx->Driver.AlphaFunc( ctx,  | ||||
| 			  ctx->Color.AlphaFunc, | ||||
| 			  ctx->Color.AlphaRef); | ||||
|  | ||||
|    ctx->Driver.BlendColor( ctx, | ||||
| 			   ctx->Color.BlendColor ); | ||||
|  | ||||
|    ctx->Driver.BlendEquationSeparate( ctx,  | ||||
| 				      ctx->Color.BlendEquationRGB, | ||||
| 				      ctx->Color.BlendEquationA); | ||||
|  | ||||
|    ctx->Driver.BlendFuncSeparate( ctx, | ||||
| 				  ctx->Color.BlendSrcRGB, | ||||
| 				  ctx->Color.BlendDstRGB, | ||||
| 				  ctx->Color.BlendSrcA, | ||||
| 				  ctx->Color.BlendDstA); | ||||
|  | ||||
|    ctx->Driver.ColorMask( ctx,  | ||||
| 			  ctx->Color.ColorMask[RCOMP], | ||||
| 			  ctx->Color.ColorMask[GCOMP], | ||||
| 			  ctx->Color.ColorMask[BCOMP], | ||||
| 			  ctx->Color.ColorMask[ACOMP]); | ||||
|  | ||||
|    ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode ); | ||||
|    ctx->Driver.DepthFunc( ctx, ctx->Depth.Func ); | ||||
|    ctx->Driver.DepthMask( ctx, ctx->Depth.Mask ); | ||||
|  | ||||
|    ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test ); | ||||
|    ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE ); | ||||
|  | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); | ||||
|  | ||||
|    ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace ); | ||||
|  | ||||
|    { | ||||
|       GLfloat f = (GLfloat)ctx->Light.Model.ColorControl; | ||||
|       ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f ); | ||||
|    } | ||||
|  | ||||
|    ctx->Driver.LineWidth( ctx, ctx->Line.Width ); | ||||
|    ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp ); | ||||
|    ctx->Driver.PointSize( ctx, ctx->Point.Size ); | ||||
|    ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple ); | ||||
|    ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|    ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT, | ||||
|                                     ctx->Stencil.Function[0], | ||||
|                                     ctx->Stencil.Ref[0], | ||||
|                                     ctx->Stencil.ValueMask[0] ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_BACK, | ||||
|                                     ctx->Stencil.Function[1], | ||||
|                                     ctx->Stencil.Ref[1], | ||||
|                                     ctx->Stencil.ValueMask[1] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] ); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_FRONT, | ||||
|                                   ctx->Stencil.FailFunc[0], | ||||
|                                   ctx->Stencil.ZFailFunc[0], | ||||
|                                   ctx->Stencil.ZPassFunc[0]); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_BACK, | ||||
|                                   ctx->Stencil.FailFunc[1], | ||||
|                                   ctx->Stencil.ZFailFunc[1], | ||||
|                                   ctx->Stencil.ZPassFunc[1]); | ||||
|  | ||||
|  | ||||
|    ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -48,88 +48,132 @@ | ||||
| #define DV_PF_565  (2<<8) | ||||
| #define DV_PF_8888 (3<<8) | ||||
|  | ||||
| #define INTEL_CONTEXT(ctx)	((intelContextPtr)(ctx)) | ||||
| struct intel_region; | ||||
| struct intel_context; | ||||
| struct _DriBufferObject; | ||||
|  | ||||
| typedef struct intel_context intelContext; | ||||
| typedef struct intel_context *intelContextPtr; | ||||
| typedef struct intel_texture_object *intelTextureObjectPtr; | ||||
|  | ||||
| typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *, | ||||
| typedef void (*intel_tri_func) (struct intel_context *, intelVertex *, | ||||
|                                 intelVertex *, intelVertex *); | ||||
| typedef void (*intel_line_func) (struct intel_context *, intelVertex *, | ||||
|                                  intelVertex *); | ||||
| typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *); | ||||
| typedef void (*intel_point_func)(intelContextPtr, intelVertex *); | ||||
| typedef void (*intel_point_func) (struct intel_context *, intelVertex *); | ||||
|  | ||||
| #define INTEL_FALLBACK_DRAW_BUFFER	 0x1 | ||||
| #define INTEL_FALLBACK_READ_BUFFER	 0x2 | ||||
| #define INTEL_FALLBACK_USER		 0x4 | ||||
| #define INTEL_FALLBACK_NO_BATCHBUFFER	 0x8 | ||||
| #define INTEL_FALLBACK_NO_TEXMEM	 0x10 | ||||
| #define INTEL_FALLBACK_DEPTH_BUFFER      0x4 | ||||
| #define INTEL_FALLBACK_STENCIL_BUFFER    0x8 | ||||
| #define INTEL_FALLBACK_USER		 0x10 | ||||
| #define INTEL_FALLBACK_RENDERMODE	 0x20 | ||||
|  | ||||
| extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ); | ||||
| extern void intelFallback(struct intel_context *intel, GLuint bit, | ||||
|                           GLboolean mode); | ||||
| #define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode ) | ||||
|  | ||||
|  | ||||
| #define INTEL_TEX_MAXLEVELS 10 | ||||
|  | ||||
| #define INTEL_WRITE_PART  0x1 | ||||
| #define INTEL_WRITE_FULL  0x2 | ||||
| #define INTEL_READ        0x4 | ||||
|  | ||||
| struct intel_texture_object | ||||
| { | ||||
|    driTextureObject    base;	/* the parent class */ | ||||
|    struct gl_texture_object base;       /* The "parent" object */ | ||||
|  | ||||
|    GLuint texelBytes; | ||||
|    GLuint age; | ||||
|    GLuint Pitch; | ||||
|    GLuint Height; | ||||
|    GLuint TextureOffset; | ||||
|    GLubyte *BufAddr;    | ||||
|    /* The mipmap tree must include at least these levels once | ||||
|     * validated: | ||||
|     */ | ||||
|    GLuint firstLevel; | ||||
|    GLuint lastLevel; | ||||
|  | ||||
|    GLuint min_level; | ||||
|    GLuint max_level; | ||||
|    GLuint depth_pitch; | ||||
|    /* Offset for firstLevel image: | ||||
|     */ | ||||
|    GLuint textureOffset; | ||||
|  | ||||
|    struct { | ||||
|       const struct gl_texture_image *image; | ||||
|       GLuint offset;       /* into BufAddr */ | ||||
|       GLuint height; | ||||
|       GLuint internalFormat; | ||||
|    } image[6][INTEL_TEX_MAXLEVELS]; | ||||
|  | ||||
|    GLuint dirty; | ||||
|    GLuint firstLevel,lastLevel; | ||||
|    /* On validation any active images held in main memory or in other | ||||
|     * regions will be copied to this region and the old storage freed. | ||||
|     */ | ||||
|    struct intel_mipmap_tree *mt; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| struct intel_texture_image | ||||
| { | ||||
|    struct gl_texture_image base; | ||||
|  | ||||
|    /* These aren't stored in gl_texture_image  | ||||
|     */ | ||||
|    GLuint level; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* If intelImage->mt != NULL, image data is stored here. | ||||
|     * Else if intelImage->base.Data != NULL, image is stored there. | ||||
|     * Else there is no image data. | ||||
|     */ | ||||
|    struct intel_mipmap_tree *mt; | ||||
| }; | ||||
|  | ||||
|  | ||||
| #define INTEL_MAX_FIXUP 64 | ||||
|  | ||||
| struct intel_context | ||||
| { | ||||
|    GLcontext ctx;               /* the parent class */ | ||||
|  | ||||
|    struct { | ||||
|       void (*destroy)( intelContextPtr intel );  | ||||
|       void (*emit_state)( intelContextPtr intel ); | ||||
|       void (*emit_invarient_state)( intelContextPtr intel ); | ||||
|       void (*lost_hardware)( intelContextPtr intel ); | ||||
|       void (*update_texture_state)( intelContextPtr intel ); | ||||
|    struct | ||||
|    { | ||||
|       void (*destroy) (struct intel_context * intel); | ||||
|       void (*emit_state) (struct intel_context * intel); | ||||
|       void (*lost_hardware) (struct intel_context * intel); | ||||
|       void (*update_texture_state) (struct intel_context * intel); | ||||
|  | ||||
|       void (*render_start)( intelContextPtr intel ); | ||||
|       void (*set_color_region)( intelContextPtr intel, const intelRegion *reg ); | ||||
|       void (*set_z_region)( intelContextPtr intel, const intelRegion *reg ); | ||||
|       void (*update_color_z_regions)(intelContextPtr intel, | ||||
|                                      const intelRegion *colorRegion, | ||||
|                                      const intelRegion *depthRegion); | ||||
|       void (*emit_flush)( intelContextPtr intel ); | ||||
|       void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim ); | ||||
|       void (*render_start) (struct intel_context * intel); | ||||
|       void (*set_draw_region) (struct intel_context * intel, | ||||
|                                struct intel_region * draw_region, | ||||
|                                struct intel_region * depth_region); | ||||
|  | ||||
|       GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected ); | ||||
|         GLuint(*flush_cmd) (void); | ||||
|  | ||||
|       void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask, | ||||
| 			       GLboolean all,  | ||||
| 			       GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|       void (*reduced_primitive_state) (struct intel_context * intel, | ||||
|                                        GLenum rprim); | ||||
|  | ||||
|       void (*rotate_window)( intelContextPtr intel, | ||||
|         GLboolean(*check_vertex_size) (struct intel_context * intel, | ||||
|                                        GLuint expected); | ||||
|  | ||||
|  | ||||
|       /* Metaops:  | ||||
|        */ | ||||
|       void (*install_meta_state) (struct intel_context * intel); | ||||
|       void (*leave_meta_state) (struct intel_context * intel); | ||||
|  | ||||
|       void (*meta_draw_region) (struct intel_context * intel, | ||||
|                                 struct intel_region * draw_region, | ||||
|                                 struct intel_region * depth_region); | ||||
|  | ||||
|       void (*meta_color_mask) (struct intel_context * intel, GLboolean); | ||||
|  | ||||
|       void (*meta_stencil_replace) (struct intel_context * intel, | ||||
|                                     GLuint mask, GLuint clear); | ||||
|  | ||||
|       void (*meta_depth_replace) (struct intel_context * intel); | ||||
|  | ||||
|       void (*meta_texture_blend_replace) (struct intel_context * intel); | ||||
|  | ||||
|       void (*meta_no_stencil_write) (struct intel_context * intel); | ||||
|       void (*meta_no_depth_write) (struct intel_context * intel); | ||||
|       void (*meta_no_texture) (struct intel_context * intel); | ||||
|  | ||||
|       void (*meta_import_pixel_state) (struct intel_context * intel); | ||||
|  | ||||
|         GLboolean(*meta_tex_rect_source) (struct intel_context * intel, | ||||
|                                           struct _DriBufferObject * buffer, | ||||
|                                           GLuint offset, | ||||
|                                           GLuint pitch, | ||||
|                                           GLuint height, | ||||
|                                           GLenum format, GLenum type); | ||||
|       void (*rotate_window) (struct intel_context * intel, | ||||
|                              __DRIdrawablePrivate * dPriv, GLuint srcBuf); | ||||
|  | ||||
|       intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj ); | ||||
|       void (*assert_not_dirty) (struct intel_context *intel); | ||||
|  | ||||
|    } vtbl; | ||||
|  | ||||
| @@ -137,68 +181,45 @@ struct intel_context | ||||
|    GLuint Fallback; | ||||
|    GLuint NewGLState; | ||||
|  | ||||
|    struct { | ||||
|       GLuint start_offset; | ||||
|       GLint size; | ||||
|       GLint space; | ||||
|       GLubyte *ptr; | ||||
|       GLuint counter; | ||||
|       GLuint last_emit_state; | ||||
|       GLboolean contains_geometry; | ||||
|       const char *func; | ||||
|       GLuint last_swap; | ||||
|    } batch; | ||||
|    struct _DriFenceObject *last_swap_fence; | ||||
|    struct _DriFenceObject *first_swap_fence; | ||||
|  | ||||
|    struct { | ||||
|       void *ptr; | ||||
|       GLint size; | ||||
|       GLuint offset; | ||||
|       GLuint active_buf; | ||||
|       GLuint irq_emitted; | ||||
|    } alloc; | ||||
|    struct intel_batchbuffer *batch; | ||||
|  | ||||
|    struct { | ||||
|    struct | ||||
|    { | ||||
|       GLuint id; | ||||
|       GLuint primitive; | ||||
|       GLubyte *start_ptr; | ||||
|       void (*flush)( GLcontext * ); | ||||
|       void (*flush) (struct intel_context *); | ||||
|    } prim; | ||||
|  | ||||
|    GLboolean locked; | ||||
|    char *prevLockFile; | ||||
|    int prevLockLine; | ||||
|  | ||||
|    GLubyte clear_red; | ||||
|    GLubyte clear_green; | ||||
|    GLubyte clear_blue; | ||||
|    GLubyte clear_alpha; | ||||
|    GLuint ClearColor; | ||||
|    GLuint ClearDepth; | ||||
|    GLuint ClearColor565; | ||||
|    GLuint ClearColor8888; | ||||
|  | ||||
|    /* Offsets of fields within the current vertex: | ||||
|     */ | ||||
|    GLuint coloroffset; | ||||
|    GLuint specoffset; | ||||
|  | ||||
|    /* Support for duplicating XYZW as WPOS parameter (crutch for I915). | ||||
|     */ | ||||
|    GLuint wpos_offset; | ||||
|    GLuint wpos_size; | ||||
|  | ||||
|    struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; | ||||
|    GLuint vertex_attr_count; | ||||
|  | ||||
|    GLfloat depth_scale; | ||||
|    GLfloat polygon_offset_scale;        /* dependent on depth_scale, bpp */ | ||||
|    GLuint depth_clear_mask; | ||||
|    GLuint stencil_clear_mask; | ||||
|  | ||||
|    GLboolean hw_stencil; | ||||
|    GLboolean hw_stipple; | ||||
|    GLboolean strict_conformance; | ||||
|  | ||||
|    /* Texture object bookkeeping | ||||
|    /* AGP memory buffer manager: | ||||
|     */ | ||||
|    GLuint                nr_heaps; | ||||
|    driTexHeap          * texture_heaps[1]; | ||||
|    driTextureObject      swapped; | ||||
|    GLuint                lastStamp; | ||||
|    struct bufmgr *bm; | ||||
|  | ||||
|    struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS]; | ||||
|  | ||||
|    /* State for intelvb.c and inteltris.c. | ||||
|     */ | ||||
| @@ -207,8 +228,15 @@ struct intel_context | ||||
|    GLenum render_primitive; | ||||
|    GLenum reduced_primitive; | ||||
|    GLuint vertex_size; | ||||
|    unsigned char *verts;	   /* points to tnl->clipspace.vertex_buf */ | ||||
|    GLubyte *verts;              /* points to tnl->clipspace.vertex_buf */ | ||||
|  | ||||
| #if 0 | ||||
|    struct intel_region *front_region;   /* XXX FBO: obsolete */ | ||||
|    struct intel_region *rotated_region; /* XXX FBO: obsolete */ | ||||
|    struct intel_region *back_region;    /* XXX FBO: obsolete */ | ||||
|    struct intel_region *draw_region;    /* XXX FBO: rename to color_region */ | ||||
|    struct intel_region *depth_region;   /**< currently bound depth/Z region */ | ||||
| #endif | ||||
|  | ||||
|    /* Fallback rasterization functions  | ||||
|     */ | ||||
| @@ -216,17 +244,13 @@ struct intel_context | ||||
|    intel_line_func draw_line; | ||||
|    intel_tri_func draw_tri; | ||||
|  | ||||
|    /* Drawing buffer state | ||||
|    /* These refer to the current drawing buffer: | ||||
|     */ | ||||
|    intelRegion *drawRegion;  /* current drawing buffer */ | ||||
|    intelRegion *readRegion;  /* current reading buffer */ | ||||
|  | ||||
|    int drawX;			/* origin of drawable in draw buffer */ | ||||
|    int drawY; | ||||
|    GLuint numClipRects;		/* cliprects for that buffer */ | ||||
|    int drawX, drawY;            /**< origin of drawing area within region */ | ||||
|    GLuint numClipRects;         /**< cliprects for drawing */ | ||||
|    drm_clip_rect_t *pClipRects; | ||||
|    drm_clip_rect_t fboRect;     /**< cliprect for FBO rendering */ | ||||
|  | ||||
|    int dirtyAge; | ||||
|    int perf_boxes; | ||||
|  | ||||
|    GLuint do_usleeps; | ||||
| @@ -234,10 +258,6 @@ struct intel_context | ||||
|    GLuint irqsEmitted; | ||||
|    drm_i915_irq_wait_t iw; | ||||
|  | ||||
|    GLboolean scissor; | ||||
|    drm_clip_rect_t draw_rect; | ||||
|    drm_clip_rect_t scissor_rect; | ||||
|  | ||||
|    drm_context_t hHWContext; | ||||
|    drmLock *driHwLock; | ||||
|    int driFd; | ||||
| @@ -247,6 +267,8 @@ struct intel_context | ||||
|    intelScreenPrivate *intelScreen; | ||||
|    drmI830Sarea *sarea; | ||||
|  | ||||
|    GLuint lastStamp; | ||||
|  | ||||
|    /** | ||||
|     * Configuration cache | ||||
|     */ | ||||
| @@ -262,87 +284,15 @@ struct intel_context | ||||
|  | ||||
|    GLuint swap_count; | ||||
|    GLuint swap_missed_count; | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| #define DEBUG_LOCKING	1 | ||||
|  | ||||
| #if DEBUG_LOCKING | ||||
| extern char *prevLockFile; | ||||
| extern int prevLockLine; | ||||
|  | ||||
| #define DEBUG_LOCK()							\ | ||||
|    do {									\ | ||||
|       prevLockFile = (__FILE__);					\ | ||||
|       prevLockLine = (__LINE__);					\ | ||||
|    } while (0) | ||||
|  | ||||
| #define DEBUG_RESET()							\ | ||||
|    do {									\ | ||||
|       prevLockFile = 0;							\ | ||||
|       prevLockLine = 0;							\ | ||||
|    } while (0) | ||||
|  | ||||
| /* Slightly less broken way of detecting recursive locking in a | ||||
|  * threaded environment.  The right way to do this would be to make | ||||
|  * prevLockFile, prevLockLine thread-local. | ||||
|  * | ||||
|  * This technique instead checks to see if the same context is | ||||
|  * requesting the lock twice -- this will not catch application | ||||
|  * breakages where the same context is active in two different threads | ||||
|  * at once, but it will catch driver breakages (recursive locking) in | ||||
|  * threaded apps. | ||||
| /* These are functions now: | ||||
|  */ | ||||
| #define DEBUG_CHECK_LOCK()						\ | ||||
|    do {									\ | ||||
|       if ( *((volatile int *)intel->driHwLock) == 			\ | ||||
| 	   (DRM_LOCK_HELD | intel->hHWContext) ) {			\ | ||||
| 	 fprintf( stderr,						\ | ||||
| 		  "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n",	\ | ||||
| 		  prevLockFile, prevLockLine, __FILE__, __LINE__ );	\ | ||||
| 	 abort();							\ | ||||
|       }									\ | ||||
|    } while (0) | ||||
| void LOCK_HARDWARE( struct intel_context *intel ); | ||||
| void UNLOCK_HARDWARE( struct intel_context *intel ); | ||||
|  | ||||
| #else | ||||
|  | ||||
| #define DEBUG_LOCK() | ||||
| #define DEBUG_RESET() | ||||
| #define DEBUG_CHECK_LOCK() | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Lock the hardware and validate our state.   | ||||
|  */ | ||||
| #define LOCK_HARDWARE( intel )				\ | ||||
| do {							\ | ||||
|     char __ret=0;					\ | ||||
|     DEBUG_CHECK_LOCK();					\ | ||||
|     assert(!(intel)->locked);				\ | ||||
|     DRM_CAS((intel)->driHwLock, (intel)->hHWContext,	\ | ||||
|         (DRM_LOCK_HELD|(intel)->hHWContext), __ret);	\ | ||||
|     if (__ret)						\ | ||||
|         intelGetLock( (intel), 0 );			\ | ||||
|       DEBUG_LOCK();					\ | ||||
|     (intel)->locked = 1;				\ | ||||
| }while (0) | ||||
|   | ||||
|    | ||||
|   /* Unlock the hardware using the global current context  | ||||
|    */ | ||||
| #define UNLOCK_HARDWARE(intel)						\ | ||||
| do {									\ | ||||
|    intel->locked = 0;							\ | ||||
|    if (0) { 								\ | ||||
|       intel->perf_boxes |= intel->sarea->perf_boxes;  			\ | ||||
|       intel->sarea->perf_boxes = 0;					\ | ||||
|    }									\ | ||||
|    DRM_UNLOCK((intel)->driFd, (intel)->driHwLock, (intel)->hHWContext);	\ | ||||
|    DEBUG_RESET();							\ | ||||
| } while (0) | ||||
| extern char *__progname; | ||||
|  | ||||
|  | ||||
| #define SUBPIXEL_X 0.125 | ||||
| @@ -351,7 +301,7 @@ do {									\ | ||||
| #define INTEL_FIREVERTICES(intel)		\ | ||||
| do {						\ | ||||
|    if ((intel)->prim.flush)			\ | ||||
|       (intel)->prim.flush(&(intel)->ctx);		\ | ||||
|       (intel)->prim.flush(intel);		\ | ||||
| } while (0) | ||||
|  | ||||
| /* ================================================================ | ||||
| @@ -372,32 +322,24 @@ do {						\ | ||||
|   ((a<<24) | (r<<16) | (g<<8) | b) | ||||
|  | ||||
|  | ||||
| #define INTEL_PACKCOLOR(format, r,  g,  b, a)		\ | ||||
| (format == DV_PF_555 ? INTEL_PACKCOLOR1555(r,g,b,a) :	\ | ||||
|  (format == DV_PF_565 ? INTEL_PACKCOLOR565(r,g,b) :	\ | ||||
|   (format == DV_PF_8888 ? INTEL_PACKCOLOR8888(r,g,b,a) :	\ | ||||
|    0))) | ||||
|  | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * From linux kernel i386 header files, copes with odd sizes better | ||||
|  * than COPY_DWORDS would: | ||||
|  * XXX Put this in src/mesa/main/imports.h ??? | ||||
|  */ | ||||
| #if defined(i386) || defined(__i386__) | ||||
| static __inline__ void * __memcpy(void * to, const void * from, size_t n) | ||||
| static INLINE void * | ||||
| __memcpy(void *to, const void *from, size_t n) | ||||
| { | ||||
|    int d0, d1, d2; | ||||
|    __asm__ __volatile__( | ||||
|       "rep ; movsl\n\t" | ||||
|    __asm__ __volatile__("rep ; movsl\n\t" | ||||
|                         "testb $2,%b4\n\t" | ||||
|                         "je 1f\n\t" | ||||
|                         "movsw\n" | ||||
|                         "1:\ttestb $1,%b4\n\t" | ||||
|                         "je 2f\n\t" | ||||
|       "movsb\n" | ||||
|       "2:" | ||||
|       : "=&c" (d0), "=&D" (d1), "=&S" (d2) | ||||
|                         "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2) | ||||
|                         :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from) | ||||
|                         :"memory"); | ||||
|    return (to); | ||||
| @@ -421,16 +363,18 @@ extern int INTEL_DEBUG; | ||||
| #define DEBUG_TEXTURE	0x1 | ||||
| #define DEBUG_STATE	0x2 | ||||
| #define DEBUG_IOCTL	0x4 | ||||
| #define DEBUG_PRIMS	0x8 | ||||
| #define DEBUG_VERTS	0x10 | ||||
| #define DEBUG_BLIT	0x8 | ||||
| #define DEBUG_MIPTREE   0x10 | ||||
| #define DEBUG_FALLBACKS	0x20 | ||||
| #define DEBUG_VERBOSE	0x40 | ||||
| #define DEBUG_DRI       0x80 | ||||
| #define DEBUG_DMA       0x100 | ||||
| #define DEBUG_SANITY    0x200 | ||||
| #define DEBUG_SYNC      0x400 | ||||
| #define DEBUG_SLEEP     0x800 | ||||
| #define DEBUG_PIXEL     0x1000 | ||||
| #define DEBUG_BATCH     0x80 | ||||
| #define DEBUG_PIXEL     0x100 | ||||
| #define DEBUG_BUFMGR    0x200 | ||||
| #define DEBUG_REGION    0x400 | ||||
| #define DEBUG_FBO       0x800 | ||||
| #define DEBUG_LOCK      0x1000 | ||||
|  | ||||
| #define DBG(...)  do { if (INTEL_DEBUG & FILE_DEBUG_FLAG) _mesa_printf(__VA_ARGS__); } while(0) | ||||
|  | ||||
|  | ||||
| #define PCI_CHIP_845_G			0x2562 | ||||
| @@ -447,21 +391,19 @@ extern int INTEL_DEBUG; | ||||
|  * intel_context.c: | ||||
|  */ | ||||
|  | ||||
| extern void intelInitDriverFunctions( struct dd_function_table *functions ); | ||||
|  | ||||
| extern GLboolean intelInitContext( intelContextPtr intel,  | ||||
| extern GLboolean intelInitContext(struct intel_context *intel, | ||||
|                                   const __GLcontextModes * mesaVis, | ||||
|                                   __DRIcontextPrivate * driContextPriv, | ||||
|                                   void *sharedContextPrivate, | ||||
|                                   struct dd_function_table *functions); | ||||
|  | ||||
| extern void intelGetLock(intelContextPtr intel, GLuint flags); | ||||
| extern void intelSetBackClipRects(intelContextPtr intel); | ||||
| extern void intelSetFrontClipRects(intelContextPtr intel); | ||||
| extern void intelWindowMoved( intelContextPtr intel ); | ||||
| extern void intelGetLock(struct intel_context *intel, GLuint flags); | ||||
|  | ||||
| extern void intelInitState(GLcontext * ctx); | ||||
| extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name ); | ||||
| extern void intelFinish(GLcontext * ctx); | ||||
| extern void intelFlush(GLcontext * ctx); | ||||
|  | ||||
| extern void intelInitDriverFunctions(struct dd_function_table *functions); | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
| @@ -521,6 +463,8 @@ extern void intelInitStateFuncs( struct dd_function_table *functions ); | ||||
| #define BLENDFACT_INV_CONST_ALPHA	0x0f | ||||
| #define BLENDFACT_MASK          	0x0f | ||||
|  | ||||
| #define MI_BATCH_BUFFER_END 	(0xA<<23) | ||||
|  | ||||
|  | ||||
| extern int intel_translate_compare_func(GLenum func); | ||||
| extern int intel_translate_stencil_op(GLenum op); | ||||
| @@ -528,20 +472,30 @@ extern int intel_translate_blend_factor( GLenum factor ); | ||||
| extern int intel_translate_logic_op(GLenum opcode); | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * intel_ioctl.c: | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.   | ||||
|  * These are better-typed than the macros used previously: | ||||
|  */ | ||||
| extern void intel_dump_batchbuffer( long offset, | ||||
| 				    int *ptr, | ||||
| 				    int count ); | ||||
| static INLINE struct intel_context * | ||||
| intel_context(GLcontext * ctx) | ||||
| { | ||||
|    return (struct intel_context *) ctx; | ||||
| } | ||||
|  | ||||
| static INLINE struct intel_texture_object * | ||||
| intel_texture_object(struct gl_texture_object *obj) | ||||
| { | ||||
|    return (struct intel_texture_object *) obj; | ||||
| } | ||||
|  | ||||
| /* ================================================================ | ||||
|  * intel_pixel.c: | ||||
|  */	 | ||||
| extern void intelInitPixelFuncs( struct dd_function_table *functions ); | ||||
| static INLINE struct intel_texture_image * | ||||
| intel_texture_image(struct gl_texture_image *img) | ||||
| { | ||||
|    return (struct intel_texture_image *) img; | ||||
| } | ||||
|  | ||||
| extern struct intel_renderbuffer *intel_renderbuffer(struct gl_renderbuffer | ||||
|                                                      *rb); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|   | ||||
							
								
								
									
										282
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,282 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "imports.h" | ||||
| #include "context.h" | ||||
| #include "depthstencil.h" | ||||
| #include "fbobject.h" | ||||
| #include "framebuffer.h" | ||||
| #include "hash.h" | ||||
| #include "mtypes.h" | ||||
| #include "renderbuffer.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_depthstencil.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * The GL_EXT_framebuffer_object allows the user to create their own | ||||
|  * framebuffer objects consisting of color renderbuffers (0 or more), | ||||
|  * depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1). | ||||
|  * | ||||
|  * The spec considers depth and stencil renderbuffers to be totally independent | ||||
|  * buffers.  In reality, most graphics hardware today uses a combined | ||||
|  * depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil). | ||||
|  * | ||||
|  * This causes difficulty because the user may create some number of depth | ||||
|  * renderbuffers and some number of stencil renderbuffers and bind them | ||||
|  * together in framebuffers in any combination. | ||||
|  * | ||||
|  * This code manages all that. | ||||
|  * | ||||
|  * 1. Depth renderbuffers are always allocated in hardware as 32bpp | ||||
|  *    GL_DEPTH24_STENCIL8 buffers. | ||||
|  * | ||||
|  * 2. Stencil renderbuffers are initially allocated in software as 8bpp | ||||
|  *    GL_STENCIL_INDEX8 buffers. | ||||
|  * | ||||
|  * 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth | ||||
|  *    fields (respectively) to indicate if the buffer's currently paired | ||||
|  *    with another stencil or depth buffer (respectively). | ||||
|  * | ||||
|  * 4. When a depth and stencil buffer are initially both attached to the | ||||
|  *    current framebuffer, we merge the stencil buffer values into the | ||||
|  *    depth buffer (really a depth+stencil buffer).  The then hardware uses | ||||
|  *    the combined buffer. | ||||
|  * | ||||
|  * 5. Whenever a depth or stencil buffer is reallocated (with | ||||
|  *    glRenderbufferStorage) we undo the pairing and copy the stencil values | ||||
|  *    from the combined depth/stencil buffer back to the stencil-only buffer. | ||||
|  * | ||||
|  * 6. We also undo the pairing when we find a change in buffer bindings. | ||||
|  * | ||||
|  * 7. If a framebuffer is only using a depth renderbuffer (no stencil), we | ||||
|  *    just use the combined depth/stencil buffer and ignore the stencil values. | ||||
|  * | ||||
|  * 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have | ||||
|  *    to promote the 8bpp software stencil buffer to a 32bpp hardware | ||||
|  *    depth+stencil buffer. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| map_regions(GLcontext * ctx, | ||||
|             struct intel_renderbuffer *depthRb, | ||||
|             struct intel_renderbuffer *stencilRb) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    if (depthRb && depthRb->region) { | ||||
|       intel_region_map(intel->intelScreen, depthRb->region); | ||||
|       depthRb->pfMap = depthRb->region->map; | ||||
|       depthRb->pfPitch = depthRb->region->pitch; | ||||
|    } | ||||
|    if (stencilRb && stencilRb->region) { | ||||
|       intel_region_map(intel->intelScreen, stencilRb->region); | ||||
|       stencilRb->pfMap = stencilRb->region->map; | ||||
|       stencilRb->pfPitch = stencilRb->region->pitch; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void | ||||
| unmap_regions(GLcontext * ctx, | ||||
|               struct intel_renderbuffer *depthRb, | ||||
|               struct intel_renderbuffer *stencilRb) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    if (depthRb && depthRb->region) { | ||||
|       intel_region_unmap(intel->intelScreen, depthRb->region); | ||||
|       depthRb->pfMap = NULL; | ||||
|       depthRb->pfPitch = 0; | ||||
|    } | ||||
|    if (stencilRb && stencilRb->region) { | ||||
|       intel_region_unmap(intel->intelScreen, stencilRb->region); | ||||
|       stencilRb->pfMap = NULL; | ||||
|       stencilRb->pfPitch = 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Undo the pairing/interleaving between depth and stencil buffers. | ||||
|  * irb should be a depth/stencil or stencil renderbuffer. | ||||
|  */ | ||||
| void | ||||
| intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb) | ||||
| { | ||||
|    if (irb->PairedStencil) { | ||||
|       /* irb is a depth/stencil buffer */ | ||||
|       struct gl_renderbuffer *stencilRb; | ||||
|       struct intel_renderbuffer *stencilIrb; | ||||
|  | ||||
|       ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|  | ||||
|       stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil); | ||||
|       stencilIrb = intel_renderbuffer(stencilRb); | ||||
|       if (stencilIrb) { | ||||
|          /* need to extract stencil values from the depth buffer */ | ||||
|          ASSERT(stencilIrb->PairedDepth == irb->Base.Name); | ||||
|          map_regions(ctx, irb, stencilIrb); | ||||
|          _mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base); | ||||
|          unmap_regions(ctx, irb, stencilIrb); | ||||
|          stencilIrb->PairedDepth = 0; | ||||
|       } | ||||
|       irb->PairedStencil = 0; | ||||
|    } | ||||
|    else if (irb->PairedDepth) { | ||||
|       /* irb is a stencil buffer */ | ||||
|       struct gl_renderbuffer *depthRb; | ||||
|       struct intel_renderbuffer *depthIrb; | ||||
|  | ||||
|       ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || | ||||
|              irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|  | ||||
|       depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth); | ||||
|       depthIrb = intel_renderbuffer(depthRb); | ||||
|       if (depthIrb) { | ||||
|          /* need to extract stencil values from the depth buffer */ | ||||
|          ASSERT(depthIrb->PairedStencil == irb->Base.Name); | ||||
|          map_regions(ctx, depthIrb, irb); | ||||
|          _mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base); | ||||
|          unmap_regions(ctx, depthIrb, irb); | ||||
|          depthIrb->PairedStencil = 0; | ||||
|       } | ||||
|       irb->PairedDepth = 0; | ||||
|    } | ||||
|    else { | ||||
|       _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing"); | ||||
|    } | ||||
|  | ||||
|    ASSERT(irb->PairedStencil == 0); | ||||
|    ASSERT(irb->PairedDepth == 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Examine the depth and stencil renderbuffers which are attached to the | ||||
|  * framebuffer.  If both depth and stencil are attached, make sure that the | ||||
|  * renderbuffers are 'paired' (combined).  If only depth or only stencil is | ||||
|  * attached, undo any previous pairing. | ||||
|  * | ||||
|  * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments | ||||
|  * change, for example). | ||||
|  */ | ||||
| void | ||||
| intel_validate_paired_depth_stencil(GLcontext * ctx, | ||||
|                                     struct gl_framebuffer *fb) | ||||
| { | ||||
|    struct intel_renderbuffer *depthRb, *stencilRb; | ||||
|  | ||||
|    depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH); | ||||
|    stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL); | ||||
|  | ||||
|    if (depthRb && stencilRb) { | ||||
|       if (depthRb == stencilRb) { | ||||
|          /* Using a user-created combined depth/stencil buffer. | ||||
|           * Nothing to do. | ||||
|           */ | ||||
|          ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT); | ||||
|          ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|       } | ||||
|       else { | ||||
|          /* Separate depth/stencil buffers, need to interleave now */ | ||||
|          ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT); | ||||
|          ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX); | ||||
|          /* may need to interleave depth/stencil now */ | ||||
|          if (depthRb->PairedStencil == stencilRb->Base.Name) { | ||||
|             /* OK, the depth and stencil buffers are already interleaved */ | ||||
|             ASSERT(stencilRb->PairedDepth == depthRb->Base.Name); | ||||
|          } | ||||
|          else { | ||||
|             /* need to setup new pairing/interleaving */ | ||||
|             if (depthRb->PairedStencil) { | ||||
|                intel_unpair_depth_stencil(ctx, depthRb); | ||||
|             } | ||||
|             if (stencilRb->PairedDepth) { | ||||
|                intel_unpair_depth_stencil(ctx, stencilRb); | ||||
|             } | ||||
|  | ||||
|             ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|             ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || | ||||
|                    stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|  | ||||
|             /* establish new pairing: interleave stencil into depth buffer */ | ||||
|             map_regions(ctx, depthRb, stencilRb); | ||||
|             _mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base); | ||||
|             unmap_regions(ctx, depthRb, stencilRb); | ||||
|             depthRb->PairedStencil = stencilRb->Base.Name; | ||||
|             stencilRb->PairedDepth = depthRb->Base.Name; | ||||
|          } | ||||
|  | ||||
|       } | ||||
|    } | ||||
|    else if (depthRb) { | ||||
|       /* Depth buffer but no stencil buffer. | ||||
|        * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits. | ||||
|        */ | ||||
|       /* can't assert this until storage is allocated: | ||||
|          ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|        */ | ||||
|       /* intel_undo any previous pairing */ | ||||
|       if (depthRb->PairedStencil) { | ||||
|          intel_unpair_depth_stencil(ctx, depthRb); | ||||
|       } | ||||
|    } | ||||
|    else if (stencilRb) { | ||||
|       /* Stencil buffer but no depth buffer. | ||||
|        * Since h/w doesn't typically support just 8bpp stencil w/out Z, | ||||
|        * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits. | ||||
|        */ | ||||
|       /* undo any previous pairing */ | ||||
|       if (stencilRb->PairedDepth) { | ||||
|          intel_unpair_depth_stencil(ctx, stencilRb); | ||||
|       } | ||||
|       if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) { | ||||
|          /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */ | ||||
|          _mesa_promote_stencil(ctx, &stencilRb->Base); | ||||
|          ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */ | ||||
|    _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); | ||||
|    if (depthRb && depthRb->PairedStencil) | ||||
|       _mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH); | ||||
|    else | ||||
|       _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); | ||||
|  | ||||
|  | ||||
|    /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer | ||||
|     * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer | ||||
|     * if present. | ||||
|     */ | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
|  | ||||
| #ifndef INTEL_DEPTH_STENCIL_H | ||||
| #define INTEL_DEPTH_STENCIL_H | ||||
|  | ||||
|  | ||||
| extern void | ||||
| intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb); | ||||
|  | ||||
| extern void | ||||
| intel_validate_paired_depth_stencil(GLcontext * ctx, | ||||
|                                     struct gl_framebuffer *fb); | ||||
|  | ||||
|  | ||||
| #endif /* INTEL_DEPTH_STENCIL_H */ | ||||
							
								
								
									
										621
									
								
								src/mesa/drivers/dri/i915/intel_fbo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										621
									
								
								src/mesa/drivers/dri/i915/intel_fbo.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,621 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include "imports.h" | ||||
| #include "mtypes.h" | ||||
| #include "fbobject.h" | ||||
| #include "framebuffer.h" | ||||
| #include "renderbuffer.h" | ||||
| #include "context.h" | ||||
| #include "texformat.h" | ||||
| #include "texrender.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_depthstencil.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_span.h" | ||||
|  | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_FBO | ||||
|  | ||||
| #define INTEL_RB_CLASS 0x12345678 | ||||
|  | ||||
|  | ||||
| /* XXX FBO: move this to intel_context.h (inlined) */ | ||||
| /** | ||||
|  * Return a gl_renderbuffer ptr casted to intel_renderbuffer. | ||||
|  * NULL will be returned if the rb isn't really an intel_renderbuffer. | ||||
|  * This is determiend by checking the ClassID. | ||||
|  */ | ||||
| struct intel_renderbuffer * | ||||
| intel_renderbuffer(struct gl_renderbuffer *rb) | ||||
| { | ||||
|    struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb; | ||||
|    if (irb && irb->Base.ClassID == INTEL_RB_CLASS) { | ||||
|       /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/ | ||||
|       return irb; | ||||
|    } | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct intel_renderbuffer * | ||||
| intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) | ||||
| { | ||||
|    return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); | ||||
| } | ||||
|  | ||||
|  | ||||
| struct intel_region * | ||||
| intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) | ||||
| { | ||||
|    struct intel_renderbuffer *irb | ||||
|       = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); | ||||
|    if (irb) | ||||
|       return irb->region; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Create a new framebuffer object. | ||||
|  */ | ||||
| static struct gl_framebuffer * | ||||
| intel_new_framebuffer(GLcontext * ctx, GLuint name) | ||||
| { | ||||
|    /* there's no intel_framebuffer at this time, just use Mesa's class */ | ||||
|    return _mesa_new_framebuffer(ctx, name); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_delete_renderbuffer(struct gl_renderbuffer *rb) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb); | ||||
|  | ||||
|    ASSERT(irb); | ||||
|  | ||||
|    if (irb->PairedStencil || irb->PairedDepth) { | ||||
|       intel_unpair_depth_stencil(ctx, irb); | ||||
|    } | ||||
|  | ||||
|    if (intel && irb->region) { | ||||
|       intel_region_release(intel->intelScreen, &irb->region); | ||||
|    } | ||||
|  | ||||
|    _mesa_free(irb); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Return a pointer to a specific pixel in a renderbuffer. | ||||
|  */ | ||||
| static void * | ||||
| intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb, | ||||
|                   GLint x, GLint y) | ||||
| { | ||||
|    /* By returning NULL we force all software rendering to go through | ||||
|     * the span routines. | ||||
|     */ | ||||
|    return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glRenderbufferStorageEXT() to set the format and allocate | ||||
|  * storage for a user-created renderbuffer. | ||||
|  */ | ||||
| static GLboolean | ||||
| intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, | ||||
|                                  GLenum internalFormat, | ||||
|                                  GLuint width, GLuint height) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb); | ||||
|    GLboolean softwareBuffer = GL_FALSE; | ||||
|    int cpp; | ||||
|  | ||||
|    ASSERT(rb->Name != 0); | ||||
|  | ||||
|    switch (internalFormat) { | ||||
|    case GL_R3_G3_B2: | ||||
|    case GL_RGB4: | ||||
|    case GL_RGB5: | ||||
|       rb->_ActualFormat = GL_RGB5; | ||||
|       rb->DataType = GL_UNSIGNED_BYTE; | ||||
|       rb->RedBits = 5; | ||||
|       rb->GreenBits = 6; | ||||
|       rb->BlueBits = 5; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_RGB: | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|    case GL_RGBA: | ||||
|    case GL_RGBA2: | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGB5_A1: | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       rb->_ActualFormat = GL_RGBA8; | ||||
|       rb->DataType = GL_UNSIGNED_BYTE; | ||||
|       rb->RedBits = 8; | ||||
|       rb->GreenBits = 8; | ||||
|       rb->BlueBits = 8; | ||||
|       rb->AlphaBits = 8; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_STENCIL_INDEX: | ||||
|    case GL_STENCIL_INDEX1_EXT: | ||||
|    case GL_STENCIL_INDEX4_EXT: | ||||
|    case GL_STENCIL_INDEX8_EXT: | ||||
|    case GL_STENCIL_INDEX16_EXT: | ||||
|       /* alloc a depth+stencil buffer */ | ||||
|       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       rb->DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       rb->StencilBits = 8; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|       rb->_ActualFormat = GL_DEPTH_COMPONENT16; | ||||
|       rb->DataType = GL_UNSIGNED_SHORT; | ||||
|       rb->DepthBits = 16; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       rb->DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       rb->DepthBits = 24; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_DEPTH_STENCIL_EXT: | ||||
|    case GL_DEPTH24_STENCIL8_EXT: | ||||
|       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       rb->DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       rb->DepthBits = 24; | ||||
|       rb->StencilBits = 8; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    default: | ||||
|       _mesa_problem(ctx, | ||||
|                     "Unexpected format in intel_alloc_renderbuffer_storage"); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    /* free old region */ | ||||
|    if (irb->region) { | ||||
|       /*LOCK_HARDWARE(intel); */ | ||||
|       intel_region_release(intel->intelScreen, &irb->region); | ||||
|       /*UNLOCK_HARDWARE(intel); */ | ||||
|    } | ||||
|  | ||||
|    /* allocate new memory region/renderbuffer */ | ||||
|    if (softwareBuffer) { | ||||
|       return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat, | ||||
|                                              width, height); | ||||
|    } | ||||
|    else { | ||||
|       /* Choose a pitch to match hardware requirements: | ||||
|        */ | ||||
|       GLuint pitch = ((cpp * width + 63) & ~63) / cpp; | ||||
|  | ||||
|       /* alloc hardware renderbuffer */ | ||||
|       DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width, | ||||
| 	  height, pitch); | ||||
|  | ||||
|       irb->region = intel_region_alloc(intel->intelScreen, cpp, pitch, height); | ||||
|       if (!irb->region) | ||||
|          return GL_FALSE;       /* out of memory? */ | ||||
|  | ||||
|       ASSERT(irb->region->buffer); | ||||
|  | ||||
|       rb->Width = width; | ||||
|       rb->Height = height; | ||||
|  | ||||
|       /* This sets the Get/PutRow/Value functions */ | ||||
|       intel_set_span_functions(&irb->Base); | ||||
|  | ||||
|       return GL_TRUE; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called for each hardware renderbuffer when a _window_ is resized. | ||||
|  * Just update fields. | ||||
|  * Not used for user-created renderbuffers! | ||||
|  */ | ||||
| static GLboolean | ||||
| intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb, | ||||
|                            GLenum internalFormat, GLuint width, GLuint height) | ||||
| { | ||||
|    ASSERT(rb->Name == 0); | ||||
|    rb->Width = width; | ||||
|    rb->Height = height; | ||||
|    rb->_ActualFormat = internalFormat; | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, | ||||
|                         GLenum internalFormat, GLuint width, GLuint height) | ||||
| { | ||||
|    _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Create a new intel_renderbuffer which corresponds to an on-screen window, | ||||
|  * not a user-created renderbuffer. | ||||
|  * \param width  the screen width | ||||
|  * \param height  the screen height | ||||
|  */ | ||||
| struct intel_renderbuffer * | ||||
| intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height, | ||||
|                           int offset, int pitch, int cpp, void *map) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|  | ||||
|    struct intel_renderbuffer *irb; | ||||
|    const GLuint name = 0; | ||||
|  | ||||
|    irb = CALLOC_STRUCT(intel_renderbuffer); | ||||
|    if (!irb) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    _mesa_init_renderbuffer(&irb->Base, name); | ||||
|    irb->Base.ClassID = INTEL_RB_CLASS; | ||||
|  | ||||
|    switch (intFormat) { | ||||
|    case GL_RGB5: | ||||
|       irb->Base._ActualFormat = GL_RGB5; | ||||
|       irb->Base._BaseFormat = GL_RGBA; | ||||
|       irb->Base.RedBits = 5; | ||||
|       irb->Base.GreenBits = 6; | ||||
|       irb->Base.BlueBits = 5; | ||||
|       irb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_RGBA8: | ||||
|       irb->Base._ActualFormat = GL_RGBA8; | ||||
|       irb->Base._BaseFormat = GL_RGBA; | ||||
|       irb->Base.RedBits = 8; | ||||
|       irb->Base.GreenBits = 8; | ||||
|       irb->Base.BlueBits = 8; | ||||
|       irb->Base.AlphaBits = 8; | ||||
|       irb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_STENCIL_INDEX8_EXT: | ||||
|       irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT; | ||||
|       irb->Base._BaseFormat = GL_STENCIL_INDEX; | ||||
|       irb->Base.StencilBits = 8; | ||||
|       irb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
|       cpp = 1; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|       irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_COMPONENT; | ||||
|       irb->Base.DepthBits = 16; | ||||
|       irb->Base.DataType = GL_UNSIGNED_SHORT; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|       irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_COMPONENT; | ||||
|       irb->Base.DepthBits = 24; | ||||
|       irb->Base.DataType = GL_UNSIGNED_INT; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_DEPTH24_STENCIL8_EXT: | ||||
|       irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; | ||||
|       irb->Base.DepthBits = 24; | ||||
|       irb->Base.StencilBits = 8; | ||||
|       irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    default: | ||||
|       _mesa_problem(NULL, | ||||
|                     "Unexpected intFormat in intel_create_renderbuffer"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    irb->Base.InternalFormat = intFormat; | ||||
|  | ||||
|    /* intel-specific methods */ | ||||
|    irb->Base.Delete = intel_delete_renderbuffer; | ||||
|    irb->Base.AllocStorage = intel_alloc_window_storage; | ||||
|    irb->Base.GetPointer = intel_get_pointer; | ||||
|    /* This sets the Get/PutRow/Value functions */ | ||||
|    intel_set_span_functions(&irb->Base); | ||||
|  | ||||
|    irb->pfMap = map; | ||||
|    irb->pfPitch = pitch / cpp;	/* in pixels */ | ||||
|  | ||||
| #if 00 | ||||
|    irb->region = intel_region_create_static(intel, | ||||
|                                             DRM_MM_TT, | ||||
|                                             offset, map, cpp, width, height); | ||||
| #endif | ||||
|  | ||||
|    return irb; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Create a new renderbuffer object. | ||||
|  * Typically called via glBindRenderbufferEXT(). | ||||
|  */ | ||||
| static struct gl_renderbuffer * | ||||
| intel_new_renderbuffer(GLcontext * ctx, GLuint name) | ||||
| { | ||||
|    /*struct intel_context *intel = intel_context(ctx); */ | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    irb = CALLOC_STRUCT(intel_renderbuffer); | ||||
|    if (!irb) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    _mesa_init_renderbuffer(&irb->Base, name); | ||||
|    irb->Base.ClassID = INTEL_RB_CLASS; | ||||
|  | ||||
|    /* intel-specific methods */ | ||||
|    irb->Base.Delete = intel_delete_renderbuffer; | ||||
|    irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; | ||||
|    irb->Base.GetPointer = intel_get_pointer; | ||||
|    /* span routines set in alloc_storage function */ | ||||
|  | ||||
|    return &irb->Base; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glBindFramebufferEXT(). | ||||
|  */ | ||||
| static void | ||||
| intel_bind_framebuffer(GLcontext * ctx, GLenum target, | ||||
|                        struct gl_framebuffer *fb) | ||||
| { | ||||
|    if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { | ||||
|       intel_draw_buffer(ctx, fb); | ||||
|       /* Integer depth range depends on depth buffer bits */ | ||||
|       ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); | ||||
|    } | ||||
|    else { | ||||
|       /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glFramebufferRenderbufferEXT(). | ||||
|  */ | ||||
| static void | ||||
| intel_framebuffer_renderbuffer(GLcontext * ctx, | ||||
|                                struct gl_framebuffer *fb, | ||||
|                                GLenum attachment, struct gl_renderbuffer *rb) | ||||
| { | ||||
|    DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); | ||||
|    intel_draw_buffer(ctx, fb); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * When glFramebufferTexture[123]D is called this function sets up the | ||||
|  * gl_renderbuffer wrapp around the texture image. | ||||
|  * This will have the region info needed for hardware rendering. | ||||
|  */ | ||||
| static struct intel_renderbuffer * | ||||
| intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage) | ||||
| { | ||||
|    const GLuint name = ~0;      /* not significant, but distinct for debugging */ | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    /* make an intel_renderbuffer to wrap the texture image */ | ||||
|    irb = CALLOC_STRUCT(intel_renderbuffer); | ||||
|    if (!irb) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    _mesa_init_renderbuffer(&irb->Base, name); | ||||
|    irb->Base.ClassID = INTEL_RB_CLASS; | ||||
|  | ||||
|    if (texImage->TexFormat == &_mesa_texformat_argb8888) { | ||||
|       irb->Base._ActualFormat = GL_RGBA8; | ||||
|       irb->Base._BaseFormat = GL_RGBA; | ||||
|       DBG("Render to RGBA8 texture OK\n"); | ||||
|    } | ||||
|    else if (texImage->TexFormat == &_mesa_texformat_rgb565) { | ||||
|       irb->Base._ActualFormat = GL_RGB5; | ||||
|       irb->Base._BaseFormat = GL_RGB; | ||||
|       DBG("Render to RGB5 texture OK\n"); | ||||
|    } | ||||
|    else if (texImage->TexFormat == &_mesa_texformat_z16) { | ||||
|       irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_COMPONENT; | ||||
|       DBG("Render to DEPTH16 texture OK\n"); | ||||
|    } | ||||
|    else { | ||||
|       DBG("Render to texture BAD FORMAT %d\n", | ||||
| 	  texImage->TexFormat->MesaFormat); | ||||
|       _mesa_free(irb); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    irb->Base.InternalFormat = irb->Base._ActualFormat; | ||||
|    irb->Base.Width = texImage->Width; | ||||
|    irb->Base.Height = texImage->Height; | ||||
|    irb->Base.DataType = GL_UNSIGNED_BYTE;       /* FBO XXX fix */ | ||||
|    irb->Base.RedBits = texImage->TexFormat->RedBits; | ||||
|    irb->Base.GreenBits = texImage->TexFormat->GreenBits; | ||||
|    irb->Base.BlueBits = texImage->TexFormat->BlueBits; | ||||
|    irb->Base.AlphaBits = texImage->TexFormat->AlphaBits; | ||||
|    irb->Base.DepthBits = texImage->TexFormat->DepthBits; | ||||
|  | ||||
|    irb->Base.Delete = intel_delete_renderbuffer; | ||||
|    irb->Base.AllocStorage = intel_nop_alloc_storage; | ||||
|    intel_set_span_functions(&irb->Base); | ||||
|  | ||||
|    irb->RenderToTexture = GL_TRUE; | ||||
|  | ||||
|    return irb; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called by glFramebufferTexture[123]DEXT() (and other places) to | ||||
|  * prepare for rendering into texture memory.  This might be called | ||||
|  * many times to choose different texture levels, cube faces, etc | ||||
|  * before intel_finish_render_texture() is ever called. | ||||
|  */ | ||||
| static void | ||||
| intel_render_texture(GLcontext * ctx, | ||||
|                      struct gl_framebuffer *fb, | ||||
|                      struct gl_renderbuffer_attachment *att) | ||||
| { | ||||
|    struct gl_texture_image *newImage | ||||
|       = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); | ||||
|    struct intel_texture_image *intel_image; | ||||
|    GLuint imageOffset; | ||||
|  | ||||
|    (void) fb; | ||||
|  | ||||
|    ASSERT(newImage); | ||||
|  | ||||
|    if (!irb) { | ||||
|       irb = intel_wrap_texture(ctx, newImage); | ||||
|       if (irb) { | ||||
|          /* bind the wrapper to the attachment point */ | ||||
|          att->Renderbuffer = &irb->Base; | ||||
|       } | ||||
|       else { | ||||
|          /* fallback to software rendering */ | ||||
|          _mesa_render_texture(ctx, fb, att); | ||||
|          return; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    DBG("Begin render texture tex=%u w=%d h=%d refcount=%d\n", | ||||
|        att->Texture->Name, newImage->Width, newImage->Height, | ||||
|        irb->Base.RefCount); | ||||
|  | ||||
|    /* point the renderbufer's region to the texture image region */ | ||||
|    intel_image = intel_texture_image(newImage); | ||||
|    if (irb->region != intel_image->mt->region) | ||||
|       intel_region_reference(&irb->region, intel_image->mt->region); | ||||
|  | ||||
|    /* compute offset of the particular 2D image within the texture region */ | ||||
|    imageOffset = intel_miptree_image_offset(intel_image->mt, | ||||
|                                             att->CubeMapFace, | ||||
|                                             att->TextureLevel); | ||||
|  | ||||
|    if (att->Texture->Target == GL_TEXTURE_3D) { | ||||
|       const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt, | ||||
|                                                           att->TextureLevel); | ||||
|       imageOffset += offsets[att->Zoffset]; | ||||
|    } | ||||
|  | ||||
|    /* store that offset in the region */ | ||||
|    intel_image->mt->region->draw_offset = imageOffset; | ||||
|  | ||||
|    /* update drawing region, etc */ | ||||
|    intel_draw_buffer(ctx, fb); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called by Mesa when rendering to a texture is done. | ||||
|  */ | ||||
| static void | ||||
| intel_finish_render_texture(GLcontext * ctx, | ||||
|                             struct gl_renderbuffer_attachment *att) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); | ||||
|  | ||||
|    DBG("End render texture (tid %u) tex %u\n", _glthread_GetID(), att->Texture->Name); | ||||
|  | ||||
|    if (irb) { | ||||
|       /* just release the region */ | ||||
|       intel_region_release(intel->intelScreen, &irb->region); | ||||
|    } | ||||
|    else if (att->Renderbuffer) { | ||||
|       /* software fallback */ | ||||
|       _mesa_finish_render_texture(ctx, att); | ||||
|       /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */ | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Do one-time context initializations related to GL_EXT_framebuffer_object. | ||||
|  * Hook in device driver functions. | ||||
|  */ | ||||
| void | ||||
| intel_fbo_init(struct intel_context *intel) | ||||
| { | ||||
|    intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; | ||||
|    intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; | ||||
|    intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; | ||||
|    intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; | ||||
|    intel->ctx.Driver.RenderTexture = intel_render_texture; | ||||
|    intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; | ||||
| } | ||||
							
								
								
									
										80
									
								
								src/mesa/drivers/dri/i915/intel_fbo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/mesa/drivers/dri/i915/intel_fbo.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_FBO_H | ||||
| #define INTEL_FBO_H | ||||
|  | ||||
|  | ||||
| struct intel_context; | ||||
| struct intel_region; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Intel renderbuffer, derived from gl_renderbuffer. | ||||
|  * Note: The PairedDepth and PairedStencil fields use renderbuffer IDs, | ||||
|  * not pointers because in some circumstances a deleted renderbuffer could | ||||
|  * result in a dangling pointer here. | ||||
|  */ | ||||
| struct intel_renderbuffer | ||||
| { | ||||
|    struct gl_renderbuffer Base; | ||||
|    struct intel_region *region; | ||||
|    void *pfMap;                 /* possibly paged flipped map pointer */ | ||||
|    GLuint pfPitch;              /* possibly paged flipped pitch */ | ||||
|    GLboolean RenderToTexture;   /* RTT? */ | ||||
|  | ||||
|    GLuint PairedDepth;   /**< only used if this is a depth renderbuffer */ | ||||
|    GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| extern struct intel_renderbuffer *intel_create_renderbuffer(GLenum intFormat, | ||||
|                                                             GLsizei width, | ||||
|                                                             GLsizei height, | ||||
|                                                             int offset, | ||||
|                                                             int pitch, | ||||
|                                                             int cpp, | ||||
|                                                             void *map); | ||||
|  | ||||
|  | ||||
| extern void intel_fbo_init(struct intel_context *intel); | ||||
|  | ||||
|  | ||||
| /* XXX make inline or macro */ | ||||
| extern struct intel_renderbuffer *intel_get_renderbuffer(struct gl_framebuffer | ||||
|                                                          *fb, | ||||
|                                                          GLuint attIndex); | ||||
|  | ||||
|  | ||||
| /* XXX make inline or macro */ | ||||
| extern struct intel_region *intel_get_rb_region(struct gl_framebuffer *fb, | ||||
|                                                 GLuint attIndex); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif /* INTEL_FBO_H */ | ||||
| @@ -38,22 +38,14 @@ | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_regions.h" | ||||
| #include "drm.h" | ||||
|  | ||||
| u_int32_t intelGetLastFrame (intelContextPtr intel)  | ||||
| { | ||||
|    int ret; | ||||
|    u_int32_t frame; | ||||
|    drm_i915_getparam_t gp; | ||||
| #define FILE_DEBUG_FLAG DEBUG_IOCTL | ||||
|  | ||||
|    gp.param = I915_PARAM_LAST_DISPATCH; | ||||
|    gp.value = (int *)&frame; | ||||
|    ret = drmCommandWriteRead( intel->driFd, DRM_I915_GETPARAM, | ||||
| 			      &gp, sizeof(gp) ); | ||||
|    return frame; | ||||
| } | ||||
|  | ||||
| int intelEmitIrqLocked( intelContextPtr intel ) | ||||
| int | ||||
| intelEmitIrqLocked(struct intel_context *intel) | ||||
| { | ||||
|    drmI830IrqEmit ie; | ||||
|    int ret, seq; | ||||
| @@ -70,591 +62,77 @@ int intelEmitIrqLocked( intelContextPtr intel ) | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s -->  %d\n", __FUNCTION__, seq ); | ||||
|    DBG("%s -->  %d\n", __FUNCTION__, seq); | ||||
|  | ||||
|    return seq; | ||||
| } | ||||
|  | ||||
| void intelWaitIrq( intelContextPtr intel, int seq ) | ||||
| void | ||||
| intelWaitIrq(struct intel_context *intel, int seq) | ||||
| { | ||||
|    int ret; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %d\n", __FUNCTION__, seq ); | ||||
|    DBG("%s %d\n", __FUNCTION__, seq); | ||||
|  | ||||
|    intel->iw.irq_seq = seq; | ||||
|  | ||||
|    do { | ||||
|      ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, sizeof(intel->iw) ); | ||||
|       ret = | ||||
|          drmCommandWrite(intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, | ||||
|                          sizeof(intel->iw)); | ||||
|    } while (ret == -EAGAIN || ret == -EINTR); | ||||
|  | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret); | ||||
|       if (0) | ||||
| 	 intel_dump_batchbuffer( intel->alloc.offset, | ||||
| 				 intel->alloc.ptr, | ||||
| 				 intel->alloc.size ); | ||||
|       exit(1); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void age_intel( intelContextPtr intel, int age ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) | ||||
|       if (intel->CurrentTexObj[i])  | ||||
| 	 intel->CurrentTexObj[i]->age = age; | ||||
| } | ||||
|  | ||||
| void intel_dump_batchbuffer( long offset, | ||||
| 			     int *ptr, | ||||
| 			     int count ) | ||||
| { | ||||
|    int i; | ||||
|    fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count); | ||||
|    for (i = 0; i < count/4; i += 4)  | ||||
|       fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",  | ||||
| 	      (unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); | ||||
|    fprintf(stderr, "END BATCH\n\n\n"); | ||||
| } | ||||
|  | ||||
| void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ) | ||||
| { | ||||
|    GLuint last_irq = intel->alloc.irq_emitted; | ||||
|    GLuint half = intel->alloc.size / 2; | ||||
|    GLuint buf = (intel->alloc.active_buf ^= 1); | ||||
|  | ||||
|    intel->alloc.irq_emitted = intelEmitIrqLocked( intel ); | ||||
|  | ||||
|    if (last_irq) { | ||||
|       if (allow_unlock) UNLOCK_HARDWARE( intel );  | ||||
|       intelWaitIrq( intel, last_irq ); | ||||
|       if (allow_unlock) LOCK_HARDWARE( intel );  | ||||
|    } | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf); | ||||
|  | ||||
|    intel->batch.start_offset = intel->alloc.offset + buf * half; | ||||
|    intel->batch.ptr = (unsigned char *)intel->alloc.ptr + buf * half; | ||||
|    intel->batch.size = half - 8; | ||||
|    intel->batch.space = half - 8; | ||||
|    assert(intel->batch.space >= 0); | ||||
| } | ||||
|  | ||||
| #define MI_BATCH_BUFFER_END 	(0xA<<23) | ||||
|  | ||||
|  | ||||
| void intelFlushBatchLocked( intelContextPtr intel,  | ||||
| 			    GLboolean ignore_cliprects, | ||||
| 			    GLboolean refill, | ||||
| 			    GLboolean allow_unlock) | ||||
| void | ||||
| intel_batch_ioctl(struct intel_context *intel, | ||||
|                   GLuint start_offset, | ||||
|                   GLuint used, | ||||
|                   GLboolean ignore_cliprects, GLboolean allow_unlock) | ||||
| { | ||||
|    drmI830BatchBuffer batch; | ||||
|  | ||||
|    assert(intel->locked); | ||||
|    assert(used); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s used %d of %d offset %x..%x refill %d (started in %s)\n", | ||||
|    DBG("%s used %d offset %x..%x ignore_cliprects %d\n", | ||||
|        __FUNCTION__, | ||||
| 	      (intel->batch.size - intel->batch.space),  | ||||
| 	      intel->batch.size, | ||||
| 	      intel->batch.start_offset, | ||||
| 	      intel->batch.start_offset +  | ||||
| 	      (intel->batch.size - intel->batch.space),  | ||||
| 	      refill, | ||||
| 	      intel->batch.func); | ||||
|        used, start_offset, start_offset + used, ignore_cliprects); | ||||
|  | ||||
|    /* Throw away non-effective packets.  Won't work once we have | ||||
|     * hardware contexts which would preserve statechanges beyond a | ||||
|     * single buffer. | ||||
|     */ | ||||
|    if (intel->numClipRects == 0 && !ignore_cliprects) { | ||||
|  | ||||
|       /* Without this yeild, an application with no cliprects can hog | ||||
|        * the hardware.  Without unlocking, the effect is much worse - | ||||
|        * effectively a lock-out of other contexts. | ||||
|        */ | ||||
|       if (allow_unlock) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 sched_yield(); | ||||
| 	 LOCK_HARDWARE( intel ); | ||||
|       } | ||||
|  | ||||
|       /* Note that any state thought to have been emitted actually | ||||
|        * hasn't: | ||||
|        */ | ||||
|       intel->batch.ptr -= (intel->batch.size - intel->batch.space); | ||||
|       intel->batch.space = intel->batch.size; | ||||
|       intel->vtbl.lost_hardware( intel );  | ||||
|    } | ||||
|  | ||||
|    if (intel->batch.space != intel->batch.size) { | ||||
|  | ||||
|       if (intel->sarea->ctxOwner != intel->hHWContext) { | ||||
| 	 intel->perf_boxes |= I830_BOX_LOST_CONTEXT; | ||||
| 	 intel->sarea->ctxOwner = intel->hHWContext; | ||||
|       } | ||||
|  | ||||
|       batch.start = intel->batch.start_offset; | ||||
|       batch.used = intel->batch.size - intel->batch.space; | ||||
|    batch.start = start_offset; | ||||
|    batch.used = used; | ||||
|    batch.cliprects = intel->pClipRects; | ||||
|    batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; | ||||
|    batch.DR1 = 0; | ||||
|    batch.DR4 = ((((GLuint) intel->drawX) & 0xffff) | | ||||
|                 (((GLuint) intel->drawY) << 16)); | ||||
|  | ||||
|       if (intel->alloc.offset) { | ||||
| 	 if ((batch.used & 0x4) == 0) { | ||||
| 	    ((int *)intel->batch.ptr)[0] = 0; | ||||
| 	    ((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END; | ||||
| 	    batch.used += 0x8; | ||||
| 	    intel->batch.ptr += 0x8; | ||||
| 	 } | ||||
| 	 else { | ||||
| 	    ((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END; | ||||
| 	    batch.used += 0x4; | ||||
| 	    intel->batch.ptr += 0x4; | ||||
| 	 }       | ||||
|       } | ||||
|    DBG("%s: 0x%x..0x%x DR4: %x cliprects: %d\n", | ||||
|        __FUNCTION__, | ||||
|        batch.start, | ||||
|        batch.start + batch.used * 4, batch.DR4, batch.num_cliprects); | ||||
|  | ||||
|       if (0) | ||||
|  	 intel_dump_batchbuffer( batch.start, | ||||
| 				 (int *)(intel->batch.ptr - batch.used), | ||||
| 				 batch.used ); | ||||
|  | ||||
|       intel->batch.start_offset += batch.used; | ||||
|       intel->batch.size -= batch.used; | ||||
|  | ||||
|       if (intel->batch.size < 8) { | ||||
| 	 refill = GL_TRUE; | ||||
| 	 intel->batch.space = intel->batch.size = 0; | ||||
|       } | ||||
|       else { | ||||
| 	 intel->batch.size -= 8; | ||||
| 	 intel->batch.space = intel->batch.size; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       assert(intel->batch.space >= 0); | ||||
|       assert(batch.start >= intel->alloc.offset); | ||||
|       assert(batch.start < intel->alloc.offset + intel->alloc.size); | ||||
|       assert(batch.start + batch.used > intel->alloc.offset); | ||||
|       assert(batch.start + batch.used <=  | ||||
| 	     intel->alloc.offset + intel->alloc.size); | ||||
|  | ||||
|  | ||||
|       if (intel->alloc.offset) { | ||||
|    if (drmCommandWrite(intel->driFd, DRM_I830_BATCHBUFFER, &batch, | ||||
|                        sizeof(batch))) { | ||||
|       fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       exit(1); | ||||
|    } | ||||
|       } else { | ||||
| 	 drmI830CmdBuffer cmd; | ||||
| 	 cmd.buf = (char *)intel->alloc.ptr + batch.start; | ||||
| 	 cmd.sz = batch.used; | ||||
| 	 cmd.DR1 = batch.DR1; | ||||
| 	 cmd.DR4 = batch.DR4; | ||||
| 	 cmd.num_cliprects = batch.num_cliprects; | ||||
| 	 cmd.cliprects = batch.cliprects; | ||||
| 	  | ||||
| 	 if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd,  | ||||
| 			      sizeof(cmd))) { | ||||
| 	    fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n",  -errno); | ||||
| 	    UNLOCK_HARDWARE(intel); | ||||
| 	    exit(1); | ||||
| 	 } | ||||
|       }	  | ||||
|  | ||||
|        | ||||
|       age_intel(intel, intel->sarea->last_enqueue); | ||||
|  | ||||
|    /* FIXME: use hardware contexts to avoid 'losing' hardware after | ||||
|     * each buffer flush. | ||||
|     */ | ||||
|       if (intel->batch.contains_geometry)  | ||||
| 	 assert(intel->batch.last_emit_state == intel->batch.counter); | ||||
|  | ||||
|       intel->batch.counter++; | ||||
|       intel->batch.contains_geometry = 0; | ||||
|       intel->batch.func = 0; | ||||
|    intel->vtbl.lost_hardware(intel); | ||||
| } | ||||
|  | ||||
|    if (refill) | ||||
|       intelRefillBatchLocked( intel, allow_unlock ); | ||||
| } | ||||
|  | ||||
| void intelFlushBatch( intelContextPtr intel, GLboolean refill ) | ||||
| { | ||||
|    if (intel->locked) { | ||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE ); | ||||
|    }  | ||||
|    else { | ||||
|       LOCK_HARDWARE(intel); | ||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE ); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelWaitForIdle( intelContextPtr intel ) | ||||
| {    | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intel->vtbl.emit_flush( intel ); | ||||
|    intelFlushBatch( intel, GL_TRUE ); | ||||
|  | ||||
|    /* Use an irq to wait for dma idle -- Need to track lost contexts | ||||
|     * to shortcircuit consecutive calls to this function: | ||||
|     */ | ||||
|    intelWaitIrq( intel, intel->alloc.irq_emitted ); | ||||
|    intel->alloc.irq_emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Check if we need to rotate/warp the front color buffer to the | ||||
|  * rotated screen.  We generally need to do this when we get a glFlush | ||||
|  * or glFinish after drawing to the front color buffer. | ||||
|  */ | ||||
| static void | ||||
| intelCheckFrontRotate(GLcontext *ctx) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) { | ||||
|       intelScreenPrivate *screen = intel->intelScreen; | ||||
|       if (screen->current_rotation != 0) { | ||||
|          __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|          intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * NOT directly called via glFlush. | ||||
|  */ | ||||
| void intelFlush( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|  | ||||
|    if (intel->Fallback) | ||||
|       _swrast_flush( ctx ); | ||||
|  | ||||
|    INTEL_FIREVERTICES( intel ); | ||||
|  | ||||
|    if (intel->batch.size != intel->batch.space) | ||||
|       intelFlushBatch( intel, GL_FALSE ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glFlush. | ||||
|  */ | ||||
| void intelglFlush( GLcontext *ctx ) | ||||
| { | ||||
|    intelFlush(ctx); | ||||
|    intelCheckFrontRotate(ctx); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelFinish( GLcontext *ctx  )  | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    intelFlush( ctx ); | ||||
|    intelWaitForIdle( intel ); | ||||
|    intelCheckFrontRotate(ctx); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 		GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); | ||||
|    GLbitfield tri_mask = 0; | ||||
|    GLbitfield blit_mask = 0; | ||||
|    GLbitfield swrast_mask = 0; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Take care of cliprects, which are handled differently for | ||||
|     * clears, etc. | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|  | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       blit_mask |= BUFFER_BIT_DEPTH; | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       if (!intel->hw_stencil) { | ||||
| 	 swrast_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|       else if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { | ||||
| 	 tri_mask |= BUFFER_BIT_STENCIL; | ||||
|       }  | ||||
|       else { | ||||
| 	 blit_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    swrast_mask |= (mask & BUFFER_BIT_ACCUM); | ||||
|  | ||||
|    if (blit_mask)  | ||||
|       intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch ); | ||||
|  | ||||
|    if (tri_mask)  | ||||
|       intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch); | ||||
|  | ||||
|    if (swrast_mask) | ||||
|       _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelRotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, | ||||
|                   GLuint srcBuffer) | ||||
| { | ||||
|    if (intel->vtbl.rotate_window) { | ||||
|       intel->vtbl.rotate_window(intel, dPriv, srcBuffer); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) | ||||
| { | ||||
|    int region_offset; | ||||
|    drmI830MemAlloc alloc; | ||||
|    int ret; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size); | ||||
|  | ||||
|    alloc.region = I830_MEM_REGION_AGP; | ||||
|    alloc.alignment = 0; | ||||
|    alloc.size = size; | ||||
|    alloc.region_offset = ®ion_offset; | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* Make sure the global heap is initialized | ||||
|     */ | ||||
|    if (intel->texture_heaps[0]) | ||||
|       driAgeTextures( intel->texture_heaps[0] ); | ||||
|  | ||||
|  | ||||
|    ret = drmCommandWriteRead( intel->driFd, | ||||
| 			      DRM_I830_ALLOC, | ||||
| 			      &alloc, sizeof(alloc)); | ||||
|     | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       return NULL; | ||||
|    } | ||||
|     | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size); | ||||
|  | ||||
|    /* Need to propogate this information (agp memory in use) to our | ||||
|     * local texture lru.  The kernel has already updated the global | ||||
|     * lru.  An alternative would have been to allocate memory the | ||||
|     * usual way and then notify the kernel to pin the allocation. | ||||
|     */ | ||||
|    if (intel->texture_heaps[0]) | ||||
|       driAgeTextures( intel->texture_heaps[0] ); | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel);    | ||||
|  | ||||
|    return (void *)((char *)intel->intelScreen->tex.map + region_offset); | ||||
| } | ||||
|  | ||||
| void intelFreeAGP( intelContextPtr intel, void *pointer ) | ||||
| { | ||||
|    int region_offset; | ||||
|    drmI830MemFree memfree; | ||||
|    int ret; | ||||
|  | ||||
|    region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map; | ||||
|  | ||||
|    if (region_offset < 0 ||  | ||||
|        region_offset > intel->intelScreen->tex.size) { | ||||
|       fprintf(stderr, "offset %d outside range 0..%d\n", region_offset, | ||||
| 	      intel->intelScreen->tex.size); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    memfree.region = I830_MEM_REGION_AGP; | ||||
|    memfree.region_offset = region_offset; | ||||
|     | ||||
|    ret = drmCommandWrite( intel->driFd, | ||||
| 			  DRM_I830_FREE, | ||||
| 			  &memfree, sizeof(memfree)); | ||||
|     | ||||
|    if (ret)  | ||||
|       fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret); | ||||
| } | ||||
|  | ||||
| /* This version of AllocateMemoryMESA allocates only agp memory, and | ||||
|  * only does so after the point at which the driver has been | ||||
|  * initialized. | ||||
|  * | ||||
|  * Theoretically a valid context isn't required.  However, in this | ||||
|  * implementation, it is, as I'm using the hardware lock to protect | ||||
|  * the kernel data structures, and the current context to get the | ||||
|  * device fd. | ||||
|  */ | ||||
| void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn, | ||||
| 			      GLsizei size, GLfloat readfreq, | ||||
| 			      GLfloat writefreq, GLfloat priority) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,  | ||||
| 	      writefreq, priority); | ||||
|  | ||||
|    if (getenv("INTEL_NO_ALLOC")) | ||||
|       return NULL; | ||||
|     | ||||
|    if (!ctx || INTEL_CONTEXT(ctx) == 0)  | ||||
|       return NULL; | ||||
|     | ||||
|    return intelAllocateAGP( INTEL_CONTEXT(ctx), size ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Called via glXFreeMemoryMESA() */ | ||||
| void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL)  | ||||
|       fprintf(stderr, "%s %p\n", __FUNCTION__, pointer); | ||||
|  | ||||
|    if (!ctx || INTEL_CONTEXT(ctx) == 0) { | ||||
|       fprintf(stderr, "%s: no context\n", __FUNCTION__); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    intelFreeAGP( INTEL_CONTEXT(ctx), pointer ); | ||||
| } | ||||
|  | ||||
| /* Called via glXGetMemoryOffsetMESA()  | ||||
|  * | ||||
|  * Returns offset of pointer from the start of agp aperture. | ||||
|  */ | ||||
| GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn,  | ||||
| 				const GLvoid *pointer) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    intelContextPtr intel; | ||||
|  | ||||
|    if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) { | ||||
|       fprintf(stderr, "%s: no context\n", __FUNCTION__); | ||||
|       return ~0; | ||||
|    } | ||||
|  | ||||
|    if (!intelIsAgpMemory( intel, pointer, 0 )) | ||||
|       return ~0; | ||||
|  | ||||
|    return intelAgpOffsetFromVirtual( intel, pointer ); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, | ||||
| 			   GLint size ) | ||||
| { | ||||
|    int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; | ||||
|    int valid = (size >= 0 && | ||||
| 		offset >= 0 && | ||||
| 		offset + size < intel->intelScreen->tex.size); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid ); | ||||
|     | ||||
|    return valid; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer ) | ||||
| { | ||||
|    int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; | ||||
|  | ||||
|    if (offset < 0 || offset > intel->intelScreen->tex.size) | ||||
|       return ~0; | ||||
|    else | ||||
|       return intel->intelScreen->tex.offset + offset; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Flip the front & back buffes | ||||
|  */ | ||||
| void intelPageFlip( const __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
| #if 0 | ||||
|    intelContextPtr intel; | ||||
|    int tmp, ret; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|  | ||||
|    intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (dPriv->pClipRects) { | ||||
|       *(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0]; | ||||
|       intel->sarea->nbox = 1; | ||||
|    } | ||||
|  | ||||
|    ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);  | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    tmp = intel->sarea->last_enqueue; | ||||
|    intelRefillBatchLocked( intel ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|  | ||||
|    intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer ); | ||||
| #endif | ||||
| } | ||||
|   | ||||
| @@ -30,44 +30,11 @@ | ||||
|  | ||||
| #include "intel_context.h" | ||||
|  | ||||
| extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock ); | ||||
| void intelWaitIrq(struct intel_context *intel, int seq); | ||||
| int intelEmitIrqLocked(struct intel_context *intel); | ||||
|  | ||||
| extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 		       GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelPageFlip( const __DRIdrawablePrivate *dpriv ); | ||||
|  | ||||
| extern void intelRotateWindow(intelContextPtr intel, | ||||
|                               __DRIdrawablePrivate *dPriv, GLuint srcBuffer); | ||||
|  | ||||
| extern void intelWaitForIdle( intelContextPtr intel ); | ||||
| extern void intelFlushBatch( intelContextPtr intel, GLboolean refill ); | ||||
| extern void intelFlushBatchLocked( intelContextPtr intel, | ||||
| 				   GLboolean ignore_cliprects, | ||||
| 				   GLboolean refill, | ||||
| 				   GLboolean allow_unlock); | ||||
| extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ); | ||||
| extern void intelFinish( GLcontext *ctx ); | ||||
| extern void intelFlush( GLcontext *ctx ); | ||||
| extern void intelglFlush( GLcontext *ctx ); | ||||
|  | ||||
| extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size ); | ||||
| extern void intelFreeAGP( intelContextPtr intel, void *pointer ); | ||||
|  | ||||
| extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn,  | ||||
| 				      GLsizei size, GLfloat readfreq, | ||||
| 				      GLfloat writefreq, GLfloat priority ); | ||||
|  | ||||
| extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn,  | ||||
| 				 GLvoid *pointer ); | ||||
|  | ||||
| extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer ); | ||||
| extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, | ||||
| 				  GLint size ); | ||||
|  | ||||
| extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p ); | ||||
|  | ||||
| extern void intelWaitIrq( intelContextPtr intel, int seq ); | ||||
| extern u_int32_t intelGetLastFrame (intelContextPtr intel); | ||||
| extern int intelEmitIrqLocked( intelContextPtr intel ); | ||||
| void intel_batch_ioctl(struct intel_context *intel, | ||||
|                        GLuint start_offset, | ||||
|                        GLuint used, | ||||
|                        GLboolean ignore_cliprects, GLboolean allow_unlock); | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										341
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										341
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,341 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_MIPTREE | ||||
|  | ||||
| static GLenum | ||||
| target_to_target(GLenum target) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: | ||||
|       return GL_TEXTURE_CUBE_MAP_ARB; | ||||
|    default: | ||||
|       return target; | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct intel_mipmap_tree * | ||||
| intel_miptree_create(struct intel_context *intel, | ||||
|                      GLenum target, | ||||
|                      GLenum internal_format, | ||||
|                      GLuint first_level, | ||||
|                      GLuint last_level, | ||||
|                      GLuint width0, | ||||
|                      GLuint height0, | ||||
|                      GLuint depth0, GLuint cpp, GLboolean compressed) | ||||
| { | ||||
|    GLboolean ok; | ||||
|    struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); | ||||
|  | ||||
|    DBG("%s target %s format %s level %d..%d\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(target), | ||||
|        _mesa_lookup_enum_by_nr(internal_format), first_level, last_level); | ||||
|  | ||||
|    mt->target = target_to_target(target); | ||||
|    mt->internal_format = internal_format; | ||||
|    mt->first_level = first_level; | ||||
|    mt->last_level = last_level; | ||||
|    mt->width0 = width0; | ||||
|    mt->height0 = height0; | ||||
|    mt->depth0 = depth0; | ||||
|    mt->cpp = compressed ? 2 : cpp; | ||||
|    mt->compressed = compressed; | ||||
|    mt->refcount = 0; /*Allow for unused miptrees */ | ||||
|  | ||||
|    switch (intel->intelScreen->deviceID) { | ||||
|    case PCI_CHIP_I945_G: | ||||
|    case PCI_CHIP_I945_GM: | ||||
|       ok = i945_miptree_layout(mt); | ||||
|       break; | ||||
|    case PCI_CHIP_I915_G: | ||||
|    case PCI_CHIP_I915_GM: | ||||
|    case PCI_CHIP_I830_M: | ||||
|    case PCI_CHIP_I855_GM: | ||||
|    case PCI_CHIP_I865_G: | ||||
|    default: | ||||
|       /* All the i830 chips and the i915 use this layout: | ||||
|        */ | ||||
|       ok = i915_miptree_layout(mt); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    if (ok) | ||||
|       mt->region = intel_region_alloc(intel->intelScreen, | ||||
|                                       mt->cpp, mt->pitch, mt->total_height); | ||||
|  | ||||
|    if (!mt->region) { | ||||
|       free(mt); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return mt; | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intel_miptree_reference(struct intel_mipmap_tree **dst, | ||||
|                         struct intel_mipmap_tree *src) | ||||
| { | ||||
|    src->refcount++; | ||||
|    *dst = src; | ||||
|    DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount); | ||||
| } | ||||
|  | ||||
| void | ||||
| intel_miptree_release(struct intel_context *intel, | ||||
|                       struct intel_mipmap_tree **mt) | ||||
| { | ||||
|    if (!*mt) | ||||
|       return; | ||||
|  | ||||
|    DBG("%s %p refcount will be %d\n", __FUNCTION__, *mt, (*mt)->refcount - 1); | ||||
|    if (--(*mt)->refcount <= 0) { | ||||
|       GLuint i; | ||||
|  | ||||
|       DBG("%s deleting %p\n", __FUNCTION__, *mt); | ||||
|  | ||||
|       intel_region_release(intel->intelScreen, &((*mt)->region)); | ||||
|  | ||||
|       for (i = 0; i < MAX_TEXTURE_LEVELS; i++) | ||||
|          if ((*mt)->level[i].image_offset) | ||||
|             free((*mt)->level[i].image_offset); | ||||
|  | ||||
|       free(*mt); | ||||
|    } | ||||
|    *mt = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Can the image be pulled into a unified mipmap tree.  This mirrors | ||||
|  * the completeness test in a lot of ways. | ||||
|  * | ||||
|  * Not sure whether I want to pass gl_texture_image here. | ||||
|  */ | ||||
| GLboolean | ||||
| intel_miptree_match_image(struct intel_mipmap_tree *mt, | ||||
|                           struct gl_texture_image *image, | ||||
|                           GLuint face, GLuint level) | ||||
| { | ||||
|    /* Images with borders are never pulled into mipmap trees.  | ||||
|     */ | ||||
|    if (image->Border)  | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (image->InternalFormat != mt->internal_format || | ||||
|        image->IsCompressed != mt->compressed) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    /* Test image dimensions against the base level image adjusted for | ||||
|     * minification.  This will also catch images not present in the | ||||
|     * tree, changed targets, etc. | ||||
|     */ | ||||
|    if (image->Width != mt->level[level].width || | ||||
|        image->Height != mt->level[level].height || | ||||
|        image->Depth != mt->level[level].depth) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intel_miptree_set_level_info(struct intel_mipmap_tree *mt, | ||||
|                              GLuint level, | ||||
|                              GLuint nr_images, | ||||
|                              GLuint x, GLuint y, GLuint w, GLuint h, GLuint d) | ||||
| { | ||||
|  | ||||
|    mt->level[level].width = w; | ||||
|    mt->level[level].height = h; | ||||
|    mt->level[level].depth = d; | ||||
|    mt->level[level].level_offset = (x + y * mt->pitch) * mt->cpp; | ||||
|    mt->level[level].nr_images = nr_images; | ||||
|  | ||||
|    DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, | ||||
|        level, w, h, d, x, y, mt->level[level].level_offset); | ||||
|  | ||||
|    /* Not sure when this would happen, but anyway:  | ||||
|     */ | ||||
|    if (mt->level[level].image_offset) { | ||||
|       free(mt->level[level].image_offset); | ||||
|       mt->level[level].image_offset = NULL; | ||||
|    } | ||||
|  | ||||
|    assert(nr_images); | ||||
|  | ||||
|    mt->level[level].image_offset = malloc(nr_images * sizeof(GLuint)); | ||||
|    mt->level[level].image_offset[0] = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, | ||||
|                                GLuint level, GLuint img, GLuint x, GLuint y) | ||||
| { | ||||
|    if (img == 0 && level == 0) | ||||
|       assert(x == 0 && y == 0); | ||||
|  | ||||
|    assert(img < mt->level[level].nr_images); | ||||
|  | ||||
|    mt->level[level].image_offset[img] = (x + y * mt->pitch); | ||||
|  | ||||
|    DBG("%s level %d img %d pos %d,%d image_offset %x\n", | ||||
|        __FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Although we use the image_offset[] array to store relative offsets | ||||
|  * to cube faces, Mesa doesn't know anything about this and expects | ||||
|  * each cube face to be treated as a separate image. | ||||
|  * | ||||
|  * These functions present that view to mesa: | ||||
|  */ | ||||
| const GLuint * | ||||
| intel_miptree_depth_offsets(struct intel_mipmap_tree *mt, GLuint level) | ||||
| { | ||||
|    static const GLuint zero = 0; | ||||
|  | ||||
|    if (mt->target != GL_TEXTURE_3D || mt->level[level].nr_images == 1) | ||||
|       return &zero; | ||||
|    else | ||||
|       return mt->level[level].image_offset; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint | ||||
| intel_miptree_image_offset(struct intel_mipmap_tree * mt, | ||||
|                            GLuint face, GLuint level) | ||||
| { | ||||
|    if (mt->target == GL_TEXTURE_CUBE_MAP_ARB) | ||||
|       return (mt->level[level].level_offset + | ||||
|               mt->level[level].image_offset[face] * mt->cpp); | ||||
|    else | ||||
|       return mt->level[level].level_offset; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Map a teximage in a mipmap tree. | ||||
|  * \param row_stride  returns row stride in bytes | ||||
|  * \param image_stride  returns image stride in bytes (for 3D textures). | ||||
|  * \return address of mapping | ||||
|  */ | ||||
| GLubyte * | ||||
| intel_miptree_image_map(struct intel_context * intel, | ||||
|                         struct intel_mipmap_tree * mt, | ||||
|                         GLuint face, | ||||
|                         GLuint level, | ||||
|                         GLuint * row_stride, GLuint * image_offsets) | ||||
| { | ||||
|    DBG("%s \n", __FUNCTION__); | ||||
|  | ||||
|    if (row_stride) | ||||
|       *row_stride = mt->pitch * mt->cpp; | ||||
|  | ||||
|    if (image_offsets) | ||||
|       memcpy(image_offsets, mt->level[level].image_offset, | ||||
|              mt->level[level].depth * sizeof(GLuint)); | ||||
|  | ||||
|    return (intel_region_map(intel->intelScreen, mt->region) + | ||||
|            intel_miptree_image_offset(mt, face, level)); | ||||
| } | ||||
|  | ||||
| void | ||||
| intel_miptree_image_unmap(struct intel_context *intel, | ||||
|                           struct intel_mipmap_tree *mt) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    intel_region_unmap(intel->intelScreen, mt->region); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload data for a particular image. | ||||
|  */ | ||||
| void | ||||
| intel_miptree_image_data(struct intel_context *intel, | ||||
|                          struct intel_mipmap_tree *dst, | ||||
|                          GLuint face, | ||||
|                          GLuint level, | ||||
|                          void *src, | ||||
|                          GLuint src_row_pitch, GLuint src_image_pitch) | ||||
| { | ||||
|    GLuint depth = dst->level[level].depth; | ||||
|    GLuint dst_offset = intel_miptree_image_offset(dst, face, level); | ||||
|    const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level); | ||||
|    GLuint i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    for (i = 0; i < depth; i++) { | ||||
|       intel_region_data(intel->intelScreen, dst->region, dst_offset + dst_depth_offset[i], 0, 0, src, src_row_pitch, 0, 0,   /* source x,y */ | ||||
|                         dst->level[level].width, dst->level[level].height); | ||||
|  | ||||
|       src += src_image_pitch; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /* Copy mipmap image between trees | ||||
|  */ | ||||
| void | ||||
| intel_miptree_image_copy(struct intel_context *intel, | ||||
|                          struct intel_mipmap_tree *dst, | ||||
|                          GLuint face, GLuint level, | ||||
|                          struct intel_mipmap_tree *src) | ||||
| { | ||||
|    GLuint width = src->level[level].width; | ||||
|    GLuint height = src->level[level].height; | ||||
|    GLuint depth = src->level[level].depth; | ||||
|    GLuint dst_offset = intel_miptree_image_offset(dst, face, level); | ||||
|    GLuint src_offset = intel_miptree_image_offset(src, face, level); | ||||
|    const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level); | ||||
|    const GLuint *src_depth_offset = intel_miptree_depth_offsets(src, level); | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0; i < depth; i++) { | ||||
|       intel_region_copy(intel->intelScreen, | ||||
|                         dst->region, dst_offset + dst_depth_offset[i], | ||||
|                         0, | ||||
|                         0, | ||||
|                         src->region, src_offset + src_depth_offset[i], | ||||
|                         0, 0, width, height); | ||||
|    } | ||||
|  | ||||
| } | ||||
							
								
								
									
										198
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,198 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_MIPMAP_TREE_H | ||||
| #define INTEL_MIPMAP_TREE_H | ||||
|  | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| /* A layer on top of the intel_regions code which adds: | ||||
|  * | ||||
|  * - Code to size and layout a region to hold a set of mipmaps. | ||||
|  * - Query to determine if a new image fits in an existing tree. | ||||
|  * - More refcounting  | ||||
|  *     - maybe able to remove refcounting from intel_region? | ||||
|  * - ? | ||||
|  * | ||||
|  * The fixed mipmap layout of intel hardware where one offset | ||||
|  * specifies the position of all images in a mipmap hierachy | ||||
|  * complicates the implementation of GL texture image commands, | ||||
|  * compared to hardware where each image is specified with an | ||||
|  * independent offset. | ||||
|  * | ||||
|  * In an ideal world, each texture object would be associated with a | ||||
|  * single bufmgr buffer or 2d intel_region, and all the images within | ||||
|  * the texture object would slot into the tree as they arrive.  The | ||||
|  * reality can be a little messier, as images can arrive from the user | ||||
|  * with sizes that don't fit in the existing tree, or in an order | ||||
|  * where the tree layout cannot be guessed immediately.   | ||||
|  *  | ||||
|  * This structure encodes an idealized mipmap tree.  The GL image | ||||
|  * commands build these where possible, otherwise store the images in | ||||
|  * temporary system buffers. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Describes the location of each texture image within a texture region. | ||||
|  */ | ||||
| struct intel_mipmap_level | ||||
| { | ||||
|    GLuint level_offset; | ||||
|    GLuint width; | ||||
|    GLuint height; | ||||
|    GLuint depth; | ||||
|    GLuint nr_images; | ||||
|  | ||||
|    /* Explicitly store the offset of each image for each cube face or | ||||
|     * depth value.  Pretty much have to accept that hardware formats | ||||
|     * are going to be so diverse that there is no unified way to | ||||
|     * compute the offsets of depth/cube images within a mipmap level, | ||||
|     * so have to store them as a lookup table: | ||||
|     */ | ||||
|    GLuint *image_offset; | ||||
| }; | ||||
|  | ||||
| struct intel_mipmap_tree | ||||
| { | ||||
|    /* Effectively the key: | ||||
|     */ | ||||
|    GLenum target; | ||||
|    GLenum internal_format; | ||||
|  | ||||
|    GLuint first_level; | ||||
|    GLuint last_level; | ||||
|  | ||||
|    GLuint width0, height0, depth0; /**< Level zero image dimensions */ | ||||
|    GLuint cpp; | ||||
|    GLboolean compressed; | ||||
|  | ||||
|    /* Derived from the above: | ||||
|     */ | ||||
|    GLuint pitch; | ||||
|    GLuint depth_pitch;          /* per-image on i945? */ | ||||
|    GLuint total_height; | ||||
|  | ||||
|    /* Includes image offset tables: | ||||
|     */ | ||||
|    struct intel_mipmap_level level[MAX_TEXTURE_LEVELS]; | ||||
|  | ||||
|    /* The data is held here: | ||||
|     */ | ||||
|    struct intel_region *region; | ||||
|  | ||||
|    /* These are also refcounted: | ||||
|     */ | ||||
|    GLuint refcount; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel, | ||||
|                                                GLenum target, | ||||
|                                                GLenum internal_format, | ||||
|                                                GLuint first_level, | ||||
|                                                GLuint last_level, | ||||
|                                                GLuint width0, | ||||
|                                                GLuint height0, | ||||
|                                                GLuint depth0, | ||||
|                                                GLuint cpp, | ||||
|                                                GLboolean compressed); | ||||
|  | ||||
| void intel_miptree_reference(struct intel_mipmap_tree **dst, | ||||
|                              struct intel_mipmap_tree *src); | ||||
|  | ||||
| void intel_miptree_release(struct intel_context *intel, | ||||
|                            struct intel_mipmap_tree **mt); | ||||
|  | ||||
| /* Check if an image fits an existing mipmap tree layout | ||||
|  */ | ||||
| GLboolean intel_miptree_match_image(struct intel_mipmap_tree *mt, | ||||
|                                     struct gl_texture_image *image, | ||||
|                                     GLuint face, GLuint level); | ||||
|  | ||||
| /* Return a pointer to an image within a tree.  Return image stride as | ||||
|  * well. | ||||
|  */ | ||||
| GLubyte *intel_miptree_image_map(struct intel_context *intel, | ||||
|                                  struct intel_mipmap_tree *mt, | ||||
|                                  GLuint face, | ||||
|                                  GLuint level, | ||||
|                                  GLuint * row_stride, GLuint * image_stride); | ||||
|  | ||||
| void intel_miptree_image_unmap(struct intel_context *intel, | ||||
|                                struct intel_mipmap_tree *mt); | ||||
|  | ||||
|  | ||||
| /* Return the linear offset of an image relative to the start of the | ||||
|  * tree: | ||||
|  */ | ||||
| GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt, | ||||
|                                   GLuint face, GLuint level); | ||||
|  | ||||
| /* Return pointers to each 2d slice within an image.  Indexed by depth | ||||
|  * value. | ||||
|  */ | ||||
| const GLuint *intel_miptree_depth_offsets(struct intel_mipmap_tree *mt, | ||||
|                                           GLuint level); | ||||
|  | ||||
|  | ||||
| void intel_miptree_set_level_info(struct intel_mipmap_tree *mt, | ||||
|                                   GLuint level, | ||||
|                                   GLuint nr_images, | ||||
|                                   GLuint x, GLuint y, | ||||
|                                   GLuint w, GLuint h, GLuint d); | ||||
|  | ||||
| void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, | ||||
|                                     GLuint level, | ||||
|                                     GLuint img, GLuint x, GLuint y); | ||||
|  | ||||
|  | ||||
| /* Upload an image into a tree | ||||
|  */ | ||||
| void intel_miptree_image_data(struct intel_context *intel, | ||||
|                               struct intel_mipmap_tree *dst, | ||||
|                               GLuint face, | ||||
|                               GLuint level, | ||||
|                               void *src, | ||||
|                               GLuint src_row_pitch, GLuint src_image_pitch); | ||||
|  | ||||
| /* Copy an image between two trees | ||||
|  */ | ||||
| void intel_miptree_image_copy(struct intel_context *intel, | ||||
|                               struct intel_mipmap_tree *dst, | ||||
|                               GLuint face, GLuint level, | ||||
|                               struct intel_mipmap_tree *src); | ||||
|  | ||||
| /* i915_mipmap_tree.c: | ||||
|  */ | ||||
| GLboolean i915_miptree_layout(struct intel_mipmap_tree *mt); | ||||
| GLboolean i945_miptree_layout(struct intel_mipmap_tree *mt); | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -1,6 +1,6 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
| @@ -12,7 +12,7 @@ | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * next paragraph) shall be included in all copies or substantial portionsalloc | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
| @@ -25,58 +25,29 @@ | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "state.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| check_color( const GLcontext *ctx, GLenum type, GLenum format, | ||||
| 	     const struct gl_pixelstore_attrib *packing, | ||||
| 	     const void *pixels, GLint sz, GLint pitch ) | ||||
| /** | ||||
|  * Check if any fragment operations are in effect which might effect | ||||
|  * glDraw/CopyPixels. | ||||
|  */ | ||||
| GLboolean | ||||
| intel_check_blit_fragment_ops(GLcontext * ctx) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLuint cpp = intel->intelScreen->cpp; | ||||
|    if (ctx->NewState) | ||||
|       _mesa_update_state(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (	(pitch & 63) || | ||||
| 	ctx->_ImageTransferState || | ||||
| 	packing->SwapBytes || | ||||
| 	packing->LsbFirst) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: failed 1\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&  | ||||
| 	cpp == 4 &&  | ||||
| 	format == GL_BGRA ) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: passed 2\n", __FUNCTION__); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s: failed\n", __FUNCTION__); | ||||
|  | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
| static GLboolean | ||||
| check_color_per_fragment_ops( const GLcontext *ctx ) | ||||
| { | ||||
|    int result; | ||||
|    result = (!(     ctx->Color.AlphaEnabled ||  | ||||
|    /* XXX Note: Scissor could be done with the blitter: | ||||
|     */ | ||||
|    return !(ctx->_ImageTransferState || | ||||
|             ctx->Color.AlphaEnabled || | ||||
|             ctx->Depth.Test || | ||||
|             ctx->Fog.Enabled || | ||||
|             ctx->Scissor.Enabled || | ||||
| @@ -86,426 +57,63 @@ check_color_per_fragment_ops( const GLcontext *ctx ) | ||||
|             !ctx->Color.ColorMask[2] || | ||||
|             !ctx->Color.ColorMask[3] || | ||||
|             ctx->Color.ColorLogicOpEnabled || | ||||
| 		    ctx->Texture._EnabledUnits | ||||
|            ) && | ||||
| 	   ctx->Current.RasterPosValid); | ||||
|     | ||||
|    return result; | ||||
|             ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Clip the given rectangle against the buffer's bounds (including scissor). | ||||
|  * \param size returns the  | ||||
|  * \return GL_TRUE if any pixels remain, GL_FALSE if totally clipped. | ||||
| GLboolean | ||||
| intel_check_meta_tex_fragment_ops(GLcontext * ctx) | ||||
| { | ||||
|    if (ctx->NewState) | ||||
|       _mesa_update_state(ctx); | ||||
|  | ||||
|    /* Some of _ImageTransferState (scale, bias) could be done with | ||||
|     * fragment programs on i915. | ||||
|     */ | ||||
|    return !(ctx->_ImageTransferState || ctx->Fog.Enabled ||     /* not done yet */ | ||||
|             ctx->Texture._EnabledUnits || ctx->FragmentProgram._Enabled); | ||||
| } | ||||
|  | ||||
| /* The intel_region struct doesn't really do enough to capture the | ||||
|  * format of the pixels in the region.  For now this code assumes that | ||||
|  * the region is a display surface and hence is either ARGB8888 or | ||||
|  * RGB565. | ||||
|  * XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd | ||||
|  * know the buffer's pixel format. | ||||
|  * | ||||
|  * XXX Replace this with _mesa_clip_drawpixels() and _mesa_clip_readpixels() | ||||
|  * from Mesa 6.4.  We shouldn't apply scissor for ReadPixels. | ||||
|  * \param format  as given to glDraw/ReadPixels | ||||
|  * \param type  as given to glDraw/ReadPixels | ||||
|  */ | ||||
| static GLboolean | ||||
| clip_pixelrect( const GLcontext *ctx, | ||||
| 		const GLframebuffer *buffer, | ||||
| 		GLint *x, GLint *y, | ||||
| 		GLsizei *width, GLsizei *height) | ||||
| GLboolean | ||||
| intel_check_blit_format(struct intel_region * region, | ||||
|                         GLenum format, GLenum type) | ||||
| { | ||||
|    /* left clipping */ | ||||
|    if (*x < buffer->_Xmin) { | ||||
|       *width -= (buffer->_Xmin - *x); | ||||
|       *x = buffer->_Xmin; | ||||
|    } | ||||
|  | ||||
|    /* right clipping */ | ||||
|    if (*x + *width > buffer->_Xmax) | ||||
|       *width -= (*x + *width - buffer->_Xmax - 1); | ||||
|  | ||||
|    if (*width <= 0) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    /* bottom clipping */ | ||||
|    if (*y < buffer->_Ymin) { | ||||
|       *height -= (buffer->_Ymin - *y); | ||||
|       *y = buffer->_Ymin; | ||||
|    } | ||||
|  | ||||
|    /* top clipping */ | ||||
|    if (*y + *height > buffer->_Ymax) | ||||
|       *height -= (*y + *height - buffer->_Ymax - 1); | ||||
|  | ||||
|    if (*height <= 0) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (region->cpp == 4 && | ||||
|        (type == GL_UNSIGNED_INT_8_8_8_8_REV || | ||||
|         type == GL_UNSIGNED_BYTE) && format == GL_BGRA) { | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Compute intersection of a clipping rectangle and pixel rectangle, | ||||
|  * returning results in x/y/w/hOut vars. | ||||
|  * \return GL_TRUE if there's intersection, GL_FALSE if disjoint. | ||||
|  */ | ||||
| static INLINE GLboolean | ||||
| intersect_region(const drm_clip_rect_t *box, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLint *xOut, GLint *yOut, GLint *wOut, GLint *hOut) | ||||
| { | ||||
|    GLint bx = box->x1; | ||||
|    GLint by = box->y1; | ||||
|    GLint bw = box->x2 - bx; | ||||
|    GLint bh = box->y2 - by; | ||||
|  | ||||
|    if (bx < x) bw -= x - bx, bx = x; | ||||
|    if (by < y) bh -= y - by, by = y; | ||||
|    if (bx + bw > x + width) bw = x + width - bx; | ||||
|    if (by + bh > y + height) bh = y + height - by; | ||||
|  | ||||
|    *xOut = bx; | ||||
|    *yOut = by; | ||||
|    *wOut = bw; | ||||
|    *hOut = bh; | ||||
|  | ||||
|    if (bw <= 0) return GL_FALSE; | ||||
|    if (bh <= 0) return GL_FALSE; | ||||
|  | ||||
|    if (region->cpp == 2 && | ||||
|        type == GL_UNSIGNED_SHORT_5_6_5_REV && format == GL_BGR) { | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intelTryReadPixels( GLcontext *ctx, | ||||
| 		  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		  GLenum format, GLenum type, | ||||
| 		  const struct gl_pixelstore_attrib *pack, | ||||
| 		  GLvoid *pixels ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLint size = 0; /* not really used */ | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Only accelerate reading to agp buffers. | ||||
|     */ | ||||
|    if ( !intelIsAgpMemory(intel, pixels,  | ||||
| 			pitch * height * intel->intelScreen->cpp ) ) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from | ||||
|     * blitter: | ||||
|     */ | ||||
|    if (!pack->Invert) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (!check_color(ctx, type, format, pack, pixels, size, pitch)) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    switch ( intel->intelScreen->cpp ) { | ||||
|    case 4: | ||||
|       break; | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* Although the blits go on the command buffer, need to do this and | ||||
|     * fire with lock held to guarentee cliprects and drawing offset are | ||||
|     * correct. | ||||
|     * | ||||
|     * This is an unusual situation however, as the code which flushes | ||||
|     * a full command buffer expects to be called unlocked.  As a | ||||
|     * workaround, immediately flush the buffer on aquiring the lock. | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       int src_offset = intel->readRegion->offset; | ||||
|       int src_pitch = intel->intelScreen->front.pitch; | ||||
|       int dst_offset = intelAgpOffsetFromVirtual( intel, pixels); | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       int i; | ||||
|  | ||||
|       assert(dst_offset != ~0);  /* should have been caught above */ | ||||
|  | ||||
|       if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s totally clipped -- nothing to do\n", | ||||
| 		    __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
|       /* convert to screen coords (y=0=top) */ | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", | ||||
| 		 src_pitch, pitch); | ||||
|  | ||||
|       /* We don't really have to do window clipping for readpixels. | ||||
|        * The OpenGL spec says that pixels read from outside the | ||||
|        * visible window region (pixel ownership) have undefined value. | ||||
|        */ | ||||
|       for (i = 0 ; i < nbox ; i++) | ||||
|       { | ||||
|          GLint bx, by, bw, bh; | ||||
|          if (intersect_region(box+i, x, y, width, height, | ||||
|                               &bx, &by, &bw, &bh)) { | ||||
|             intelEmitCopyBlitLocked( intel, | ||||
|                                      intel->intelScreen->cpp, | ||||
|                                      src_pitch, src_offset, | ||||
|                                      pitch, dst_offset, | ||||
|                                      bx, by, | ||||
|                                      bx - x, by - y, | ||||
|                                      bw, bh ); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( &intel->ctx ); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| intelReadPixels( GLcontext *ctx, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLenum format, GLenum type, | ||||
| 		 const struct gl_pixelstore_attrib *pack, | ||||
| 		 GLvoid *pixels ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,  | ||||
|                             pixels)) | ||||
|       _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,  | ||||
| 			  pixels); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void do_draw_pix( GLcontext *ctx, | ||||
| 			 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			 GLint pitch, | ||||
| 			 const void *pixels, | ||||
| 			 GLuint dest ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|    int nbox = dPriv->numClipRects; | ||||
|    int i; | ||||
|    int src_offset = intelAgpOffsetFromVirtual( intel, pixels); | ||||
|    int src_pitch = pitch; | ||||
|  | ||||
|    assert(src_offset != ~0);  /* should be caught earlier */ | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    if (ctx->DrawBuffer) | ||||
|    { | ||||
|       y -= height;			/* cope with pixel zoom */ | ||||
|     | ||||
|       if (!clip_pixelrect(ctx, ctx->DrawBuffer, | ||||
| 			  &x, &y, &width, &height)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 return; | ||||
|       } | ||||
|  | ||||
|       y = dPriv->h - y - height; 	/* convert from gl to hardware coords */ | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++ ) | ||||
|       { | ||||
| 	 GLint bx, by, bw, bh; | ||||
| 	 if (intersect_region(box + i, x, y, width, height, | ||||
| 			      &bx, &by, &bw, &bh)) { | ||||
|             intelEmitCopyBlitLocked( intel, | ||||
|                                      intel->intelScreen->cpp, | ||||
|                                      src_pitch, src_offset, | ||||
|                                      intel->intelScreen->front.pitch, | ||||
|                                      intel->drawRegion->offset, | ||||
|                                      bx - x, by - y, | ||||
|                                      bx, by, | ||||
|                                      bw, bh ); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( &intel->ctx ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intelTryDrawPixels( GLcontext *ctx, | ||||
| 		  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		  GLenum format, GLenum type, | ||||
| 		  const struct gl_pixelstore_attrib *unpack, | ||||
| 		  const GLvoid *pixels ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLint pitch = unpack->RowLength ? unpack->RowLength : width; | ||||
|    GLuint dest; | ||||
|    GLuint cpp = intel->intelScreen->cpp; | ||||
|    GLint size = width * pitch * cpp; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    switch (format) { | ||||
|    case GL_RGB: | ||||
|    case GL_RGBA: | ||||
|    case GL_BGRA: | ||||
|       dest = intel->drawRegion->offset; | ||||
|  | ||||
|       /* Planemask doesn't have full support in blits. | ||||
|        */ | ||||
|       if (!ctx->Color.ColorMask[RCOMP] || | ||||
| 	  !ctx->Color.ColorMask[GCOMP] || | ||||
| 	  !ctx->Color.ColorMask[BCOMP] || | ||||
| 	  !ctx->Color.ColorMask[ACOMP]) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s: planemask\n", __FUNCTION__); | ||||
| 	 return GL_FALSE;	 | ||||
|       } | ||||
|  | ||||
|       /* Can't do conversions on agp reads/draws.  | ||||
|        */ | ||||
|       if ( !intelIsAgpMemory( intel, pixels, size ) ) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s: not agp memory\n", __FUNCTION__); | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       if (!check_color_per_fragment_ops(ctx)) { | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       if (ctx->Pixel.ZoomX != 1.0F || | ||||
| 	  ctx->Pixel.ZoomY != -1.0F) | ||||
| 	 return GL_FALSE; | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if ( intelIsAgpMemory(intel, pixels, size) ) | ||||
|    { | ||||
|       do_draw_pix( ctx, x, y, width, height, pitch, pixels, dest ); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|    else if (0) | ||||
|    { | ||||
|       /* Pixels is in regular memory -- get dma buffers and perform | ||||
|        * upload through them.  No point doing this for regular uploads | ||||
|        * but once we remove some of the restrictions above (colormask, | ||||
|        * pixelformat conversion, zoom?, etc), this could be a win. | ||||
|        */ | ||||
|    } | ||||
|    else | ||||
|       return GL_FALSE; | ||||
|       fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n", | ||||
|               __FUNCTION__, region->cpp, | ||||
|               _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format)); | ||||
|  | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| intelDrawPixels( GLcontext *ctx, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLenum format, GLenum type, | ||||
| 		 const struct gl_pixelstore_attrib *unpack, | ||||
| 		 const GLvoid *pixels ) | ||||
|  | ||||
| void | ||||
| intelInitPixelFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!intelTryDrawPixels( ctx, x, y, width, height, format, type, | ||||
|                             unpack, pixels )) | ||||
|       _swrast_DrawPixels( ctx, x, y, width, height, format, type, | ||||
| 			  unpack, pixels ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Implement glCopyPixels for the front color buffer (or back buffer Pixmap) | ||||
|  * for the color buffer.  Don't support zooming, pixel transfer, etc. | ||||
|  * We do support copying from one window to another, ala glXMakeCurrentRead. | ||||
|  */ | ||||
| static void | ||||
| intelCopyPixels( GLcontext *ctx, | ||||
| 		 GLint srcx, GLint srcy, GLsizei width, GLsizei height, | ||||
| 		 GLint destx, GLint desty, GLenum type ) | ||||
| { | ||||
| #if 0 | ||||
|    const XMesaContext xmesa = XMESA_CONTEXT(ctx); | ||||
|    const SWcontext *swrast = SWRAST_CONTEXT( ctx ); | ||||
|    XMesaDisplay *dpy = xmesa->xm_visual->display; | ||||
|    const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer; | ||||
|    const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer; | ||||
|    const XMesaGC gc = xmesa->xm_draw_buffer->gc; | ||||
|  | ||||
|    ASSERT(dpy); | ||||
|    ASSERT(gc); | ||||
|  | ||||
|    if (drawBuffer &&  /* buffer != 0 means it's a Window or Pixmap */ | ||||
|        readBuffer && | ||||
|        type == GL_COLOR && | ||||
|        (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */ | ||||
|        ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */ | ||||
|        ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */ | ||||
|        ctx->Pixel.ZoomY == 1.0) { | ||||
|       /* Note: we don't do any special clipping work here.  We could, | ||||
|        * but X will do it for us. | ||||
|        */ | ||||
|       srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1; | ||||
|       desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1; | ||||
|       XCopyArea(dpy, readBuffer, drawBuffer, gc, | ||||
|                 srcx, srcy, width, height, destx, desty); | ||||
|    } | ||||
| #else | ||||
|    _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type ); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelInitPixelFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    /* Pixel path fallbacks. | ||||
|     */ | ||||
|    functions->Accum = _swrast_Accum; | ||||
|    functions->Bitmap = _swrast_Bitmap; | ||||
|    functions->CopyPixels = intelCopyPixels; | ||||
|  | ||||
|    if (!getenv("INTEL_NO_BLITS")) { | ||||
|    functions->ReadPixels = intelReadPixels; | ||||
|    functions->DrawPixels = intelDrawPixels; | ||||
| } | ||||
|    else { | ||||
|       functions->ReadPixels = _swrast_ReadPixels; | ||||
|       functions->DrawPixels = _swrast_DrawPixels; | ||||
|    } | ||||
| } | ||||
|   | ||||
							
								
								
									
										63
									
								
								src/mesa/drivers/dri/i915/intel_pixel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/mesa/drivers/dri/i915/intel_pixel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_PIXEL_H | ||||
| #define INTEL_PIXEL_H | ||||
|  | ||||
| #include "mtypes.h" | ||||
|  | ||||
| void intelInitPixelFuncs(struct dd_function_table *functions); | ||||
|  | ||||
| GLboolean intel_check_blit_fragment_ops(GLcontext * ctx); | ||||
|  | ||||
| GLboolean intel_check_meta_tex_fragment_ops(GLcontext * ctx); | ||||
|  | ||||
| GLboolean intel_check_blit_format(struct intel_region *region, | ||||
|                                   GLenum format, GLenum type); | ||||
|  | ||||
|  | ||||
| void intelReadPixels(GLcontext * ctx, | ||||
|                      GLint x, GLint y, | ||||
|                      GLsizei width, GLsizei height, | ||||
|                      GLenum format, GLenum type, | ||||
|                      const struct gl_pixelstore_attrib *pack, | ||||
|                      GLvoid * pixels); | ||||
|  | ||||
| void intelDrawPixels(GLcontext * ctx, | ||||
|                      GLint x, GLint y, | ||||
|                      GLsizei width, GLsizei height, | ||||
|                      GLenum format, | ||||
|                      GLenum type, | ||||
|                      const struct gl_pixelstore_attrib *unpack, | ||||
|                      const GLvoid * pixels); | ||||
|  | ||||
| void intelCopyPixels(GLcontext * ctx, | ||||
|                      GLint srcx, GLint srcy, | ||||
|                      GLsizei width, GLsizei height, | ||||
|                      GLint destx, GLint desty, GLenum type); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										380
									
								
								src/mesa/drivers/dri/i915/intel_pixel_copy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								src/mesa/drivers/dri/i915/intel_pixel_copy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,380 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "state.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_pixel.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_PIXEL | ||||
|  | ||||
| static struct intel_region * | ||||
| copypix_src_region(struct intel_context *intel, GLenum type) | ||||
| { | ||||
|    switch (type) { | ||||
|    case GL_COLOR: | ||||
|       return intel_readbuf_region(intel); | ||||
|    case GL_DEPTH: | ||||
|       /* Don't think this is really possible execpt at 16bpp, when we have no stencil. | ||||
|        */ | ||||
|       if (intel->intelScreen->depth_region &&  | ||||
| 	  intel->intelScreen->depth_region->cpp == 2) | ||||
|          return intel->intelScreen->depth_region; | ||||
|    case GL_STENCIL: | ||||
|       /* Don't think this is really possible.  | ||||
|        */ | ||||
|       break; | ||||
|    case GL_DEPTH_STENCIL_EXT: | ||||
|       /* Does it matter whether it is stencil/depth or depth/stencil? | ||||
|        */ | ||||
|       return intel->intelScreen->depth_region; | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Check if any fragment operations are in effect which might effect | ||||
|  * glCopyPixels.  Differs from intel_check_blit_fragment_ops in that | ||||
|  * we allow Scissor. | ||||
|  */ | ||||
| static GLboolean | ||||
| intel_check_copypixel_blit_fragment_ops(GLcontext * ctx) | ||||
| { | ||||
|    if (ctx->NewState) | ||||
|       _mesa_update_state(ctx); | ||||
|  | ||||
|    /* Could do logicop with the blitter:  | ||||
|     */ | ||||
|    return !(ctx->_ImageTransferState || | ||||
|             ctx->Color.AlphaEnabled || | ||||
|             ctx->Depth.Test || | ||||
|             ctx->Fog.Enabled || | ||||
|             ctx->Stencil.Enabled || | ||||
|             !ctx->Color.ColorMask[0] || | ||||
|             !ctx->Color.ColorMask[1] || | ||||
|             !ctx->Color.ColorMask[2] || | ||||
|             !ctx->Color.ColorMask[3] || | ||||
|             ctx->Color.ColorLogicOpEnabled || | ||||
|             ctx->Texture._EnabledUnits || | ||||
| 	    ctx->FragmentProgram._Enabled); | ||||
| } | ||||
|  | ||||
| /* Doesn't work for overlapping regions.  Could do a double copy or | ||||
|  * just fallback. | ||||
|  */ | ||||
| static GLboolean | ||||
| do_texture_copypixels(GLcontext * ctx, | ||||
|                       GLint srcx, GLint srcy, | ||||
|                       GLsizei width, GLsizei height, | ||||
|                       GLint dstx, GLint dsty, GLenum type) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *dst = intel_drawbuf_region(intel); | ||||
|    struct intel_region *src = copypix_src_region(intel, type); | ||||
|    GLenum src_format; | ||||
|    GLenum src_type; | ||||
|  | ||||
|    DBG("%s %d,%d %dx%d --> %d,%d\n", __FUNCTION__,  | ||||
|        srcx, srcy, width, height, dstx, dsty); | ||||
|  | ||||
|    if (!src || !dst || type != GL_COLOR) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    /* Can't handle overlapping regions.  Don't have sufficient control | ||||
|     * over rasterization to pull it off in-place.  Punt on these for | ||||
|     * now. | ||||
|     *  | ||||
|     * XXX: do a copy to a temporary.  | ||||
|     */ | ||||
|    if (src->buffer == dst->buffer) { | ||||
|       drm_clip_rect_t srcbox; | ||||
|       drm_clip_rect_t dstbox; | ||||
|       drm_clip_rect_t tmp; | ||||
|  | ||||
|       srcbox.x1 = srcx; | ||||
|       srcbox.y1 = srcy; | ||||
|       srcbox.x2 = srcx + width; | ||||
|       srcbox.y2 = srcy + height; | ||||
|  | ||||
|       dstbox.x1 = dstx; | ||||
|       dstbox.y1 = dsty; | ||||
|       dstbox.x2 = dstx + width * ctx->Pixel.ZoomX; | ||||
|       dstbox.y2 = dsty + height * ctx->Pixel.ZoomY; | ||||
|  | ||||
|       DBG("src %d,%d %d,%d\n", srcbox.x1, srcbox.y1, srcbox.x2, srcbox.y2); | ||||
|       DBG("dst %d,%d %d,%d (%dx%d) (%f,%f)\n", dstbox.x1, dstbox.y1, dstbox.x2, dstbox.y2, | ||||
| 	  width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY); | ||||
|  | ||||
|       if (intel_intersect_cliprects(&tmp, &srcbox, &dstbox)) { | ||||
|          DBG("%s: regions overlap\n", __FUNCTION__); | ||||
|          return GL_FALSE; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|  | ||||
|    intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|    /* Is this true?  Also will need to turn depth testing on according | ||||
|     * to state: | ||||
|     */ | ||||
|    intel->vtbl.meta_no_stencil_write(intel); | ||||
|    intel->vtbl.meta_no_depth_write(intel); | ||||
|  | ||||
|    /* Set the 3d engine to draw into the destination region: | ||||
|     */ | ||||
|    intel->vtbl.meta_draw_region(intel, dst, intel->intelScreen->depth_region); | ||||
|  | ||||
|    intel->vtbl.meta_import_pixel_state(intel); | ||||
|  | ||||
|    if (src->cpp == 2) { | ||||
|       src_format = GL_RGB; | ||||
|       src_type = GL_UNSIGNED_SHORT_5_6_5; | ||||
|    } | ||||
|    else { | ||||
|       src_format = GL_BGRA; | ||||
|       src_type = GL_UNSIGNED_BYTE; | ||||
|    } | ||||
|  | ||||
|    /* Set the frontbuffer up as a large rectangular texture. | ||||
|     */ | ||||
|    if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, 0, | ||||
|                                          src->pitch, | ||||
|                                          src->height, src_format, src_type)) { | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    intel->vtbl.meta_texture_blend_replace(intel); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|  | ||||
|       srcy = dPriv->h - srcy - height;  /* convert from gl to hardware coords */ | ||||
|  | ||||
|       srcx += dPriv->x; | ||||
|       srcy += dPriv->y; | ||||
|  | ||||
|       /* Clip against the source region.  This is the only source | ||||
|        * clipping we do.  XXX: Just set the texcord wrap mode to clamp | ||||
|        * or similar. | ||||
|        * | ||||
|        */ | ||||
|       if (0) { | ||||
|          GLint orig_x = srcx; | ||||
|          GLint orig_y = srcy; | ||||
|  | ||||
|          if (!_mesa_clip_to_region(0, 0, src->pitch, src->height, | ||||
|                                    &srcx, &srcy, &width, &height)) | ||||
|             goto out; | ||||
|  | ||||
|          dstx += srcx - orig_x; | ||||
|          dsty += (srcy - orig_y) * ctx->Pixel.ZoomY; | ||||
|       } | ||||
|  | ||||
|       /* Just use the regular cliprect mechanism...  Does this need to | ||||
|        * even hold the lock??? | ||||
|        */ | ||||
|       intel_meta_draw_quad(intel,  | ||||
| 			   dstx,  | ||||
| 			   dstx + width * ctx->Pixel.ZoomX,  | ||||
| 			   dPriv->h - (dsty + height * ctx->Pixel.ZoomY),  | ||||
| 			   dPriv->h - (dsty), 0,   /* XXX: what z value? */ | ||||
|                            0x00ff00ff, | ||||
|                            srcx, srcx + width, srcy, srcy + height); | ||||
|  | ||||
|     out: | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    DBG("%s: success\n", __FUNCTION__); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * CopyPixels with the blitter.  Don't support zooming, pixel transfer, etc. | ||||
|  */ | ||||
| static GLboolean | ||||
| do_blit_copypixels(GLcontext * ctx, | ||||
|                    GLint srcx, GLint srcy, | ||||
|                    GLsizei width, GLsizei height, | ||||
|                    GLint dstx, GLint dsty, GLenum type) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *dst = intel_drawbuf_region(intel); | ||||
|    struct intel_region *src = copypix_src_region(intel, type); | ||||
|  | ||||
|    /* Copypixels can be more than a straight copy.  Ensure all the | ||||
|     * extra operations are disabled: | ||||
|     */ | ||||
|    if (!intel_check_copypixel_blit_fragment_ops(ctx) || | ||||
|        ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (!src || !dst) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t dest_rect; | ||||
|       GLint nbox = dPriv->numClipRects; | ||||
|       GLint delta_x = 0; | ||||
|       GLint delta_y = 0; | ||||
|       GLuint i; | ||||
|  | ||||
|       /* Do scissoring in GL coordinates: | ||||
|        */ | ||||
|       if (ctx->Scissor.Enabled) | ||||
|       { | ||||
| 	 GLint x = ctx->Scissor.X; | ||||
| 	 GLint y = ctx->Scissor.Y; | ||||
| 	 GLuint w = ctx->Scissor.Width; | ||||
| 	 GLuint h = ctx->Scissor.Height; | ||||
| 	 GLint dx = dstx - srcx; | ||||
|          GLint dy = dsty - srcy; | ||||
|  | ||||
|          if (!_mesa_clip_to_region(x, y, x+w, y+h, &dstx, &dsty, &width, &height)) | ||||
|             goto out; | ||||
| 	  | ||||
|          srcx = dstx - dx; | ||||
|          srcy = dsty - dy; | ||||
|       } | ||||
|  | ||||
|       /* Convert from GL to hardware coordinates: | ||||
|        */ | ||||
|       dsty = dPriv->h - dsty - height;   | ||||
|       srcy = dPriv->h - srcy - height;   | ||||
|       dstx += dPriv->x; | ||||
|       dsty += dPriv->y; | ||||
|       srcx += dPriv->x; | ||||
|       srcy += dPriv->y; | ||||
|  | ||||
|       /* Clip against the source region.  This is the only source | ||||
|        * clipping we do.  Dst is clipped with cliprects below. | ||||
|        */ | ||||
|       { | ||||
|          delta_x = srcx - dstx; | ||||
|          delta_y = srcy - dsty; | ||||
|  | ||||
|          if (!_mesa_clip_to_region(0, 0, src->pitch, src->height, | ||||
|                                    &srcx, &srcy, &width, &height)) | ||||
|             goto out; | ||||
|  | ||||
|          dstx = srcx - delta_x; | ||||
|          dsty = srcy - delta_y; | ||||
|       } | ||||
|  | ||||
|       dest_rect.x1 = dstx; | ||||
|       dest_rect.y1 = dsty; | ||||
|       dest_rect.x2 = dstx + width; | ||||
|       dest_rect.y2 = dsty + height; | ||||
|  | ||||
|       /* Could do slightly more clipping: Eg, take the intersection of | ||||
|        * the existing set of cliprects and those cliprects translated | ||||
|        * by delta_x, delta_y: | ||||
|        *  | ||||
|        * This code will not overwrite other windows, but will | ||||
|        * introduce garbage when copying from obscured window regions. | ||||
|        */ | ||||
|       for (i = 0; i < nbox; i++) { | ||||
|          drm_clip_rect_t rect; | ||||
|  | ||||
|          if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i])) | ||||
|             continue; | ||||
|  | ||||
|  | ||||
|          intelEmitCopyBlit(intel, dst->cpp,  | ||||
| 			   src->pitch, src->buffer, 0,  | ||||
| 			   dst->pitch, dst->buffer, 0,  | ||||
| 			   rect.x1 + delta_x, rect.y1 + delta_y,       /* srcx, srcy */ | ||||
|                            rect.x1, rect.y1,    /* dstx, dsty */ | ||||
|                            rect.x2 - rect.x1, rect.y2 - rect.y1); | ||||
|       } | ||||
|  | ||||
|     out: | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    DBG("%s: success\n", __FUNCTION__); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelCopyPixels(GLcontext * ctx, | ||||
|                 GLint srcx, GLint srcy, | ||||
|                 GLsizei width, GLsizei height, | ||||
|                 GLint destx, GLint desty, GLenum type) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) | ||||
|       return; | ||||
|  | ||||
|    if (do_texture_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) | ||||
|       return; | ||||
|  | ||||
|    DBG("fallback to _swrast_CopyPixels\n"); | ||||
|  | ||||
|    _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type); | ||||
| } | ||||
							
								
								
									
										365
									
								
								src/mesa/drivers/dri/i915/intel_pixel_draw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										365
									
								
								src/mesa/drivers/dri/i915/intel_pixel_draw.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,365 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portionsalloc | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "bufferobj.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "intel_tris.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| do_texture_drawpixels(GLcontext * ctx, | ||||
|                       GLint x, GLint y, | ||||
|                       GLsizei width, GLsizei height, | ||||
|                       GLenum format, GLenum type, | ||||
|                       const struct gl_pixelstore_attrib *unpack, | ||||
|                       const GLvoid * pixels) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *dst = intel_drawbuf_region(intel); | ||||
|    struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj); | ||||
|    GLuint rowLength = unpack->RowLength ? unpack->RowLength : width; | ||||
|    GLuint src_offset; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|    intel->vtbl.render_start(intel); | ||||
|    intel->vtbl.emit_state(intel); | ||||
|  | ||||
|    if (!dst) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (src) { | ||||
|       if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, | ||||
|                                      format, type, pixels)) { | ||||
|          _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); | ||||
|          return GL_TRUE; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* PBO only for now: | ||||
|        */ | ||||
| /*       _mesa_printf("%s - not PBO\n", __FUNCTION__); */ | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* There are a couple of things we can't do yet, one of which is | ||||
|     * set the correct state for pixel operations when GL texturing is | ||||
|     * enabled.  That's a pretty rare state and probably not worth the | ||||
|     * effort.  A completely device-independent version of this may do | ||||
|     * more. | ||||
|     * | ||||
|     * Similarly, we make no attempt to merge metaops processing with | ||||
|     * an enabled fragment program, though it would certainly be | ||||
|     * possible. | ||||
|     */ | ||||
|    if (!intel_check_meta_tex_fragment_ops(ctx)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - bad GL fragment state for metaops texture\n", | ||||
|                       __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|  | ||||
|    /* Is this true?  Also will need to turn depth testing on according | ||||
|     * to state: | ||||
|     */ | ||||
|    intel->vtbl.meta_no_stencil_write(intel); | ||||
|    intel->vtbl.meta_no_depth_write(intel); | ||||
|  | ||||
|    /* Set the 3d engine to draw into the destination region: | ||||
|     */ | ||||
|    intel->vtbl.meta_draw_region(intel, dst, intel->intelScreen->depth_region); | ||||
|  | ||||
|    intel->vtbl.meta_import_pixel_state(intel); | ||||
|  | ||||
|    src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height, | ||||
|                                              format, type, 0, 0, 0); | ||||
|  | ||||
|  | ||||
|    /* Setup the pbo up as a rectangular texture, if possible. | ||||
|     * | ||||
|     * TODO: This is almost always possible if the i915 fragment | ||||
|     * program is adjusted to correctly swizzle the sampled colors. | ||||
|     * The major exception is any 24bit texture, like RGB888, for which | ||||
|     * there is no hardware support.   | ||||
|     */ | ||||
|    if (!intel->vtbl.meta_tex_rect_source(intel, src->buffer, src_offset, | ||||
|                                          rowLength, height, format, type)) { | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.meta_texture_blend_replace(intel); | ||||
|  | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       GLint srcx, srcy; | ||||
|       GLint dstx, dsty; | ||||
|  | ||||
|       dstx = x; | ||||
|       dsty = dPriv->h - (y + height); | ||||
|  | ||||
|       srcx = 0;                 /* skiprows/pixels already done */ | ||||
|       srcy = 0; | ||||
|  | ||||
|       if (0) { | ||||
|          const GLint orig_x = dstx; | ||||
|          const GLint orig_y = dsty; | ||||
|  | ||||
|          if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height, | ||||
|                                    &dstx, &dsty, &width, &height)) | ||||
|             goto out; | ||||
|  | ||||
|          srcx += dstx - orig_x; | ||||
|          srcy += dsty - orig_y; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("draw %d,%d %dx%d\n", dstx, dsty, width, height); | ||||
|  | ||||
|       /* Must use the regular cliprect mechanism in order to get the | ||||
|        * drawing origin set correctly.  Otherwise scissor state is in | ||||
|        * incorrect coordinate space.  Does this even need to hold the | ||||
|        * lock??? | ||||
|        */ | ||||
|       intel_meta_draw_quad(intel, | ||||
|                            dstx, dstx + width * ctx->Pixel.ZoomX, | ||||
|                            dPriv->h - (y + height * ctx->Pixel.ZoomY), | ||||
|                            dPriv->h - (y), | ||||
|                            -ctx->Current.RasterPos[2] * .5, | ||||
|                            0x00ff00ff, | ||||
|                            srcx, srcx + width, srcy + height, srcy); | ||||
|     out: | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Pros:   | ||||
|  *   - no waiting for idle before updating framebuffer. | ||||
|  *    | ||||
|  * Cons: | ||||
|  *   - if upload is by memcpy, this may actually be slower than fallback path. | ||||
|  *   - uploads the whole image even if destination is clipped | ||||
|  *    | ||||
|  * Need to benchmark. | ||||
|  * | ||||
|  * Given the questions about performance, implement for pbo's only. | ||||
|  * This path is definitely a win if the pbo is already in agp.  If it | ||||
|  * turns out otherwise, we can add the code necessary to upload client | ||||
|  * data to agp space before performing the blit.  (Though it may turn | ||||
|  * out to be better/simpler just to use the texture engine). | ||||
|  */ | ||||
| static GLboolean | ||||
| do_blit_drawpixels(GLcontext * ctx, | ||||
|                    GLint x, GLint y, | ||||
|                    GLsizei width, GLsizei height, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const struct gl_pixelstore_attrib *unpack, | ||||
|                    const GLvoid * pixels) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *dest = intel_drawbuf_region(intel); | ||||
|    struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj); | ||||
|    GLuint src_offset; | ||||
|    GLuint rowLength; | ||||
|    struct _DriFenceObject *fence = NULL; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s\n", __FUNCTION__); | ||||
|  | ||||
|  | ||||
|    if (!dest) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - no dest\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (src) { | ||||
|       /* This validation should be done by core mesa: | ||||
|        */ | ||||
|       if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, | ||||
|                                      format, type, pixels)) { | ||||
|          _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); | ||||
|          return GL_TRUE; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* PBO only for now: | ||||
|        */ | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - not PBO\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (!intel_check_blit_format(dest, format, type)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - bad format for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (!intel_check_meta_tex_fragment_ops(ctx)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - bad GL fragment state for meta tex\n", | ||||
|                       __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (ctx->Pixel.ZoomX != 1.0F) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (unpack->RowLength > 0) | ||||
|       rowLength = unpack->RowLength; | ||||
|    else | ||||
|       rowLength = width; | ||||
|  | ||||
|    if (ctx->Pixel.ZoomY == -1.0F) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE;          /* later */ | ||||
|       y -= height; | ||||
|    } | ||||
|    else if (ctx->Pixel.ZoomY == 1.0F) { | ||||
|       rowLength = -rowLength; | ||||
|    } | ||||
|    else { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height, | ||||
|                                              format, type, 0, 0, 0); | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t rect; | ||||
|       drm_clip_rect_t dest_rect; | ||||
|       struct _DriBufferObject *src_buffer = | ||||
|          intel_bufferobj_buffer(intel, src, INTEL_READ); | ||||
|       int i; | ||||
|  | ||||
|       dest_rect.x1 = dPriv->x + x; | ||||
|       dest_rect.y1 = dPriv->y + dPriv->h - (y + height); | ||||
|       dest_rect.x2 = dest_rect.x1 + width; | ||||
|       dest_rect.y2 = dest_rect.y1 + height; | ||||
|  | ||||
|       for (i = 0; i < nbox; i++) { | ||||
|          if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i])) | ||||
|             continue; | ||||
|  | ||||
|          intelEmitCopyBlit(intel, | ||||
|                            dest->cpp, | ||||
|                            rowLength, | ||||
|                            src_buffer, src_offset, | ||||
|                            dest->pitch, | ||||
|                            dest->buffer, 0, | ||||
|                            rect.x1 - dest_rect.x1, | ||||
|                            rect.y2 - dest_rect.y2, | ||||
|                            rect.x1, | ||||
|                            rect.y1, rect.x2 - rect.x1, rect.y2 - rect.y1); | ||||
|       } | ||||
|       fence = intel_batchbuffer_flush(intel->batch); | ||||
|       driFenceReference(fence); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|       driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW, GL_FALSE); | ||||
|  | ||||
|    driFenceUnReference(fence); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s - DONE\n", __FUNCTION__); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intelDrawPixels(GLcontext * ctx, | ||||
|                 GLint x, GLint y, | ||||
|                 GLsizei width, GLsizei height, | ||||
|                 GLenum format, | ||||
|                 GLenum type, | ||||
|                 const struct gl_pixelstore_attrib *unpack, | ||||
|                 const GLvoid * pixels) | ||||
| { | ||||
|    if (do_blit_drawpixels(ctx, x, y, width, height, format, type, | ||||
|                           unpack, pixels)) | ||||
|       return; | ||||
|  | ||||
|    if (do_texture_drawpixels(ctx, x, y, width, height, format, type, | ||||
|                              unpack, pixels)) | ||||
|       return; | ||||
|  | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); | ||||
|  | ||||
|    _swrast_DrawPixels(ctx, x, y, width, height, format, type, unpack, pixels); | ||||
| } | ||||
							
								
								
									
										317
									
								
								src/mesa/drivers/dri/i915/intel_pixel_read.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								src/mesa/drivers/dri/i915/intel_pixel_read.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,317 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "image.h" | ||||
| #include "bufferobj.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_buffer_objects.h" | ||||
|  | ||||
| /* For many applications, the new ability to pull the source buffers | ||||
|  * back out of the GTT and then do the packing/conversion operations | ||||
|  * in software will be as much of an improvement as trying to get the | ||||
|  * blitter and/or texture engine to do the work.  | ||||
|  * | ||||
|  * This step is gated on private backbuffers. | ||||
|  *  | ||||
|  * Obviously the frontbuffer can't be pulled back, so that is either | ||||
|  * an argument for blit/texture readpixels, or for blitting to a | ||||
|  * temporary and then pulling that back. | ||||
|  * | ||||
|  * When the destination is a pbo, however, it's not clear if it is | ||||
|  * ever going to be pulled to main memory (though the access param | ||||
|  * will be a good hint).  So it sounds like we do want to be able to | ||||
|  * choose between blit/texture implementation on the gpu and pullback | ||||
|  * and cpu-based copying. | ||||
|  * | ||||
|  * Unless you can magically turn client memory into a PBO for the | ||||
|  * duration of this call, there will be a cpu-based copying step in | ||||
|  * any case. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| do_texture_readpixels(GLcontext * ctx, | ||||
|                       GLint x, GLint y, GLsizei width, GLsizei height, | ||||
|                       GLenum format, GLenum type, | ||||
|                       const struct gl_pixelstore_attrib *pack, | ||||
|                       struct intel_region *dest_region) | ||||
| { | ||||
| #if 0 | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    int textureFormat; | ||||
|    GLenum glTextureFormat; | ||||
|    int destFormat, depthFormat, destPitch; | ||||
|    drm_clip_rect_t tmp; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|  | ||||
|    if (ctx->_ImageTransferState || | ||||
|        pack->SwapBytes || pack->LsbFirst || !pack->Invert) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          fprintf(stderr, "%s: check_color failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel)); | ||||
|  | ||||
|    if (!intel->vtbl.meta_render_dest(intel, dest_region, type, format)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          fprintf(stderr, "%s: couldn't set dest %s/%s\n", | ||||
|                  __FUNCTION__, | ||||
|                  _mesa_lookup_enum_by_nr(type), | ||||
|                  _mesa_lookup_enum_by_nr(format)); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) { | ||||
|       intel->vtbl.install_meta_state(intel); | ||||
|       intel->vtbl.meta_no_depth_write(intel); | ||||
|       intel->vtbl.meta_no_stencil_write(intel); | ||||
|  | ||||
|       if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
|          UNLOCK_HARDWARE(intel); | ||||
|          SET_STATE(i830, state); | ||||
|          if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|             fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); | ||||
|          return GL_TRUE; | ||||
|       } | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       /* Set the frontbuffer up as a large rectangular texture. | ||||
|        */ | ||||
|       intel->vtbl.meta_tex_rect_source(intel, src_region, textureFormat); | ||||
|  | ||||
|  | ||||
|       intel->vtbl.meta_texture_blend_replace(i830, glTextureFormat); | ||||
|  | ||||
|  | ||||
|       /* Set the 3d engine to draw into the destination region: | ||||
|        */ | ||||
|  | ||||
|       intel->vtbl.meta_draw_region(intel, dest_region); | ||||
|       intel->vtbl.meta_draw_format(intel, destFormat, depthFormat);     /* ?? */ | ||||
|  | ||||
|  | ||||
|       /* Draw a single quad, no cliprects: | ||||
|        */ | ||||
|       intel->vtbl.meta_disable_cliprects(intel); | ||||
|  | ||||
|       intel->vtbl.draw_quad(intel, | ||||
|                             0, width, 0, height, | ||||
|                             0x00ff00ff, x, x + width, y, y + height); | ||||
|  | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    intel_region_wait_fence(ctx, dest_region);   /* required by GL */ | ||||
|    return GL_TRUE; | ||||
| #endif | ||||
|  | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| do_blit_readpixels(GLcontext * ctx, | ||||
|                    GLint x, GLint y, GLsizei width, GLsizei height, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const struct gl_pixelstore_attrib *pack, GLvoid * pixels) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *src = intel_readbuf_region(intel); | ||||
|    struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); | ||||
|    GLuint dst_offset; | ||||
|    GLuint rowLength; | ||||
|    struct _DriFenceObject *fence = NULL; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!src) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (dst) { | ||||
|       /* XXX This validation should be done by core mesa: | ||||
|        */ | ||||
|       if (!_mesa_validate_pbo_access(2, pack, width, height, 1, | ||||
|                                      format, type, pixels)) { | ||||
|          _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); | ||||
|          return GL_TRUE; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* PBO only for now: | ||||
|        */ | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - not PBO\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (ctx->_ImageTransferState || | ||||
|        !intel_check_blit_format(src, format, type)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s - bad format for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s: bad packing params\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (pack->RowLength > 0) | ||||
|       rowLength = pack->RowLength; | ||||
|    else | ||||
|       rowLength = width; | ||||
|  | ||||
|    if (pack->Invert) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|          _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|    else { | ||||
|       rowLength = -rowLength; | ||||
|    } | ||||
|  | ||||
|    /* XXX 64-bit cast? */ | ||||
|    dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height, | ||||
|                                              format, type, 0, 0, 0); | ||||
|  | ||||
|  | ||||
|    /* Although the blits go on the command buffer, need to do this and | ||||
|     * fire with lock held to guarentee cliprects are correct. | ||||
|     */ | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) { | ||||
|       GLboolean all = (width * height * src->cpp == dst->Base.Size && | ||||
|                        x == 0 && dst_offset == 0); | ||||
|  | ||||
|       struct _DriBufferObject *dst_buffer = | ||||
|          intel_bufferobj_buffer(intel, dst, all ? INTEL_WRITE_FULL : | ||||
|                                 INTEL_WRITE_PART); | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t rect; | ||||
|       drm_clip_rect_t src_rect; | ||||
|       int i; | ||||
|  | ||||
|       src_rect.x1 = dPriv->x + x; | ||||
|       src_rect.y1 = dPriv->y + dPriv->h - (y + height); | ||||
|       src_rect.x2 = src_rect.x1 + width; | ||||
|       src_rect.y2 = src_rect.y1 + height; | ||||
|  | ||||
|  | ||||
|  | ||||
|       for (i = 0; i < nbox; i++) { | ||||
|          if (!intel_intersect_cliprects(&rect, &src_rect, &box[i])) | ||||
|             continue; | ||||
|  | ||||
|          intelEmitCopyBlit(intel, | ||||
|                            src->cpp, | ||||
|                            src->pitch, src->buffer, 0, | ||||
|                            rowLength, | ||||
|                            dst_buffer, dst_offset, | ||||
|                            rect.x1, | ||||
|                            rect.y1, | ||||
|                            rect.x1 - src_rect.x1, | ||||
|                            rect.y2 - src_rect.y2, | ||||
|                            rect.x2 - rect.x1, rect.y2 - rect.y1); | ||||
|       } | ||||
|  | ||||
|       fence = intel_batchbuffer_flush(intel->batch); | ||||
|       driFenceReference(fence); | ||||
|  | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|       driFenceFinish(fence, DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,  | ||||
| 		     GL_FALSE); | ||||
|  | ||||
|    driFenceUnReference(fence); | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s - DONE\n", __FUNCTION__); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| void | ||||
| intelReadPixels(GLcontext * ctx, | ||||
|                 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
|                 GLenum format, GLenum type, | ||||
|                 const struct gl_pixelstore_attrib *pack, GLvoid * pixels) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    if (do_blit_readpixels | ||||
|        (ctx, x, y, width, height, format, type, pack, pixels)) | ||||
|       return; | ||||
|  | ||||
|    if (do_texture_readpixels | ||||
|        (ctx, x, y, width, height, format, type, pack, pixels)) | ||||
|       return; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); | ||||
|  | ||||
|    _swrast_ReadPixels(ctx, x, y, width, height, format, type, pack, pixels); | ||||
| } | ||||
							
								
								
									
										458
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										458
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,458 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| /* Provide additional functionality on top of bufmgr buffers: | ||||
|  *   - 2d semantics and blit operations | ||||
|  *   - refcounting of buffers for multiple images in a buffer. | ||||
|  *   - refcounting of buffer mappings. | ||||
|  *   - some logic for moving the buffers to the best memory pools for | ||||
|  *     given operations. | ||||
|  * | ||||
|  * Most of this is to make it easier to implement the fixed-layout | ||||
|  * mipmap tree required by intel hardware in the face of GL's | ||||
|  * programming interface where each image can be specifed in random | ||||
|  * order and it isn't clear what layout the tree should have until the | ||||
|  * last moment. | ||||
|  */ | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "dri_bufmgr.h" | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_REGION | ||||
|  | ||||
| void | ||||
| intel_region_idle(intelScreenPrivate *intelScreen, struct intel_region *region) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    if (region && region->buffer) | ||||
|       driBOWaitIdle(region->buffer, GL_FALSE); | ||||
| } | ||||
|  | ||||
| /* XXX: Thread safety? | ||||
|  */ | ||||
| GLubyte * | ||||
| intel_region_map(intelScreenPrivate *intelScreen, struct intel_region *region) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    if (!region->map_refcount++) { | ||||
|       if (region->pbo) | ||||
|          intel_region_cow(intelScreen, region); | ||||
|  | ||||
|       region->map = driBOMap(region->buffer, | ||||
|                              DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0); | ||||
|    } | ||||
|  | ||||
|    return region->map; | ||||
| } | ||||
|  | ||||
| void | ||||
| intel_region_unmap(intelScreenPrivate *intelScreen, struct intel_region *region) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    if (!--region->map_refcount) { | ||||
|       driBOUnmap(region->buffer); | ||||
|       region->map = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct intel_region * | ||||
| intel_region_alloc(intelScreenPrivate *intelScreen, | ||||
|                    GLuint cpp, GLuint pitch, GLuint height) | ||||
| { | ||||
|    struct intel_region *region = calloc(sizeof(*region), 1); | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    region->cpp = cpp; | ||||
|    region->pitch = pitch; | ||||
|    region->height = height;     /* needed? */ | ||||
|    region->refcount = 1; | ||||
|  | ||||
|    driGenBuffers(intelScreen->regionPool, | ||||
|                  "region", 1, ®ion->buffer, 64, 0, 0); | ||||
|    driBOData(region->buffer, pitch * cpp * height, NULL, 0); | ||||
|    return region; | ||||
| } | ||||
|  | ||||
| void | ||||
| intel_region_reference(struct intel_region **dst, struct intel_region *src) | ||||
| { | ||||
|    assert(*dst == NULL); | ||||
|    if (src) { | ||||
|       src->refcount++; | ||||
|       *dst = src; | ||||
|    } | ||||
| } | ||||
|  | ||||
| void | ||||
| intel_region_release(intelScreenPrivate *intelScreen, | ||||
|                      struct intel_region **region) | ||||
| { | ||||
|    if (!*region) | ||||
|       return; | ||||
|  | ||||
|    DBG("%s %d\n", __FUNCTION__, (*region)->refcount - 1); | ||||
|  | ||||
|    ASSERT((*region)->refcount > 0); | ||||
|    (*region)->refcount--; | ||||
|  | ||||
|    if ((*region)->refcount == 0) { | ||||
|       assert((*region)->map_refcount == 0); | ||||
|  | ||||
|       if ((*region)->pbo) | ||||
| 	 (*region)->pbo->region = NULL; | ||||
|       (*region)->pbo = NULL; | ||||
|       driBOUnReference((*region)->buffer); | ||||
|       free(*region); | ||||
|    } | ||||
|    *region = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct intel_region * | ||||
| intel_region_create_static(intelScreenPrivate *intelScreen, | ||||
|                            GLuint mem_type, | ||||
|                            GLuint offset, | ||||
|                            void *virtual, | ||||
|                            GLuint cpp, GLuint pitch, GLuint height) | ||||
| { | ||||
|    struct intel_region *region = calloc(sizeof(*region), 1); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    region->cpp = cpp; | ||||
|    region->pitch = pitch; | ||||
|    region->height = height;     /* needed? */ | ||||
|    region->refcount = 1; | ||||
|  | ||||
|    /* | ||||
|     * We use a "shared" buffer type to indicate buffers created and | ||||
|     * shared by others. | ||||
|     */ | ||||
|  | ||||
|    driGenBuffers(intelScreen->staticPool, "static region", 1, | ||||
|                  ®ion->buffer, 64, | ||||
|                  DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_EVICT | | ||||
|                  DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0); | ||||
|    driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0); | ||||
|  | ||||
|    return region; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intel_region_update_static(intelScreenPrivate *intelScreen, | ||||
| 			   struct intel_region *region, | ||||
|                            GLuint mem_type, | ||||
|                            GLuint offset, | ||||
|                            void *virtual, | ||||
|                            GLuint cpp, GLuint pitch, GLuint height) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    region->cpp = cpp; | ||||
|    region->pitch = pitch; | ||||
|    region->height = height;     /* needed? */ | ||||
|  | ||||
|    /* | ||||
|     * We use a "shared" buffer type to indicate buffers created and | ||||
|     * shared by others. | ||||
|     */ | ||||
|  | ||||
|    driDeleteBuffers(1, ®ion->buffer); | ||||
|    driGenBuffers(intelScreen->staticPool, "static region", 1, | ||||
|                  ®ion->buffer, 64, | ||||
|                  DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_EVICT | | ||||
|                  DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0); | ||||
|    driBOSetStatic(region->buffer, offset, pitch * cpp * height, virtual, 0); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * XXX Move this into core Mesa? | ||||
|  */ | ||||
| static void | ||||
| _mesa_copy_rect(GLubyte * dst, | ||||
|                 GLuint cpp, | ||||
|                 GLuint dst_pitch, | ||||
|                 GLuint dst_x, | ||||
|                 GLuint dst_y, | ||||
|                 GLuint width, | ||||
|                 GLuint height, | ||||
|                 GLubyte * src, GLuint src_pitch, GLuint src_x, GLuint src_y) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|    src_pitch *= cpp; | ||||
|    dst += dst_x * cpp; | ||||
|    src += src_x * cpp; | ||||
|    dst += dst_y * dst_pitch; | ||||
|    src += src_y * dst_pitch; | ||||
|    width *= cpp; | ||||
|  | ||||
|    if (width == dst_pitch && width == src_pitch) | ||||
|       memcpy(dst, src, height * width); | ||||
|    else { | ||||
|       for (i = 0; i < height; i++) { | ||||
|          memcpy(dst, src, width); | ||||
|          dst += dst_pitch; | ||||
|          src += src_pitch; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Upload data to a rectangular sub-region.  Lots of choices how to do this: | ||||
|  * | ||||
|  * - memcpy by span to current destination | ||||
|  * - upload data as new buffer and blit | ||||
|  * | ||||
|  * Currently always memcpy. | ||||
|  */ | ||||
| void | ||||
| intel_region_data(intelScreenPrivate *intelScreen, | ||||
|                   struct intel_region *dst, | ||||
|                   GLuint dst_offset, | ||||
|                   GLuint dstx, GLuint dsty, | ||||
|                   void *src, GLuint src_pitch, | ||||
|                   GLuint srcx, GLuint srcy, GLuint width, GLuint height) | ||||
| { | ||||
|    struct intel_context *intel = intelScreenContext(intelScreen); | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (intel == NULL) | ||||
|       return; | ||||
|  | ||||
|    if (dst->pbo) { | ||||
|       if (dstx == 0 && | ||||
|           dsty == 0 && width == dst->pitch && height == dst->height) | ||||
|          intel_region_release_pbo(intelScreen, dst); | ||||
|       else | ||||
|          intel_region_cow(intelScreen, dst); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    _mesa_copy_rect(intel_region_map(intelScreen, dst) + dst_offset, | ||||
|                    dst->cpp, | ||||
|                    dst->pitch, | ||||
|                    dstx, dsty, width, height, src, src_pitch, srcx, srcy); | ||||
|  | ||||
|    intel_region_unmap(intelScreen, dst); | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
| } | ||||
|  | ||||
| /* Copy rectangular sub-regions. Need better logic about when to | ||||
|  * push buffers into AGP - will currently do so whenever possible. | ||||
|  */ | ||||
| void | ||||
| intel_region_copy(intelScreenPrivate *intelScreen, | ||||
|                   struct intel_region *dst, | ||||
|                   GLuint dst_offset, | ||||
|                   GLuint dstx, GLuint dsty, | ||||
|                   struct intel_region *src, | ||||
|                   GLuint src_offset, | ||||
|                   GLuint srcx, GLuint srcy, GLuint width, GLuint height) | ||||
| { | ||||
|    struct intel_context *intel = intelScreenContext(intelScreen); | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (intel == NULL) | ||||
|       return; | ||||
|  | ||||
|    if (dst->pbo) { | ||||
|       if (dstx == 0 && | ||||
|           dsty == 0 && width == dst->pitch && height == dst->height) | ||||
|          intel_region_release_pbo(intelScreen, dst); | ||||
|       else | ||||
|          intel_region_cow(intelScreen, dst); | ||||
|    } | ||||
|  | ||||
|    assert(src->cpp == dst->cpp); | ||||
|  | ||||
|    intelEmitCopyBlit(intel, | ||||
|                      dst->cpp, | ||||
|                      src->pitch, src->buffer, src_offset, | ||||
|                      dst->pitch, dst->buffer, dst_offset, | ||||
|                      srcx, srcy, dstx, dsty, width, height); | ||||
| } | ||||
|  | ||||
| /* Fill a rectangular sub-region.  Need better logic about when to | ||||
|  * push buffers into AGP - will currently do so whenever possible. | ||||
|  */ | ||||
| void | ||||
| intel_region_fill(intelScreenPrivate *intelScreen, | ||||
|                   struct intel_region *dst, | ||||
|                   GLuint dst_offset, | ||||
|                   GLuint dstx, GLuint dsty, | ||||
|                   GLuint width, GLuint height, GLuint color) | ||||
| { | ||||
|    struct intel_context *intel = intelScreenContext(intelScreen); | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (intel == NULL) | ||||
|       return;    | ||||
|  | ||||
|    if (dst->pbo) { | ||||
|       if (dstx == 0 && | ||||
|           dsty == 0 && width == dst->pitch && height == dst->height) | ||||
|          intel_region_release_pbo(intelScreen, dst); | ||||
|       else | ||||
|          intel_region_cow(intelScreen, dst); | ||||
|    } | ||||
|  | ||||
|    intelEmitFillBlit(intel, | ||||
|                      dst->cpp, | ||||
|                      dst->pitch, dst->buffer, dst_offset, | ||||
|                      dstx, dsty, width, height, color); | ||||
| } | ||||
|  | ||||
| /* Attach to a pbo, discarding our data.  Effectively zero-copy upload | ||||
|  * the pbo's data. | ||||
|  */ | ||||
| void | ||||
| intel_region_attach_pbo(intelScreenPrivate *intelScreen, | ||||
|                         struct intel_region *region, | ||||
|                         struct intel_buffer_object *pbo) | ||||
| { | ||||
|    if (region->pbo == pbo) | ||||
|       return; | ||||
|  | ||||
|    /* If there is already a pbo attached, break the cow tie now. | ||||
|     * Don't call intel_region_release_pbo() as that would | ||||
|     * unnecessarily allocate a new buffer we would have to immediately | ||||
|     * discard. | ||||
|     */ | ||||
|    if (region->pbo) { | ||||
|       region->pbo->region = NULL; | ||||
|       region->pbo = NULL; | ||||
|    } | ||||
|  | ||||
|    if (region->buffer) { | ||||
|       driDeleteBuffers(1, ®ion->buffer); | ||||
|       region->buffer = NULL; | ||||
|    } | ||||
|  | ||||
|    region->pbo = pbo; | ||||
|    region->pbo->region = region; | ||||
|    region->buffer = driBOReference(pbo->buffer); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Break the COW tie to the pbo.  The pbo gets to keep the data. | ||||
|  */ | ||||
| void | ||||
| intel_region_release_pbo(intelScreenPrivate *intelScreen, | ||||
|                          struct intel_region *region) | ||||
| { | ||||
|    assert(region->buffer == region->pbo->buffer); | ||||
|    region->pbo->region = NULL; | ||||
|    region->pbo = NULL; | ||||
|    driBOUnReference(region->buffer); | ||||
|    region->buffer = NULL; | ||||
|  | ||||
|    driGenBuffers(intelScreen->regionPool, | ||||
|                  "region", 1, ®ion->buffer, 64, 0, 0); | ||||
|    driBOData(region->buffer, | ||||
|              region->cpp * region->pitch * region->height, NULL, 0); | ||||
| } | ||||
|  | ||||
| /* Break the COW tie to the pbo.  Both the pbo and the region end up | ||||
|  * with a copy of the data. | ||||
|  */ | ||||
| void | ||||
| intel_region_cow(intelScreenPrivate *intelScreen, struct intel_region *region) | ||||
| { | ||||
|    struct intel_context *intel = intelScreenContext(intelScreen); | ||||
|    struct intel_buffer_object *pbo = region->pbo; | ||||
|  | ||||
|    if (intel == NULL) | ||||
|       return; | ||||
|  | ||||
|    intel_region_release_pbo(intelScreen, region); | ||||
|  | ||||
|    assert(region->cpp * region->pitch * region->height == pbo->Base.Size); | ||||
|  | ||||
|    DBG("%s (%d bytes)\n", __FUNCTION__, pbo->Base.Size); | ||||
|  | ||||
|    /* Now blit from the texture buffer to the new buffer:  | ||||
|     */ | ||||
|  | ||||
|    intel_batchbuffer_flush(intel->batch); | ||||
|  | ||||
|    if (!intel->locked) { | ||||
|       LOCK_HARDWARE(intel); | ||||
|       intelEmitCopyBlit(intel, | ||||
| 			region->cpp, | ||||
| 			region->pitch, | ||||
| 			region->buffer, 0, | ||||
| 			region->pitch, | ||||
| 			pbo->buffer, 0, | ||||
| 			0, 0, 0, 0, region->pitch, region->height); | ||||
|        | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|    } | ||||
|    else { | ||||
|       intelEmitCopyBlit(intel, | ||||
| 			region->cpp, | ||||
| 			region->pitch, | ||||
| 			region->buffer, 0, | ||||
| 			region->pitch, | ||||
| 			pbo->buffer, 0, | ||||
| 			0, 0, 0, 0, region->pitch, region->height); | ||||
|        | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct _DriBufferObject * | ||||
| intel_region_buffer(intelScreenPrivate *intelScreen, | ||||
|                     struct intel_region *region, GLuint flag) | ||||
| { | ||||
|    if (region->pbo) { | ||||
|       if (flag == INTEL_WRITE_PART) | ||||
|          intel_region_cow(intelScreen, region); | ||||
|       else if (flag == INTEL_WRITE_FULL) | ||||
|          intel_region_release_pbo(intelScreen, region); | ||||
|    } | ||||
|  | ||||
|    return region->buffer; | ||||
| } | ||||
							
								
								
									
										142
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_REGIONS_H | ||||
| #define INTEL_REGIONS_H | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| struct intel_context; | ||||
| struct intel_buffer_object; | ||||
|  | ||||
| /** | ||||
|  * A layer on top of the bufmgr buffers that adds a few useful things: | ||||
|  * | ||||
|  * - Refcounting for local buffer references. | ||||
|  * - Refcounting for buffer maps | ||||
|  * - Buffer dimensions - pitch and height. | ||||
|  * - Blitter commands for copying 2D regions between buffers. (really???) | ||||
|  */ | ||||
| struct intel_region | ||||
| { | ||||
|    struct _DriBufferObject *buffer;   /**< buffer manager's buffer ID */ | ||||
|    GLuint refcount; /**< Reference count for region */ | ||||
|    GLuint cpp;      /**< bytes per pixel */ | ||||
|    GLuint pitch;    /**< in pixels */ | ||||
|    GLuint height;   /**< in pixels */ | ||||
|    GLubyte *map;    /**< only non-NULL when region is actually mapped */ | ||||
|    GLuint map_refcount;  /**< Reference count for mapping */ | ||||
|  | ||||
|    GLuint draw_offset; /**< Offset of drawing address within the region */ | ||||
|  | ||||
|    struct intel_buffer_object *pbo;     /* zero-copy uploads */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* Allocate a refcounted region.  Pointers to regions should only be | ||||
|  * copied by calling intel_reference_region(). | ||||
|  */ | ||||
| struct intel_region *intel_region_alloc(intelScreenPrivate *intelScreen, | ||||
|                                         GLuint cpp, | ||||
|                                         GLuint pitch, GLuint height); | ||||
|  | ||||
| void intel_region_reference(struct intel_region **dst, | ||||
|                             struct intel_region *src); | ||||
|  | ||||
| void intel_region_release(intelScreenPrivate *intelScreen, | ||||
|                           struct intel_region **ib); | ||||
|  | ||||
| extern struct intel_region  | ||||
| *intel_region_create_static(intelScreenPrivate *intelScreen, | ||||
| 			    GLuint mem_type, | ||||
| 			    GLuint offset, | ||||
| 			    void *virtual, | ||||
| 			    GLuint cpp, | ||||
| 			    GLuint pitch, GLuint height); | ||||
| extern void  | ||||
| intel_region_update_static(intelScreenPrivate *intelScreen, | ||||
| 			   struct intel_region *region, | ||||
| 			   GLuint mem_type, | ||||
| 			   GLuint offset, | ||||
| 			   void *virtual, | ||||
| 			   GLuint cpp, GLuint pitch, GLuint height); | ||||
|  | ||||
|  | ||||
| void intel_region_idle(intelScreenPrivate *intelScreen, | ||||
| 		       struct intel_region *ib); | ||||
|  | ||||
| /* Map/unmap regions.  This is refcounted also:  | ||||
|  */ | ||||
| GLubyte *intel_region_map(intelScreenPrivate *intelScreen, | ||||
|                           struct intel_region *ib); | ||||
|  | ||||
| void intel_region_unmap(intelScreenPrivate *intelScreen, struct intel_region *ib); | ||||
|  | ||||
|  | ||||
| /* Upload data to a rectangular sub-region | ||||
|  */ | ||||
| void intel_region_data(intelScreenPrivate *intelScreen, | ||||
|                        struct intel_region *dest, | ||||
|                        GLuint dest_offset, | ||||
|                        GLuint destx, GLuint desty, | ||||
|                        void *src, GLuint src_stride, | ||||
|                        GLuint srcx, GLuint srcy, GLuint width, GLuint height); | ||||
|  | ||||
| /* Copy rectangular sub-regions | ||||
|  */ | ||||
| void intel_region_copy(intelScreenPrivate *intelScreen, | ||||
|                        struct intel_region *dest, | ||||
|                        GLuint dest_offset, | ||||
|                        GLuint destx, GLuint desty, | ||||
|                        struct intel_region *src, | ||||
|                        GLuint src_offset, | ||||
|                        GLuint srcx, GLuint srcy, GLuint width, GLuint height); | ||||
|  | ||||
| /* Fill a rectangular sub-region | ||||
|  */ | ||||
| void intel_region_fill(intelScreenPrivate *intelScreen, | ||||
|                        struct intel_region *dest, | ||||
|                        GLuint dest_offset, | ||||
|                        GLuint destx, GLuint desty, | ||||
|                        GLuint width, GLuint height, GLuint color); | ||||
|  | ||||
| /* Helpers for zerocopy uploads, particularly texture image uploads: | ||||
|  */ | ||||
| void intel_region_attach_pbo(intelScreenPrivate *intelScreen, | ||||
|                              struct intel_region *region, | ||||
|                              struct intel_buffer_object *pbo); | ||||
| void intel_region_release_pbo(intelScreenPrivate *intelScreen, | ||||
|                               struct intel_region *region); | ||||
| void intel_region_cow(intelScreenPrivate *intelScreen, | ||||
|                       struct intel_region *region); | ||||
|  | ||||
| struct _DriBufferObject *intel_region_buffer(intelScreenPrivate *intelScreen, | ||||
|                                              struct intel_region *region, | ||||
|                                              GLuint flag); | ||||
|  | ||||
| #endif | ||||
| @@ -106,24 +106,27 @@ static const int scale_prim[GL_POLYGON+1] = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| static void intelDmaPrimitive( intelContextPtr intel, GLenum prim ) | ||||
| static void | ||||
| intelDmaPrimitive(struct intel_context *intel, GLenum prim) | ||||
| { | ||||
|    if (0) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|    INTEL_FIREVERTICES(intel); | ||||
|    intel->vtbl.reduced_primitive_state(intel, reduced_prim[prim]); | ||||
|    intelStartInlinePrimitive( intel, hw_prim[prim] ); | ||||
|    intelStartInlinePrimitive(intel, hw_prim[prim], INTEL_BATCH_CLIPRECTS); | ||||
| } | ||||
|  | ||||
|  | ||||
| #define LOCAL_VARS intelContextPtr intel = INTEL_CONTEXT(ctx) | ||||
| #define LOCAL_VARS struct intel_context *intel = intel_context(ctx) | ||||
| #define INIT( prim ) 				\ | ||||
| do {						\ | ||||
|    intelDmaPrimitive( intel, prim );		\ | ||||
| } while (0) | ||||
|  | ||||
| #define FLUSH() INTEL_FIREVERTICES(intel) | ||||
|  | ||||
| #define GET_SUBSEQUENT_VB_MAX_VERTS() \ | ||||
|   (((intel->alloc.size / 2) - 1500) / (intel->vertex_size*4)) | ||||
|   ((BATCH_SZ - 1500) / (intel->vertex_size*4)) | ||||
| #define GET_CURRENT_VB_MAX_VERTS() GET_SUBSEQUENT_VB_MAX_VERTS() | ||||
|  | ||||
| #define ALLOC_VERTS( nr ) \ | ||||
| @@ -142,8 +145,8 @@ do {						\ | ||||
|  | ||||
| /* Heuristic to choose between the two render paths:   | ||||
|  */ | ||||
| static GLboolean choose_render( intelContextPtr intel, | ||||
| 				struct vertex_buffer *VB ) | ||||
| static GLboolean | ||||
| choose_render(struct intel_context *intel, struct vertex_buffer *VB) | ||||
| { | ||||
|    int vertsz = intel->vertex_size; | ||||
|    int cost_render = 0; | ||||
| @@ -191,10 +194,10 @@ static GLboolean choose_render( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean intel_run_render( GLcontext *ctx,  | ||||
| 				 struct tnl_pipeline_stage *stage ) | ||||
| static GLboolean | ||||
| intel_run_render(GLcontext * ctx, struct tnl_pipeline_stage *stage) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|    GLuint i; | ||||
| @@ -202,8 +205,7 @@ static GLboolean intel_run_render( GLcontext *ctx, | ||||
|    /* Don't handle clipping or indexed vertices. | ||||
|     */ | ||||
|    if (intel->RenderIndex != 0 || | ||||
|        !intel_validate_render( ctx, VB ) ||  | ||||
|        !choose_render( intel, VB )) { | ||||
|        !intel_validate_render(ctx, VB) || !choose_render(intel, VB)) { | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|  | ||||
| @@ -211,8 +213,7 @@ static GLboolean intel_run_render( GLcontext *ctx, | ||||
|  | ||||
|    tnl->Driver.Render.Start(ctx); | ||||
|  | ||||
|    for (i = 0 ; i < VB->PrimitiveCount ; i++) | ||||
|    { | ||||
|    for (i = 0; i < VB->PrimitiveCount; i++) { | ||||
|       GLuint prim = VB->Primitive[i].mode; | ||||
|       GLuint start = VB->Primitive[i].start; | ||||
|       GLuint length = VB->Primitive[i].count; | ||||
| @@ -220,17 +221,18 @@ static GLboolean intel_run_render( GLcontext *ctx, | ||||
|       if (!length) | ||||
|          continue; | ||||
|  | ||||
|       intel_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length, | ||||
| 						     prim ); | ||||
|       intel_render_tab_verts[prim & PRIM_MODE_MASK] (ctx, start, | ||||
|                                                      start + length, prim); | ||||
|    } | ||||
|  | ||||
|    tnl->Driver.Render.Finish(ctx); | ||||
|  | ||||
|    INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|    return GL_FALSE;             /* finished the pipe */ | ||||
| } | ||||
|  | ||||
| const struct tnl_pipeline_stage _intel_render_stage = | ||||
| { | ||||
| const struct tnl_pipeline_stage _intel_render_stage = { | ||||
|    "intel render", | ||||
|    NULL, | ||||
|    NULL, | ||||
|   | ||||
| @@ -15,11 +15,14 @@ | ||||
|  | ||||
| void | ||||
| matrix23Set(struct matrix23 *m, | ||||
|             int m00, int m01, int m02, | ||||
|             int m10, int m11, int m12) | ||||
|             int m00, int m01, int m02, int m10, int m11, int m12) | ||||
| { | ||||
|    m->m00 = m00;   m->m01 = m01;   m->m02 = m02; | ||||
|    m->m10 = m10;   m->m11 = m11;   m->m12 = m12; | ||||
|    m->m00 = m00; | ||||
|    m->m01 = m01; | ||||
|    m->m02 = m02; | ||||
|    m->m10 = m10; | ||||
|    m->m11 = m11; | ||||
|    m->m12 = m12; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -76,7 +79,8 @@ matrix23TransformDistance(const struct matrix23 *m, int *xDist, int *yDist) | ||||
|  * Transform the rect defined by (x, y, w, h) by m. | ||||
|  */ | ||||
| void | ||||
| matrix23TransformRect(const struct matrix23 *m, int *x, int *y, int *w, int *h) | ||||
| matrix23TransformRect(const struct matrix23 *m, int *x, int *y, int *w, | ||||
|                       int *h) | ||||
| { | ||||
|    int x0 = *x, y0 = *y; | ||||
|    int x1 = *x + *w, y1 = *y; | ||||
| @@ -129,16 +133,24 @@ void | ||||
| matrix23Flip(struct matrix23 *m, int width, int height, int xflip, int yflip) | ||||
| { | ||||
|    if (xflip) { | ||||
|       m->m00 = -1;  m->m01 = 0;   m->m02 = width - 1; | ||||
|       m->m00 = -1; | ||||
|       m->m01 = 0; | ||||
|       m->m02 = width - 1; | ||||
|    } | ||||
|    else { | ||||
|       m->m00 = 1;   m->m01 = 0;   m->m02 = 0; | ||||
|       m->m00 = 1; | ||||
|       m->m01 = 0; | ||||
|       m->m02 = 0; | ||||
|    } | ||||
|    if (yflip) { | ||||
|       m->m10 = 0;   m->m11 = -1;  m->m12 = height - 1; | ||||
|       m->m10 = 0; | ||||
|       m->m11 = -1; | ||||
|       m->m12 = height - 1; | ||||
|    } | ||||
|    else { | ||||
|       m->m10 = 0;   m->m11 = 1;   m->m12 = 0; | ||||
|       m->m10 = 0; | ||||
|       m->m11 = 1; | ||||
|       m->m12 = 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
| @@ -173,10 +185,14 @@ main(int argc, char *argv[]) | ||||
|    int coords[4][2]; | ||||
|  | ||||
|    /* four corner coords to test with */ | ||||
|    coords[0][0] = 0;  coords[0][1] = 0; | ||||
|    coords[1][0] = width-1;  coords[1][1] = 0; | ||||
|    coords[2][0] = width-1;  coords[2][1] = height-1; | ||||
|    coords[3][0] = 0;  coords[3][1] = height-1; | ||||
|    coords[0][0] = 0; | ||||
|    coords[0][1] = 0; | ||||
|    coords[1][0] = width - 1; | ||||
|    coords[1][1] = 0; | ||||
|    coords[2][0] = width - 1; | ||||
|    coords[2][1] = height - 1; | ||||
|    coords[3][0] = 0; | ||||
|    coords[3][1] = height - 1; | ||||
|  | ||||
|  | ||||
|    for (rot = 0; rot < 360; rot += 90) { | ||||
|   | ||||
| @@ -11,11 +11,9 @@ struct matrix23 | ||||
|  | ||||
| extern void | ||||
| matrix23Set(struct matrix23 *m, | ||||
|             int m00, int m01, int m02, | ||||
|             int m10, int m11, int m12); | ||||
|             int m00, int m01, int m02, int m10, int m11, int m12); | ||||
|  | ||||
| extern void | ||||
| matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y); | ||||
| extern void matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y); | ||||
|  | ||||
| extern void | ||||
| matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y); | ||||
|   | ||||
| @@ -38,24 +38,25 @@ | ||||
|  | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_span.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_fbo.h" | ||||
|  | ||||
| #include "i830_dri.h" | ||||
| #include "dri_bufpool.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| PUBLIC const char __driConfigOptions[] = | ||||
| DRI_CONF_BEGIN | ||||
|     DRI_CONF_SECTION_PERFORMANCE | ||||
|    DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE | ||||
|    DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) | ||||
|    DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) | ||||
|     DRI_CONF_SECTION_END | ||||
|     DRI_CONF_SECTION_QUALITY | ||||
|    DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY | ||||
|    DRI_CONF_FORCE_S3TC_ENABLE(false) | ||||
|    DRI_CONF_ALLOW_LARGE_TEXTURES(1) | ||||
|       DRI_CONF_SECTION_END | ||||
| DRI_CONF_END; | ||||
|    DRI_CONF_SECTION_END DRI_CONF_END; | ||||
|      const GLuint __driNConfigOptions = 4; | ||||
|  | ||||
| #ifdef USE_NEW_INTERFACE | ||||
| @@ -86,6 +87,7 @@ intelMapScreenRegions(__DRIscreenPrivate *sPriv) | ||||
|       _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!"); | ||||
|    } | ||||
|  | ||||
|    _mesa_printf("Back 0x%08x ", intelScreen->back.handle); | ||||
|    if (drmMap(sPriv->fd, | ||||
|               intelScreen->back.handle, | ||||
|               intelScreen->back.size, | ||||
| @@ -94,6 +96,7 @@ intelMapScreenRegions(__DRIscreenPrivate *sPriv) | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle); | ||||
|    if (drmMap(sPriv->fd, | ||||
|               intelScreen->depth.handle, | ||||
|               intelScreen->depth.size, | ||||
| @@ -102,6 +105,8 @@ intelMapScreenRegions(__DRIscreenPrivate *sPriv) | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
| #if 0 | ||||
|    _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle); | ||||
|    if (drmMap(sPriv->fd, | ||||
|               intelScreen->tex.handle, | ||||
|               intelScreen->tex.size, | ||||
| @@ -109,17 +114,111 @@ intelMapScreenRegions(__DRIscreenPrivate *sPriv) | ||||
|       intelUnmapScreenRegions(intelScreen); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
| #endif | ||||
|    if (0) | ||||
|       printf("Mappings:  front: %p  back: %p  depth: %p  tex: %p\n", | ||||
|              intelScreen->front.map, | ||||
|              intelScreen->back.map, | ||||
|           intelScreen->depth.map, | ||||
|           intelScreen->tex.map); | ||||
|              intelScreen->depth.map, intelScreen->tex.map); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static struct intel_region * | ||||
| intel_recreate_static(intelScreenPrivate *intelScreen, | ||||
| 		      struct intel_region *region, | ||||
| 		      GLuint mem_type, | ||||
| 		      GLuint offset, | ||||
| 		      void *virtual, | ||||
| 		      GLuint cpp, GLuint pitch, GLuint height) | ||||
| { | ||||
|   if (region) { | ||||
|     intel_region_update_static(intelScreen, region, mem_type, offset, | ||||
| 			       virtual, cpp, pitch, height); | ||||
|   } else { | ||||
|     region = intel_region_create_static(intelScreen, mem_type, offset, | ||||
| 					virtual, cpp, pitch, height); | ||||
|   } | ||||
|   return region; | ||||
| } | ||||
|      | ||||
|  | ||||
| /* Create intel_region structs to describe the static front,back,depth | ||||
|  * buffers created by the xserver.  | ||||
|  * | ||||
|  * Although FBO's mean we now no longer use these as render targets in | ||||
|  * all circumstances, they won't go away until the back and depth | ||||
|  * buffers become private, and the front and rotated buffers will | ||||
|  * remain even then. | ||||
|  * | ||||
|  * Note that these don't allocate video memory, just describe | ||||
|  * allocations alread made by the X server. | ||||
|  */ | ||||
| static void | ||||
| intel_recreate_static_regions(intelScreenPrivate *intelScreen) | ||||
| { | ||||
|    intelScreen->front_region = | ||||
|       intel_recreate_static(intelScreen, | ||||
| 			    intelScreen->front_region, | ||||
| 			    DRM_BO_FLAG_MEM_TT, | ||||
| 			    intelScreen->front.offset, | ||||
| 			    intelScreen->front.map, | ||||
| 			    intelScreen->cpp, | ||||
| 			    intelScreen->front.pitch / intelScreen->cpp, | ||||
| 			    intelScreen->height); | ||||
|  | ||||
|    intelScreen->rotated_region = | ||||
|       intel_recreate_static(intelScreen, | ||||
| 			    intelScreen->rotated_region, | ||||
| 			    DRM_BO_FLAG_MEM_TT, | ||||
| 			    intelScreen->rotated.offset, | ||||
| 			    intelScreen->rotated.map, | ||||
| 			    intelScreen->cpp, | ||||
| 			    intelScreen->rotated.pitch / | ||||
| 			    intelScreen->cpp, intelScreen->height); | ||||
|  | ||||
|  | ||||
|    intelScreen->back_region = | ||||
|       intel_recreate_static(intelScreen, | ||||
| 			    intelScreen->back_region, | ||||
| 			    DRM_BO_FLAG_MEM_TT, | ||||
| 			    intelScreen->back.offset, | ||||
| 			    intelScreen->back.map, | ||||
| 			    intelScreen->cpp, | ||||
| 			    intelScreen->back.pitch / intelScreen->cpp, | ||||
| 			    intelScreen->height); | ||||
|  | ||||
|    /* Still assuming front.cpp == depth.cpp | ||||
|     */ | ||||
|    intelScreen->depth_region = | ||||
|       intel_recreate_static(intelScreen, | ||||
| 			    intelScreen->depth_region, | ||||
| 			    DRM_BO_FLAG_MEM_TT, | ||||
| 			    intelScreen->depth.offset, | ||||
| 			    intelScreen->depth.map, | ||||
| 			    intelScreen->cpp, | ||||
| 			    intelScreen->depth.pitch / intelScreen->cpp, | ||||
| 			    intelScreen->height); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Use the information in the sarea to update the screen parameters | ||||
|  * related to screen rotation. Needs to be called locked. | ||||
|  */ | ||||
| void | ||||
| intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea) | ||||
| { | ||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; | ||||
|  | ||||
|    intelUnmapScreenRegions(intelScreen); | ||||
|    intelUpdateScreenFromSAREA(intelScreen, sarea); | ||||
|    if (!intelMapScreenRegions(sPriv)) { | ||||
|       fprintf(stderr, "ERROR Remapping screen regions!!!\n"); | ||||
|    } | ||||
|    intel_recreate_static_regions(intelScreen); | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelUnmapScreenRegions(intelScreenPrivate * intelScreen) | ||||
| { | ||||
| @@ -155,8 +254,7 @@ intelUnmapScreenRegions(intelScreenPrivate *intelScreen) | ||||
|  | ||||
| static void | ||||
| intelPrintDRIInfo(intelScreenPrivate * intelScreen, | ||||
|                   __DRIscreenPrivate *sPriv, | ||||
|                   I830DRIPtr gDRIPriv) | ||||
|                   __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv) | ||||
| { | ||||
|    fprintf(stderr, "*** Front size:   0x%x  offset: 0x%x  pitch: %d\n", | ||||
|            intelScreen->front.size, intelScreen->front.offset, | ||||
| @@ -179,7 +277,8 @@ intelPrintDRIInfo(intelScreenPrivate *intelScreen, | ||||
| static void | ||||
| intelPrintSAREA(const drmI830Sarea * sarea) | ||||
| { | ||||
|    fprintf(stderr, "SAREA: sarea width %d  height %d\n", sarea->width, sarea->height); | ||||
|    fprintf(stderr, "SAREA: sarea width %d  height %d\n", sarea->width, | ||||
|            sarea->height); | ||||
|    fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); | ||||
|    fprintf(stderr, | ||||
|            "SAREA: front offset: 0x%08x  size: 0x%x  handle: 0x%x\n", | ||||
| @@ -193,8 +292,7 @@ intelPrintSAREA(const drmI830Sarea *sarea) | ||||
|            sarea->depth_offset, sarea->depth_size, | ||||
|            (unsigned) sarea->depth_handle); | ||||
|    fprintf(stderr, "SAREA: tex   offset: 0x%08x  size: 0x%x  handle: 0x%x\n", | ||||
|            sarea->tex_offset, sarea->tex_size, | ||||
|            (unsigned) sarea->tex_handle); | ||||
|            sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle); | ||||
|    fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation); | ||||
|    fprintf(stderr, | ||||
|            "SAREA: rotated offset: 0x%08x  size: 0x%x\n", | ||||
| @@ -248,17 +346,20 @@ intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen, | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
| static GLboolean | ||||
| intelInitDriver(__DRIscreenPrivate * sPriv) | ||||
| { | ||||
|    intelScreenPrivate *intelScreen; | ||||
|    I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv; | ||||
|    drmI830Sarea *sarea; | ||||
|    PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = | ||||
|      (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension")); | ||||
|       (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface-> | ||||
|                                       getProcAddress("glxEnableExtension")); | ||||
|    void *const psc = sPriv->psc->screenConfigs; | ||||
|  | ||||
|    if (sPriv->devPrivSize != sizeof(I830DRIRec)) { | ||||
|       fprintf(stderr,"\nERROR!  sizeof(I830DRIRec) does not match passed size from device driver\n"); | ||||
|       fprintf(stderr, | ||||
|               "\nERROR!  sizeof(I830DRIRec) does not match passed size from device driver\n"); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
| @@ -283,16 +384,19 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|    intelScreen->cpp = gDRIPriv->cpp; | ||||
|  | ||||
|    switch (gDRIPriv->bitsPerPixel) { | ||||
|    case 15: intelScreen->fbFormat = DV_PF_555; break; | ||||
|    case 16: intelScreen->fbFormat = DV_PF_565; break; | ||||
|    case 32: intelScreen->fbFormat = DV_PF_8888; break; | ||||
|    case 16: | ||||
|       intelScreen->fbFormat = DV_PF_565; | ||||
|       break; | ||||
|    case 32: | ||||
|       intelScreen->fbFormat = DV_PF_8888; | ||||
|       break; | ||||
|    default: | ||||
|       exit(1); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    intelUpdateScreenFromSAREA(intelScreen, sarea); | ||||
|  | ||||
|    if (0) | ||||
|       intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); | ||||
|  | ||||
|    if (!intelMapScreenRegions(sPriv)) { | ||||
|       fprintf(stderr, "\nERROR!  mapping regions\n"); | ||||
|       _mesa_free(intelScreen); | ||||
| @@ -300,6 +404,29 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
| #if 0 | ||||
|  | ||||
|    /* | ||||
|     * FIXME: Remove this code and its references. | ||||
|     */ | ||||
|  | ||||
|    intelScreen->tex.offset = gDRIPriv->textureOffset; | ||||
|    intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity; | ||||
|    intelScreen->tex.handle = gDRIPriv->textures; | ||||
|    intelScreen->tex.size = gDRIPriv->textureSize; | ||||
|  | ||||
| #else | ||||
|    intelScreen->tex.offset = 0; | ||||
|    intelScreen->logTextureGranularity = 0; | ||||
|    intelScreen->tex.handle = 0; | ||||
|    intelScreen->tex.size = 0; | ||||
| #endif | ||||
|  | ||||
|    intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; | ||||
|  | ||||
|    if (1) | ||||
|       intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); | ||||
|  | ||||
|    intelScreen->drmMinor = sPriv->drmMinor; | ||||
|  | ||||
|    /* Determine if IRQs are active? */ | ||||
| @@ -340,111 +467,127 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|       (*glx_enable_extension) (psc, "GLX_MESA_swap_control"); | ||||
|       (*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage"); | ||||
|       (*glx_enable_extension) (psc, "GLX_SGI_make_current_read"); | ||||
|       (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" ); | ||||
|       (*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" ); | ||||
|    } | ||||
|  | ||||
|    sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA; | ||||
|    sPriv->psc->freeMemory     = (void *) intelFreeMemoryMESA; | ||||
|    sPriv->psc->memoryOffset   = (void *) intelGetMemoryOffsetMESA; | ||||
|    intelScreen->regionPool = driDRMPoolInit(sPriv->fd); | ||||
|    if (!intelScreen->regionPool) | ||||
|       return GL_FALSE; | ||||
|    intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd); | ||||
|    if (!intelScreen->staticPool) | ||||
|       return GL_FALSE; | ||||
|    intelScreen->texPool = intelScreen->regionPool; | ||||
|    intelScreen->batchPool = driBatchPoolInit(sPriv->fd, | ||||
|                                              DRM_BO_FLAG_EXE | | ||||
|                                              DRM_BO_FLAG_MEM_TT | | ||||
|                                              DRM_BO_FLAG_MEM_LOCAL, | ||||
|                                              4096, 100, 5); | ||||
|    intel_recreate_static_regions(intelScreen); | ||||
|  | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelDestroyScreen(__DRIscreenPrivate *sPriv) | ||||
| static void | ||||
| intelDestroyScreen(__DRIscreenPrivate * sPriv) | ||||
| { | ||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; | ||||
|  | ||||
|    intelUnmapScreenRegions(intelScreen); | ||||
|  | ||||
|    driPoolTakeDown(intelScreen->regionPool); | ||||
|    driPoolTakeDown(intelScreen->staticPool); | ||||
|    driPoolTakeDown(intelScreen->batchPool); | ||||
|    FREE(intelScreen); | ||||
|    sPriv->private = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv, | ||||
| /** | ||||
|  * This is called when we need to set up GL rendering to a new X window. | ||||
|  */ | ||||
| static GLboolean | ||||
| intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, | ||||
|                   __DRIdrawablePrivate * driDrawPriv, | ||||
| 				    const __GLcontextModes *mesaVis, | ||||
| 				    GLboolean isPixmap ) | ||||
|                   const __GLcontextModes * mesaVis, GLboolean isPixmap) | ||||
| { | ||||
|    intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private; | ||||
|  | ||||
|    if (isPixmap) { | ||||
|       return GL_FALSE;          /* not implemented */ | ||||
|    } else { | ||||
|    } | ||||
|    else { | ||||
|       GLboolean swStencil = (mesaVis->stencilBits > 0 && | ||||
|                              mesaVis->depthBits != 24); | ||||
|       GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8); | ||||
|  | ||||
|       struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); | ||||
|  | ||||
|       /* setup the hardware-based renderbuffers */ | ||||
|       { | ||||
|          driRenderbuffer *frontRb | ||||
|             = driNewRenderbuffer(GL_RGBA, | ||||
|                                  screen->front.map, | ||||
|          struct intel_renderbuffer *frontRb | ||||
|             = intel_create_renderbuffer(rgbFormat, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->front.offset, | ||||
|                                         screen->front.pitch, | ||||
|                                         screen->cpp, | ||||
|                                  screen->front.offset, screen->front.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(frontRb, mesaVis); | ||||
|                                         screen->front.map); | ||||
|          intel_set_span_functions(&frontRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); | ||||
|       } | ||||
|  | ||||
|       if (mesaVis->doubleBufferMode) { | ||||
|          driRenderbuffer *backRb | ||||
|             = driNewRenderbuffer(GL_RGBA, | ||||
|                                  screen->back.map, | ||||
|          struct intel_renderbuffer *backRb | ||||
|             = intel_create_renderbuffer(rgbFormat, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->back.offset, | ||||
|                                         screen->back.pitch, | ||||
|                                         screen->cpp, | ||||
|                                  screen->back.offset, screen->back.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(backRb, mesaVis); | ||||
|                                         screen->back.map); | ||||
|          intel_set_span_functions(&backRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); | ||||
|       } | ||||
|  | ||||
|       if (mesaVis->depthBits == 16) { | ||||
|          driRenderbuffer *depthRb | ||||
|             = driNewRenderbuffer(GL_DEPTH_COMPONENT16, | ||||
|                                  screen->depth.map, | ||||
|                                  screen->cpp, | ||||
|                                  screen->depth.offset, screen->depth.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(depthRb, mesaVis); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); | ||||
|       if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { | ||||
|          /* combined depth/stencil buffer */ | ||||
|          struct intel_renderbuffer *depthStencilRb | ||||
|             = intel_create_renderbuffer(GL_DEPTH24_STENCIL8_EXT, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->depth.offset, | ||||
|                                         screen->depth.pitch, | ||||
|                                         screen->cpp,    /* 4! */ | ||||
|                                         screen->depth.map); | ||||
|          intel_set_span_functions(&depthStencilRb->Base); | ||||
|          /* note: bind RB to two attachment points */ | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); | ||||
|       } | ||||
|       else if (mesaVis->depthBits == 24) { | ||||
|          driRenderbuffer *depthRb | ||||
|             = driNewRenderbuffer(GL_DEPTH_COMPONENT24, | ||||
|                                  screen->depth.map, | ||||
|                                  screen->cpp, | ||||
|                                  screen->depth.offset, screen->depth.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(depthRb, mesaVis); | ||||
|       else if (mesaVis->depthBits == 16) { | ||||
|          /* just 16-bit depth buffer, no hw stencil */ | ||||
|          struct intel_renderbuffer *depthRb | ||||
|             = intel_create_renderbuffer(GL_DEPTH_COMPONENT16, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->depth.offset, | ||||
|                                         screen->depth.pitch, | ||||
|                                         screen->cpp,    /* 2! */ | ||||
|                                         screen->depth.map); | ||||
|          intel_set_span_functions(&depthRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); | ||||
|       } | ||||
|  | ||||
|       if (mesaVis->stencilBits > 0 && !swStencil) { | ||||
|          driRenderbuffer *stencilRb | ||||
|             = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, | ||||
|                                  screen->depth.map, | ||||
|                                  screen->cpp, | ||||
|                                  screen->depth.offset, screen->depth.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(stencilRb, mesaVis); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); | ||||
|       } | ||||
|  | ||||
|       _mesa_add_soft_renderbuffers(fb, | ||||
|                                    GL_FALSE, /* color */ | ||||
|                                    GL_FALSE, /* depth */ | ||||
|                                    swStencil, | ||||
|                                    mesaVis->accumRedBits > 0, | ||||
|                                    GL_FALSE, /* alpha */ | ||||
|                                    GL_FALSE /* aux */); | ||||
|       /* now add any/all software-based renderbuffers we may need */ | ||||
|       _mesa_add_soft_renderbuffers(fb, GL_FALSE,        /* never sw color */ | ||||
|                                    GL_FALSE,    /* never sw depth */ | ||||
|                                    swStencil, mesaVis->accumRedBits > 0, GL_FALSE,      /* never sw alpha */ | ||||
|                                    GL_FALSE /* never sw aux */ ); | ||||
|       driDrawPriv->driverPrivate = (void *) fb; | ||||
|  | ||||
|       return (driDrawPriv->driverPrivate != NULL); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) | ||||
| static void | ||||
| intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) | ||||
| { | ||||
|    _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); | ||||
| } | ||||
| @@ -456,7 +599,7 @@ static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) | ||||
| static int | ||||
| intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) | ||||
| { | ||||
|    intelContextPtr intel; | ||||
|    struct intel_context *intel; | ||||
|  | ||||
|    if ((dPriv == NULL) || (dPriv->driContextPriv == NULL) | ||||
|        || (dPriv->driContextPriv->driverPrivate == NULL) | ||||
| @@ -492,7 +635,8 @@ extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, | ||||
| static GLboolean | ||||
| intelCreateContext(const __GLcontextModes * mesaVis, | ||||
|                    __DRIcontextPrivate * driContextPriv, | ||||
|                    void *sharedContextPrivate) | ||||
| { | ||||
| @@ -500,19 +644,19 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, | ||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; | ||||
|  | ||||
|    switch (intelScreen->deviceID) { | ||||
|       /* Don't deal with i830 until texture work complete: | ||||
|        */ | ||||
|    case PCI_CHIP_845_G: | ||||
|    case PCI_CHIP_I830_M: | ||||
|    case PCI_CHIP_I855_GM: | ||||
|    case PCI_CHIP_I865_G: | ||||
|       return i830CreateContext( mesaVis, driContextPriv,  | ||||
| 				sharedContextPrivate ); | ||||
|       return i830CreateContext(mesaVis, driContextPriv, sharedContextPrivate); | ||||
|  | ||||
|    case PCI_CHIP_I915_G: | ||||
|    case PCI_CHIP_I915_GM: | ||||
|    case PCI_CHIP_I945_G: | ||||
|    case PCI_CHIP_I945_GM: | ||||
|       return i915CreateContext( mesaVis, driContextPriv,  | ||||
| 			       sharedContextPrivate ); | ||||
|       return i915CreateContext(mesaVis, driContextPriv, sharedContextPrivate); | ||||
|  | ||||
|    default: | ||||
|       fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); | ||||
| @@ -589,22 +733,24 @@ intelFillInModes( unsigned pixel_bits, unsigned depth_bits, | ||||
|       fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; | ||||
|    } | ||||
|  | ||||
|    modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) ); | ||||
|    modes = | ||||
|       (*dri_interface->createContextModes) (num_modes, | ||||
|                                             sizeof(__GLcontextModes)); | ||||
|    m = modes; | ||||
|    if (!driFillInModes(&m, fb_format, fb_type, | ||||
| 			  depth_bits_array, stencil_bits_array, depth_buffer_factor, | ||||
| 			  back_buffer_modes, back_buffer_factor, | ||||
| 			  GLX_TRUE_COLOR ) ) { | ||||
| 	fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", | ||||
| 		 __func__, __LINE__ ); | ||||
|                        depth_bits_array, stencil_bits_array, | ||||
|                        depth_buffer_factor, back_buffer_modes, | ||||
|                        back_buffer_factor, GLX_TRUE_COLOR)) { | ||||
|       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, | ||||
|               __LINE__); | ||||
|       return NULL; | ||||
|    } | ||||
|    if (!driFillInModes(&m, fb_format, fb_type, | ||||
| 			  depth_bits_array, stencil_bits_array, depth_buffer_factor, | ||||
| 			  back_buffer_modes, back_buffer_factor, | ||||
| 			  GLX_DIRECT_COLOR ) ) { | ||||
| 	fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", | ||||
| 		 __func__, __LINE__ ); | ||||
|                        depth_bits_array, stencil_bits_array, | ||||
|                        depth_buffer_factor, back_buffer_modes, | ||||
|                        back_buffer_factor, GLX_DIRECT_COLOR)) { | ||||
|       fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, | ||||
|               __LINE__); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
| @@ -630,8 +776,9 @@ intelFillInModes( unsigned pixel_bits, unsigned depth_bits, | ||||
|  * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on  | ||||
|  *         failure. | ||||
|  */ | ||||
| PUBLIC | ||||
| void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, | ||||
| PUBLIC void * | ||||
| __driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn, | ||||
|                               __DRIscreen * psc, | ||||
|                               const __GLcontextModes * modes, | ||||
|                               const __DRIversion * ddx_version, | ||||
|                               const __DRIversion * dri_version, | ||||
| @@ -641,12 +788,11 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc | ||||
|                               int internal_api_version, | ||||
|                               const __DRIinterfaceMethods * interface, | ||||
|                               __GLcontextModes ** driver_modes) | ||||
| 			      | ||||
| { | ||||
|    __DRIscreenPrivate *psp; | ||||
|    static const __DRIversion ddx_expected = { 1, 5, 0 }; | ||||
|    static const __DRIversion dri_expected = { 4, 0, 0 }; | ||||
|    static const __DRIversion drm_expected = { 1, 4, 0 }; | ||||
|    static const __DRIversion drm_expected = { 1, 6, 0 }; | ||||
|  | ||||
|    dri_interface = interface; | ||||
|  | ||||
| @@ -665,8 +811,7 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc | ||||
|       I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv; | ||||
|       *driver_modes = intelFillInModes(dri_priv->cpp * 8, | ||||
|                                        (dri_priv->cpp == 2) ? 16 : 24, | ||||
| 					(dri_priv->cpp == 2) ? 0  : 8, | ||||
| 					1 ); | ||||
|                                        (dri_priv->cpp == 2) ? 0 : 8, 1); | ||||
|  | ||||
|       /* Calling driInitExtensions here, with a NULL context pointer, does not actually | ||||
|        * enable the extensions.  It just makes sure that all the dispatch offsets for all | ||||
| @@ -681,3 +826,19 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc | ||||
|  | ||||
|    return (void *) psp; | ||||
| } | ||||
|  | ||||
| struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) | ||||
| { | ||||
|   /* | ||||
|    * This should probably change to have the screen allocate a dummy | ||||
|    * context at screen creation. For now just use the current context. | ||||
|    */ | ||||
|  | ||||
|   GET_CURRENT_CONTEXT(ctx); | ||||
|   if (ctx == NULL) { | ||||
|      _mesa_problem(NULL, "No current context in intelScreenContext\n"); | ||||
|      return NULL; | ||||
|   } | ||||
|   return intel_context(ctx); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -29,14 +29,17 @@ | ||||
| #define _INTEL_INIT_H_ | ||||
|  | ||||
| #include <sys/time.h> | ||||
| #include "xmlconfig.h" | ||||
| #include "dri_util.h" | ||||
| #include "intel_rotate.h" | ||||
| #include "i830_common.h" | ||||
| #include "xmlconfig.h" | ||||
| #include "dri_bufpool.h" | ||||
|  | ||||
|  | ||||
| /* This roughly corresponds to a gl_renderbuffer (Mesa 6.4) */ | ||||
| typedef struct { | ||||
| /* XXX: change name or eliminate to avoid conflict with "struct | ||||
|  * intel_region"!!! | ||||
|  */ | ||||
| typedef struct | ||||
| { | ||||
|    drm_handle_t handle; | ||||
|    drmSize size;                /* region size in bytes */ | ||||
|    char *map;                   /* memory map */ | ||||
| @@ -52,13 +55,19 @@ typedef struct | ||||
|    intelRegion depth; | ||||
|    intelRegion tex; | ||||
|  | ||||
|    struct intel_region *front_region; | ||||
|    struct intel_region *back_region; | ||||
|    struct intel_region *depth_region; | ||||
|    struct intel_region *rotated_region; | ||||
|  | ||||
|    int deviceID; | ||||
|    int width; | ||||
|    int height; | ||||
|    int mem;                     /* unused */ | ||||
|  | ||||
|    int cpp;                     /* for front and back buffers */ | ||||
|    int fbFormat; | ||||
| /*    int bitsPerPixel;   */ | ||||
|    int fbFormat;                /* XXX FBO: this is obsolete - remove after i830 updates */ | ||||
|  | ||||
|    int logTextureGranularity; | ||||
|  | ||||
| @@ -79,34 +88,44 @@ typedef struct | ||||
|    * Configuration cache with default values for all contexts | ||||
|    */ | ||||
|    driOptionCache optionCache; | ||||
|    struct _DriBufferPool *batchPool; | ||||
|    struct _DriBufferPool *texPool; | ||||
|    struct _DriBufferPool *regionPool; | ||||
|    struct _DriBufferPool *staticPool; | ||||
| } intelScreenPrivate; | ||||
|  | ||||
|  | ||||
| extern GLboolean | ||||
| intelMapScreenRegions(__DRIscreenPrivate *sPriv); | ||||
|  | ||||
| extern void | ||||
| intelUnmapScreenRegions(intelScreenPrivate *intelScreen); | ||||
| extern GLboolean intelMapScreenRegions(__DRIscreenPrivate * sPriv); | ||||
|  | ||||
| extern void intelUnmapScreenRegions(intelScreenPrivate * intelScreen); | ||||
|  | ||||
| extern void | ||||
| intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen, | ||||
|                            drmI830Sarea * sarea); | ||||
|  | ||||
| extern void | ||||
| intelDestroyContext(__DRIcontextPrivate *driContextPriv); | ||||
| extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv); | ||||
|  | ||||
| extern GLboolean | ||||
| intelUnbindContext(__DRIcontextPrivate *driContextPriv); | ||||
| extern GLboolean intelUnbindContext(__DRIcontextPrivate * driContextPriv); | ||||
|  | ||||
| extern GLboolean | ||||
| intelMakeCurrent(__DRIcontextPrivate * driContextPriv, | ||||
|                  __DRIdrawablePrivate * driDrawPriv, | ||||
|                  __DRIdrawablePrivate * driReadPriv); | ||||
|  | ||||
| extern void | ||||
| intelSwapBuffers(__DRIdrawablePrivate *dPriv); | ||||
| extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); | ||||
|  | ||||
| extern void | ||||
| intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h); | ||||
|  | ||||
| extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags, | ||||
|                                                unsigned long bufSize, | ||||
|                                                unsigned numBufs, | ||||
|                                                unsigned checkDelayed); | ||||
|  | ||||
| extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen); | ||||
|  | ||||
| extern void | ||||
| intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -30,195 +30,346 @@ | ||||
| #include "mtypes.h" | ||||
| #include "colormac.h" | ||||
|  | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| #include "intel_span.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_tex.h" | ||||
|  | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| /* | ||||
|   break intelWriteRGBASpan_ARGB8888 | ||||
| */ | ||||
|  | ||||
| #undef DBG | ||||
| #define DBG 0 | ||||
|  | ||||
| #define LOCAL_VARS							\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch;					\ | ||||
|    GLuint height = dPriv->h;					\ | ||||
|    char *buf = (char *) drb->Base.Data +			\ | ||||
| 			dPriv->x * drb->cpp +			\ | ||||
| 			dPriv->y * pitch;			\ | ||||
|    GLushort p;							\ | ||||
|    (void) buf; (void) p | ||||
|    struct intel_context *intel = intel_context(ctx);			\ | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb);		\ | ||||
|    const GLint yScale = irb->RenderToTexture ? 1 : -1;			\ | ||||
|    const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;	\ | ||||
|    GLubyte *buf = (GLubyte *) irb->pfMap				\ | ||||
|       + (intel->drawY * irb->pfPitch + intel->drawX) * irb->region->cpp;\ | ||||
|    GLuint p;								\ | ||||
|    assert(irb->pfMap);\ | ||||
|    (void) p; | ||||
|  | ||||
| #define LOCAL_DEPTH_VARS					\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch;					\ | ||||
|    GLuint height = dPriv->h;					\ | ||||
|    char *buf = (char *) drb->Base.Data +			\ | ||||
| 			dPriv->x * drb->cpp +			\ | ||||
| 			dPriv->y * pitch | ||||
| /* XXX FBO: this is identical to the macro in spantmp2.h except we get | ||||
|  * the cliprect info from the context, not the driDrawable. | ||||
|  * Move this into spantmp2.h someday. | ||||
|  */ | ||||
| #define HW_CLIPLOOP()							\ | ||||
|    do {									\ | ||||
|       int _nc = intel->numClipRects;					\ | ||||
|       while ( _nc-- ) {							\ | ||||
| 	 int minx = intel->pClipRects[_nc].x1 - intel->drawX;		\ | ||||
| 	 int miny = intel->pClipRects[_nc].y1 - intel->drawY;		\ | ||||
| 	 int maxx = intel->pClipRects[_nc].x2 - intel->drawX;		\ | ||||
| 	 int maxy = intel->pClipRects[_nc].y2 - intel->drawY; | ||||
|  | ||||
| #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS  | ||||
|  | ||||
| #define INIT_MONO_PIXEL(p,color)\ | ||||
| 	 p = INTEL_PACKCOLOR565(color[0],color[1],color[2]) | ||||
|  | ||||
| #define Y_FLIP(_y) (height - _y - 1) | ||||
|  | ||||
| #define Y_FLIP(_y) ((_y) * yScale + yBias) | ||||
|  | ||||
| #define HW_LOCK() | ||||
|  | ||||
| #define HW_UNLOCK() | ||||
|  | ||||
| /* 16 bit, 565 rgb color spanline and pixel functions | ||||
| /* 16 bit, RGB565 color spanline and pixel functions | ||||
|  */ | ||||
| #define WRITE_RGBA( _x, _y, r, g, b, a )				\ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch)  = ( (((int)r & 0xf8) << 8) |	\ | ||||
| 		                             (((int)g & 0xfc) << 3) |	\ | ||||
| 		                             (((int)b & 0xf8) >> 3)) | ||||
| #define WRITE_PIXEL( _x, _y, p )  \ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch) = p | ||||
| #define SPANTMP_PIXEL_FMT GL_RGB | ||||
| #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5 | ||||
|  | ||||
| #define READ_RGBA( rgba, _x, _y )				\ | ||||
| do {								\ | ||||
|    GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch);		\ | ||||
|    rgba[0] = (((p >> 11) & 0x1f) * 255) / 31;			\ | ||||
|    rgba[1] = (((p >>  5) & 0x3f) * 255) / 63;			\ | ||||
|    rgba[2] = (((p >>  0) & 0x1f) * 255) / 31;			\ | ||||
|    rgba[3] = 255;						\ | ||||
| } while(0) | ||||
| #define TAG(x)    intel##x##_RGB565 | ||||
| #define TAG2(x,y) intel##x##_RGB565##y | ||||
| #define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 2) | ||||
| #include "spantmp2.h" | ||||
|  | ||||
| #define TAG(x) intel##x##_565 | ||||
| #include "spantmp.h" | ||||
|  | ||||
| /* 15 bit, 555 rgb color spanline and pixel functions | ||||
| /* 32 bit, ARGB8888 color spanline and pixel functions | ||||
|  */ | ||||
| #define WRITE_RGBA( _x, _y, r, g, b, a )			\ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch)  = (((r & 0xf8) << 7) |	\ | ||||
| 		                            ((g & 0xf8) << 3) |	\ | ||||
|                          		    ((b & 0xf8) >> 3)) | ||||
| #define SPANTMP_PIXEL_FMT GL_BGRA | ||||
| #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV | ||||
|  | ||||
| #define WRITE_PIXEL( _x, _y, p )  \ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch)  = p | ||||
| #define TAG(x)    intel##x##_ARGB8888 | ||||
| #define TAG2(x,y) intel##x##_ARGB8888##y | ||||
| #define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 4) | ||||
| #include "spantmp2.h" | ||||
|  | ||||
| #define READ_RGBA( rgba, _x, _y )				\ | ||||
| do {								\ | ||||
|    GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch);		\ | ||||
|    rgba[0] = (p >> 7) & 0xf8;					\ | ||||
|    rgba[1] = (p >> 3) & 0xf8;					\ | ||||
|    rgba[2] = (p << 3) & 0xf8;					\ | ||||
|    rgba[3] = 255;						\ | ||||
| } while(0) | ||||
|  | ||||
| #define TAG(x) intel##x##_555 | ||||
| #include "spantmp.h" | ||||
| #define LOCAL_DEPTH_VARS						\ | ||||
|    struct intel_context *intel = intel_context(ctx);			\ | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb);		\ | ||||
|    const GLuint pitch = irb->pfPitch/***XXX region->pitch*/; /* in pixels */ \ | ||||
|    const GLint yScale = irb->RenderToTexture ? 1 : -1;			\ | ||||
|    const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;	\ | ||||
|    char *buf = (char *) irb->pfMap/*XXX use region->map*/ +             \ | ||||
|       (intel->drawY * pitch + intel->drawX) * irb->region->cpp; | ||||
|  | ||||
| /* 16 bit depthbuffer functions. | ||||
|  */ | ||||
|  | ||||
| #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS | ||||
|  | ||||
| /** | ||||
|  ** 16-bit depthbuffer functions. | ||||
|  **/ | ||||
| #define WRITE_DEPTH( _x, _y, d ) \ | ||||
|    *(GLushort *)(buf + (_x)*2 + (_y)*pitch)  = d; | ||||
|    ((GLushort *)buf)[(_x) + (_y) * pitch] = d; | ||||
|  | ||||
| #define READ_DEPTH( d, _x, _y )	\ | ||||
|    d = *(GLushort *)(buf + (_x)*2 + (_y)*pitch);	  | ||||
|    d = ((GLushort *)buf)[(_x) + (_y) * pitch]; | ||||
|  | ||||
|  | ||||
| #define TAG(x) intel##x##_z16 | ||||
| #include "depthtmp.h" | ||||
|  | ||||
|  | ||||
| #undef LOCAL_VARS | ||||
| #define LOCAL_VARS						\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch;					\ | ||||
|    GLuint height = dPriv->h;					\ | ||||
|    char *buf = (char *)drb->Base.Data +				\ | ||||
| 			dPriv->x * drb->cpp +			\ | ||||
| 			dPriv->y * pitch;			\ | ||||
|    GLuint p;							\ | ||||
|    (void) buf; (void) p | ||||
|  | ||||
| #undef INIT_MONO_PIXEL | ||||
| #define INIT_MONO_PIXEL(p,color)\ | ||||
| 	 p = INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]) | ||||
|  | ||||
| /* 32 bit, 8888 argb color spanline and pixel functions | ||||
|  */ | ||||
| #define WRITE_RGBA(_x, _y, r, g, b, a)			\ | ||||
|     *(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) |	\ | ||||
| 					  (g << 8)  |	\ | ||||
| 					  (b << 0)  |	\ | ||||
| 					  (a << 24) ) | ||||
|  | ||||
| #define WRITE_PIXEL(_x, _y, p)			\ | ||||
|     *(GLuint *)(buf + _x*4 + _y*pitch) = p | ||||
|  | ||||
|  | ||||
| #define READ_RGBA(rgba, _x, _y)					\ | ||||
|     do {							\ | ||||
| 	GLuint p = *(GLuint *)(buf + _x*4 + _y*pitch);		\ | ||||
| 	rgba[0] = (p >> 16) & 0xff;				\ | ||||
| 	rgba[1] = (p >> 8)  & 0xff;				\ | ||||
| 	rgba[2] = (p >> 0)  & 0xff;				\ | ||||
| 	rgba[3] = (p >> 24) & 0xff;				\ | ||||
|     } while (0) | ||||
|  | ||||
| #define TAG(x) intel##x##_8888 | ||||
| #include "spantmp.h" | ||||
|  | ||||
|  | ||||
| /* 24/8 bit interleaved depth/stencil functions | ||||
|  */ | ||||
| /** | ||||
|  ** 24/8-bit interleaved depth/stencil functions | ||||
|  ** Note: we're actually reading back combined depth+stencil values. | ||||
|  ** The wrappers in main/depthstencil.c are used to extract the depth | ||||
|  ** and stencil values. | ||||
|  **/ | ||||
| /* Change ZZZS -> SZZZ */ | ||||
| #define WRITE_DEPTH( _x, _y, d ) {				\ | ||||
|    GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch);	\ | ||||
|    tmp &= 0xff000000;					\ | ||||
|    tmp |= (d) & 0xffffff;				\ | ||||
|    *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp;		\ | ||||
|    GLuint tmp = ((d) >> 8) | ((d) << 24);			\ | ||||
|    ((GLuint *)buf)[(_x) + (_y) * pitch] = tmp;			\ | ||||
| } | ||||
|  | ||||
| #define READ_DEPTH( d, _x, _y )		\ | ||||
|    d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) & 0xffffff; | ||||
|  | ||||
| /* Change SZZZ -> ZZZS */ | ||||
| #define READ_DEPTH( d, _x, _y ) {				\ | ||||
|    GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch];		\ | ||||
|    d = (tmp << 8) | (tmp >> 24);				\ | ||||
| } | ||||
|  | ||||
| #define TAG(x) intel##x##_z24_s8 | ||||
| #include "depthtmp.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  ** 8-bit stencil function (XXX FBO: This is obsolete) | ||||
|  **/ | ||||
| #define WRITE_STENCIL( _x, _y, d ) {				\ | ||||
|    GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch);	\ | ||||
|    GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch];		\ | ||||
|    tmp &= 0xffffff;						\ | ||||
|    tmp |= ((d) << 24);						\ | ||||
|    *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp;		\ | ||||
|    ((GLuint *) buf)[(_x) + (_y) * pitch] = tmp;			\ | ||||
| } | ||||
|  | ||||
| #define READ_STENCIL( d, _x, _y )				\ | ||||
|    d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) >> 24; | ||||
|    d = ((GLuint *)buf)[(_x) + (_y) * pitch] >> 24; | ||||
|  | ||||
| #define TAG(x) intel##x##_z24_s8 | ||||
| #include "stenciltmp.h" | ||||
|  | ||||
|  | ||||
| /* Move locking out to get reasonable span performance. | ||||
|  */ | ||||
| void intelSpanRenderStart( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    intelWaitForIdle(intel); | ||||
| /** | ||||
|  * Map or unmap all the renderbuffers which we may need during | ||||
|  * software rendering. | ||||
|  * XXX in the future, we could probably convey extra information to | ||||
|  * reduce the number of mappings needed.  I.e. if doing a glReadPixels | ||||
|  * from the depth buffer, we really only need one mapping. | ||||
|  * | ||||
|  * XXX Rewrite this function someday. | ||||
|  * We can probably just loop over all the renderbuffer attachments, | ||||
|  * map/unmap all of them, and not worry about the _ColorDrawBuffers | ||||
|  * _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields. | ||||
|  */ | ||||
| static void | ||||
| intel_map_unmap_buffers(struct intel_context *intel, GLboolean map) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLuint i, j; | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    /* color draw buffers */ | ||||
|    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { | ||||
|       for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers[i]; j++) { | ||||
|          struct gl_renderbuffer *rb = | ||||
|             ctx->DrawBuffer->_ColorDrawBuffers[i][j]; | ||||
|          irb = intel_renderbuffer(rb); | ||||
|          if (irb) { | ||||
|             /* this is a user-created intel_renderbuffer */ | ||||
|             if (irb->region) { | ||||
|                if (map) | ||||
|                   intel_region_map(intel->intelScreen, irb->region); | ||||
|                else | ||||
|                   intel_region_unmap(intel->intelScreen, irb->region); | ||||
|             } | ||||
|             irb->pfMap = irb->region->map; | ||||
|             irb->pfPitch = irb->region->pitch; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
| void intelSpanRenderFinish( GLcontext *ctx ) | ||||
|    /* check for render to textures */ | ||||
|    for (i = 0; i < BUFFER_COUNT; i++) { | ||||
|       struct gl_renderbuffer_attachment *att = | ||||
|          ctx->DrawBuffer->Attachment + i; | ||||
|       struct gl_texture_object *tex = att->Texture; | ||||
|       if (tex) { | ||||
|          /* render to texture */ | ||||
|          ASSERT(att->Renderbuffer); | ||||
|          if (map) { | ||||
|             struct gl_texture_image *texImg; | ||||
|             texImg = tex->Image[att->CubeMapFace][att->TextureLevel]; | ||||
|             intel_tex_map_images(intel, intel_texture_object(tex)); | ||||
|          } | ||||
|          else { | ||||
|             intel_tex_unmap_images(intel, intel_texture_object(tex)); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* color read buffers */ | ||||
|    irb = intel_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); | ||||
|    if (irb && irb->region) { | ||||
|       if (map) | ||||
|          intel_region_map(intel->intelScreen, irb->region); | ||||
|       else | ||||
|          intel_region_unmap(intel->intelScreen, irb->region); | ||||
|       irb->pfMap = irb->region->map; | ||||
|       irb->pfPitch = irb->region->pitch; | ||||
|    } | ||||
|  | ||||
|    /* Account for front/back color page flipping. | ||||
|     * The span routines use the pfMap and pfPitch fields which will | ||||
|     * swap the front/back region map/pitch if we're page flipped. | ||||
|     * Do this after mapping, above, so the map field is valid. | ||||
|     */ | ||||
| #if 0 | ||||
|    if (map && ctx->DrawBuffer->Name == 0) { | ||||
|       struct intel_renderbuffer *irbFront | ||||
|          = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_FRONT_LEFT); | ||||
|       struct intel_renderbuffer *irbBack | ||||
|          = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_BACK_LEFT); | ||||
|       if (irbBack) { | ||||
|          /* double buffered */ | ||||
|          if (intel->sarea->pf_current_page == 0) { | ||||
|             irbFront->pfMap = irbFront->region->map; | ||||
|             irbFront->pfPitch = irbFront->region->pitch; | ||||
|             irbBack->pfMap = irbBack->region->map; | ||||
|             irbBack->pfPitch = irbBack->region->pitch; | ||||
|          } | ||||
|          else { | ||||
|             irbFront->pfMap = irbBack->region->map; | ||||
|             irbFront->pfPitch = irbBack->region->pitch; | ||||
|             irbBack->pfMap = irbFront->region->map; | ||||
|             irbBack->pfPitch = irbFront->region->pitch; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    /* depth buffer (Note wrapper!) */ | ||||
|    if (ctx->DrawBuffer->_DepthBuffer) { | ||||
|       irb = intel_renderbuffer(ctx->DrawBuffer->_DepthBuffer->Wrapped); | ||||
|       if (irb && irb->region && irb->Base.Name != 0) { | ||||
|          if (map) { | ||||
|             intel_region_map(intel->intelScreen, irb->region); | ||||
|             irb->pfMap = irb->region->map; | ||||
|             irb->pfPitch = irb->region->pitch; | ||||
|          } | ||||
|          else { | ||||
|             intel_region_unmap(intel->intelScreen, irb->region); | ||||
|             irb->pfMap = NULL; | ||||
|             irb->pfPitch = 0; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* stencil buffer (Note wrapper!) */ | ||||
|    if (ctx->DrawBuffer->_StencilBuffer) { | ||||
|       irb = intel_renderbuffer(ctx->DrawBuffer->_StencilBuffer->Wrapped); | ||||
|       if (irb && irb->region && irb->Base.Name != 0) { | ||||
|          if (map) { | ||||
|             intel_region_map(intel->intelScreen, irb->region); | ||||
|             irb->pfMap = irb->region->map; | ||||
|             irb->pfPitch = irb->region->pitch; | ||||
|          } | ||||
|          else { | ||||
|             intel_region_unmap(intel->intelScreen, irb->region); | ||||
|             irb->pfMap = NULL; | ||||
|             irb->pfPitch = 0; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Prepare for softare rendering.  Map current read/draw framebuffers' | ||||
|  * renderbuffes and all currently bound texture objects. | ||||
|  * | ||||
|  * Old note: Moved locking out to get reasonable span performance. | ||||
|  */ | ||||
| void | ||||
| intelSpanRenderStart(GLcontext * ctx) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint i; | ||||
|  | ||||
|    intelFinish(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
| #if 0 | ||||
|    /* Just map the framebuffer and all textures.  Bufmgr code will | ||||
|     * take care of waiting on the necessary fences: | ||||
|     */ | ||||
|    intel_region_map(intel->intelScreen, intel->front_region); | ||||
|    intel_region_map(intel->intelScreen, intel->back_region); | ||||
|    intel_region_map(intel->intelScreen, intel->intelScreen->depth_region); | ||||
| #endif | ||||
|  | ||||
|    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { | ||||
|       if (ctx->Texture.Unit[i]._ReallyEnabled) { | ||||
|          struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current; | ||||
|          intel_tex_map_images(intel, intel_texture_object(texObj)); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intel_map_unmap_buffers(intel, GL_TRUE); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Called when done softare rendering.  Unmap the buffers we mapped in | ||||
|  * the above function. | ||||
|  */ | ||||
| void | ||||
| intelSpanRenderFinish(GLcontext * ctx) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint i; | ||||
|  | ||||
|    _swrast_flush(ctx); | ||||
|  | ||||
|    /* Now unmap the framebuffer: | ||||
|     */ | ||||
| #if 0 | ||||
|    intel_region_unmap(intel, intel->front_region); | ||||
|    intel_region_unmap(intel, intel->back_region); | ||||
|    intel_region_unmap(intel, intel->intelScreen->depth_region); | ||||
| #endif | ||||
|  | ||||
|    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { | ||||
|       if (ctx->Texture.Unit[i]._ReallyEnabled) { | ||||
|          struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current; | ||||
|          intel_tex_unmap_images(intel, intel_texture_object(texObj)); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intel_map_unmap_buffers(intel, GL_FALSE); | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
| void intelInitSpanFuncs( GLcontext *ctx ) | ||||
|  | ||||
| void | ||||
| intelInitSpanFuncs(GLcontext * ctx) | ||||
| { | ||||
|    struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); | ||||
|    swdd->SpanRenderStart = intelSpanRenderStart; | ||||
| @@ -227,32 +378,32 @@ void intelInitSpanFuncs( GLcontext *ctx ) | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Plug in the Get/Put routines for the given driRenderbuffer. | ||||
|  * Plug in appropriate span read/write functions for the given renderbuffer. | ||||
|  * These are used for the software fallbacks. | ||||
|  */ | ||||
| void | ||||
| intelSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) | ||||
| intel_set_span_functions(struct gl_renderbuffer *rb) | ||||
| { | ||||
|    if (drb->Base.InternalFormat == GL_RGBA) { | ||||
|       if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) { | ||||
|          intelInitPointers_555(&drb->Base); | ||||
|    if (rb->_ActualFormat == GL_RGB5) { | ||||
|       /* 565 RGB */ | ||||
|       intelInitPointers_RGB565(rb); | ||||
|    } | ||||
|       else if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { | ||||
|          intelInitPointers_565(&drb->Base); | ||||
|    else if (rb->_ActualFormat == GL_RGBA8) { | ||||
|       /* 8888 RGBA */ | ||||
|       intelInitPointers_ARGB8888(rb); | ||||
|    } | ||||
|    else if (rb->_ActualFormat == GL_DEPTH_COMPONENT16) { | ||||
|       intelInitDepthPointers_z16(rb); | ||||
|    } | ||||
|    else if (rb->_ActualFormat == GL_DEPTH_COMPONENT24 ||        /* XXX FBO remove */ | ||||
|             rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) { | ||||
|       intelInitDepthPointers_z24_s8(rb); | ||||
|    } | ||||
|    else if (rb->_ActualFormat == GL_STENCIL_INDEX8_EXT) {       /* XXX FBO remove */ | ||||
|       intelInitStencilPointers_z24_s8(rb); | ||||
|    } | ||||
|    else { | ||||
|          assert(vis->redBits == 8); | ||||
|          assert(vis->greenBits == 8); | ||||
|          assert(vis->blueBits == 8); | ||||
|          intelInitPointers_8888(&drb->Base); | ||||
|       } | ||||
|    } | ||||
|    else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) { | ||||
|       intelInitDepthPointers_z16(&drb->Base); | ||||
|    } | ||||
|    else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) { | ||||
|       intelInitDepthPointers_z24_s8(&drb->Base); | ||||
|    } | ||||
|    else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) { | ||||
|       intelInitStencilPointers_z24_s8(&drb->Base); | ||||
|       _mesa_problem(NULL, | ||||
|                     "Unexpected _ActualFormat in intelSetSpanFunctions"); | ||||
|    } | ||||
| } | ||||
|   | ||||
| @@ -28,14 +28,11 @@ | ||||
| #ifndef _INTEL_SPAN_H | ||||
| #define _INTEL_SPAN_H | ||||
|  | ||||
| #include "drirenderbuffer.h" | ||||
|  | ||||
| extern void intelInitSpanFuncs(GLcontext * ctx); | ||||
|  | ||||
| extern void intelSpanRenderFinish(GLcontext * ctx); | ||||
| extern void intelSpanRenderStart(GLcontext * ctx); | ||||
|  | ||||
| extern void | ||||
| intelSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis); | ||||
| extern void intel_set_span_functions(struct gl_renderbuffer *rb); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -30,13 +30,17 @@ | ||||
| #include "context.h" | ||||
| #include "macros.h" | ||||
| #include "enums.h" | ||||
| #include "colormac.h" | ||||
| #include "dd.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_regions.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| int intel_translate_compare_func( GLenum func ) | ||||
| int | ||||
| intel_translate_compare_func(GLenum func) | ||||
| { | ||||
|    switch (func) { | ||||
|    case GL_NEVER: | ||||
| @@ -61,7 +65,8 @@ int intel_translate_compare_func( GLenum func ) | ||||
|    return COMPAREFUNC_ALWAYS; | ||||
| } | ||||
|  | ||||
| int intel_translate_stencil_op( GLenum op ) | ||||
| int | ||||
| intel_translate_stencil_op(GLenum op) | ||||
| { | ||||
|    switch (op) { | ||||
|    case GL_KEEP: | ||||
| @@ -85,7 +90,8 @@ int intel_translate_stencil_op( GLenum op ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| int intel_translate_blend_factor( GLenum factor ) | ||||
| int | ||||
| intel_translate_blend_factor(GLenum factor) | ||||
| { | ||||
|    switch (factor) { | ||||
|    case GL_ZERO: | ||||
| @@ -124,7 +130,8 @@ int intel_translate_blend_factor( GLenum factor ) | ||||
|    return BLENDFACT_ZERO; | ||||
| } | ||||
|  | ||||
| int intel_translate_logic_op( GLenum opcode ) | ||||
| int | ||||
| intel_translate_logic_op(GLenum opcode) | ||||
| { | ||||
|    switch (opcode) { | ||||
|    case GL_CLEAR: | ||||
| @@ -164,118 +171,193 @@ int intel_translate_logic_op( GLenum opcode ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelDrawBuffer(GLcontext *ctx, GLenum mode ) | ||||
|  | ||||
| static void | ||||
| intelClearColor(GLcontext * ctx, const GLfloat color[4]) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    int front = 0; | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLubyte clear[4]; | ||||
|  | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]); | ||||
|  | ||||
|    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) { | ||||
|    case BUFFER_BIT_FRONT_LEFT: | ||||
|       front = 1; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    case BUFFER_BIT_BACK_LEFT: | ||||
|       front = 0; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    default: | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE ); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if ( intel->sarea->pf_current_page == 1 )  | ||||
|       front ^= 1; | ||||
|     | ||||
|    intelSetFrontClipRects( intel ); | ||||
|  | ||||
|    if (front) { | ||||
|       intel->drawRegion = &intel->intelScreen->front; | ||||
|       intel->readRegion = &intel->intelScreen->front; | ||||
|    } else { | ||||
|       intel->drawRegion = &intel->intelScreen->back; | ||||
|       intel->readRegion = &intel->intelScreen->back; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.set_color_region( intel, intel->drawRegion ); | ||||
| } | ||||
|  | ||||
| static void intelReadBuffer( GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ | ||||
|    /* compute both 32 and 16-bit clear values */ | ||||
|    intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1], | ||||
|                                                clear[2], clear[3]); | ||||
|    intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelClearColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|  | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]); | ||||
|  | ||||
|    intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat, | ||||
| 				       intel->clear_red,  | ||||
| 				       intel->clear_green,  | ||||
| 				       intel->clear_blue,  | ||||
| 				       intel->clear_alpha); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelCalcViewport( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    const GLfloat *v = ctx->Viewport._WindowMap.m; | ||||
|    GLfloat *m = intel->ViewportMatrix.m; | ||||
|    GLint h = 0; | ||||
|  | ||||
|    if (intel->driDrawable)  | ||||
|       h = intel->driDrawable->h + SUBPIXEL_Y; | ||||
|  | ||||
|    /* See also intel_translate_vertex.  SUBPIXEL adjustments can be done | ||||
|     * via state vars, too. | ||||
| /** | ||||
|  * Update the viewport transformation matrix.  Depends on: | ||||
|  *  - viewport pos/size | ||||
|  *  - depthrange | ||||
|  *  - window pos/size or FBO size | ||||
|  */ | ||||
| static void | ||||
| intelCalcViewport(GLcontext * ctx) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    const GLfloat *v = ctx->Viewport._WindowMap.m; | ||||
|    const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; | ||||
|    GLfloat *m = intel->ViewportMatrix.m; | ||||
|    GLfloat yScale, yBias; | ||||
|  | ||||
|    if (ctx->DrawBuffer->Name) { | ||||
|       /* User created FBO */ | ||||
|       struct intel_renderbuffer *irb | ||||
|          = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]); | ||||
|       if (irb && !irb->RenderToTexture) { | ||||
|          /* y=0=top */ | ||||
|          yScale = -1.0; | ||||
|          yBias = irb->Base.Height; | ||||
|       } | ||||
|       else { | ||||
|          /* y=0=bottom */ | ||||
|          yScale = 1.0; | ||||
|          yBias = 0.0; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* window buffer, y=0=top */ | ||||
|       yScale = -1.0; | ||||
|       yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F; | ||||
|    } | ||||
|  | ||||
|    m[MAT_SX] = v[MAT_SX]; | ||||
|    m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X; | ||||
|    m[MAT_SY] = - v[MAT_SY]; | ||||
|    m[MAT_TY] = - v[MAT_TY] + h; | ||||
|    m[MAT_SZ] =   v[MAT_SZ] * intel->depth_scale; | ||||
|    m[MAT_TZ] =   v[MAT_TZ] * intel->depth_scale; | ||||
|  | ||||
|    m[MAT_SY] = v[MAT_SY] * yScale; | ||||
|    m[MAT_TY] = v[MAT_TY] * yScale + yBias + SUBPIXEL_Y; | ||||
|  | ||||
|    m[MAT_SZ] = v[MAT_SZ] * depthScale; | ||||
|    m[MAT_TZ] = v[MAT_TZ] * depthScale; | ||||
| } | ||||
|  | ||||
| static void intelViewport( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, | ||||
| 			  GLsizei width, GLsizei height ) | ||||
| static void | ||||
| intelViewport(GLcontext * ctx, | ||||
|               GLint x, GLint y, GLsizei width, GLsizei height) | ||||
| { | ||||
|    intelCalcViewport(ctx); | ||||
| } | ||||
|  | ||||
| static void intelDepthRange( GLcontext *ctx, | ||||
| 			    GLclampd nearval, GLclampd farval ) | ||||
| static void | ||||
| intelDepthRange(GLcontext * ctx, GLclampd nearval, GLclampd farval) | ||||
| { | ||||
|    intelCalcViewport(ctx); | ||||
| } | ||||
|  | ||||
| /* Fallback to swrast for select and feedback. | ||||
|  */ | ||||
| static void intelRenderMode( GLcontext *ctx, GLenum mode ) | ||||
| static void | ||||
| intelRenderMode(GLcontext * ctx, GLenum mode) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER)); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitStateFuncs( struct dd_function_table *functions ) | ||||
| void | ||||
| intelInitStateFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|    functions->DrawBuffer = intelDrawBuffer; | ||||
|    functions->ReadBuffer = intelReadBuffer; | ||||
|    functions->RenderMode = intelRenderMode; | ||||
|    functions->Viewport = intelViewport; | ||||
|    functions->DepthRange = intelDepthRange; | ||||
|    functions->ClearColor = intelClearColor; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intelInitState(GLcontext * ctx) | ||||
| { | ||||
|    /* Mesa should do this for us: | ||||
|     */ | ||||
|    ctx->Driver.AlphaFunc(ctx, ctx->Color.AlphaFunc, ctx->Color.AlphaRef); | ||||
|  | ||||
|    ctx->Driver.BlendColor(ctx, ctx->Color.BlendColor); | ||||
|  | ||||
|    ctx->Driver.BlendEquationSeparate(ctx, | ||||
|                                      ctx->Color.BlendEquationRGB, | ||||
|                                      ctx->Color.BlendEquationA); | ||||
|  | ||||
|    ctx->Driver.BlendFuncSeparate(ctx, | ||||
|                                  ctx->Color.BlendSrcRGB, | ||||
|                                  ctx->Color.BlendDstRGB, | ||||
|                                  ctx->Color.BlendSrcA, ctx->Color.BlendDstA); | ||||
|  | ||||
|    ctx->Driver.ColorMask(ctx, | ||||
|                          ctx->Color.ColorMask[RCOMP], | ||||
|                          ctx->Color.ColorMask[GCOMP], | ||||
|                          ctx->Color.ColorMask[BCOMP], | ||||
|                          ctx->Color.ColorMask[ACOMP]); | ||||
|  | ||||
|    ctx->Driver.CullFace(ctx, ctx->Polygon.CullFaceMode); | ||||
|    ctx->Driver.DepthFunc(ctx, ctx->Depth.Func); | ||||
|    ctx->Driver.DepthMask(ctx, ctx->Depth.Mask); | ||||
|  | ||||
|    ctx->Driver.Enable(ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled); | ||||
|    ctx->Driver.Enable(ctx, GL_BLEND, ctx->Color.BlendEnabled); | ||||
|    ctx->Driver.Enable(ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled); | ||||
|    ctx->Driver.Enable(ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled); | ||||
|    ctx->Driver.Enable(ctx, GL_CULL_FACE, ctx->Polygon.CullFlag); | ||||
|    ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test); | ||||
|    ctx->Driver.Enable(ctx, GL_DITHER, ctx->Color.DitherFlag); | ||||
|    ctx->Driver.Enable(ctx, GL_FOG, ctx->Fog.Enabled); | ||||
|    ctx->Driver.Enable(ctx, GL_LIGHTING, ctx->Light.Enabled); | ||||
|    ctx->Driver.Enable(ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag); | ||||
|    ctx->Driver.Enable(ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag); | ||||
|    ctx->Driver.Enable(ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled); | ||||
|    ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); | ||||
|    ctx->Driver.Enable(ctx, GL_TEXTURE_1D, GL_FALSE); | ||||
|    ctx->Driver.Enable(ctx, GL_TEXTURE_2D, GL_FALSE); | ||||
|    ctx->Driver.Enable(ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE); | ||||
|    ctx->Driver.Enable(ctx, GL_TEXTURE_3D, GL_FALSE); | ||||
|    ctx->Driver.Enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); | ||||
|  | ||||
|    ctx->Driver.Fogfv(ctx, GL_FOG_COLOR, ctx->Fog.Color); | ||||
|    ctx->Driver.Fogfv(ctx, GL_FOG_MODE, 0); | ||||
|    ctx->Driver.Fogfv(ctx, GL_FOG_DENSITY, &ctx->Fog.Density); | ||||
|    ctx->Driver.Fogfv(ctx, GL_FOG_START, &ctx->Fog.Start); | ||||
|    ctx->Driver.Fogfv(ctx, GL_FOG_END, &ctx->Fog.End); | ||||
|  | ||||
|    ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); | ||||
|  | ||||
|    { | ||||
|       GLfloat f = (GLfloat) ctx->Light.Model.ColorControl; | ||||
|       ctx->Driver.LightModelfv(ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f); | ||||
|    } | ||||
|  | ||||
|    ctx->Driver.LineWidth(ctx, ctx->Line.Width); | ||||
|    ctx->Driver.LogicOpcode(ctx, ctx->Color.LogicOp); | ||||
|    ctx->Driver.PointSize(ctx, ctx->Point.Size); | ||||
|    ctx->Driver.PolygonStipple(ctx, (const GLubyte *) ctx->PolygonStipple); | ||||
|    ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
|                        ctx->Scissor.Width, ctx->Scissor.Height); | ||||
|    ctx->Driver.ShadeModel(ctx, ctx->Light.ShadeModel); | ||||
|    ctx->Driver.StencilFuncSeparate(ctx, GL_FRONT, | ||||
|                                    ctx->Stencil.Function[0], | ||||
|                                    ctx->Stencil.Ref[0], | ||||
|                                    ctx->Stencil.ValueMask[0]); | ||||
|    ctx->Driver.StencilFuncSeparate(ctx, GL_BACK, | ||||
|                                    ctx->Stencil.Function[1], | ||||
|                                    ctx->Stencil.Ref[1], | ||||
|                                    ctx->Stencil.ValueMask[1]); | ||||
|    ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT, ctx->Stencil.WriteMask[0]); | ||||
|    ctx->Driver.StencilMaskSeparate(ctx, GL_BACK, ctx->Stencil.WriteMask[1]); | ||||
|    ctx->Driver.StencilOpSeparate(ctx, GL_FRONT, | ||||
|                                  ctx->Stencil.FailFunc[0], | ||||
|                                  ctx->Stencil.ZFailFunc[0], | ||||
|                                  ctx->Stencil.ZPassFunc[0]); | ||||
|    ctx->Driver.StencilOpSeparate(ctx, GL_BACK, | ||||
|                                  ctx->Stencil.FailFunc[1], | ||||
|                                  ctx->Stencil.ZFailFunc[1], | ||||
|                                  ctx->Stencil.ZPassFunc[1]); | ||||
|  | ||||
|  | ||||
|    /* XXX this isn't really needed */ | ||||
|    ctx->Driver.DrawBuffer(ctx, ctx->Color.DrawBuffer[0]); | ||||
| } | ||||
|   | ||||
| @@ -1,854 +1,161 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "mtypes.h" | ||||
| #include "imports.h" | ||||
| #include "macros.h" | ||||
| #include "simple_list.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "texstore.h" | ||||
| #include "texformat.h" | ||||
| #include "teximage.h" | ||||
| #include "texmem.h" | ||||
| #include "texobj.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "mm.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_TEXTURE | ||||
|  | ||||
| static GLboolean | ||||
| intelValidateClientStorage( intelContextPtr intel, GLenum target, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint srcWidth, GLint srcHeight,  | ||||
| 			    GLenum format, GLenum type,  const void *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage) | ||||
|  | ||||
| intelIsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    int texelBytes; | ||||
| #if 0 | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(texObj); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "intformat %s format %s type %s\n", | ||||
| 	      _mesa_lookup_enum_by_nr( internalFormat ), | ||||
| 	      _mesa_lookup_enum_by_nr( format ), | ||||
| 	      _mesa_lookup_enum_by_nr( type )); | ||||
|  | ||||
|    if (!ctx->Unpack.ClientStorage) | ||||
|       return 0; | ||||
|  | ||||
|    if (ctx->_ImageTransferState || | ||||
|        texImage->IsCompressed || | ||||
|        texObj->GenerateMipmap) | ||||
|       return 0; | ||||
|  | ||||
|  | ||||
|    /* This list is incomplete | ||||
|     */ | ||||
|    switch ( internalFormat ) { | ||||
|    case GL_RGBA: | ||||
|       if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_argb8888; | ||||
| 	 texelBytes = 4; | ||||
|       } | ||||
|       else | ||||
| 	 return 0; | ||||
|       break; | ||||
|  | ||||
|    case GL_RGB: | ||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_rgb565; | ||||
| 	 texelBytes = 2; | ||||
|       } | ||||
|       else | ||||
| 	 return 0; | ||||
|       break; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if ( format == GL_YCBCR_MESA &&  | ||||
| 	   type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_ycbcr_rev; | ||||
| 	 texelBytes = 2; | ||||
|       } | ||||
|       else if ( format == GL_YCBCR_MESA &&  | ||||
| 		(type == GL_UNSIGNED_SHORT_8_8_APPLE ||  | ||||
| 		 type == GL_UNSIGNED_BYTE)) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_ycbcr; | ||||
| 	 texelBytes = 2; | ||||
|       } | ||||
|       else | ||||
| 	 return 0; | ||||
|       break; | ||||
|        | ||||
| 	  | ||||
|    default: | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    /* Could deal with these packing issues, but currently don't: | ||||
|     */ | ||||
|    if (packing->SkipPixels ||  | ||||
|        packing->SkipRows ||  | ||||
|        packing->SwapBytes || | ||||
|        packing->LsbFirst) { | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    {       | ||||
|       GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, | ||||
| 						  format, type); | ||||
|  | ||||
|        | ||||
|       if (0) | ||||
| 	 fprintf(stderr, "%s: srcRowStride %d/%x\n",  | ||||
| 		 __FUNCTION__, srcRowStride, srcRowStride); | ||||
|  | ||||
|       /* Could check this later in upload, pitch restrictions could be | ||||
|        * relaxed, but would need to store the image pitch somewhere, | ||||
|        * as packing details might change before image is uploaded: | ||||
|        */ | ||||
|       if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) || | ||||
| 	  (srcRowStride & 63)) | ||||
| 	 return 0; | ||||
|  | ||||
|  | ||||
|       /* Have validated that _mesa_transfer_teximage would be a straight | ||||
|        * memcpy at this point.  NOTE: future calls to TexSubImage will | ||||
|        * overwrite the client data.  This is explicitly mentioned in the | ||||
|        * extension spec. | ||||
|        */ | ||||
|       texImage->Data = (void *)pixels; | ||||
|       texImage->IsClientData = GL_TRUE; | ||||
|       texImage->RowStride = srcRowStride / texelBytes; | ||||
|    return | ||||
|       intelObj->mt && | ||||
|       intelObj->mt->region && | ||||
|       intel_is_region_resident(intel, intelObj->mt->region); | ||||
| #endif | ||||
|    return 1; | ||||
| } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint width, GLint border, | ||||
| 			    GLenum format, GLenum type, const GLvoid *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage ) | ||||
| static struct gl_texture_image * | ||||
| intelNewTextureImage(GLcontext * ctx) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|  | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    _mesa_store_teximage1d( ctx, target, level, internalFormat, | ||||
| 			   width, border, format, type, | ||||
| 			   pixels, packing, texObj, texImage ); | ||||
|  | ||||
|    t->dirty_images[0] |= (1 << level); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    (void) ctx; | ||||
|    return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image); | ||||
| } | ||||
|  | ||||
| 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 ) | ||||
|  | ||||
| static struct gl_texture_object * | ||||
| intelNewTextureObject(GLcontext * ctx, GLuint name, GLenum target) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    _mesa_initialize_texture_object(&obj->base, name, target); | ||||
|  | ||||
|    _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,  | ||||
| 			     format, type, pixels, packing, texObj, | ||||
| 			     texImage); | ||||
|    return &obj->base; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Handles 2D, CUBE, RECT: | ||||
|  */ | ||||
| static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint width, GLint height, GLint border, | ||||
| 			    GLenum format, GLenum type, const GLvoid *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage ) | ||||
| static void  | ||||
| intelDeleteTextureObject(GLcontext *ctx, | ||||
| 			 struct gl_texture_object *texObj) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(texObj); | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    } | ||||
|    if (intelObj->mt) | ||||
|       intel_miptree_release(intel, &intelObj->mt); | ||||
|  | ||||
|    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); | ||||
|    _mesa_delete_texture_object(ctx, texObj); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                    GLint xoffset, GLint yoffset, GLint zoffset, | ||||
|                    GLsizei width, GLsizei height, GLsizei depth, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const GLvoid *pixels, | ||||
|                    const struct gl_pixelstore_attrib *packing, | ||||
|                    struct gl_texture_object *texObj, | ||||
|                    struct gl_texture_image *texImage ) | ||||
| intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|  | ||||
|    assert( t ); /* this _should_ be true */ | ||||
|    driSwapOutTextureObject( t ); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset, | ||||
|                              width, height, depth, | ||||
|                              format, type, pixels, packing, texObj, texImage); | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|    } | ||||
|  | ||||
|    t->dirty_images[0] |= (1 << level); | ||||
|    if (texImage->Data) { | ||||
|       free(texImage->Data); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) | ||||
| #ifndef __x86_64__ | ||||
| static unsigned | ||||
| fastrdtsc(void) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) tObj->DriverData; | ||||
|    unsigned eax; | ||||
|    __asm__ volatile ("\t" | ||||
|                      "pushl  %%ebx\n\t" | ||||
|                      "cpuid\n\t" ".byte 0x0f, 0x31\n\t" | ||||
|                      "popl %%ebx\n":"=a" (eax) | ||||
|                      :"0"(0) | ||||
|                      :"ecx", "edx", "cc"); | ||||
|  | ||||
|    if ( t != NULL ) { | ||||
|       intelFlush( ctx ); | ||||
|       driDestroyTextureObject( t ); | ||||
|    return eax; | ||||
| } | ||||
|     | ||||
|    /* 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 ) | ||||
| #else | ||||
| static unsigned | ||||
| fastrdtsc(void) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 && | ||||
| 			       intel->intelScreen->tex.size > 4*1024*1024); | ||||
|    unsigned eax; | ||||
|    __asm__ volatile ("\t" "cpuid\n\t" ".byte 0x0f, 0x31\n\t":"=a" (eax) | ||||
|                      :"0"(0) | ||||
|                      :"ecx", "edx", "ebx", "cc"); | ||||
|  | ||||
|    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; | ||||
|    return eax; | ||||
| } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { | ||||
|             return &_mesa_texformat_argb4444; | ||||
| #endif | ||||
|  | ||||
| static unsigned | ||||
| time_diff(unsigned t, unsigned t2) | ||||
| { | ||||
|    return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); | ||||
| } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { | ||||
| 	    return &_mesa_texformat_argb1555; | ||||
|  | ||||
|  | ||||
| /* The system memcpy (at least on ubuntu 5.10) has problems copying | ||||
|  * to agp (writecombined) memory from a source which isn't 64-byte | ||||
|  * aligned - there is a 4x performance falloff. | ||||
|  * | ||||
|  * The x86 __memcpy is immune to this but is slightly slower | ||||
|  * (10%-ish) than the system memcpy. | ||||
|  * | ||||
|  * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but | ||||
|  * isn't much faster than x86_memcpy for agp copies. | ||||
|  *  | ||||
|  * TODO: switch dynamically. | ||||
|  */ | ||||
| static void * | ||||
| do_memcpy(void *dest, const void *src, size_t n) | ||||
| { | ||||
|    if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) { | ||||
|       return __memcpy(dest, src, n); | ||||
|    } | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case 3: | ||||
|    case GL_RGB: | ||||
|    case GL_COMPRESSED_RGB: | ||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | ||||
| 	 return &_mesa_texformat_rgb565; | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGBA2: | ||||
|       return &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGB5_A1: | ||||
|       return &_mesa_texformat_argb1555; | ||||
|  | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGB5: | ||||
|    case GL_RGB4: | ||||
|    case GL_R3_G3_B2: | ||||
|       return &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_ALPHA: | ||||
|    case GL_ALPHA4: | ||||
|    case GL_ALPHA8: | ||||
|    case GL_ALPHA12: | ||||
|    case GL_ALPHA16: | ||||
|    case GL_COMPRESSED_ALPHA: | ||||
|       return &_mesa_texformat_a8; | ||||
|  | ||||
|    case 1: | ||||
|    case GL_LUMINANCE: | ||||
|    case GL_LUMINANCE4: | ||||
|    case GL_LUMINANCE8: | ||||
|    case GL_LUMINANCE12: | ||||
|    case GL_LUMINANCE16: | ||||
|    case GL_COMPRESSED_LUMINANCE: | ||||
|       return &_mesa_texformat_l8; | ||||
|  | ||||
|    case 2: | ||||
|    case GL_LUMINANCE_ALPHA: | ||||
|    case GL_LUMINANCE4_ALPHA4: | ||||
|    case GL_LUMINANCE6_ALPHA2: | ||||
|    case GL_LUMINANCE8_ALPHA8: | ||||
|    case GL_LUMINANCE12_ALPHA4: | ||||
|    case GL_LUMINANCE12_ALPHA12: | ||||
|    case GL_LUMINANCE16_ALPHA16: | ||||
|    case GL_COMPRESSED_LUMINANCE_ALPHA: | ||||
|       return &_mesa_texformat_al88; | ||||
|  | ||||
|    case GL_INTENSITY: | ||||
|    case GL_INTENSITY4: | ||||
|    case GL_INTENSITY8: | ||||
|    case GL_INTENSITY12: | ||||
|    case GL_INTENSITY16: | ||||
|    case GL_COMPRESSED_INTENSITY: | ||||
|       return &_mesa_texformat_i8; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if (type == GL_UNSIGNED_SHORT_8_8_MESA || | ||||
| 	  type == GL_UNSIGNED_BYTE) | ||||
|          return &_mesa_texformat_ycbcr; | ||||
|    else | ||||
|          return &_mesa_texformat_ycbcr_rev; | ||||
|  | ||||
|    case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgb_fxt1; | ||||
|    case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgba_fxt1; | ||||
|  | ||||
|    case GL_RGB_S3TC: | ||||
|    case GL_RGB4_S3TC: | ||||
|    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgb_dxt1; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt1; | ||||
|  | ||||
|    case GL_RGBA_S3TC: | ||||
|    case GL_RGBA4_S3TC: | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt3; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt5; | ||||
|  | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       return &_mesa_texformat_z16; | ||||
|  | ||||
|    default: | ||||
|       fprintf(stderr, "unexpected texture format %s in %s\n",  | ||||
| 	      _mesa_lookup_enum_by_nr(internalFormat), | ||||
| 	      __FUNCTION__); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return NULL; /* never get here */ | ||||
|       return memcpy(dest, src, n); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t) | ||||
| static void * | ||||
| timed_memcpy(void *dest, const void *src, size_t n) | ||||
| { | ||||
|    unsigned   i; | ||||
|    void *ret; | ||||
|    unsigned t1, t2; | ||||
|    double rate; | ||||
|  | ||||
|    if ( intel == NULL )  | ||||
|       return; | ||||
|    if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) | ||||
|       _mesa_printf("Warning - non-aligned texture copy!\n"); | ||||
|  | ||||
|    if ( t->age > intel->dirtyAge ) | ||||
|       intel->dirtyAge = t->age; | ||||
|    t1 = fastrdtsc(); | ||||
|    ret = do_memcpy(dest, src, n); | ||||
|    t2 = fastrdtsc(); | ||||
|  | ||||
|    for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) { | ||||
|       if ( t == intel->CurrentTexObj[ i ] )  | ||||
| 	 intel->CurrentTexObj[ i ] = NULL; | ||||
|    } | ||||
|    rate = time_diff(t1, t2); | ||||
|    rate /= (double) n; | ||||
|    _mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate); | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload an image from mesa's internal copy.  Image may be 1D, 2D or | ||||
|  * 3D.  Cubemaps are expanded elsewhere. | ||||
|  */ | ||||
| static void intelUploadTexImage( intelContextPtr intel, | ||||
| 				 intelTextureObjectPtr t, | ||||
| 				 const struct gl_texture_image *image, | ||||
| 				 const GLuint offset ) | ||||
| void | ||||
| intelInitTextureFuncs(struct dd_function_table *functions) | ||||
| { | ||||
|  | ||||
|    if (!image || !image->Data)  | ||||
|       return; | ||||
|  | ||||
|    if (image->Depth == 1 && image->IsClientData) { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "Blit uploading\n"); | ||||
|  | ||||
|       /* Do it with a blit. | ||||
|        */ | ||||
|       intelEmitCopyBlitLocked( intel, | ||||
| 			       image->TexFormat->TexelBytes, | ||||
| 			       image->RowStride, /* ? */ | ||||
| 			       intelGetMemoryOffsetMESA( NULL, 0, image->Data ), | ||||
| 			       t->Pitch / image->TexFormat->TexelBytes, | ||||
| 			       intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ), | ||||
| 			       0, 0, | ||||
| 			       0, 0, | ||||
| 			       image->Width, | ||||
| 			       image->Height); | ||||
|    } | ||||
|    else if (image->IsCompressed) { | ||||
|       GLuint row_len = image->Width * 2; | ||||
|       GLubyte *dst = (GLubyte *)(t->BufAddr + offset); | ||||
|       GLubyte *src = (GLubyte *)image->Data; | ||||
|       GLuint j; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr,  | ||||
| 		 "Upload image %dx%dx%d offset %xm row_len %x " | ||||
| 		 "pitch %x depth_pitch %x\n", | ||||
| 		 image->Width, image->Height, image->Depth, offset, | ||||
| 		 row_len, t->Pitch, t->depth_pitch); | ||||
|  | ||||
|       switch (image->InternalFormat) { | ||||
| 	case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
| 	case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
| 	case GL_RGB_S3TC: | ||||
| 	case GL_RGB4_S3TC: | ||||
| 	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
| 	  for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { | ||||
| 	    __memcpy(dst, src, row_len ); | ||||
| 	    src += row_len; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	case GL_RGBA_S3TC: | ||||
| 	case GL_RGBA4_S3TC: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
| 	  for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { | ||||
| 	    __memcpy(dst, src, (image->Width*4) ); | ||||
| 	    src += image->Width*4; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat); | ||||
| 	  break; | ||||
|       } | ||||
|    } | ||||
|    /* Time for another vtbl entry: | ||||
|     */ | ||||
|    else if (intel->intelScreen->deviceID == PCI_CHIP_I945_G || | ||||
|             intel->intelScreen->deviceID == PCI_CHIP_I945_GM) { | ||||
|       GLuint row_len = image->Width * image->TexFormat->TexelBytes; | ||||
|       GLubyte *dst = (GLubyte *)(t->BufAddr + offset); | ||||
|       GLubyte *src = (GLubyte *)image->Data; | ||||
|       GLuint d, j; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr,  | ||||
| 		 "Upload image %dx%dx%d offset %xm row_len %x " | ||||
| 		 "pitch %x depth_pitch %x\n", | ||||
| 		 image->Width, image->Height, image->Depth, offset, | ||||
| 		 row_len, t->Pitch, t->depth_pitch); | ||||
|  | ||||
|       if (row_len == t->Pitch) { | ||||
| 	 memcpy( dst, src, row_len * image->Height * image->Depth ); | ||||
|       } | ||||
|       else {  | ||||
| 	 GLuint x = 0, y = 0; | ||||
|  | ||||
| 	 for (d = 0 ; d < image->Depth ; d++) { | ||||
| 	    GLubyte *dst0 = dst + x + y * t->Pitch; | ||||
|  | ||||
| 	    for (j = 0 ; j < image->Height ; j++) { | ||||
| 	       __memcpy(dst0, src, row_len ); | ||||
| 	       src += row_len; | ||||
| 	       dst0 += t->Pitch; | ||||
| 	    } | ||||
|  | ||||
| 	    x += MIN2(4, row_len); /* Guess: 4 byte minimum alignment */ | ||||
| 	    if (x > t->Pitch) { | ||||
| 	       x = 0; | ||||
| 	       y += image->Height; | ||||
| 	    } | ||||
| 	 } | ||||
|       } | ||||
|  | ||||
|    } | ||||
|    else { | ||||
|       GLuint row_len = image->Width * image->TexFormat->TexelBytes; | ||||
|       GLubyte *dst = (GLubyte *)(t->BufAddr + offset); | ||||
|       GLubyte *src = (GLubyte *)image->Data; | ||||
|       GLuint d, j; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr,  | ||||
| 		 "Upload image %dx%dx%d offset %xm row_len %x " | ||||
| 		 "pitch %x depth_pitch %x\n", | ||||
| 		 image->Width, image->Height, image->Depth, offset, | ||||
| 		 row_len, t->Pitch, t->depth_pitch); | ||||
|  | ||||
|       if (row_len == t->Pitch) { | ||||
| 	 for (d = 0; d < image->Depth; d++) { | ||||
| 	    memcpy( dst, src, t->Pitch * image->Height ); | ||||
| 	    dst += t->depth_pitch; | ||||
| 	    src += row_len * image->Height; | ||||
| 	 } | ||||
|       } | ||||
|       else {  | ||||
| 	 for (d = 0 ; d < image->Depth ; d++) { | ||||
| 	    for (j = 0 ; j < image->Height ; j++) { | ||||
| 	       __memcpy(dst, src, row_len ); | ||||
| 	       src += row_len; | ||||
| 	       dst += t->Pitch; | ||||
| 	    } | ||||
|  | ||||
| 	    dst += t->depth_pitch - (t->Pitch * image->Height); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| int intelUploadTexImages( intelContextPtr intel,  | ||||
| 			  intelTextureObjectPtr t, | ||||
| 			  GLuint face) | ||||
| { | ||||
|    const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; | ||||
|    const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image; | ||||
|    int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes; | ||||
|  | ||||
|    /* Can we texture out of the existing client data? */ | ||||
|    if ( numLevels == 1 && | ||||
| 	firstImage->IsClientData && | ||||
| 	(pitch & 3) == 0) { | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "AGP texturing from client memory\n"); | ||||
|  | ||||
|       t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data ); | ||||
|       t->BufAddr = 0; | ||||
|       t->dirty = ~0; | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|    else { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE)  | ||||
| 	 fprintf(stderr, "Uploading client data to agp\n"); | ||||
|  | ||||
|       INTEL_FIREVERTICES( intel ); | ||||
|       LOCK_HARDWARE( intel ); | ||||
|  | ||||
|       if ( t->base.memBlock == NULL ) { | ||||
| 	 int heap; | ||||
|  | ||||
| 	 heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps, | ||||
| 				    (driTextureObject *) t ); | ||||
| 	 if ( heap == -1 ) { | ||||
| 	    UNLOCK_HARDWARE( intel ); | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
|  | ||||
| 	 /* Set the base offset of the texture image */ | ||||
| 	 t->BufAddr = (GLubyte *) (intel->intelScreen->tex.map +  | ||||
| 				   t->base.memBlock->ofs); | ||||
| 	 t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs; | ||||
| 	 t->dirty = ~0; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* Let the world know we've used this memory recently. | ||||
|        */ | ||||
|       driUpdateTextureLRU( (driTextureObject *) t ); | ||||
|  | ||||
|  | ||||
|       /* Upload any images that are new */ | ||||
|       if (t->base.dirty_images[face]) { | ||||
| 	 int i; | ||||
|  | ||||
|  	 intelWaitForIdle( intel ); | ||||
| 	     | ||||
| 	 for (i = 0 ; i < numLevels ; i++) {  | ||||
| 	    int level = i + t->base.firstLevel; | ||||
|  | ||||
| 	    if (t->base.dirty_images[face] & (1<<level)) { | ||||
|  | ||||
| 	       const struct gl_texture_image *image = t->image[face][i].image; | ||||
| 	       GLuint offset = t->image[face][i].offset; | ||||
|  | ||||
|      	       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	          fprintf(stderr, "upload level %d, offset %x\n",  | ||||
| 			  level, offset); | ||||
|  | ||||
| 	       intelUploadTexImage( intel, t, image, offset ); | ||||
| 	    } | ||||
| 	 } | ||||
| 	 t->base.dirty_images[face] = 0; | ||||
| 	 intel->perf_boxes |= I830_BOX_TEXTURE_LOAD; | ||||
|       } | ||||
|        | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Allocate a new texture object. | ||||
|  * Called via ctx->Driver.NewTextureObject. | ||||
|  * Note: this function will be called during context creation to | ||||
|  * allocate the default texture objects. | ||||
|  * Note: we could use containment here to 'derive' the driver-specific | ||||
|  * texture object from the core mesa gl_texture_object.  Not done at this time. | ||||
|  */ | ||||
| static struct gl_texture_object * | ||||
| intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target ) | ||||
| { | ||||
|    struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target); | ||||
|    INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj ); | ||||
|    return obj; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitTextureFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->NewTextureObject          = intelNewTextureObject; | ||||
|    functions->ChooseTextureFormat = intelChooseTextureFormat; | ||||
|    functions->TexImage1D = intelTexImage1D; | ||||
|    functions->TexImage2D = intelTexImage2D; | ||||
| @@ -856,16 +163,20 @@ void intelInitTextureFuncs( struct dd_function_table *functions ) | ||||
|    functions->TexSubImage1D = intelTexSubImage1D; | ||||
|    functions->TexSubImage2D = intelTexSubImage2D; | ||||
|    functions->TexSubImage3D = intelTexSubImage3D; | ||||
|    functions->CopyTexImage1D            = _swrast_copy_teximage1d; | ||||
|    functions->CopyTexImage2D            = _swrast_copy_teximage2d; | ||||
|    functions->CopyTexSubImage1D         = _swrast_copy_texsubimage1d; | ||||
|    functions->CopyTexSubImage2D         = _swrast_copy_texsubimage2d; | ||||
|    functions->CopyTexSubImage3D         = _swrast_copy_texsubimage3d; | ||||
|    functions->DeleteTexture             = intelDeleteTexture; | ||||
|    functions->UpdateTexturePalette      = NULL; | ||||
|    functions->IsTextureResident         = driIsTextureResident; | ||||
|    functions->TestProxyTexImage         = _mesa_test_proxy_teximage; | ||||
|    functions->DeleteTexture             = intelDeleteTexture; | ||||
|    functions->CompressedTexImage2D      = intelCompressedTexImage2D; | ||||
|    functions->CompressedTexSubImage2D   = intelCompressedTexSubImage2D; | ||||
|    functions->CopyTexImage1D = intelCopyTexImage1D; | ||||
|    functions->CopyTexImage2D = intelCopyTexImage2D; | ||||
|    functions->CopyTexSubImage1D = intelCopyTexSubImage1D; | ||||
|    functions->CopyTexSubImage2D = intelCopyTexSubImage2D; | ||||
|    functions->GetTexImage = intelGetTexImage; | ||||
|    functions->NewTextureObject = intelNewTextureObject; | ||||
|    functions->NewTextureImage = intelNewTextureImage; | ||||
|    functions->DeleteTexture = intelDeleteTextureObject; | ||||
|    functions->FreeTexImageData = intelFreeTextureImageData; | ||||
|    functions->UpdateTexturePalette = 0; | ||||
|    functions->IsTextureResident = intelIsTextureResident; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_BUFMGR) | ||||
|       functions->TextureMemCpy = timed_memcpy; | ||||
|    else | ||||
|       functions->TextureMemCpy = do_memcpy; | ||||
| } | ||||
|   | ||||
| @@ -35,11 +35,100 @@ | ||||
|  | ||||
| void intelInitTextureFuncs(struct dd_function_table *functions); | ||||
|  | ||||
| void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t ); | ||||
| int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t, | ||||
| 			  GLuint face ); | ||||
| const struct gl_texture_format *intelChooseTextureFormat(GLcontext * ctx, | ||||
|                                                          GLint internalFormat, | ||||
|                                                          GLenum format, | ||||
|                                                          GLenum type); | ||||
|  | ||||
|  | ||||
| void intelTexImage3D(GLcontext * ctx, | ||||
|                      GLenum target, GLint level, | ||||
|                      GLint internalFormat, | ||||
|                      GLint width, GLint height, GLint depth, | ||||
|                      GLint border, | ||||
|                      GLenum format, GLenum type, const void *pixels, | ||||
|                      const struct gl_pixelstore_attrib *packing, | ||||
|                      struct gl_texture_object *texObj, | ||||
|                      struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexSubImage3D(GLcontext * ctx, | ||||
|                         GLenum target, | ||||
|                         GLint level, | ||||
|                         GLint xoffset, GLint yoffset, GLint zoffset, | ||||
|                         GLsizei width, GLsizei height, GLsizei depth, | ||||
|                         GLenum format, GLenum type, | ||||
|                         const GLvoid * pixels, | ||||
|                         const struct gl_pixelstore_attrib *packing, | ||||
|                         struct gl_texture_object *texObj, | ||||
|                         struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexImage2D(GLcontext * ctx, | ||||
|                      GLenum target, GLint level, | ||||
|                      GLint internalFormat, | ||||
|                      GLint width, GLint height, GLint border, | ||||
|                      GLenum format, GLenum type, const void *pixels, | ||||
|                      const struct gl_pixelstore_attrib *packing, | ||||
|                      struct gl_texture_object *texObj, | ||||
|                      struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexSubImage2D(GLcontext * ctx, | ||||
|                         GLenum target, | ||||
|                         GLint level, | ||||
|                         GLint xoffset, GLint yoffset, | ||||
|                         GLsizei width, GLsizei height, | ||||
|                         GLenum format, GLenum type, | ||||
|                         const GLvoid * pixels, | ||||
|                         const struct gl_pixelstore_attrib *packing, | ||||
|                         struct gl_texture_object *texObj, | ||||
|                         struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexImage1D(GLcontext * ctx, | ||||
|                      GLenum target, GLint level, | ||||
|                      GLint internalFormat, | ||||
|                      GLint width, GLint border, | ||||
|                      GLenum format, GLenum type, const void *pixels, | ||||
|                      const struct gl_pixelstore_attrib *packing, | ||||
|                      struct gl_texture_object *texObj, | ||||
|                      struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexSubImage1D(GLcontext * ctx, | ||||
|                         GLenum target, | ||||
|                         GLint level, | ||||
|                         GLint xoffset, | ||||
|                         GLsizei width, | ||||
|                         GLenum format, GLenum type, | ||||
|                         const GLvoid * pixels, | ||||
|                         const struct gl_pixelstore_attrib *packing, | ||||
|                         struct gl_texture_object *texObj, | ||||
|                         struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                          GLenum internalFormat, | ||||
|                          GLint x, GLint y, GLsizei width, GLint border); | ||||
|  | ||||
| void intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                          GLenum internalFormat, | ||||
|                          GLint x, GLint y, GLsizei width, GLsizei height, | ||||
|                          GLint border); | ||||
|  | ||||
| void intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                             GLint xoffset, GLint x, GLint y, GLsizei width); | ||||
|  | ||||
| void intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                             GLint xoffset, GLint yoffset, | ||||
|                             GLint x, GLint y, GLsizei width, GLsizei height); | ||||
|  | ||||
| void intelGetTexImage(GLcontext * ctx, GLenum target, GLint level, | ||||
|                       GLenum format, GLenum type, GLvoid * pixels, | ||||
|                       struct gl_texture_object *texObj, | ||||
|                       struct gl_texture_image *texImage); | ||||
|  | ||||
| GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit); | ||||
|  | ||||
| void intel_tex_map_images(struct intel_context *intel, | ||||
|                           struct intel_texture_object *intelObj); | ||||
|  | ||||
| void intel_tex_unmap_images(struct intel_context *intel, | ||||
|                             struct intel_texture_object *intelObj); | ||||
|  | ||||
| GLboolean  | ||||
| intel_driReinitTextureHeap( driTexHeap *heap, | ||||
| 			    unsigned size ); | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										291
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,291 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "teximage.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_pixel.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Get the intel_region which is the source for any glCopyTex[Sub]Image call. | ||||
|  * | ||||
|  * Do the best we can using the blitter.  A future project is to use | ||||
|  * the texture engine and fragment programs for these copies. | ||||
|  */ | ||||
| static const struct intel_region * | ||||
| get_teximage_source(struct intel_context *intel, GLenum internalFormat) | ||||
| { | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    if (0) | ||||
|       _mesa_printf("%s %s\n", __FUNCTION__, | ||||
|                    _mesa_lookup_enum_by_nr(internalFormat)); | ||||
|  | ||||
|    switch (internalFormat) { | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16_ARB: | ||||
|       irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); | ||||
|       if (irb && irb->region && irb->region->cpp == 2) | ||||
|          return irb->region; | ||||
|       return NULL; | ||||
|    case GL_DEPTH24_STENCIL8_EXT: | ||||
|    case GL_DEPTH_STENCIL_EXT: | ||||
|       irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); | ||||
|       if (irb && irb->region && irb->region->cpp == 4) | ||||
|          return irb->region; | ||||
|       return NULL; | ||||
|    case GL_RGBA: | ||||
|       return intel_readbuf_region(intel); | ||||
|    case GL_RGB: | ||||
|       if (intel->intelScreen->cpp == 2) | ||||
|          return intel_readbuf_region(intel); | ||||
|       return NULL; | ||||
|    default: | ||||
|       return NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| do_copy_texsubimage(struct intel_context *intel, | ||||
|                     struct intel_texture_image *intelImage, | ||||
|                     GLenum internalFormat, | ||||
|                     GLint dstx, GLint dsty, | ||||
|                     GLint x, GLint y, GLsizei width, GLsizei height) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    const struct intel_region *src = | ||||
|       get_teximage_source(intel, internalFormat); | ||||
|  | ||||
|    if (!intelImage->mt || !src) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    { | ||||
|       GLuint image_offset = intel_miptree_image_offset(intelImage->mt, | ||||
|                                                        intelImage->face, | ||||
|                                                        intelImage->level); | ||||
|       const GLint orig_x = x; | ||||
|       const GLint orig_y = y; | ||||
|       const struct gl_framebuffer *fb = ctx->DrawBuffer; | ||||
|  | ||||
|       if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, | ||||
|                                &x, &y, &width, &height)) { | ||||
|          /* Update dst for clipped src.  Need to also clip the source rect. | ||||
|           */ | ||||
|          dstx += x - orig_x; | ||||
|          dsty += y - orig_y; | ||||
|  | ||||
|          if (ctx->ReadBuffer->Name == 0) { | ||||
|             /* reading from a window, adjust x, y */ | ||||
|             __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|             GLuint window_y; | ||||
|             /* window_y = position of window on screen if y=0=bottom */ | ||||
|             window_y = intel->intelScreen->height - (dPriv->y + dPriv->h); | ||||
|             y = window_y + y; | ||||
|             x += dPriv->x; | ||||
|          } | ||||
|          else { | ||||
|             /* reading from a FBO */ | ||||
|             /* invert Y */ | ||||
|             y = ctx->ReadBuffer->Height - y - 1; | ||||
|          } | ||||
|  | ||||
|  | ||||
|          /* A bit of fiddling to get the blitter to work with -ve | ||||
|           * pitches.  But we get a nice inverted blit this way, so it's | ||||
|           * worth it: | ||||
|           */ | ||||
|          intelEmitCopyBlit(intel, | ||||
|                            intelImage->mt->cpp, | ||||
|                            -src->pitch, | ||||
|                            src->buffer, | ||||
|                            src->height * src->pitch * src->cpp, | ||||
|                            intelImage->mt->pitch, | ||||
|                            intelImage->mt->region->buffer, | ||||
|                            image_offset, | ||||
|                            x, y + height, dstx, dsty, width, height); | ||||
|  | ||||
|          intel_batchbuffer_flush(intel->batch); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap -- this can be accelerated now. | ||||
|     * XXX Add a ctx->Driver.GenerateMipmaps() function? | ||||
|     */ | ||||
|    if (level == texObj->BaseLevel && texObj->GenerateMipmap) { | ||||
|       intel_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                     GLenum internalFormat, | ||||
|                     GLint x, GLint y, GLsizei width, GLint border) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = | ||||
|       &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_object *texObj = | ||||
|       _mesa_select_tex_object(ctx, texUnit, target); | ||||
|    struct gl_texture_image *texImage = | ||||
|       _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|  | ||||
|    if (border) | ||||
|       goto fail; | ||||
|  | ||||
|    /* Setup or redefine the texture object, mipmap tree and texture | ||||
|     * image.  Don't populate yet.   | ||||
|     */ | ||||
|    ctx->Driver.TexImage1D(ctx, target, level, internalFormat, | ||||
|                           width, border, | ||||
|                           GL_RGBA, CHAN_TYPE, NULL, | ||||
|                           &ctx->DefaultPacking, texObj, texImage); | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx), | ||||
|                             intel_texture_image(texImage), | ||||
|                             internalFormat, 0, 0, x, y, width, 1)) | ||||
|       goto fail; | ||||
|  | ||||
|    return; | ||||
|  | ||||
|  fail: | ||||
|    _swrast_copy_teximage1d(ctx, target, level, internalFormat, x, y, | ||||
|                            width, border); | ||||
| } | ||||
|  | ||||
| void | ||||
| intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                     GLenum internalFormat, | ||||
|                     GLint x, GLint y, GLsizei width, GLsizei height, | ||||
|                     GLint border) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = | ||||
|       &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_object *texObj = | ||||
|       _mesa_select_tex_object(ctx, texUnit, target); | ||||
|    struct gl_texture_image *texImage = | ||||
|       _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|  | ||||
|    if (border) | ||||
|       goto fail; | ||||
|  | ||||
|    /* Setup or redefine the texture object, mipmap tree and texture | ||||
|     * image.  Don't populate yet.   | ||||
|     */ | ||||
|    ctx->Driver.TexImage2D(ctx, target, level, internalFormat, | ||||
|                           width, height, border, | ||||
|                           GL_RGBA, CHAN_TYPE, NULL, | ||||
|                           &ctx->DefaultPacking, texObj, texImage); | ||||
|  | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx), | ||||
|                             intel_texture_image(texImage), | ||||
|                             internalFormat, 0, 0, x, y, width, height)) | ||||
|       goto fail; | ||||
|  | ||||
|    return; | ||||
|  | ||||
|  fail: | ||||
|    _swrast_copy_teximage2d(ctx, target, level, internalFormat, x, y, | ||||
|                            width, height, border); | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                        GLint xoffset, GLint x, GLint y, GLsizei width) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = | ||||
|       &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_image *texImage = | ||||
|       _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|    GLenum internalFormat = texImage->InternalFormat; | ||||
|  | ||||
|    /* XXX need to check <border> as in above function? */ | ||||
|  | ||||
|    /* Need to check texture is compatible with source format.  | ||||
|     */ | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx), | ||||
|                             intel_texture_image(texImage), | ||||
|                             internalFormat, xoffset, 0, x, y, width, 1)) { | ||||
|       _swrast_copy_texsubimage1d(ctx, target, level, xoffset, x, y, width); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, | ||||
|                        GLint xoffset, GLint yoffset, | ||||
|                        GLint x, GLint y, GLsizei width, GLsizei height) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = | ||||
|       &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_image *texImage = | ||||
|       _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|    GLenum internalFormat = texImage->InternalFormat; | ||||
|  | ||||
|  | ||||
|    /* Need to check texture is compatible with source format.  | ||||
|     */ | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx), | ||||
|                             intel_texture_image(texImage), | ||||
|                             internalFormat, | ||||
|                             xoffset, yoffset, x, y, width, height)) { | ||||
|       _swrast_copy_texsubimage2d(ctx, target, level, | ||||
|                                  xoffset, yoffset, x, y, width, height); | ||||
|    } | ||||
| } | ||||
							
								
								
									
										146
									
								
								src/mesa/drivers/dri/i915/intel_tex_format.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								src/mesa/drivers/dri/i915/intel_tex_format.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| #include "intel_context.h" | ||||
| #include "intel_tex.h" | ||||
| #include "texformat.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| /* It works out that this function is fine for all the supported | ||||
|  * hardware.  However, there is still a need to map the formats onto | ||||
|  * hardware descriptors. | ||||
|  */ | ||||
| /* Note that the i915 can actually support many more formats than | ||||
|  * these if we take the step of simply swizzling the colors | ||||
|  * immediately after sampling... | ||||
|  */ | ||||
| const struct gl_texture_format * | ||||
| intelChooseTextureFormat(GLcontext * ctx, GLint internalFormat, | ||||
|                          GLenum format, GLenum type) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    const GLboolean do32bpt = (intel->intelScreen->cpp == 4); | ||||
|  | ||||
|    switch (internalFormat) { | ||||
|    case 4: | ||||
|    case GL_RGBA: | ||||
|    case GL_COMPRESSED_RGBA: | ||||
|       if (format == GL_BGRA) { | ||||
|          if (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) { | ||||
|             return &_mesa_texformat_argb8888; | ||||
|          } | ||||
|          else if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) { | ||||
|             return &_mesa_texformat_argb4444; | ||||
|          } | ||||
|          else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) { | ||||
|             return &_mesa_texformat_argb1555; | ||||
|          } | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case 3: | ||||
|    case GL_RGB: | ||||
|    case GL_COMPRESSED_RGB: | ||||
|       if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) { | ||||
|          return &_mesa_texformat_rgb565; | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGBA2: | ||||
|       return &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGB5_A1: | ||||
|       return &_mesa_texformat_argb1555; | ||||
|  | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|       return &_mesa_texformat_argb8888; | ||||
|  | ||||
|    case GL_RGB5: | ||||
|    case GL_RGB4: | ||||
|    case GL_R3_G3_B2: | ||||
|       return &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_ALPHA: | ||||
|    case GL_ALPHA4: | ||||
|    case GL_ALPHA8: | ||||
|    case GL_ALPHA12: | ||||
|    case GL_ALPHA16: | ||||
|    case GL_COMPRESSED_ALPHA: | ||||
|       return &_mesa_texformat_a8; | ||||
|  | ||||
|    case 1: | ||||
|    case GL_LUMINANCE: | ||||
|    case GL_LUMINANCE4: | ||||
|    case GL_LUMINANCE8: | ||||
|    case GL_LUMINANCE12: | ||||
|    case GL_LUMINANCE16: | ||||
|    case GL_COMPRESSED_LUMINANCE: | ||||
|       return &_mesa_texformat_l8; | ||||
|  | ||||
|    case 2: | ||||
|    case GL_LUMINANCE_ALPHA: | ||||
|    case GL_LUMINANCE4_ALPHA4: | ||||
|    case GL_LUMINANCE6_ALPHA2: | ||||
|    case GL_LUMINANCE8_ALPHA8: | ||||
|    case GL_LUMINANCE12_ALPHA4: | ||||
|    case GL_LUMINANCE12_ALPHA12: | ||||
|    case GL_LUMINANCE16_ALPHA16: | ||||
|    case GL_COMPRESSED_LUMINANCE_ALPHA: | ||||
|       return &_mesa_texformat_al88; | ||||
|  | ||||
|    case GL_INTENSITY: | ||||
|    case GL_INTENSITY4: | ||||
|    case GL_INTENSITY8: | ||||
|    case GL_INTENSITY12: | ||||
|    case GL_INTENSITY16: | ||||
|    case GL_COMPRESSED_INTENSITY: | ||||
|       return &_mesa_texformat_i8; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE) | ||||
|          return &_mesa_texformat_ycbcr; | ||||
|       else | ||||
|          return &_mesa_texformat_ycbcr_rev; | ||||
|  | ||||
|    case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
|       return &_mesa_texformat_rgb_fxt1; | ||||
|    case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
|       return &_mesa_texformat_rgba_fxt1; | ||||
|  | ||||
|    case GL_RGB_S3TC: | ||||
|    case GL_RGB4_S3TC: | ||||
|    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
|       return &_mesa_texformat_rgb_dxt1; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt1; | ||||
|  | ||||
|    case GL_RGBA_S3TC: | ||||
|    case GL_RGBA4_S3TC: | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt3; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt5; | ||||
|  | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       return &_mesa_texformat_z16; | ||||
|  | ||||
|    default: | ||||
|       fprintf(stderr, "unexpected texture format %s in %s\n", | ||||
|               _mesa_lookup_enum_by_nr(internalFormat), __FUNCTION__); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return NULL;                 /* never get here */ | ||||
| } | ||||
							
								
								
									
										626
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										626
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,626 @@ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "macros.h" | ||||
| #include "mtypes.h" | ||||
| #include "enums.h" | ||||
| #include "colortab.h" | ||||
| #include "convolve.h" | ||||
| #include "context.h" | ||||
| #include "simple_list.h" | ||||
| #include "texcompress.h" | ||||
| #include "texformat.h" | ||||
| #include "texobj.h" | ||||
| #include "texstore.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_blit.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_TEXTURE | ||||
|  | ||||
| /* Functions to store texture images.  Where possible, mipmap_tree's | ||||
|  * will be created or further instantiated with image data, otherwise | ||||
|  * images will be stored in malloc'd memory.  A validation step is | ||||
|  * required to pull those images into a mipmap tree, or otherwise | ||||
|  * decide a fallback is required. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| static int | ||||
| logbase2(int n) | ||||
| { | ||||
|    GLint i = 1; | ||||
|    GLint log2 = 0; | ||||
|  | ||||
|    while (n > i) { | ||||
|       i *= 2; | ||||
|       log2++; | ||||
|    } | ||||
|  | ||||
|    return log2; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Otherwise, store it in memory if (Border != 0) or (any dimension == | ||||
|  * 1). | ||||
|  *     | ||||
|  * Otherwise, if max_level >= level >= min_level, create tree with | ||||
|  * space for textures from min_level down to max_level. | ||||
|  * | ||||
|  * Otherwise, create tree with space for textures from (level | ||||
|  * 0)..(1x1).  Consider pruning this tree at a validation if the | ||||
|  * saving is worth it. | ||||
|  */ | ||||
| static void | ||||
| guess_and_alloc_mipmap_tree(struct intel_context *intel, | ||||
|                             struct intel_texture_object *intelObj, | ||||
|                             struct intel_texture_image *intelImage) | ||||
| { | ||||
|    GLuint firstLevel; | ||||
|    GLuint lastLevel; | ||||
|    GLuint width = intelImage->base.Width; | ||||
|    GLuint height = intelImage->base.Height; | ||||
|    GLuint depth = intelImage->base.Depth; | ||||
|    GLuint l2width, l2height, l2depth; | ||||
|    GLuint i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (intelImage->base.Border) | ||||
|       return; | ||||
|  | ||||
|    if (intelImage->level > intelObj->base.BaseLevel && | ||||
|        (intelImage->base.Width == 1 || | ||||
|         (intelObj->base.Target != GL_TEXTURE_1D && | ||||
|          intelImage->base.Height == 1) || | ||||
|         (intelObj->base.Target == GL_TEXTURE_3D && | ||||
|          intelImage->base.Depth == 1))) | ||||
|       return; | ||||
|  | ||||
|    /* If this image disrespects BaseLevel, allocate from level zero. | ||||
|     * Usually BaseLevel == 0, so it's unlikely to happen. | ||||
|     */ | ||||
|    if (intelImage->level < intelObj->base.BaseLevel) | ||||
|       firstLevel = 0; | ||||
|    else | ||||
|       firstLevel = intelObj->base.BaseLevel; | ||||
|  | ||||
|  | ||||
|    /* Figure out image dimensions at start level.  | ||||
|     */ | ||||
|    for (i = intelImage->level; i > firstLevel; i--) { | ||||
|       width <<= 1; | ||||
|       if (height != 1) | ||||
|          height <<= 1; | ||||
|       if (depth != 1) | ||||
|          depth <<= 1; | ||||
|    } | ||||
|  | ||||
|    /* Guess a reasonable value for lastLevel.  This is probably going | ||||
|     * to be wrong fairly often and might mean that we have to look at | ||||
|     * resizable buffers, or require that buffers implement lazy | ||||
|     * pagetable arrangements. | ||||
|     */ | ||||
|    if ((intelObj->base.MinFilter == GL_NEAREST || | ||||
|         intelObj->base.MinFilter == GL_LINEAR) && | ||||
|        intelImage->level == firstLevel) { | ||||
|       lastLevel = firstLevel; | ||||
|    } | ||||
|    else { | ||||
|       l2width = logbase2(width); | ||||
|       l2height = logbase2(height); | ||||
|       l2depth = logbase2(depth); | ||||
|       lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); | ||||
|    } | ||||
|  | ||||
|    assert(!intelObj->mt); | ||||
|    intelObj->mt = intel_miptree_create(intel, | ||||
|                                        intelObj->base.Target, | ||||
|                                        intelImage->base.InternalFormat, | ||||
|                                        firstLevel, | ||||
|                                        lastLevel, | ||||
|                                        width, | ||||
|                                        height, | ||||
|                                        depth, | ||||
|                                        intelImage->base.TexFormat->TexelBytes, | ||||
|                                        intelImage->base.IsCompressed); | ||||
|  | ||||
|    DBG("%s - success\n", __FUNCTION__); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLuint | ||||
| target_to_face(GLenum target) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: | ||||
|       return ((GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); | ||||
|    default: | ||||
|       return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /* There are actually quite a few combinations this will work for, | ||||
|  * more than what I've listed here. | ||||
|  */ | ||||
| static GLboolean | ||||
| check_pbo_format(GLint internalFormat, | ||||
|                  GLenum format, GLenum type, | ||||
|                  const struct gl_texture_format *mesa_format) | ||||
| { | ||||
|    switch (internalFormat) { | ||||
|    case 4: | ||||
|    case GL_RGBA: | ||||
|       return (format == GL_BGRA && | ||||
|               (type == GL_UNSIGNED_BYTE || | ||||
|                type == GL_UNSIGNED_INT_8_8_8_8_REV) && | ||||
|               mesa_format == &_mesa_texformat_argb8888); | ||||
|    case 3: | ||||
|    case GL_RGB: | ||||
|       return (format == GL_RGB && | ||||
|               type == GL_UNSIGNED_SHORT_5_6_5 && | ||||
|               mesa_format == &_mesa_texformat_rgb565); | ||||
|    case GL_YCBCR_MESA: | ||||
|       return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE); | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* XXX: Do this for TexSubImage also: | ||||
|  */ | ||||
| static GLboolean | ||||
| try_pbo_upload(struct intel_context *intel, | ||||
|                struct intel_texture_image *intelImage, | ||||
|                const struct gl_pixelstore_attrib *unpack, | ||||
|                GLint internalFormat, | ||||
|                GLint width, GLint height, | ||||
|                GLenum format, GLenum type, const void *pixels) | ||||
| { | ||||
|    struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); | ||||
|    GLuint src_offset, src_stride; | ||||
|    GLuint dst_offset, dst_stride; | ||||
|  | ||||
|    if (!pbo || | ||||
|        intel->ctx._ImageTransferState || | ||||
|        unpack->SkipPixels || unpack->SkipRows) { | ||||
|       _mesa_printf("%s: failure 1\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    src_offset = (GLuint) pixels; | ||||
|  | ||||
|    if (unpack->RowLength > 0) | ||||
|       src_stride = unpack->RowLength; | ||||
|    else | ||||
|       src_stride = width; | ||||
|  | ||||
|    dst_offset = intel_miptree_image_offset(intelImage->mt, | ||||
|                                            intelImage->face, | ||||
|                                            intelImage->level); | ||||
|  | ||||
|    dst_stride = intelImage->mt->pitch; | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    { | ||||
|       struct _DriBufferObject *src_buffer = | ||||
|          intel_bufferobj_buffer(intel, pbo, INTEL_READ); | ||||
|       struct _DriBufferObject *dst_buffer = | ||||
|          intel_region_buffer(intel->intelScreen, intelImage->mt->region, | ||||
|                              INTEL_WRITE_FULL); | ||||
|  | ||||
|  | ||||
|       intelEmitCopyBlit(intel, | ||||
|                         intelImage->mt->cpp, | ||||
|                         src_stride, src_buffer, src_offset, | ||||
|                         dst_stride, dst_buffer, dst_offset, | ||||
|                         0, 0, 0, 0, width, height); | ||||
|  | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| try_pbo_zcopy(struct intel_context *intel, | ||||
|               struct intel_texture_image *intelImage, | ||||
|               const struct gl_pixelstore_attrib *unpack, | ||||
|               GLint internalFormat, | ||||
|               GLint width, GLint height, | ||||
|               GLenum format, GLenum type, const void *pixels) | ||||
| { | ||||
|    struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); | ||||
|    GLuint src_offset, src_stride; | ||||
|    GLuint dst_offset, dst_stride; | ||||
|  | ||||
|    if (!pbo || | ||||
|        intel->ctx._ImageTransferState || | ||||
|        unpack->SkipPixels || unpack->SkipRows) { | ||||
|       _mesa_printf("%s: failure 1\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    src_offset = (GLuint) pixels; | ||||
|  | ||||
|    if (unpack->RowLength > 0) | ||||
|       src_stride = unpack->RowLength; | ||||
|    else | ||||
|       src_stride = width; | ||||
|  | ||||
|    dst_offset = intel_miptree_image_offset(intelImage->mt, | ||||
|                                            intelImage->face, | ||||
|                                            intelImage->level); | ||||
|  | ||||
|    dst_stride = intelImage->mt->pitch; | ||||
|  | ||||
|    if (src_stride != dst_stride || dst_offset != 0 || src_offset != 0) { | ||||
|       _mesa_printf("%s: failure 2\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intel_region_attach_pbo(intel->intelScreen, intelImage->mt->region, pbo); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelTexImage(GLcontext * ctx, | ||||
|               GLint dims, | ||||
|               GLenum target, GLint level, | ||||
|               GLint internalFormat, | ||||
|               GLint width, GLint height, GLint depth, | ||||
|               GLint border, | ||||
|               GLenum format, GLenum type, const void *pixels, | ||||
|               const struct gl_pixelstore_attrib *unpack, | ||||
|               struct gl_texture_object *texObj, | ||||
|               struct gl_texture_image *texImage) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(texObj); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|    GLint postConvWidth = width; | ||||
|    GLint postConvHeight = height; | ||||
|    GLint texelBytes, sizeInBytes; | ||||
|    GLuint dstRowStride; | ||||
|  | ||||
|  | ||||
|    DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    intelImage->face = target_to_face(target); | ||||
|    intelImage->level = level; | ||||
|  | ||||
|    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { | ||||
|       _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, | ||||
|                                          &postConvHeight); | ||||
|    } | ||||
|  | ||||
|    /* choose the texture format */ | ||||
|    texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat, | ||||
|                                                   format, type); | ||||
|  | ||||
|    assert(texImage->TexFormat); | ||||
|  | ||||
|    switch (dims) { | ||||
|    case 1: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; | ||||
|       break; | ||||
|    case 2: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; | ||||
|       break; | ||||
|    case 3: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df; | ||||
|       break; | ||||
|    default: | ||||
|       assert(0); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    texelBytes = texImage->TexFormat->TexelBytes; | ||||
|  | ||||
|  | ||||
|    /* Minimum pitch of 32 bytes */ | ||||
|    if (postConvWidth * texelBytes < 32) { | ||||
|       postConvWidth = 32 / texelBytes; | ||||
|       texImage->RowStride = postConvWidth; | ||||
|    } | ||||
|  | ||||
|    assert(texImage->RowStride == postConvWidth); | ||||
|  | ||||
|    /* Release the reference to a potentially orphaned buffer.    | ||||
|     * Release any old malloced memory. | ||||
|     */ | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|       assert(!texImage->Data); | ||||
|    } | ||||
|    else if (texImage->Data) { | ||||
|       free(texImage->Data); | ||||
|    } | ||||
|  | ||||
|    /* If this is the only texture image in the tree, could call | ||||
|     * bmBufferData with NULL data to free the old block and avoid | ||||
|     * waiting on any outstanding fences. | ||||
|     */ | ||||
|    if (intelObj->mt && | ||||
|        intelObj->mt->first_level == level && | ||||
|        intelObj->mt->last_level == level && | ||||
|        intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB && | ||||
|        !intel_miptree_match_image(intelObj->mt, &intelImage->base, | ||||
|                                   intelImage->face, intelImage->level)) { | ||||
|  | ||||
|       DBG("release it\n"); | ||||
|       intel_miptree_release(intel, &intelObj->mt); | ||||
|       assert(!intelObj->mt); | ||||
|    } | ||||
|  | ||||
|    if (!intelObj->mt) { | ||||
|       guess_and_alloc_mipmap_tree(intel, intelObj, intelImage); | ||||
|       if (!intelObj->mt) { | ||||
| 	 DBG("guess_and_alloc_mipmap_tree: failed\n"); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    assert(!intelImage->mt); | ||||
|  | ||||
|    if (intelObj->mt && | ||||
|        intel_miptree_match_image(intelObj->mt, &intelImage->base, | ||||
|                                  intelImage->face, intelImage->level)) { | ||||
|  | ||||
|       intel_miptree_reference(&intelImage->mt, intelObj->mt); | ||||
|       assert(intelImage->mt); | ||||
|    } | ||||
|  | ||||
|    if (!intelImage->mt) | ||||
|       DBG("XXX: Image did not fit into tree - storing in local memory!\n"); | ||||
|  | ||||
|    /* PBO fastpaths: | ||||
|     */ | ||||
|    if (dims <= 2 && | ||||
|        intelImage->mt && | ||||
|        intel_buffer_object(unpack->BufferObj) && | ||||
|        check_pbo_format(internalFormat, format, | ||||
|                         type, intelImage->base.TexFormat)) { | ||||
|  | ||||
|       DBG("trying pbo upload\n"); | ||||
|  | ||||
|       /* Attempt to texture directly from PBO data (zero copy upload). | ||||
|        * | ||||
|        * Currently disable as it can lead to worse as well as better | ||||
|        * performance (in particular when intel_region_cow() is | ||||
|        * required). | ||||
|        */ | ||||
|       if (intelObj->mt == intelImage->mt && | ||||
|           intelObj->mt->first_level == level && | ||||
|           intelObj->mt->last_level == level) { | ||||
|  | ||||
|          if (try_pbo_zcopy(intel, intelImage, unpack, | ||||
|                            internalFormat, | ||||
|                            width, height, format, type, pixels)) { | ||||
|  | ||||
|             DBG("pbo zcopy upload succeeded\n"); | ||||
|             return; | ||||
|          } | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* Otherwise, attempt to use the blitter for PBO image uploads. | ||||
|        */ | ||||
|       if (try_pbo_upload(intel, intelImage, unpack, | ||||
|                          internalFormat, | ||||
|                          width, height, format, type, pixels)) { | ||||
|          DBG("pbo upload succeeded\n"); | ||||
|          return; | ||||
|       } | ||||
|  | ||||
|       DBG("pbo upload failed\n"); | ||||
|    } | ||||
|  | ||||
|  | ||||
|  | ||||
|    /* intelCopyTexImage calls this function with pixels == NULL, with | ||||
|     * the expectation that the mipmap tree will be set up but nothing | ||||
|     * more will be done.  This is where those calls return: | ||||
|     */ | ||||
|    pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, | ||||
|                                         format, type, | ||||
|                                         pixels, unpack, "glTexImage"); | ||||
|    if (!pixels) | ||||
|       return; | ||||
|  | ||||
|  | ||||
|    if (intelImage->mt) | ||||
|       intel_region_idle(intel->intelScreen, intelImage->mt->region); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       texImage->Data = intel_miptree_image_map(intel, | ||||
|                                                intelImage->mt, | ||||
|                                                intelImage->face, | ||||
|                                                intelImage->level, | ||||
|                                                &dstRowStride, | ||||
|                                                intelImage->base.ImageOffsets); | ||||
|    } | ||||
|    else { | ||||
|       /* Allocate regular memory and store the image there temporarily.   */ | ||||
|       if (texImage->IsCompressed) { | ||||
|          sizeInBytes = texImage->CompressedSize; | ||||
|          dstRowStride = | ||||
|             _mesa_compressed_row_stride(texImage->InternalFormat, width); | ||||
|          assert(dims != 3); | ||||
|       } | ||||
|       else { | ||||
|          dstRowStride = postConvWidth * texelBytes; | ||||
|          sizeInBytes = depth * dstRowStride * postConvHeight; | ||||
|       } | ||||
|  | ||||
|       texImage->Data = malloc(sizeInBytes); | ||||
|    } | ||||
|  | ||||
|    DBG("Upload image %dx%dx%d row_len %x " | ||||
|        "pitch %x\n", | ||||
|        width, height, depth, width * texelBytes, dstRowStride); | ||||
|  | ||||
|    /* Copy data.  Would like to know when it's ok for us to eg. use | ||||
|     * the blitter to copy.  Or, use the hardware to do the format | ||||
|     * conversion and copy: | ||||
|     */ | ||||
|    if (!texImage->TexFormat->StoreImage(ctx, dims,  | ||||
| 					texImage->_BaseFormat,  | ||||
| 					texImage->TexFormat,  | ||||
| 					texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */ | ||||
|                                         dstRowStride, | ||||
|                                         texImage->ImageOffsets, | ||||
|                                         width, height, depth, | ||||
|                                         format, type, pixels, unpack)) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); | ||||
|    } | ||||
|  | ||||
|    _mesa_unmap_teximage_pbo(ctx, unpack); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap -- this can be accelerated now. | ||||
|     */ | ||||
|    if (level == texObj->BaseLevel && texObj->GenerateMipmap) { | ||||
|       intel_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void | ||||
| intelTexImage3D(GLcontext * ctx, | ||||
|                 GLenum target, GLint level, | ||||
|                 GLint internalFormat, | ||||
|                 GLint width, GLint height, GLint depth, | ||||
|                 GLint border, | ||||
|                 GLenum format, GLenum type, const void *pixels, | ||||
|                 const struct gl_pixelstore_attrib *unpack, | ||||
|                 struct gl_texture_object *texObj, | ||||
|                 struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage(ctx, 3, target, level, | ||||
|                  internalFormat, width, height, depth, border, | ||||
|                  format, type, pixels, unpack, texObj, texImage); | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelTexImage2D(GLcontext * ctx, | ||||
|                 GLenum target, GLint level, | ||||
|                 GLint internalFormat, | ||||
|                 GLint width, GLint height, GLint border, | ||||
|                 GLenum format, GLenum type, const void *pixels, | ||||
|                 const struct gl_pixelstore_attrib *unpack, | ||||
|                 struct gl_texture_object *texObj, | ||||
|                 struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage(ctx, 2, target, level, | ||||
|                  internalFormat, width, height, 1, border, | ||||
|                  format, type, pixels, unpack, texObj, texImage); | ||||
| } | ||||
|  | ||||
| void | ||||
| intelTexImage1D(GLcontext * ctx, | ||||
|                 GLenum target, GLint level, | ||||
|                 GLint internalFormat, | ||||
|                 GLint width, GLint border, | ||||
|                 GLenum format, GLenum type, const void *pixels, | ||||
|                 const struct gl_pixelstore_attrib *unpack, | ||||
|                 struct gl_texture_object *texObj, | ||||
|                 struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage(ctx, 1, target, level, | ||||
|                  internalFormat, width, 1, 1, border, | ||||
|                  format, type, pixels, unpack, texObj, texImage); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Need to map texture image into memory before copying image data, | ||||
|  * then unmap it. | ||||
|  */ | ||||
| void | ||||
| intelGetTexImage(GLcontext * ctx, GLenum target, GLint level, | ||||
|                  GLenum format, GLenum type, GLvoid * pixels, | ||||
|                  struct gl_texture_object *texObj, | ||||
|                  struct gl_texture_image *texImage) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|  | ||||
|    /* Map */ | ||||
|    if (intelImage->mt) { | ||||
|       /* Image is stored in hardware format in a buffer managed by the | ||||
|        * kernel.  Need to explicitly map and unmap it. | ||||
|        */ | ||||
|       intelImage->base.Data = | ||||
|          intel_miptree_image_map(intel, | ||||
|                                  intelImage->mt, | ||||
|                                  intelImage->face, | ||||
|                                  intelImage->level, | ||||
|                                  &intelImage->base.RowStride, | ||||
|                                  intelImage->base.ImageOffsets); | ||||
|    } | ||||
|    else { | ||||
|       /* Otherwise, the image should actually be stored in | ||||
|        * intelImage->base.Data.  This is pretty confusing for | ||||
|        * everybody, I'd much prefer to separate the two functions of | ||||
|        * texImage->Data - storage for texture images in main memory | ||||
|        * and access (ie mappings) of images.  In other words, we'd | ||||
|        * create a new texImage->Map field and leave Data simply for | ||||
|        * storage. | ||||
|        */ | ||||
|       assert(intelImage->base.Data); | ||||
|    } | ||||
|  | ||||
|    _mesa_get_teximage(ctx, target, level, format, type, pixels, | ||||
|                       texObj, texImage); | ||||
|  | ||||
|    /* Unmap */ | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       intelImage->base.Data = NULL; | ||||
|    } | ||||
| } | ||||
							
								
								
									
										183
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | ||||
|  | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "texobj.h" | ||||
| #include "texstore.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_TEXTURE | ||||
|  | ||||
| static void | ||||
| intelTexSubimage(GLcontext * ctx, | ||||
|                  GLint dims, | ||||
|                  GLenum target, GLint level, | ||||
|                  GLint xoffset, GLint yoffset, GLint zoffset, | ||||
|                  GLint width, GLint height, GLint depth, | ||||
|                  GLenum format, GLenum type, const void *pixels, | ||||
|                  const struct gl_pixelstore_attrib *packing, | ||||
|                  struct gl_texture_object *texObj, | ||||
|                  struct gl_texture_image *texImage) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|    GLuint dstImageStride; | ||||
|    GLuint dstRowStride; | ||||
|  | ||||
|    DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, | ||||
|        _mesa_lookup_enum_by_nr(target), | ||||
|        level, xoffset, yoffset, width, height); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    pixels = | ||||
|       _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, | ||||
|                                   type, pixels, packing, "glTexSubImage2D"); | ||||
|    if (!pixels) | ||||
|       return; | ||||
|  | ||||
|    if (intelImage->mt) | ||||
|       intel_region_idle(intel->intelScreen, intelImage->mt->region); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* Map buffer if necessary.  Need to lock to prevent other contexts | ||||
|     * from uploading the buffer under us. | ||||
|     */ | ||||
|    if (intelImage->mt)  | ||||
|       texImage->Data = intel_miptree_image_map(intel, | ||||
|                                                intelImage->mt, | ||||
|                                                intelImage->face, | ||||
|                                                intelImage->level, | ||||
|                                                &dstRowStride, | ||||
|                                                &dstImageStride); | ||||
|  | ||||
|    assert(dstRowStride); | ||||
|  | ||||
|    if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, | ||||
|                                         texImage->TexFormat, | ||||
|                                         texImage->Data, | ||||
|                                         xoffset, yoffset, zoffset, | ||||
|                                         dstRowStride, | ||||
|                                         texImage->ImageOffsets, | ||||
|                                         width, height, depth, | ||||
|                                         format, type, pixels, packing)) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); | ||||
|    } | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap */ | ||||
|    if (level == texObj->BaseLevel && texObj->GenerateMipmap) { | ||||
|       _mesa_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    _mesa_unmap_teximage_pbo(ctx, packing); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intelTexSubImage3D(GLcontext * ctx, | ||||
|                    GLenum target, | ||||
|                    GLint level, | ||||
|                    GLint xoffset, GLint yoffset, GLint zoffset, | ||||
|                    GLsizei width, GLsizei height, GLsizei depth, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const GLvoid * pixels, | ||||
|                    const struct gl_pixelstore_attrib *packing, | ||||
|                    struct gl_texture_object *texObj, | ||||
|                    struct gl_texture_image *texImage) | ||||
| { | ||||
|  | ||||
|    intelTexSubimage(ctx, 3, | ||||
|                     target, level, | ||||
|                     xoffset, yoffset, zoffset, | ||||
|                     width, height, depth, | ||||
|                     format, type, pixels, packing, texObj, texImage); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intelTexSubImage2D(GLcontext * ctx, | ||||
|                    GLenum target, | ||||
|                    GLint level, | ||||
|                    GLint xoffset, GLint yoffset, | ||||
|                    GLsizei width, GLsizei height, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const GLvoid * pixels, | ||||
|                    const struct gl_pixelstore_attrib *packing, | ||||
|                    struct gl_texture_object *texObj, | ||||
|                    struct gl_texture_image *texImage) | ||||
| { | ||||
|  | ||||
|    intelTexSubimage(ctx, 2, | ||||
|                     target, level, | ||||
|                     xoffset, yoffset, 0, | ||||
|                     width, height, 1, | ||||
|                     format, type, pixels, packing, texObj, texImage); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelTexSubImage1D(GLcontext * ctx, | ||||
|                    GLenum target, | ||||
|                    GLint level, | ||||
|                    GLint xoffset, | ||||
|                    GLsizei width, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const GLvoid * pixels, | ||||
|                    const struct gl_pixelstore_attrib *packing, | ||||
|                    struct gl_texture_object *texObj, | ||||
|                    struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexSubimage(ctx, 1, | ||||
|                     target, level, | ||||
|                     xoffset, 0, 0, | ||||
|                     width, 1, 1, | ||||
|                     format, type, pixels, packing, texObj, texImage); | ||||
|  | ||||
| } | ||||
							
								
								
									
										253
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,253 @@ | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
|  | ||||
| #define FILE_DEBUG_FLAG DEBUG_TEXTURE | ||||
|  | ||||
| /** | ||||
|  * Compute which mipmap levels that really need to be sent to the hardware. | ||||
|  * This depends on the base image size, GL_TEXTURE_MIN_LOD, | ||||
|  * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. | ||||
|  */ | ||||
| static void | ||||
| intel_calculate_first_last_level(struct intel_texture_object *intelObj) | ||||
| { | ||||
|    struct gl_texture_object *tObj = &intelObj->base; | ||||
|    const struct gl_texture_image *const baseImage = | ||||
|       tObj->Image[0][tObj->BaseLevel]; | ||||
|  | ||||
|    /* These must be signed values.  MinLod and MaxLod can be negative numbers, | ||||
|     * and having firstLevel and lastLevel as signed prevents the need for | ||||
|     * extra sign checks. | ||||
|     */ | ||||
|    int firstLevel; | ||||
|    int lastLevel; | ||||
|  | ||||
|    /* Yes, this looks overly complicated, but it's all needed. | ||||
|     */ | ||||
|    switch (tObj->Target) { | ||||
|    case GL_TEXTURE_1D: | ||||
|    case GL_TEXTURE_2D: | ||||
|    case GL_TEXTURE_3D: | ||||
|    case GL_TEXTURE_CUBE_MAP: | ||||
|       if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { | ||||
|          /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. | ||||
|           */ | ||||
|          firstLevel = lastLevel = tObj->BaseLevel; | ||||
|       } | ||||
|       else { | ||||
|          firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5); | ||||
|          firstLevel = MAX2(firstLevel, tObj->BaseLevel); | ||||
|          lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); | ||||
|          lastLevel = MAX2(lastLevel, tObj->BaseLevel); | ||||
|          lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); | ||||
|          lastLevel = MIN2(lastLevel, tObj->MaxLevel); | ||||
|          lastLevel = MAX2(firstLevel, lastLevel);       /* need at least one level */ | ||||
|       } | ||||
|       break; | ||||
|    case GL_TEXTURE_RECTANGLE_NV: | ||||
|    case GL_TEXTURE_4D_SGIS: | ||||
|       firstLevel = lastLevel = 0; | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* save these values */ | ||||
|    intelObj->firstLevel = firstLevel; | ||||
|    intelObj->lastLevel = lastLevel; | ||||
| } | ||||
|  | ||||
| static void | ||||
| copy_image_data_to_tree(struct intel_context *intel, | ||||
|                         struct intel_texture_object *intelObj, | ||||
|                         struct intel_texture_image *intelImage) | ||||
| { | ||||
|    if (intelImage->mt) { | ||||
|       /* Copy potentially with the blitter: | ||||
|        */ | ||||
|       intel_miptree_image_copy(intel, | ||||
|                                intelObj->mt, | ||||
|                                intelImage->face, | ||||
|                                intelImage->level, intelImage->mt); | ||||
|  | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|    } | ||||
|    else { | ||||
|       assert(intelImage->base.Data != NULL); | ||||
|  | ||||
|       /* More straightforward upload.   | ||||
|        */ | ||||
|       intel_miptree_image_data(intel, | ||||
|                                intelObj->mt, | ||||
|                                intelImage->face, | ||||
|                                intelImage->level, | ||||
|                                intelImage->base.Data, | ||||
|                                intelImage->base.RowStride, | ||||
|                                intelImage->base.RowStride * | ||||
|                                intelImage->base.Height); | ||||
|  | ||||
|       free(intelImage->base.Data); | ||||
|       intelImage->base.Data = NULL; | ||||
|    } | ||||
|  | ||||
|    intel_miptree_reference(&intelImage->mt, intelObj->mt); | ||||
| } | ||||
|  | ||||
|  | ||||
| /*   | ||||
|  */ | ||||
| GLuint | ||||
| intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) | ||||
| { | ||||
|    struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(tObj); | ||||
|  | ||||
|    GLuint face, i; | ||||
|    GLuint nr_faces = 0; | ||||
|    struct intel_texture_image *firstImage; | ||||
|  | ||||
|    /* We know/require this is true by now:  | ||||
|     */ | ||||
|    assert(intelObj->base.Complete); | ||||
|  | ||||
|    /* What levels must the tree include at a minimum? | ||||
|     */ | ||||
|    intel_calculate_first_last_level(intelObj); | ||||
|    firstImage = | ||||
|       intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]); | ||||
|  | ||||
|    /* Fallback case: | ||||
|     */ | ||||
|    if (firstImage->base.Border) { | ||||
|       if (intelObj->mt) { | ||||
|          intel_miptree_release(intel, &intelObj->mt); | ||||
|       } | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* If both firstImage and intelObj have a tree which can contain | ||||
|     * all active images, favour firstImage.  Note that because of the | ||||
|     * completeness requirement, we know that the image dimensions | ||||
|     * will match. | ||||
|     */ | ||||
|    if (firstImage->mt && | ||||
|        firstImage->mt != intelObj->mt && | ||||
|        firstImage->mt->first_level <= intelObj->firstLevel && | ||||
|        firstImage->mt->last_level >= intelObj->lastLevel) { | ||||
|  | ||||
|       if (intelObj->mt) | ||||
|          intel_miptree_release(intel, &intelObj->mt); | ||||
|  | ||||
|       intel_miptree_reference(&intelObj->mt, firstImage->mt); | ||||
|    } | ||||
|  | ||||
|    /* Check tree can hold all active levels.  Check tree matches | ||||
|     * target, imageFormat, etc. | ||||
|     *  | ||||
|     * XXX: For some layouts (eg i945?), the test might have to be | ||||
|     * first_level == firstLevel, as the tree isn't valid except at the | ||||
|     * original start level.  Hope to get around this by | ||||
|     * programming minLod, maxLod, baseLevel into the hardware and | ||||
|     * leaving the tree alone. | ||||
|     */ | ||||
|    if (intelObj->mt && | ||||
|        ((intelObj->mt->first_level > intelObj->firstLevel) || | ||||
|         (intelObj->mt->last_level < intelObj->lastLevel) || | ||||
|         (intelObj->mt->internal_format != firstImage->base.InternalFormat))) { | ||||
|       intel_miptree_release(intel, &intelObj->mt); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* May need to create a new tree: | ||||
|     */ | ||||
|    if (!intelObj->mt) { | ||||
|       intelObj->mt = intel_miptree_create(intel, | ||||
|                                           intelObj->base.Target, | ||||
|                                           firstImage->base.InternalFormat, | ||||
|                                           intelObj->firstLevel, | ||||
|                                           intelObj->lastLevel, | ||||
|                                           firstImage->base.Width, | ||||
|                                           firstImage->base.Height, | ||||
|                                           firstImage->base.Depth, | ||||
|                                           firstImage->base.TexFormat-> | ||||
|                                           TexelBytes, | ||||
|                                           firstImage->base.IsCompressed); | ||||
|    } | ||||
|  | ||||
|    /* Pull in any images not in the object's tree: | ||||
|     */ | ||||
|    nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { | ||||
|          struct intel_texture_image *intelImage = | ||||
|             intel_texture_image(intelObj->base.Image[face][i]); | ||||
|  | ||||
|          /* Need to import images in main memory or held in other trees. | ||||
|           */ | ||||
|          if (intelObj->mt != intelImage->mt) { | ||||
|             copy_image_data_to_tree(intel, intelObj, intelImage); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intel_tex_map_images(struct intel_context *intel, | ||||
|                      struct intel_texture_object *intelObj) | ||||
| { | ||||
|    GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    GLuint face, i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { | ||||
|          struct intel_texture_image *intelImage = | ||||
|             intel_texture_image(intelObj->base.Image[face][i]); | ||||
|  | ||||
|          if (intelImage->mt) { | ||||
|             intelImage->base.Data = | ||||
|                intel_miptree_image_map(intel, | ||||
|                                        intelImage->mt, | ||||
|                                        intelImage->face, | ||||
|                                        intelImage->level, | ||||
|                                        &intelImage->base.RowStride, | ||||
|                                        intelImage->base.ImageOffsets); | ||||
|             /* convert stride to texels, not bytes */ | ||||
|             intelImage->base.RowStride /= intelImage->mt->cpp; | ||||
| /*             intelImage->base.ImageStride /= intelImage->mt->cpp; */ | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void | ||||
| intel_tex_unmap_images(struct intel_context *intel, | ||||
|                        struct intel_texture_object *intelObj) | ||||
| { | ||||
|    GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    GLuint face, i; | ||||
|  | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { | ||||
|          struct intel_texture_image *intelImage = | ||||
|             intel_texture_image(intelObj->base.Image[face][i]); | ||||
|  | ||||
|          if (intelImage->mt) { | ||||
|             intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|             intelImage->base.Data = NULL; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
| @@ -1,72 +0,0 @@ | ||||
| #include "texmem.h" | ||||
| #include "simple_list.h" | ||||
| #include "imports.h" | ||||
| #include "macros.h" | ||||
|  | ||||
| #include "intel_tex.h" | ||||
|  | ||||
| static GLuint | ||||
| driLog2( GLuint n ) | ||||
| { | ||||
|    GLuint log2; | ||||
|  | ||||
|    for ( log2 = 1 ; n > 1 ; log2++ ) { | ||||
|       n >>= 1; | ||||
|    } | ||||
|  | ||||
|    return log2; | ||||
| } | ||||
|  | ||||
| static void calculate_heap_size( driTexHeap * heap, unsigned size,  | ||||
| 				 unsigned nr_regions, unsigned alignmentShift ) | ||||
| { | ||||
|    unsigned     l; | ||||
|  | ||||
|    l = driLog2( (size - 1) / nr_regions ); | ||||
|    if ( l < alignmentShift ) | ||||
|    { | ||||
|       l = alignmentShift; | ||||
|    } | ||||
|  | ||||
|    heap->logGranularity = l; | ||||
|    heap->size = size & ~((1L << l) - 1); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean  | ||||
| intel_driReinitTextureHeap( driTexHeap *heap, | ||||
| 			    unsigned size ) | ||||
| { | ||||
|    driTextureObject *t, *tmp; | ||||
|  | ||||
|    /* Kick out everything: | ||||
|     */ | ||||
|    foreach_s ( t, tmp, & heap->texture_objects ) { | ||||
|       if ( t->tObj != NULL ) { | ||||
| 	 driSwapOutTextureObject( t ); | ||||
|       } | ||||
|       else { | ||||
| 	 driDestroyTextureObject( t ); | ||||
|       } | ||||
|    } | ||||
|     | ||||
|    /* Destroy the memory manager: | ||||
|     */ | ||||
|    mmDestroy( heap->memory_heap ); | ||||
|        | ||||
|    /* Recreate the memory manager: | ||||
|     */ | ||||
|    calculate_heap_size(heap, size, heap->nrRegions, heap->alignmentShift); | ||||
|    heap->memory_heap = mmInit( 0, heap->size ); | ||||
|    if ( heap->memory_heap == NULL ) { | ||||
|       fprintf(stderr, "driReinitTextureHeap: couldn't recreate memory heap\n"); | ||||
|       FREE( heap ); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    make_empty_list( & heap->texture_objects ); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -38,13 +38,117 @@ | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_reg.h" | ||||
| #include "intel_span.h" | ||||
| #include "intel_tex.h" | ||||
|  | ||||
| static void intelRenderPrimitive(GLcontext * ctx, GLenum prim); | ||||
| static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ); | ||||
| static void intelRasterPrimitive(GLcontext * ctx, GLenum rprim, | ||||
|                                  GLuint hwprim); | ||||
|  | ||||
| /* | ||||
|  */ | ||||
| static void | ||||
| intel_flush_inline_primitive(struct intel_context *intel) | ||||
| { | ||||
|    GLuint used = intel->batch->ptr - intel->prim.start_ptr; | ||||
|  | ||||
|    assert(intel->prim.primitive != ~0); | ||||
|  | ||||
| /*    _mesa_printf("/\n"); */ | ||||
|  | ||||
|    if (used < 8) | ||||
|       goto do_discard; | ||||
|  | ||||
|    *(int *) intel->prim.start_ptr = (_3DPRIMITIVE | | ||||
|                                      intel->prim.primitive | (used / 4 - 2)); | ||||
|  | ||||
|    goto finished; | ||||
|  | ||||
|  do_discard: | ||||
|    intel->batch->ptr -= used; | ||||
|  | ||||
|  finished: | ||||
|    intel->prim.primitive = ~0; | ||||
|    intel->prim.start_ptr = 0; | ||||
|    intel->prim.flush = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Emit a primitive referencing vertices in a vertex buffer. | ||||
|  */ | ||||
| void | ||||
| intelStartInlinePrimitive(struct intel_context *intel, | ||||
|                           GLuint prim, GLuint batch_flags) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    /* Need to make sure at the very least that we don't wrap | ||||
|     * batchbuffers in BEGIN_BATCH below, otherwise the primitive will | ||||
|     * be emitted to a batchbuffer missing the required full-state | ||||
|     * preamble. | ||||
|     */ | ||||
|    if (intel_batchbuffer_space(intel->batch) < 100) { | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|       intel->vtbl.emit_state(intel); | ||||
|    } | ||||
|  | ||||
| /*    _mesa_printf("%s *", __progname); */ | ||||
|  | ||||
|    /* Emit a slot which will be filled with the inline primitive | ||||
|     * command later. | ||||
|     */ | ||||
|    BEGIN_BATCH(2, batch_flags); | ||||
|    OUT_BATCH(0); | ||||
|  | ||||
|    intel->prim.start_ptr = intel->batch->ptr; | ||||
|    intel->prim.primitive = prim; | ||||
|    intel->prim.flush = intel_flush_inline_primitive; | ||||
|  | ||||
|    OUT_BATCH(0); | ||||
|    ADVANCE_BATCH(); | ||||
|  | ||||
| /*    _mesa_printf(">"); */ | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| intelWrapInlinePrimitive(struct intel_context *intel) | ||||
| { | ||||
|    GLuint prim = intel->prim.primitive; | ||||
|    GLuint batchflags = intel->batch->flags; | ||||
|  | ||||
|    intel_flush_inline_primitive(intel); | ||||
|    intel_batchbuffer_flush(intel->batch); | ||||
|    intel->vtbl.emit_state(intel); | ||||
|    intelStartInlinePrimitive(intel, prim, batchflags);  /* ??? */ | ||||
| } | ||||
|  | ||||
| GLuint * | ||||
| intelExtendInlinePrimitive(struct intel_context *intel, GLuint dwords) | ||||
| { | ||||
|    GLuint sz = dwords * sizeof(GLuint); | ||||
|    GLuint *ptr; | ||||
|  | ||||
|    assert(intel->prim.flush == intel_flush_inline_primitive); | ||||
|  | ||||
|    if (intel_batchbuffer_space(intel->batch) < sz) | ||||
|       intelWrapInlinePrimitive(intel); | ||||
|  | ||||
| /*    _mesa_printf("."); */ | ||||
|  | ||||
|    intel->vtbl.assert_not_dirty(intel); | ||||
|  | ||||
|    ptr = (GLuint *) intel->batch->ptr; | ||||
|    intel->batch->ptr += sz; | ||||
|  | ||||
|    return ptr; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /*********************************************************************** | ||||
|  *                    Emit primitives as inline vertices               * | ||||
| @@ -63,22 +167,17 @@ do {								\ | ||||
| #else | ||||
| #define COPY_DWORDS( j, vb, vertsize, v )	\ | ||||
| do {						\ | ||||
|    if (0) fprintf(stderr, "\n");	\ | ||||
|    for ( j = 0 ; j < vertsize ; j++ ) {		\ | ||||
|       if (0) fprintf(stderr, "   -- v(%d): %x/%f\n",j,	\ | ||||
| 	      ((GLuint *)v)[j],			\ | ||||
| 	      ((GLfloat *)v)[j]);		\ | ||||
|       vb[j] = ((GLuint *)v)[j];			\ | ||||
|    }						\ | ||||
|    vb += vertsize;				\ | ||||
| } while (0) | ||||
| #endif | ||||
|  | ||||
| static void __inline__ intel_draw_quad( intelContextPtr intel, | ||||
| static void | ||||
| intel_draw_quad(struct intel_context *intel, | ||||
|                 intelVertexPtr v0, | ||||
| 					intelVertexPtr v1, | ||||
| 					intelVertexPtr v2, | ||||
| 					intelVertexPtr v3 ) | ||||
|                 intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive(intel, 6 * vertsize); | ||||
| @@ -92,10 +191,9 @@ static void __inline__ intel_draw_quad( intelContextPtr intel, | ||||
|    COPY_DWORDS(j, vb, vertsize, v3); | ||||
| } | ||||
|  | ||||
| static void __inline__ intel_draw_triangle( intelContextPtr intel, | ||||
| 					    intelVertexPtr v0, | ||||
| 					    intelVertexPtr v1, | ||||
| 					    intelVertexPtr v2 ) | ||||
| static void | ||||
| intel_draw_triangle(struct intel_context *intel, | ||||
|                     intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive(intel, 3 * vertsize); | ||||
| @@ -107,9 +205,9 @@ static void __inline__ intel_draw_triangle( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ void intel_draw_line( intelContextPtr intel, | ||||
| 					intelVertexPtr v0, | ||||
| 					intelVertexPtr v1 ) | ||||
| static void | ||||
| intel_draw_line(struct intel_context *intel, | ||||
|                 intelVertexPtr v0, intelVertexPtr v1) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive(intel, 2 * vertsize); | ||||
| @@ -120,8 +218,8 @@ static __inline__ void intel_draw_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ void intel_draw_point( intelContextPtr intel, | ||||
| 					 intelVertexPtr v0 ) | ||||
| static void | ||||
| intel_draw_point(struct intel_context *intel, intelVertexPtr v0) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive(intel, vertsize); | ||||
| @@ -140,7 +238,11 @@ static __inline__ void intel_draw_point( intelContextPtr intel, | ||||
|  *                Fixup for ARB_point_parameters                       * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 ) | ||||
| /* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly | ||||
|  * represented in the fragment program InputsRead field. | ||||
|  */ | ||||
| static void | ||||
| intel_atten_point(struct intel_context *intel, intelVertexPtr v0) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLfloat psz[4], col[4], restore_psz, restore_alpha; | ||||
| @@ -189,10 +291,9 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intel_wpos_triangle( intelContextPtr intel, | ||||
| 				 intelVertexPtr v0, | ||||
| 				 intelVertexPtr v1, | ||||
| 				 intelVertexPtr v2 ) | ||||
| static void | ||||
| intel_wpos_triangle(struct intel_context *intel, | ||||
|                     intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) | ||||
| { | ||||
|    GLuint offset = intel->wpos_offset; | ||||
|    GLuint size = intel->wpos_size; | ||||
| @@ -205,9 +306,9 @@ static void intel_wpos_triangle( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intel_wpos_line( intelContextPtr intel, | ||||
| 			     intelVertexPtr v0, | ||||
| 			     intelVertexPtr v1 ) | ||||
| static void | ||||
| intel_wpos_line(struct intel_context *intel, | ||||
|                 intelVertexPtr v0, intelVertexPtr v1) | ||||
| { | ||||
|    GLuint offset = intel->wpos_offset; | ||||
|    GLuint size = intel->wpos_size; | ||||
| @@ -219,8 +320,8 @@ static void intel_wpos_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intel_wpos_point( intelContextPtr intel, | ||||
| 			      intelVertexPtr v0 ) | ||||
| static void | ||||
| intel_wpos_point(struct intel_context *intel, intelVertexPtr v0) | ||||
| { | ||||
|    GLuint offset = intel->wpos_offset; | ||||
|    GLuint size = intel->wpos_size; | ||||
| @@ -284,7 +385,8 @@ do { 						\ | ||||
| #define INTEL_MAX_TRIFUNC	0x10 | ||||
|  | ||||
|  | ||||
| static struct { | ||||
| static struct | ||||
| { | ||||
|    tnl_points_func points; | ||||
|    tnl_line_func line; | ||||
|    tnl_triangle_func triangle; | ||||
| @@ -349,7 +451,7 @@ do {							\ | ||||
| #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] | ||||
|  | ||||
| #define LOCAL_VARS(n)							\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);				\ | ||||
|    struct intel_context *intel = intel_context(ctx);				\ | ||||
|    GLuint color[n], spec[n];						\ | ||||
|    GLuint coloroffset = intel->coloroffset;		\ | ||||
|    GLboolean specoffset = intel->specoffset;			\ | ||||
| @@ -450,7 +552,8 @@ static const GLuint hw_prim[GL_POLYGON+1] = { | ||||
| #include "tnl_dd/t_dd_tritmp.h" | ||||
|  | ||||
|  | ||||
| static void init_rast_tab( void ) | ||||
| static void | ||||
| init_rast_tab(void) | ||||
| { | ||||
|    init(); | ||||
|    init_offset(); | ||||
| @@ -481,10 +584,8 @@ static void init_rast_tab( void ) | ||||
|  * primitives. | ||||
|  */ | ||||
| static void | ||||
| intel_fallback_tri( intelContextPtr intel, | ||||
| 		   intelVertex *v0, | ||||
| 		   intelVertex *v1, | ||||
| 		   intelVertex *v2 ) | ||||
| intel_fallback_tri(struct intel_context *intel, | ||||
|                    intelVertex * v0, intelVertex * v1, intelVertex * v2) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    SWvertex v[3]; | ||||
| @@ -492,6 +593,8 @@ intel_fallback_tri( intelContextPtr intel, | ||||
|    if (0) | ||||
|       fprintf(stderr, "\n%s\n", __FUNCTION__); | ||||
|  | ||||
|    INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|    _swsetup_Translate(ctx, v0, &v[0]); | ||||
|    _swsetup_Translate(ctx, v1, &v[1]); | ||||
|    _swsetup_Translate(ctx, v2, &v[2]); | ||||
| @@ -502,9 +605,8 @@ intel_fallback_tri( intelContextPtr intel, | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_fallback_line( intelContextPtr intel, | ||||
| 		    intelVertex *v0, | ||||
| 		    intelVertex *v1 ) | ||||
| intel_fallback_line(struct intel_context *intel, | ||||
|                     intelVertex * v0, intelVertex * v1) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    SWvertex v[2]; | ||||
| @@ -512,6 +614,8 @@ intel_fallback_line( intelContextPtr intel, | ||||
|    if (0) | ||||
|       fprintf(stderr, "\n%s\n", __FUNCTION__); | ||||
|  | ||||
|    INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|    _swsetup_Translate(ctx, v0, &v[0]); | ||||
|    _swsetup_Translate(ctx, v1, &v[1]); | ||||
|    intelSpanRenderStart(ctx); | ||||
| @@ -519,9 +623,8 @@ intel_fallback_line( intelContextPtr intel, | ||||
|    intelSpanRenderFinish(ctx); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_fallback_point( intelContextPtr intel, | ||||
| intel_fallback_point(struct intel_context *intel, | ||||
| 		     intelVertex * v0) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
| @@ -530,6 +633,8 @@ intel_fallback_point( intelContextPtr intel, | ||||
|    if (0) | ||||
|       fprintf(stderr, "\n%s\n", __FUNCTION__); | ||||
|  | ||||
|    INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|    _swsetup_Translate(ctx, v0, &v[0]); | ||||
|    intelSpanRenderStart(ctx); | ||||
|    _swrast_Point(ctx, &v[0]); | ||||
| @@ -537,7 +642,6 @@ intel_fallback_point( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /*               Render unclipped begin/end objects                   */ | ||||
| /**********************************************************************/ | ||||
| @@ -552,7 +656,7 @@ intel_fallback_point( intelContextPtr intel, | ||||
| #define INIT(x) intelRenderPrimitive( ctx, x ) | ||||
| #undef LOCAL_VARS | ||||
| #define LOCAL_VARS						\ | ||||
|     intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|     struct intel_context *intel = intel_context(ctx);			\ | ||||
|     GLubyte *vertptr = (GLubyte *)intel->verts;			\ | ||||
|     const GLuint vertsize = intel->vertex_size;       	\ | ||||
|     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;	\ | ||||
| @@ -575,10 +679,10 @@ intel_fallback_point( intelContextPtr intel, | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
| 				   GLuint n ) | ||||
| static void | ||||
| intelRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; | ||||
|    GLuint prim = intel->render_primitive; | ||||
| @@ -599,17 +703,18 @@ static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
|       tnl->Driver.Render.PrimitiveNotify(ctx, prim); | ||||
| } | ||||
|  | ||||
| static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) | ||||
| static void | ||||
| intelRenderClippedLine(GLcontext * ctx, GLuint ii, GLuint jj) | ||||
| { | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|  | ||||
|    tnl->Driver.Render.Line(ctx, ii, jj); | ||||
| } | ||||
|  | ||||
| static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
| 				       GLuint n ) | ||||
| static void | ||||
| intelFastRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    const GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive(intel, (n - 2) * 3 * vertsize); | ||||
|    GLubyte *vertptr = (GLubyte *) intel->verts; | ||||
| @@ -630,17 +735,14 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
|  | ||||
|  | ||||
|  | ||||
| #define POINT_FALLBACK (0) | ||||
| #define LINE_FALLBACK (DD_LINE_STIPPLE) | ||||
| #define TRI_FALLBACK (0) | ||||
| #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\ | ||||
|                             DD_TRI_STIPPLE|DD_POINT_ATTEN) | ||||
| #define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN | DD_POINT_SMOOTH | DD_TRI_SMOOTH) | ||||
| #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED) | ||||
|  | ||||
| void intelChooseRenderState(GLcontext *ctx) | ||||
| void | ||||
| intelChooseRenderState(GLcontext * ctx) | ||||
| { | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint flags = ctx->_TriangleCaps; | ||||
|    const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; | ||||
|    GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS)); | ||||
| @@ -652,9 +754,12 @@ void intelChooseRenderState(GLcontext *ctx) | ||||
|    if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) { | ||||
|  | ||||
|       if (flags & ANY_RASTER_FLAGS) { | ||||
| 	 if (flags & DD_TRI_LIGHT_TWOSIDE)    index |= INTEL_TWOSIDE_BIT; | ||||
| 	 if (flags & DD_TRI_OFFSET)	      index |= INTEL_OFFSET_BIT; | ||||
| 	 if (flags & DD_TRI_UNFILLED)	      index |= INTEL_UNFILLED_BIT; | ||||
|          if (flags & DD_TRI_LIGHT_TWOSIDE) | ||||
|             index |= INTEL_TWOSIDE_BIT; | ||||
|          if (flags & DD_TRI_OFFSET) | ||||
|             index |= INTEL_OFFSET_BIT; | ||||
|          if (flags & DD_TRI_UNFILLED) | ||||
|             index |= INTEL_UNFILLED_BIT; | ||||
|       } | ||||
|  | ||||
|       if (have_wpos) { | ||||
| @@ -674,22 +779,29 @@ void intelChooseRenderState(GLcontext *ctx) | ||||
|  | ||||
|       /* Hook in fallbacks for specific primitives. | ||||
|        */ | ||||
|       if (flags & ANY_FALLBACK_FLAGS) | ||||
|       { | ||||
| 	 if (flags & POINT_FALLBACK) | ||||
| 	    intel->draw_point = intel_fallback_point; | ||||
|  | ||||
| 	 if (flags & LINE_FALLBACK) | ||||
|       if (flags & ANY_FALLBACK_FLAGS) { | ||||
|          if (flags & DD_LINE_STIPPLE) | ||||
|             intel->draw_line = intel_fallback_line; | ||||
|  | ||||
| 	 if (flags & TRI_FALLBACK) | ||||
| 	    intel->draw_tri = intel_fallback_tri; | ||||
|  | ||||
|          if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple) | ||||
|             intel->draw_tri = intel_fallback_tri; | ||||
|  | ||||
| 	 if (flags & DD_POINT_ATTEN) | ||||
|          if (flags & DD_TRI_SMOOTH) { | ||||
| 	    if (intel->strict_conformance) | ||||
| 	       intel->draw_tri = intel_fallback_tri; | ||||
| 	 } | ||||
|  | ||||
|          if (flags & DD_POINT_ATTEN) { | ||||
| 	    if (0) | ||||
| 	       intel->draw_point = intel_atten_point; | ||||
| 	    else | ||||
| 	       intel->draw_point = intel_fallback_point; | ||||
| 	 } | ||||
|  | ||||
| 	 if (flags & DD_POINT_SMOOTH) { | ||||
| 	    if (intel->strict_conformance) | ||||
| 	       intel->draw_point = intel_fallback_point; | ||||
| 	 } | ||||
|  | ||||
|          index |= INTEL_FALLBACK_BIT; | ||||
|       } | ||||
| @@ -708,7 +820,8 @@ void intelChooseRenderState(GLcontext *ctx) | ||||
|          tnl->Driver.Render.PrimTabElts = intel_render_tab_elts; | ||||
|          tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ | ||||
|          tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly; | ||||
|       } else { | ||||
|       } | ||||
|       else { | ||||
|          tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; | ||||
|          tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; | ||||
|          tnl->Driver.Render.ClippedLine = intelRenderClippedLine; | ||||
| @@ -738,9 +851,10 @@ static const GLenum reduced_prim[GL_POLYGON+1] = { | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intelRunPipeline( GLcontext *ctx ) | ||||
| static void | ||||
| intelRunPipeline(GLcontext * ctx) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (intel->NewGLState) { | ||||
|       if (intel->NewGLState & _NEW_TEXTURE) { | ||||
| @@ -758,15 +872,24 @@ static void intelRunPipeline( GLcontext *ctx ) | ||||
|    _tnl_run_pipeline(ctx); | ||||
| } | ||||
|  | ||||
| static void intelRenderStart( GLcontext *ctx ) | ||||
| static void | ||||
| intelRenderStart(GLcontext * ctx) | ||||
| { | ||||
|    INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) ); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    intel->vtbl.render_start(intel_context(ctx)); | ||||
|    intel->vtbl.emit_state(intel); | ||||
| } | ||||
|  | ||||
| static void intelRenderFinish( GLcontext *ctx ) | ||||
| static void | ||||
| intelRenderFinish(GLcontext * ctx) | ||||
| { | ||||
|    if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT) | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (intel->RenderIndex & INTEL_FALLBACK_BIT) | ||||
|       _swrast_flush(ctx); | ||||
|  | ||||
|    INTEL_FIREVERTICES(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -775,9 +898,10 @@ static void intelRenderFinish( GLcontext *ctx ) | ||||
|  /* System to flush dma and emit state changes based on the rasterized | ||||
|   * primitive. | ||||
|   */ | ||||
| static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
| static void | ||||
| intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %s %x\n", __FUNCTION__, | ||||
| @@ -787,16 +911,20 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
|  | ||||
|    /* Start a new primitive.  Arrange to have it flushed later on. | ||||
|     */ | ||||
|    if (hwprim != intel->prim.primitive)  | ||||
|       intelStartInlinePrimitive( intel, hwprim ); | ||||
|    if (hwprim != intel->prim.primitive) { | ||||
|       INTEL_FIREVERTICES(intel); | ||||
|  | ||||
|       intelStartInlinePrimitive(intel, hwprim, INTEL_BATCH_CLIPRECTS); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  /*  | ||||
|   */ | ||||
|  static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ) | ||||
| static void | ||||
| intelRenderPrimitive(GLcontext * ctx, GLenum prim) | ||||
| { | ||||
|     intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
| @@ -826,18 +954,26 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
|  /**********************************************************************/ | ||||
|  | ||||
| static char *fallbackStrings[] = { | ||||
|     "Texture", | ||||
|     "Draw buffer", | ||||
|     "Read buffer", | ||||
|     "Color mask", | ||||
|     "Render mode", | ||||
|     "Stencil", | ||||
|     "Stipple", | ||||
|     "User disable" | ||||
|    [0] = "Draw buffer", | ||||
|    [1] = "Read buffer", | ||||
|    [2] = "Depth buffer", | ||||
|    [3] = "Stencil buffer", | ||||
|    [4] = "User disable", | ||||
|    [5] = "Render mode", | ||||
|  | ||||
|    [12] = "Texture", | ||||
|    [13] = "Color mask", | ||||
|    [14] = "Stencil", | ||||
|    [15] = "Stipple", | ||||
|    [16] = "Program", | ||||
|    [17] = "Logic op", | ||||
|    [18] = "Smooth polygon", | ||||
|    [19] = "Smooth point", | ||||
| }; | ||||
|  | ||||
|  | ||||
|  static char *getFallbackString(GLuint bit) | ||||
| static char * | ||||
| getFallbackString(GLuint bit) | ||||
| { | ||||
|    int i = 0; | ||||
|    while (bit > 1) { | ||||
| @@ -849,7 +985,8 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
|  | ||||
|  | ||||
|  | ||||
|  void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ) | ||||
| void | ||||
| intelFallback(struct intel_context *intel, GLuint bit, GLboolean mode) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
| @@ -891,6 +1028,77 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| union fi | ||||
| { | ||||
|    GLfloat f; | ||||
|    GLint i; | ||||
| }; | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /*             Used only with the metaops callbacks.                  */ | ||||
| /**********************************************************************/ | ||||
| void | ||||
| intel_meta_draw_poly(struct intel_context *intel, | ||||
|                      GLuint n, | ||||
|                      GLfloat xy[][2], | ||||
|                      GLfloat z, GLuint color, GLfloat tex[][2]) | ||||
| { | ||||
|    union fi *vb; | ||||
|    GLint i; | ||||
|  | ||||
|    intel->vtbl.emit_state(intel); | ||||
|  | ||||
|    /* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS, | ||||
|     * otherwise the drawing origin (DR4) might not be set correctly. | ||||
|     */ | ||||
|    intelStartInlinePrimitive(intel, PRIM3D_TRIFAN, INTEL_BATCH_CLIPRECTS); | ||||
|    vb = (union fi *) intelExtendInlinePrimitive(intel, n * 6); | ||||
|  | ||||
|    for (i = 0; i < n; i++) { | ||||
|       vb[0].f = xy[i][0]; | ||||
|       vb[1].f = xy[i][1]; | ||||
|       vb[2].f = z; | ||||
|       vb[3].i = color; | ||||
|       vb[4].f = tex[i][0]; | ||||
|       vb[5].f = tex[i][1]; | ||||
|       vb += 6; | ||||
|    } | ||||
|  | ||||
|    INTEL_FIREVERTICES(intel); | ||||
| } | ||||
|  | ||||
| void | ||||
| intel_meta_draw_quad(struct intel_context *intel, | ||||
|                      GLfloat x0, GLfloat x1, | ||||
|                      GLfloat y0, GLfloat y1, | ||||
|                      GLfloat z, | ||||
|                      GLuint color, | ||||
|                      GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1) | ||||
| { | ||||
|    GLfloat xy[4][2]; | ||||
|    GLfloat tex[4][2]; | ||||
|  | ||||
|    xy[0][0] = x0; | ||||
|    xy[0][1] = y0; | ||||
|    xy[1][0] = x1; | ||||
|    xy[1][1] = y0; | ||||
|    xy[2][0] = x1; | ||||
|    xy[2][1] = y1; | ||||
|    xy[3][0] = x0; | ||||
|    xy[3][1] = y1; | ||||
|  | ||||
|    tex[0][0] = s0; | ||||
|    tex[0][1] = t0; | ||||
|    tex[1][0] = s1; | ||||
|    tex[1][1] = t0; | ||||
|    tex[2][0] = s1; | ||||
|    tex[2][1] = t1; | ||||
|    tex[3][0] = s0; | ||||
|    tex[3][1] = t1; | ||||
|  | ||||
|    intel_meta_draw_poly(intel, 4, xy, z, color, tex); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -899,7 +1107,8 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
| /**********************************************************************/ | ||||
|  | ||||
|  | ||||
| void intelInitTriFuncs( GLcontext *ctx ) | ||||
| void | ||||
| intelInitTriFuncs(GLcontext * ctx) | ||||
| { | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    static int firsttime = 1; | ||||
|   | ||||
| @@ -30,6 +30,8 @@ | ||||
|  | ||||
| #include "mtypes.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| #define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |		\ | ||||
| 			       _DD_NEW_TRI_UNFILLED |		\ | ||||
| 			       _DD_NEW_TRI_LIGHT_TWOSIDE |	\ | ||||
| @@ -40,7 +42,28 @@ | ||||
|  | ||||
| extern void intelInitTriFuncs(GLcontext * ctx); | ||||
|  | ||||
| extern void intelPrintRenderState( const char *msg, GLuint state ); | ||||
| extern void intelChooseRenderState(GLcontext * ctx); | ||||
|  | ||||
| extern void intelStartInlinePrimitive(struct intel_context *intel, | ||||
|                                       GLuint prim, GLuint flags); | ||||
| extern void intelWrapInlinePrimitive(struct intel_context *intel); | ||||
|  | ||||
| GLuint *intelExtendInlinePrimitive(struct intel_context *intel, | ||||
|                                    GLuint dwords); | ||||
|  | ||||
|  | ||||
| void intel_meta_draw_quad(struct intel_context *intel, | ||||
|                           GLfloat x0, GLfloat x1, | ||||
|                           GLfloat y0, GLfloat y1, | ||||
|                           GLfloat z, | ||||
|                           GLuint color, | ||||
|                           GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1); | ||||
|  | ||||
| void intel_meta_draw_poly(struct intel_context *intel, | ||||
|                           GLuint n, | ||||
|                           GLfloat xy[][2], | ||||
|                           GLfloat z, GLuint color, GLfloat tex[][2]); | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -276,6 +276,8 @@ _mesa_PushAttrib(GLbitfield mask) | ||||
|       struct gl_pixel_attrib *attr; | ||||
|       attr = MALLOC_STRUCT( gl_pixel_attrib ); | ||||
|       MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) ); | ||||
|       /* push the Read FBO's ReadBuffer state, not ctx->Pixel.ReadBuffer */ | ||||
|       attr->ReadBuffer = ctx->ReadBuffer->ColorReadBuffer; | ||||
|       newnode = new_attrib_node( GL_PIXEL_MODE_BIT ); | ||||
|       newnode->data = attr; | ||||
|       newnode->next = head; | ||||
|   | ||||
| @@ -591,11 +591,9 @@ _mesa_ReadBuffer(GLenum buffer) | ||||
|  * \note This function should only be called through the GL API, not | ||||
|  * from device drivers (as was done in the past). | ||||
|  */ | ||||
| void GLAPIENTRY | ||||
| _mesa_ResizeBuffersMESA( void ) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|  | ||||
| void _mesa_resizebuffers( GLcontext *ctx ) | ||||
| { | ||||
|    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); | ||||
|  | ||||
|    if (MESA_VERBOSE & VERBOSE_API) | ||||
| @@ -637,6 +635,14 @@ _mesa_ResizeBuffersMESA( void ) | ||||
|    ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */ | ||||
| } | ||||
|  | ||||
| void GLAPIENTRY | ||||
| _mesa_ResizeBuffersMESA( void ) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|  | ||||
|    _mesa_resizebuffers( ctx ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * XXX move somewhere else someday? | ||||
|   | ||||
| @@ -78,4 +78,6 @@ extern void | ||||
| _mesa_set_scissor(GLcontext *ctx,  | ||||
|                   GLint x, GLint y, GLsizei width, GLsizei height); | ||||
|  | ||||
| extern void _mesa_resizebuffers( GLcontext *ctx ); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -704,9 +704,7 @@ alloc_shared_state( GLcontext *ctx ) | ||||
|  | ||||
|    ss->ArrayObjects = _mesa_NewHashTable(); | ||||
|  | ||||
| #if FEATURE_ARB_shader_objects | ||||
|    ss->GL2Objects = _mesa_NewHashTable (); | ||||
| #endif | ||||
|  | ||||
|    ss->Default1D = (*ctx->Driver.NewTextureObject)(ctx, 0, GL_TEXTURE_1D); | ||||
|    if (!ss->Default1D) | ||||
| @@ -777,10 +775,8 @@ alloc_shared_state( GLcontext *ctx ) | ||||
|    if (ss->ArrayObjects) | ||||
|       _mesa_DeleteHashTable (ss->ArrayObjects); | ||||
|  | ||||
| #if FEATURE_ARB_shader_objects | ||||
|    if (ss->GL2Objects) | ||||
|       _mesa_DeleteHashTable (ss->GL2Objects); | ||||
| #endif | ||||
|  | ||||
| #if FEATURE_EXT_framebuffer_object | ||||
|    if (ss->FrameBuffers) | ||||
| @@ -933,9 +929,7 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss ) | ||||
|    _mesa_HashDeleteAll(ss->ArrayObjects, delete_arrayobj_cb, ctx); | ||||
|    _mesa_DeleteHashTable(ss->ArrayObjects); | ||||
|  | ||||
| #if FEATURE_ARB_shader_objects | ||||
|    _mesa_DeleteHashTable(ss->GL2Objects); | ||||
| #endif | ||||
|  | ||||
| #if FEATURE_EXT_framebuffer_object | ||||
|    _mesa_DeleteHashTable(ss->FrameBuffers); | ||||
| @@ -1713,6 +1707,8 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer, | ||||
|          if (readBuffer != drawBuffer && !readBuffer->Initialized) { | ||||
|             initialize_framebuffer_size(newCtx, readBuffer); | ||||
|          } | ||||
|  | ||||
| 	 _mesa_resizebuffers(newCtx); | ||||
| #endif | ||||
|          if (newCtx->FirstTimeCurrent) { | ||||
|             /* set initial viewport and scissor size now */ | ||||
|   | ||||
| @@ -570,6 +570,11 @@ _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) | ||||
|    } | ||||
|  | ||||
|    FLUSH_VERTICES(ctx, _NEW_BUFFERS); | ||||
|    /* The above doesn't fully flush the drivers in the way that a | ||||
|     * glFlush does, but that is required here: | ||||
|     */ | ||||
|    ctx->Driver.Flush(ctx); | ||||
|  | ||||
|  | ||||
|    if (renderbuffer) { | ||||
|       newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer); | ||||
| @@ -972,7 +977,9 @@ _mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) | ||||
|    } | ||||
|  | ||||
|    FLUSH_VERTICES(ctx, _NEW_BUFFERS); | ||||
|  | ||||
|    if (ctx->Driver.Flush) {   | ||||
|       ctx->Driver.Flush(ctx); | ||||
|    } | ||||
|    if (framebuffer) { | ||||
|       /* Binding a user-created framebuffer object */ | ||||
|       newFb = _mesa_lookup_framebuffer(ctx, framebuffer); | ||||
| @@ -1047,6 +1054,10 @@ _mesa_DeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) | ||||
|  | ||||
|    ASSERT_OUTSIDE_BEGIN_END(ctx); | ||||
|    FLUSH_VERTICES(ctx, _NEW_BUFFERS); | ||||
|    /* The above doesn't fully flush the drivers in the way that a | ||||
|     * glFlush does, but that is required here: | ||||
|     */ | ||||
|    ctx->Driver.Flush(ctx); | ||||
|  | ||||
|    for (i = 0; i < n; i++) { | ||||
|       if (framebuffers[i] > 0) { | ||||
| @@ -1262,6 +1273,10 @@ framebuffer_texture(GLuint dims, GLenum target, GLenum attachment, | ||||
|    } | ||||
|  | ||||
|    FLUSH_VERTICES(ctx, _NEW_BUFFERS); | ||||
|    /* The above doesn't fully flush the drivers in the way that a | ||||
|     * glFlush does, but that is required here: | ||||
|     */ | ||||
|    ctx->Driver.Flush(ctx); | ||||
|  | ||||
|    _glthread_LOCK_MUTEX(fb->Mutex); | ||||
|    if (texObj) { | ||||
| @@ -1380,6 +1395,10 @@ _mesa_FramebufferRenderbufferEXT(GLenum target, GLenum attachment, | ||||
|    } | ||||
|  | ||||
|    FLUSH_VERTICES(ctx, _NEW_BUFFERS); | ||||
|    /* The above doesn't fully flush the drivers in the way that a | ||||
|     * glFlush does, but that is required here: | ||||
|     */ | ||||
|    ctx->Driver.Flush(ctx); | ||||
|  | ||||
|    assert(ctx->Driver.FramebufferRenderbuffer); | ||||
|    ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb); | ||||
| @@ -1443,6 +1462,10 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, | ||||
|    } | ||||
|  | ||||
|    FLUSH_VERTICES(ctx, _NEW_BUFFERS); | ||||
|    /* The above doesn't fully flush the drivers in the way that a | ||||
|     * glFlush does, but that is required here: | ||||
|     */ | ||||
|    ctx->Driver.Flush(ctx); | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT: | ||||
|   | ||||
| @@ -604,6 +604,17 @@ do {                                                                    \ | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Return 1 if this is a little endian machine, 0 if big endian. | ||||
|  */ | ||||
| static INLINE GLboolean | ||||
| _mesa_little_endian(void) | ||||
| { | ||||
|    const GLuint ui = 1; /* intentionally not static */ | ||||
|    return *((const GLubyte *) &ui); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /********************************************************************** | ||||
|  * Functions | ||||
|   | ||||
| @@ -658,7 +658,7 @@ _mesa_free_texture_image_data(GLcontext *ctx, | ||||
| void | ||||
| _mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) | ||||
| { | ||||
|    if (texImage->Data) { | ||||
|    if (texImage->Data || ctx->Driver.FreeTexImageData) { | ||||
|       ctx->Driver.FreeTexImageData( ctx, texImage ); | ||||
|    } | ||||
|    ASSERT(texImage->Data == NULL); | ||||
|   | ||||
| @@ -63,11 +63,21 @@ | ||||
| #include "texformat.h" | ||||
| #include "teximage.h" | ||||
| #include "texstore.h" | ||||
| #include "enums.h" | ||||
|  | ||||
|  | ||||
| static const GLint ZERO = 4, ONE = 5; | ||||
| enum { | ||||
|    ZERO = 4,  | ||||
|    ONE = 5 | ||||
| }; | ||||
|  | ||||
| static GLboolean can_swizzle(GLenum logicalBaseFormat) | ||||
|  | ||||
| /** | ||||
|  * Return GL_TRUE if the given image format is one that be converted | ||||
|  * to another format by swizzling. | ||||
|  */ | ||||
| static GLboolean | ||||
| can_swizzle(GLenum logicalBaseFormat) | ||||
| { | ||||
|    switch (logicalBaseFormat) { | ||||
|    case GL_RGBA: | ||||
| @@ -76,6 +86,12 @@ static GLboolean can_swizzle(GLenum logicalBaseFormat) | ||||
|    case GL_INTENSITY: | ||||
|    case GL_ALPHA: | ||||
|    case GL_LUMINANCE: | ||||
|    case GL_RED: | ||||
|    case GL_GREEN: | ||||
|    case GL_BLUE: | ||||
|    case GL_BGR: | ||||
|    case GL_BGRA: | ||||
|    case GL_ABGR_EXT: | ||||
|       return GL_TRUE; | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
| @@ -83,89 +99,172 @@ static GLboolean can_swizzle(GLenum logicalBaseFormat) | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| enum { | ||||
|    IDX_LUMINANCE = 0, | ||||
|    IDX_ALPHA, | ||||
|    IDX_INTENSITY, | ||||
|    IDX_LUMINANCE_ALPHA, | ||||
|    IDX_RGB, | ||||
|    IDX_RGBA, | ||||
|    IDX_RED, | ||||
|    IDX_GREEN, | ||||
|    IDX_BLUE, | ||||
|    IDX_BGR, | ||||
|    IDX_BGRA, | ||||
|    IDX_ABGR, | ||||
|    MAX_IDX | ||||
| }; | ||||
|  | ||||
| #define MAP1(x)       MAP4(x, ZERO, ZERO, ZERO) | ||||
| #define MAP2(x,y)     MAP4(x, y, ZERO, ZERO) | ||||
| #define MAP3(x,y,z)   MAP4(x, y, z, ZERO) | ||||
| #define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE } | ||||
|  | ||||
|  | ||||
| static const struct { | ||||
|    GLubyte format_idx; | ||||
|    GLubyte to_rgba[6]; | ||||
|    GLubyte from_rgba[6]; | ||||
| } mappings[MAX_IDX] =  | ||||
| { | ||||
|    { | ||||
|       IDX_LUMINANCE, | ||||
|       MAP4(0,0,0,ONE), | ||||
|       MAP1(0) | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_ALPHA, | ||||
|       MAP4(ZERO, ZERO, ZERO, 0), | ||||
|       MAP1(3) | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_INTENSITY, | ||||
|       MAP4(0, 0, 0, 0), | ||||
|       MAP1(0), | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_LUMINANCE_ALPHA, | ||||
|       MAP4(0,0,0,1), | ||||
|       MAP2(0,3) | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_RGB, | ||||
|       MAP4(0,1,2,ONE), | ||||
|       MAP3(0,1,2) | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_RGBA, | ||||
|       MAP4(0,1,2,3), | ||||
|       MAP4(0,1,2,3), | ||||
|    }, | ||||
|  | ||||
|  | ||||
|    { | ||||
|       IDX_RED, | ||||
|       MAP4(0, ZERO, ZERO, ONE), | ||||
|       MAP1(0), | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_GREEN, | ||||
|       MAP4(ZERO, 0, ZERO, ONE), | ||||
|       MAP1(1), | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_BLUE, | ||||
|       MAP4(ZERO, ZERO, 0, ONE), | ||||
|       MAP1(2), | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_BGR, | ||||
|       MAP4(2,1,0,ONE), | ||||
|       MAP3(2,1,0) | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_BGRA, | ||||
|       MAP4(2,1,0,3), | ||||
|       MAP4(2,1,0,3) | ||||
|    }, | ||||
|  | ||||
|    { | ||||
|       IDX_ABGR, | ||||
|       MAP4(3,2,1,0), | ||||
|       MAP4(3,2,1,0) | ||||
|    }, | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Convert a GL image format enum to an IDX_* value (see above). | ||||
|  */ | ||||
| static int | ||||
| get_map_idx(GLenum value) | ||||
| { | ||||
|    switch (value) { | ||||
|    case GL_LUMINANCE: return IDX_LUMINANCE; | ||||
|    case GL_ALPHA: return IDX_ALPHA; | ||||
|    case GL_INTENSITY: return IDX_INTENSITY; | ||||
|    case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA; | ||||
|    case GL_RGB: return IDX_RGB; | ||||
|    case GL_RGBA: return IDX_RGBA; | ||||
|    case GL_RED: return IDX_RED; | ||||
|    case GL_GREEN: return IDX_GREEN; | ||||
|    case GL_BLUE: return IDX_BLUE; | ||||
|    case GL_BGR: return IDX_BGR; | ||||
|    case GL_BGRA: return IDX_BGRA; | ||||
|    case GL_ABGR_EXT: return IDX_ABGR; | ||||
|    default: | ||||
|       _mesa_problem(NULL, "Unexpected inFormat"); | ||||
|       return 0; | ||||
|    } | ||||
| }    | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * When promoting texture formats (see below) we need to compute the | ||||
|  * mapping of dest components back to source components. | ||||
|  * This function does that. | ||||
|  * \param logicalBaseFormat  the logical format of the texture | ||||
|  * \param textureBaseFormat  the final texture format | ||||
|  * \return map[4]  the four mapping values | ||||
|  * \param inFormat  the incoming format of the texture | ||||
|  * \param outFormat  the final texture format | ||||
|  * \return map[6]  a full 6-component map | ||||
|  */ | ||||
| static void | ||||
| compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat, | ||||
|                           GLubyte map[6]) | ||||
| compute_component_mapping(GLenum inFormat, GLenum outFormat,  | ||||
| 			  GLubyte *map) | ||||
| { | ||||
|    const int inFmt = get_map_idx(inFormat); | ||||
|    const int outFmt = get_map_idx(outFormat); | ||||
|    const GLubyte *in2rgba = mappings[inFmt].to_rgba; | ||||
|    const GLubyte *rgba2out = mappings[outFmt].from_rgba; | ||||
|    int i; | ||||
|     | ||||
|    for (i = 0; i < 4; i++) | ||||
|       map[i] = in2rgba[rgba2out[i]]; | ||||
|  | ||||
|    map[ZERO] = ZERO; | ||||
|    map[ONE] = ONE;    | ||||
|  | ||||
|    /* compute mapping from dest components back to src components */ | ||||
|    switch (textureBaseFormat) { | ||||
|    case GL_RGB: | ||||
|    case GL_RGBA: | ||||
|       switch (logicalBaseFormat) { | ||||
|       case GL_LUMINANCE: | ||||
|          map[0] = map[1] = map[2] = 0; | ||||
|          if (textureBaseFormat == GL_RGBA) | ||||
|             map[3] = ONE; | ||||
|          break; | ||||
|       case GL_ALPHA: | ||||
|          ASSERT(textureBaseFormat == GL_RGBA); | ||||
|          map[0] = map[1] = map[2] = ZERO; | ||||
|          map[3] = 0; | ||||
|          break; | ||||
|       case GL_INTENSITY: | ||||
|          map[0] = map[1] = map[2] = 0; | ||||
|          if (textureBaseFormat == GL_RGBA) | ||||
|             map[3] = 0; | ||||
|          break; | ||||
|       case GL_LUMINANCE_ALPHA: | ||||
|          ASSERT(textureBaseFormat == GL_RGBA); | ||||
|          map[0] = map[1] = map[2] = 0; | ||||
|          map[3] = 1; | ||||
|          break; | ||||
|       case GL_RGB: | ||||
|          ASSERT(textureBaseFormat == GL_RGBA); | ||||
|          map[0] = 0; | ||||
|          map[1] = 1; | ||||
|          map[2] = 2; | ||||
|          map[3] = ONE; | ||||
|          break; | ||||
|       case GL_RGBA: | ||||
|          ASSERT(textureBaseFormat == GL_RGBA); | ||||
|          map[0] = 0; | ||||
|          map[1] = 1; | ||||
|          map[2] = 2; | ||||
|          map[3] = 3; | ||||
|          break; | ||||
|       default: | ||||
|          _mesa_problem(NULL, "Unexpected logicalBaseFormat"); | ||||
|          map[0] = map[1] = map[2] = map[3] = 0; | ||||
|       } | ||||
|       break; | ||||
|    case GL_LUMINANCE_ALPHA: | ||||
|       switch (logicalBaseFormat) { | ||||
|       case GL_LUMINANCE: | ||||
|          map[0] = 0; | ||||
|          map[1] = ONE; | ||||
|          break; | ||||
|       case GL_ALPHA: | ||||
|          map[0] = ZERO; | ||||
|          map[1] = 0; | ||||
|          break; | ||||
|       case GL_INTENSITY: | ||||
|          map[0] = 0; | ||||
|          map[1] = 0; | ||||
|          break; | ||||
|       default: | ||||
|          _mesa_problem(NULL, "Unexpected logicalBaseFormat"); | ||||
|          map[0] = map[1] = 0; | ||||
|       } | ||||
|       break; | ||||
|    default: | ||||
|       _mesa_problem(NULL, "Unexpected logicalBaseFormat"); | ||||
|       map[0] = map[1] = 0; | ||||
|       break; | ||||
|    }    | ||||
| /* | ||||
|    _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n", | ||||
| 		inFormat, _mesa_lookup_enum_by_nr(inFormat), | ||||
| 		outFormat, _mesa_lookup_enum_by_nr(outFormat), | ||||
| 		map[0],  | ||||
| 		map[1],  | ||||
| 		map[2],  | ||||
| 		map[3],  | ||||
| 		map[4],  | ||||
| 		map[5]);  | ||||
| */ | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -552,14 +651,16 @@ _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, | ||||
|  * \param dstComponents  number of color components in destination pixels | ||||
|  * \param src  source pixels | ||||
|  * \param srcComponents  number of color components in source pixels | ||||
|  * \param map  the swizzle mapping | ||||
|  * \param map  the swizzle mapping.  map[X] says where to find the X component | ||||
|  *             in the source image's pixels.  For example, if the source image | ||||
|  *             is GL_BGRA and X = red, map[0] yields 2. | ||||
|  * \param count  number of pixels to copy/swizzle. | ||||
|  */ | ||||
| static void | ||||
| swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,  | ||||
|              GLuint srcComponents, const GLubyte *map, GLuint count) | ||||
| { | ||||
|    GLubyte tmp[8]; | ||||
|    GLubyte tmp[6]; | ||||
|    GLuint i; | ||||
|  | ||||
|    tmp[ZERO] = 0x0; | ||||
| @@ -596,10 +697,60 @@ swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src, | ||||
| 	 dst += 2; | ||||
|       } | ||||
|       break; | ||||
|    case 1: | ||||
|       for (i = 0; i < count; i++) { | ||||
|  	 COPY_4UBV(tmp, src);  | ||||
| 	 src += srcComponents;       | ||||
| 	 dst[0] = tmp[map[0]]; | ||||
| 	 dst += 1; | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE }; | ||||
| static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE }; | ||||
|  | ||||
| /* Deal with the _REV input types: | ||||
|  */ | ||||
| static const GLubyte * | ||||
| type_mapping( GLenum srcType ) | ||||
| { | ||||
|    switch (srcType) { | ||||
|    case GL_UNSIGNED_BYTE: | ||||
|       return map_identity; | ||||
|    case GL_UNSIGNED_INT_8_8_8_8: | ||||
|       return map_3210; | ||||
|    case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       return map_identity; | ||||
|    default: | ||||
|       return NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /* Mapping required if input type is  | ||||
|  */ | ||||
| static const GLubyte * | ||||
| byteswap_mapping( GLboolean swapBytes, | ||||
| 		  GLenum srcType ) | ||||
| { | ||||
|    if (!swapBytes)  | ||||
|       return map_identity; | ||||
|  | ||||
|    switch (srcType) { | ||||
|    case GL_UNSIGNED_BYTE: | ||||
|       return map_identity; | ||||
|    case GL_UNSIGNED_INT_8_8_8_8: | ||||
|    case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       return map_3210; | ||||
|    default: | ||||
|       return NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Transfer a GLubyte texture image with component swizzling. | ||||
|  */ | ||||
| @@ -607,7 +758,12 @@ static void | ||||
| _mesa_swizzle_ubyte_image(GLcontext *ctx,  | ||||
| 			  GLuint dimensions, | ||||
| 			  GLenum srcFormat, | ||||
| 			  const GLubyte *dstmap, GLint dstComponents, | ||||
| 			  GLenum srcType, | ||||
|  | ||||
| 			  GLenum baseInternalFormat, | ||||
|  | ||||
| 			  const GLubyte *rgba2dst, | ||||
| 			  GLuint dstComponents, | ||||
|  | ||||
| 			  GLvoid *dstAddr, | ||||
| 			  GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, | ||||
| @@ -619,9 +775,9 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx, | ||||
| 			  const struct gl_pixelstore_attrib *srcPacking ) | ||||
| { | ||||
|    GLint srcComponents = _mesa_components_in_format(srcFormat); | ||||
|    GLubyte srcmap[6], map[4]; | ||||
|    const GLubyte *srctype2ubyte, *swap; | ||||
|    GLubyte map[4], src2base[6], base2rgba[6]; | ||||
|    GLint i; | ||||
|  | ||||
|    const GLint srcRowStride = | ||||
|       _mesa_image_row_stride(srcPacking, srcWidth, | ||||
|                              srcFormat, GL_UNSIGNED_BYTE); | ||||
| @@ -635,10 +791,20 @@ _mesa_swizzle_ubyte_image(GLcontext *ctx, | ||||
|  | ||||
|    (void) ctx; | ||||
|  | ||||
|    compute_component_mapping(srcFormat, GL_RGBA, srcmap); | ||||
|    /* Translate from src->baseInternal->GL_RGBA->dst.  This will | ||||
|     * correctly deal with RGBA->RGB->RGBA conversions where the final | ||||
|     * A value must be 0xff regardless of the incoming alpha values. | ||||
|     */ | ||||
|    compute_component_mapping(srcFormat, baseInternalFormat, src2base); | ||||
|    compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba); | ||||
|    swap = byteswap_mapping(srcPacking->SwapBytes, srcType); | ||||
|    srctype2ubyte = type_mapping(srcType); | ||||
|  | ||||
|  | ||||
|    for (i = 0; i < 4; i++) | ||||
|       map[i] = srcmap[dstmap[i]]; | ||||
|       map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]]; | ||||
|  | ||||
| /*    _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]);  */ | ||||
|  | ||||
|    if (srcRowStride == srcWidth * srcComponents && | ||||
|        dimensions < 3) { | ||||
| @@ -817,6 +983,59 @@ _mesa_texstore_rgba(TEXSTORE_PARAMS) | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    else if (!ctx->_ImageTransferState && | ||||
| 	    _mesa_little_endian() && | ||||
| 	    CHAN_TYPE == GL_UNSIGNED_BYTE && | ||||
| 	    (srcType == GL_UNSIGNED_BYTE || | ||||
| 	     srcType == GL_UNSIGNED_INT_8_8_8_8 || | ||||
| 	     srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && | ||||
| 	    can_swizzle(baseInternalFormat) && | ||||
| 	    can_swizzle(srcFormat)) { | ||||
|  | ||||
|       const GLubyte *dstmap; | ||||
|       GLuint components; | ||||
|  | ||||
|       /* dstmap - how to swizzle from RGBA to dst format: | ||||
|        */ | ||||
|       if (dstFormat == &_mesa_texformat_rgba) { | ||||
| 	 dstmap = mappings[IDX_RGBA].from_rgba; | ||||
| 	 components = 4; | ||||
|       } | ||||
|       else if (dstFormat == &_mesa_texformat_rgb) { | ||||
| 	 dstmap = mappings[IDX_RGB].from_rgba; | ||||
| 	 components = 3; | ||||
|       } | ||||
|       else if (dstFormat == &_mesa_texformat_alpha) { | ||||
| 	 dstmap = mappings[IDX_ALPHA].from_rgba; | ||||
| 	 components = 1; | ||||
|       } | ||||
|       else if (dstFormat == &_mesa_texformat_luminance) { | ||||
| 	 dstmap = mappings[IDX_LUMINANCE].from_rgba; | ||||
| 	 components = 1; | ||||
|       } | ||||
|       else if (dstFormat == &_mesa_texformat_luminance_alpha) { | ||||
| 	 dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba; | ||||
| 	 components = 2; | ||||
|       } | ||||
|       else if (dstFormat == &_mesa_texformat_intensity) { | ||||
| 	 dstmap = mappings[IDX_INTENSITY].from_rgba; | ||||
| 	 components = 1; | ||||
|       } | ||||
|       else { | ||||
|          _mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba"); | ||||
|          return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       _mesa_swizzle_ubyte_image(ctx, dims, | ||||
| 				srcFormat, | ||||
| 				srcType, | ||||
| 				baseInternalFormat, | ||||
| 				dstmap, components, | ||||
| 				dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| 				dstRowStride, dstImageOffsets, | ||||
| 				srcWidth, srcHeight, srcDepth, srcAddr, | ||||
| 				srcPacking);       | ||||
|    } | ||||
|    else { | ||||
|       /* general path */ | ||||
|       const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, | ||||
| @@ -1050,13 +1269,14 @@ _mesa_texstore_rgb565(TEXSTORE_PARAMS) | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV. | ||||
|  */ | ||||
| GLboolean | ||||
| _mesa_texstore_rgba8888(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLuint ui = 1; | ||||
|    const GLubyte littleEndian = *((const GLubyte *) &ui); | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|  | ||||
|    (void)littleEndian; | ||||
|    ASSERT(dstFormat == &_mesa_texformat_rgba8888 || | ||||
|           dstFormat == &_mesa_texformat_rgba8888_rev); | ||||
|    ASSERT(dstFormat->TexelBytes == 4); | ||||
| @@ -1066,7 +1286,9 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS) | ||||
|        dstFormat == &_mesa_texformat_rgba8888 && | ||||
|        baseInternalFormat == GL_RGBA && | ||||
|       ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || | ||||
|        (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) { | ||||
|        (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) || | ||||
|        (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || | ||||
|        (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) { | ||||
|        /* simple memcpy path */ | ||||
|       memcpy_texture(ctx, dims, | ||||
|                      dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| @@ -1075,40 +1297,57 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS) | ||||
|                      srcWidth, srcHeight, srcDepth, srcFormat, srcType, | ||||
|                      srcAddr, srcPacking); | ||||
|    } | ||||
| #if 0 | ||||
|    /* broken? */ | ||||
|    else if (!ctx->_ImageTransferState && | ||||
|        !srcPacking->SwapBytes && | ||||
| 	    srcType == GL_UNSIGNED_BYTE &&  | ||||
| 	    dstFormat == &_mesa_texformat_rgba8888 && | ||||
|        dstFormat == &_mesa_texformat_rgba8888_rev && | ||||
|        baseInternalFormat == GL_RGBA && | ||||
|       ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || | ||||
|        (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) || | ||||
|        (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) || | ||||
|        (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) { | ||||
|       /* simple memcpy path */ | ||||
|       memcpy_texture(ctx, dims, | ||||
|                      dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
|                      dstRowStride, | ||||
|                      dstImageOffsets, | ||||
|                      srcWidth, srcHeight, srcDepth, srcFormat, srcType, | ||||
|                      srcAddr, srcPacking); | ||||
|    } | ||||
|    else if (!ctx->_ImageTransferState && | ||||
| 	    littleEndian &&  | ||||
| 	    /* Three texture formats involved: srcFormat, | ||||
| 	     * baseInternalFormat and destFormat (GL_RGBA). Only two | ||||
| 	     * may differ. _mesa_swizzle_ubyte_image can't handle two | ||||
| 	     * propagations at once correctly. */ | ||||
| 	    (srcFormat == baseInternalFormat || | ||||
| 	     baseInternalFormat == GL_RGBA) && | ||||
| 	    (srcType == GL_UNSIGNED_BYTE || | ||||
| 	     srcType == GL_UNSIGNED_INT_8_8_8_8 || | ||||
| 	     srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && | ||||
| 	    can_swizzle(baseInternalFormat) && | ||||
| 	    can_swizzle(srcFormat)) { | ||||
|  | ||||
|       GLubyte dstmap[4]; | ||||
|  | ||||
|       /* dstmap - how to swizzle from GL_RGBA to dst format: | ||||
|        * | ||||
|        * FIXME - add !litteEndian and _rev varients: | ||||
|       /* dstmap - how to swizzle from RGBA to dst format: | ||||
|        */ | ||||
|       if (dstFormat == &_mesa_texformat_rgba8888) { | ||||
| 	 dstmap[3] = 0; | ||||
| 	 dstmap[2] = 1; | ||||
| 	 dstmap[1] = 2; | ||||
| 	 dstmap[0] = 3; | ||||
|       } | ||||
|       else { | ||||
| 	 dstmap[3] = 3; | ||||
| 	 dstmap[2] = 2; | ||||
| 	 dstmap[1] = 1; | ||||
| 	 dstmap[0] = 0; | ||||
|       } | ||||
|        | ||||
|       _mesa_swizzle_ubyte_image(ctx, dims, | ||||
| 				srcFormat, | ||||
| 				srcType, | ||||
| 				baseInternalFormat, | ||||
| 				dstmap, 4, | ||||
| 				dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| 				dstRowStride, dstImageStride, | ||||
| 				dstRowStride, dstImageOffsets, | ||||
| 				srcWidth, srcHeight, srcDepth, srcAddr, | ||||
| 				srcPacking);       | ||||
|    } | ||||
| #endif | ||||
|    else { | ||||
|       /* general path */ | ||||
|       const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, | ||||
| @@ -1159,8 +1398,7 @@ _mesa_texstore_rgba8888(TEXSTORE_PARAMS) | ||||
| GLboolean | ||||
| _mesa_texstore_argb8888(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLuint ui = 1; | ||||
|    const GLubyte littleEndian = *((const GLubyte *) &ui); | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_argb8888 || | ||||
|           dstFormat == &_mesa_texformat_argb8888_rev); | ||||
| @@ -1200,6 +1438,8 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) | ||||
|             !srcPacking->SwapBytes && | ||||
| 	    dstFormat == &_mesa_texformat_argb8888 && | ||||
|             srcFormat == GL_RGB && | ||||
| 	    (baseInternalFormat == GL_RGBA || | ||||
| 	     baseInternalFormat == GL_RGB) && | ||||
|             srcType == GL_UNSIGNED_BYTE) { | ||||
|  | ||||
|       int img, row, col; | ||||
| @@ -1228,6 +1468,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) | ||||
|             !srcPacking->SwapBytes && | ||||
| 	    dstFormat == &_mesa_texformat_argb8888 && | ||||
|             srcFormat == GL_RGBA && | ||||
| 	    baseInternalFormat == GL_RGBA && | ||||
|             (srcType == GL_UNSIGNED_BYTE && littleEndian)) { | ||||
|       GLint img, row, col; | ||||
|       /* For some reason, streaming copies to write-combined regions | ||||
| @@ -1262,6 +1503,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) | ||||
|             !srcPacking->SwapBytes && | ||||
| 	    dstFormat == &_mesa_texformat_argb8888 && | ||||
|             srcFormat == GL_RGBA && | ||||
| 	    baseInternalFormat == GL_RGBA && | ||||
|             srcType == GL_UNSIGNED_BYTE) { | ||||
|  | ||||
|       GLint img, row, col; | ||||
| @@ -1287,29 +1529,36 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) | ||||
|       } | ||||
|    } | ||||
|    else if (!ctx->_ImageTransferState && | ||||
| 	    !srcPacking->SwapBytes && | ||||
| 	    dstFormat == &_mesa_texformat_argb8888 && | ||||
| 	    srcType == GL_UNSIGNED_BYTE &&  | ||||
| 	    littleEndian && | ||||
| 	    /* Three texture formats involved: srcFormat, | ||||
| 	     * baseInternalFormat and destFormat (GL_RGBA). Only two | ||||
| 	     * may differ. _mesa_swizzle_ubyte_image can't handle two | ||||
| 	     * propagations at once correctly. */ | ||||
| 	    (srcFormat == baseInternalFormat || | ||||
| 	     baseInternalFormat == GL_RGBA) && | ||||
| 	    (srcType == GL_UNSIGNED_BYTE || | ||||
| 	     srcType == GL_UNSIGNED_INT_8_8_8_8 || | ||||
| 	     srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && | ||||
| 	    can_swizzle(baseInternalFormat) &&	    | ||||
| 	    can_swizzle(srcFormat)) { | ||||
|  | ||||
|       GLubyte dstmap[4]; | ||||
|  | ||||
|       /* dstmap - how to swizzle from GL_RGBA to dst format: | ||||
|       /* dstmap - how to swizzle from RGBA to dst format: | ||||
|        */ | ||||
|       if (dstFormat == &_mesa_texformat_argb8888) { | ||||
| 	 dstmap[3] = 3;		/* alpha */ | ||||
| 	 dstmap[2] = 0;		/* red */ | ||||
| 	 dstmap[1] = 1;		/* green */ | ||||
| 	 dstmap[0] = 2;		/* blue */ | ||||
|       } | ||||
|       else { | ||||
| 	 assert(dstFormat == &_mesa_texformat_argb8888_rev); | ||||
| 	 dstmap[3] = 2; | ||||
| 	 dstmap[2] = 1; | ||||
| 	 dstmap[1] = 0; | ||||
| 	 dstmap[0] = 3; | ||||
|       } | ||||
|   | ||||
|       _mesa_swizzle_ubyte_image(ctx, dims, | ||||
| 				srcFormat, | ||||
| 				srcType, | ||||
|  | ||||
| 				baseInternalFormat, | ||||
| 				dstmap, 4, | ||||
| 				dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| 				dstRowStride, | ||||
| @@ -1367,8 +1616,7 @@ _mesa_texstore_argb8888(TEXSTORE_PARAMS) | ||||
| GLboolean | ||||
| _mesa_texstore_rgb888(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLuint ui = 1; | ||||
|    const GLubyte littleEndian = *((const GLubyte *) &ui); | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_rgb888); | ||||
|    ASSERT(dstFormat->TexelBytes == 3); | ||||
| @@ -1413,6 +1661,31 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS) | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    else if (!ctx->_ImageTransferState && | ||||
| 	    littleEndian && | ||||
| 	    srcType == GL_UNSIGNED_BYTE && | ||||
| 	    can_swizzle(baseInternalFormat) && | ||||
| 	    can_swizzle(srcFormat)) { | ||||
|  | ||||
|       GLubyte dstmap[4]; | ||||
|  | ||||
|       /* dstmap - how to swizzle from RGBA to dst format: | ||||
|        */ | ||||
|       dstmap[0] = 2; | ||||
|       dstmap[1] = 1; | ||||
|       dstmap[2] = 0; | ||||
|       dstmap[3] = ONE;		/* ? */ | ||||
|        | ||||
|       _mesa_swizzle_ubyte_image(ctx, dims, | ||||
| 				srcFormat, | ||||
| 				srcType, | ||||
| 				baseInternalFormat, | ||||
| 				dstmap, 3, | ||||
| 				dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| 				dstRowStride, dstImageOffsets, | ||||
| 				srcWidth, srcHeight, srcDepth, srcAddr, | ||||
| 				srcPacking);       | ||||
|    } | ||||
|    else { | ||||
|       /* general path */ | ||||
|       const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, | ||||
| @@ -1469,8 +1742,7 @@ _mesa_texstore_rgb888(TEXSTORE_PARAMS) | ||||
| GLboolean | ||||
| _mesa_texstore_bgr888(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLuint ui = 1; | ||||
|    const GLubyte littleEndian = *((const GLubyte *) &ui); | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_bgr888); | ||||
|    ASSERT(dstFormat->TexelBytes == 3); | ||||
| @@ -1515,6 +1787,31 @@ _mesa_texstore_bgr888(TEXSTORE_PARAMS) | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|    else if (!ctx->_ImageTransferState && | ||||
| 	    littleEndian && | ||||
| 	    srcType == GL_UNSIGNED_BYTE && | ||||
| 	    can_swizzle(baseInternalFormat) && | ||||
| 	    can_swizzle(srcFormat)) { | ||||
|  | ||||
|       GLubyte dstmap[4]; | ||||
|  | ||||
|       /* dstmap - how to swizzle from RGBA to dst format: | ||||
|        */ | ||||
|       dstmap[0] = 0; | ||||
|       dstmap[1] = 1; | ||||
|       dstmap[2] = 2; | ||||
|       dstmap[3] = ONE;		/* ? */ | ||||
|        | ||||
|       _mesa_swizzle_ubyte_image(ctx, dims, | ||||
| 				srcFormat, | ||||
| 				srcType, | ||||
| 				baseInternalFormat, | ||||
| 				dstmap, 3, | ||||
| 				dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| 				dstRowStride, dstImageOffsets, | ||||
| 				srcWidth, srcHeight, srcDepth, srcAddr, | ||||
| 				srcPacking);       | ||||
|    }    | ||||
|    else { | ||||
|       /* general path */ | ||||
|       const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, | ||||
| @@ -1689,8 +1986,7 @@ _mesa_texstore_argb1555(TEXSTORE_PARAMS) | ||||
| GLboolean | ||||
| _mesa_texstore_al88(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLuint ui = 1; | ||||
|    const GLubyte littleEndian = *((const GLubyte *) &ui); | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_al88 || | ||||
|           dstFormat == &_mesa_texformat_al88_rev); | ||||
| @@ -1711,6 +2007,37 @@ _mesa_texstore_al88(TEXSTORE_PARAMS) | ||||
|                      srcWidth, srcHeight, srcDepth, srcFormat, srcType, | ||||
|                      srcAddr, srcPacking); | ||||
|    } | ||||
|    else if (!ctx->_ImageTransferState && | ||||
| 	    littleEndian && | ||||
| 	    srcType == GL_UNSIGNED_BYTE && | ||||
| 	    can_swizzle(baseInternalFormat) && | ||||
| 	    can_swizzle(srcFormat)) { | ||||
|  | ||||
|       GLubyte dstmap[4]; | ||||
|  | ||||
|       /* dstmap - how to swizzle from RGBA to dst format: | ||||
|        */ | ||||
|       if (dstFormat == &_mesa_texformat_al88) { | ||||
| 	 dstmap[0] = 0; | ||||
| 	 dstmap[1] = 3; | ||||
|       } | ||||
|       else { | ||||
| 	 dstmap[0] = 3; | ||||
| 	 dstmap[1] = 0; | ||||
|       } | ||||
|       dstmap[2] = ZERO;		/* ? */ | ||||
|       dstmap[3] = ONE;		/* ? */ | ||||
|        | ||||
|       _mesa_swizzle_ubyte_image(ctx, dims, | ||||
| 				srcFormat, | ||||
| 				srcType, | ||||
| 				baseInternalFormat, | ||||
| 				dstmap, 2, | ||||
| 				dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| 				dstRowStride, dstImageOffsets, | ||||
| 				srcWidth, srcHeight, srcDepth, srcAddr, | ||||
| 				srcPacking);       | ||||
|    }    | ||||
|    else { | ||||
|       /* general path */ | ||||
|       const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, | ||||
| @@ -1831,6 +2158,36 @@ _mesa_texstore_a8(TEXSTORE_PARAMS) | ||||
|                      srcWidth, srcHeight, srcDepth, srcFormat, srcType, | ||||
|                      srcAddr, srcPacking); | ||||
|    } | ||||
|    else if (!ctx->_ImageTransferState && | ||||
| 	    _mesa_little_endian() && | ||||
| 	    srcType == GL_UNSIGNED_BYTE && | ||||
| 	    can_swizzle(baseInternalFormat) && | ||||
| 	    can_swizzle(srcFormat)) { | ||||
|  | ||||
|       GLubyte dstmap[4]; | ||||
|  | ||||
|       /* dstmap - how to swizzle from RGBA to dst format: | ||||
|        */ | ||||
|       if (dstFormat == &_mesa_texformat_a8) { | ||||
| 	 dstmap[0] = 3; | ||||
|       } | ||||
|       else { | ||||
| 	 dstmap[0] = 0; | ||||
|       } | ||||
|       dstmap[1] = ZERO;		/* ? */ | ||||
|       dstmap[2] = ZERO;		/* ? */ | ||||
|       dstmap[3] = ONE;		/* ? */ | ||||
|        | ||||
|       _mesa_swizzle_ubyte_image(ctx, dims, | ||||
| 				srcFormat, | ||||
| 				srcType, | ||||
| 				baseInternalFormat, | ||||
| 				dstmap, 1, | ||||
| 				dstAddr, dstXoffset, dstYoffset, dstZoffset, | ||||
| 				dstRowStride, dstImageOffsets, | ||||
| 				srcWidth, srcHeight, srcDepth, srcAddr, | ||||
| 				srcPacking);       | ||||
|    }    | ||||
|    else { | ||||
|       /* general path */ | ||||
|       const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, | ||||
| @@ -1912,8 +2269,7 @@ _mesa_texstore_ci8(TEXSTORE_PARAMS) | ||||
| GLboolean | ||||
| _mesa_texstore_ycbcr(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLuint ui = 1; | ||||
|    const GLubyte littleEndian = *((const GLubyte *) &ui); | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|    (void) ctx; (void) dims; (void) baseInternalFormat; | ||||
|  | ||||
|    ASSERT((dstFormat == &_mesa_texformat_ycbcr) || | ||||
| @@ -2164,6 +2520,113 @@ _mesa_texstore_rgba_float16(TEXSTORE_PARAMS) | ||||
| } | ||||
|  | ||||
|  | ||||
| #if FEATURE_EXT_texture_sRGB | ||||
| GLboolean | ||||
| _mesa_texstore_srgb8(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|    const struct gl_texture_format *newDstFormat; | ||||
|    StoreTexImageFunc store; | ||||
|    GLboolean k; | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_srgb8); | ||||
|  | ||||
|    /* reuse normal rgb texstore code */ | ||||
|    if (littleEndian) { | ||||
|       newDstFormat = &_mesa_texformat_bgr888; | ||||
|       store = _mesa_texstore_bgr888; | ||||
|    } | ||||
|    else { | ||||
|       newDstFormat = &_mesa_texformat_rgb888; | ||||
|       store = _mesa_texstore_rgb888; | ||||
|    } | ||||
|  | ||||
|    k = store(ctx, dims, baseInternalFormat, | ||||
|              newDstFormat, dstAddr, | ||||
|              dstXoffset, dstYoffset, dstZoffset, | ||||
|              dstRowStride, dstImageOffsets, | ||||
|              srcWidth, srcHeight, srcDepth, | ||||
|              srcFormat, srcType, | ||||
|              srcAddr, srcPacking); | ||||
|    return k; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean | ||||
| _mesa_texstore_srgba8(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|    const struct gl_texture_format *newDstFormat; | ||||
|    GLboolean k; | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_srgba8); | ||||
|  | ||||
|    /* reuse normal rgba texstore code */ | ||||
|    if (littleEndian) | ||||
|       newDstFormat = &_mesa_texformat_rgba8888_rev; | ||||
|    else | ||||
|       newDstFormat = &_mesa_texformat_rgba8888; | ||||
|  | ||||
|    k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat, | ||||
|                                newDstFormat, dstAddr, | ||||
|                                dstXoffset, dstYoffset, dstZoffset, | ||||
|                                dstRowStride, dstImageOffsets, | ||||
|                                srcWidth, srcHeight, srcDepth, | ||||
|                                srcFormat, srcType, | ||||
|                                srcAddr, srcPacking); | ||||
|    return k; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean | ||||
| _mesa_texstore_sl8(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const struct gl_texture_format *newDstFormat; | ||||
|    GLboolean k; | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_sl8); | ||||
|  | ||||
|    newDstFormat = &_mesa_texformat_l8; | ||||
|  | ||||
|    /* _mesa_textore_a8 handles luminance8 too */ | ||||
|    k = _mesa_texstore_a8(ctx, dims, baseInternalFormat, | ||||
|                          newDstFormat, dstAddr, | ||||
|                          dstXoffset, dstYoffset, dstZoffset, | ||||
|                          dstRowStride, dstImageOffsets, | ||||
|                          srcWidth, srcHeight, srcDepth, | ||||
|                          srcFormat, srcType, | ||||
|                          srcAddr, srcPacking); | ||||
|    return k; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean | ||||
| _mesa_texstore_sla8(TEXSTORE_PARAMS) | ||||
| { | ||||
|    const GLboolean littleEndian = _mesa_little_endian(); | ||||
|    const struct gl_texture_format *newDstFormat; | ||||
|    GLboolean k; | ||||
|  | ||||
|    ASSERT(dstFormat == &_mesa_texformat_sla8); | ||||
|  | ||||
|    /* reuse normal luminance/alpha texstore code */ | ||||
|    if (littleEndian) | ||||
|       newDstFormat = &_mesa_texformat_al88; | ||||
|    else | ||||
|       newDstFormat = &_mesa_texformat_al88_rev; | ||||
|  | ||||
|    k = _mesa_texstore_al88(ctx, dims, baseInternalFormat, | ||||
|                            newDstFormat, dstAddr, | ||||
|                            dstXoffset, dstYoffset, dstZoffset, | ||||
|                            dstRowStride, dstImageOffsets, | ||||
|                            srcWidth, srcHeight, srcDepth, | ||||
|                            srcFormat, srcType, | ||||
|                            srcAddr, srcPacking); | ||||
|    return k; | ||||
| } | ||||
|  | ||||
| #endif /* FEATURE_EXT_texture_sRGB */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Check if an unpack PBO is active prior to fetching a texture image. | ||||
|   | ||||
| @@ -98,7 +98,7 @@ _swrast_update_rasterflags( GLcontext *ctx ) | ||||
|       rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */ | ||||
|    } | ||||
|  | ||||
|    if (ctx->FragmentProgram._Active) { | ||||
|    if (ctx->FragmentProgram._Enabled) { | ||||
|       rasterMask |= FRAGPROG_BIT; | ||||
|    } | ||||
|  | ||||
| @@ -206,7 +206,7 @@ _swrast_update_fog_state( GLcontext *ctx ) | ||||
|  | ||||
|    /* determine if fog is needed, and if so, which fog mode */ | ||||
|    swrast->_FogEnabled = GL_FALSE; | ||||
|    if (ctx->FragmentProgram._Active) { | ||||
|    if (ctx->FragmentProgram._Enabled) { | ||||
|       if (ctx->FragmentProgram._Current->Base.Target==GL_FRAGMENT_PROGRAM_ARB) { | ||||
|          const struct gl_fragment_program *fp | ||||
|             = ctx->FragmentProgram._Current; | ||||
| @@ -230,7 +230,7 @@ _swrast_update_fog_state( GLcontext *ctx ) | ||||
| static void | ||||
| _swrast_update_fragment_program( GLcontext *ctx ) | ||||
| { | ||||
|    if (ctx->FragmentProgram._Active) { | ||||
|    if (ctx->FragmentProgram._Enabled) { | ||||
|       const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; | ||||
|       _mesa_load_state_parameters(ctx, fp->Base.Parameters); | ||||
|    } | ||||
| @@ -299,7 +299,7 @@ _swrast_validate_triangle( GLcontext *ctx, | ||||
|  | ||||
|    if (ctx->Texture._EnabledUnits == 0 | ||||
|        && NEED_SECONDARY_COLOR(ctx) | ||||
|        && !ctx->FragmentProgram._Active) { | ||||
|        && !ctx->FragmentProgram._Enabled) { | ||||
|       /* separate specular color, but no texture */ | ||||
|       swrast->SpecTriangle = swrast->Triangle; | ||||
|       swrast->Triangle = _swrast_add_spec_terms_triangle; | ||||
| @@ -322,7 +322,7 @@ _swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) | ||||
|  | ||||
|    if (ctx->Texture._EnabledUnits == 0 | ||||
|        && NEED_SECONDARY_COLOR(ctx) | ||||
|        && !ctx->FragmentProgram._Active) { | ||||
|        && !ctx->FragmentProgram._Enabled) { | ||||
|       swrast->SpecLine = swrast->Line; | ||||
|       swrast->Line = _swrast_add_spec_terms_line; | ||||
|    } | ||||
| @@ -345,7 +345,7 @@ _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 ) | ||||
|  | ||||
|    if (ctx->Texture._EnabledUnits == 0 | ||||
|        && NEED_SECONDARY_COLOR(ctx) | ||||
|        && !ctx->FragmentProgram._Active) { | ||||
|        && !ctx->FragmentProgram._Enabled) { | ||||
|       swrast->SpecPoint = swrast->Point; | ||||
|       swrast->Point = _swrast_add_spec_terms_point; | ||||
|    } | ||||
|   | ||||
| @@ -129,7 +129,7 @@ _swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span ) | ||||
|    GLuint i; | ||||
|    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { | ||||
|       const GLfloat *tc = ctx->Current.RasterTexCoords[i]; | ||||
|       if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled) { | ||||
|       if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled) { | ||||
|          COPY_4V(span->tex[i], tc); | ||||
|       } | ||||
|       else if (tc[3] > 0.0F) { | ||||
| @@ -410,7 +410,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) | ||||
|             if (obj) { | ||||
|                const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; | ||||
|                needLambda = (obj->MinFilter != obj->MagFilter) | ||||
|                   || ctx->FragmentProgram._Active; | ||||
|                   || ctx->FragmentProgram._Enabled; | ||||
|                texW = img->WidthScale; | ||||
|                texH = img->HeightScale; | ||||
|             } | ||||
| @@ -435,7 +435,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) | ||||
|                GLfloat r = span->tex[u][2]; | ||||
|                GLfloat q = span->tex[u][3]; | ||||
|                GLuint i; | ||||
|                if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled || | ||||
|                if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled || | ||||
|                    ctx->ShaderObjects._FragmentShaderPresent) { | ||||
|                   /* do perspective correction but don't divide s, t, r by q */ | ||||
|                   const GLfloat dwdx = span->dwdx; | ||||
| @@ -487,7 +487,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) | ||||
|                GLfloat r = span->tex[u][2]; | ||||
|                GLfloat q = span->tex[u][3]; | ||||
|                GLuint i; | ||||
|                if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled || | ||||
|                if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled || | ||||
|                    ctx->ShaderObjects._FragmentShaderPresent) { | ||||
|                   /* do perspective correction but don't divide s, t, r by q */ | ||||
|                   const GLfloat dwdx = span->dwdx; | ||||
| @@ -546,7 +546,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) | ||||
|       if (obj) { | ||||
|          const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; | ||||
|          needLambda = (obj->MinFilter != obj->MagFilter) | ||||
|             || ctx->FragmentProgram._Active; | ||||
|             || ctx->FragmentProgram._Enabled; | ||||
|          texW = (GLfloat) img->WidthScale; | ||||
|          texH = (GLfloat) img->HeightScale; | ||||
|       } | ||||
| @@ -571,7 +571,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) | ||||
|          GLfloat r = span->tex[0][2]; | ||||
|          GLfloat q = span->tex[0][3]; | ||||
|          GLuint i; | ||||
|          if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled || | ||||
|          if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled || | ||||
|              ctx->ShaderObjects._FragmentShaderPresent) { | ||||
|             /* do perspective correction but don't divide s, t, r by q */ | ||||
|             const GLfloat dwdx = span->dwdx; | ||||
| @@ -623,7 +623,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span) | ||||
|          GLfloat r = span->tex[0][2]; | ||||
|          GLfloat q = span->tex[0][3]; | ||||
|          GLuint i; | ||||
|          if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled || | ||||
|          if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled || | ||||
|              ctx->ShaderObjects._FragmentShaderPresent) { | ||||
|             /* do perspective correction but don't divide s, t, r by q */ | ||||
|             const GLfloat dwdx = span->dwdx; | ||||
| @@ -1120,7 +1120,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) | ||||
|    const GLbitfield origInterpMask = span->interpMask; | ||||
|    const GLbitfield origArrayMask = span->arrayMask; | ||||
|    const GLboolean deferredTexture = !(ctx->Color.AlphaEnabled || | ||||
|                                        ctx->FragmentProgram._Active || | ||||
|                                        ctx->FragmentProgram._Enabled || | ||||
|                                        ctx->ShaderObjects._FragmentShaderPresent); | ||||
|  | ||||
|    ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE || | ||||
| @@ -1197,15 +1197,12 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) | ||||
|          interpolate_fog(ctx, span); | ||||
|  | ||||
|       /* Compute fragment colors with fragment program or texture lookups */ | ||||
| #if FEATURE_ARB_fragment_shader | ||||
|       if (ctx->ShaderObjects._FragmentShaderPresent) { | ||||
|          if (span->interpMask & SPAN_Z) | ||||
|             _swrast_span_interpolate_z (ctx, span); | ||||
|          _swrast_exec_arbshader (ctx, span); | ||||
|       } | ||||
|       else | ||||
| #endif | ||||
|       if (ctx->FragmentProgram._Active) { | ||||
|       else if (ctx->FragmentProgram._Enabled) { | ||||
|          /* frag prog may need Z values */ | ||||
|          if (span->interpMask & SPAN_Z) | ||||
|             _swrast_span_interpolate_z(ctx, span); | ||||
| @@ -1284,15 +1281,12 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) | ||||
|       if (span->interpMask & SPAN_FOG) | ||||
|          interpolate_fog(ctx, span); | ||||
|  | ||||
| #if FEATURE_ARB_fragment_shader | ||||
|       if (ctx->ShaderObjects._FragmentShaderPresent) { | ||||
|          if (span->interpMask & SPAN_Z) | ||||
|             _swrast_span_interpolate_z (ctx, span); | ||||
|          _swrast_exec_arbshader (ctx, span); | ||||
|       } | ||||
|       else | ||||
| #endif | ||||
|       if (ctx->FragmentProgram._Active) | ||||
|       else if (ctx->FragmentProgram._Enabled) | ||||
|          _swrast_exec_fragment_program( ctx, span ); | ||||
|       else if (ctx->ATIFragmentShader._Enabled) | ||||
|          _swrast_exec_fragment_shader( ctx, span ); | ||||
|   | ||||
| @@ -1072,7 +1072,7 @@ _swrast_choose_triangle( GLcontext *ctx ) | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       if (ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Active || | ||||
|       if (ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Enabled || | ||||
|           ctx->ATIFragmentShader._Enabled || ctx->ShaderObjects._FragmentShaderPresent) { | ||||
|          /* Ugh, we do a _lot_ of tests to pick the best textured tri func */ | ||||
|          const struct gl_texture_object *texObj2D; | ||||
| @@ -1088,7 +1088,7 @@ _swrast_choose_triangle( GLcontext *ctx ) | ||||
|  | ||||
|          /* First see if we can use an optimized 2-D texture function */ | ||||
|          if (ctx->Texture._EnabledCoordUnits == 0x1 | ||||
|              && !ctx->FragmentProgram._Active | ||||
|              && !ctx->FragmentProgram._Enabled | ||||
|              && !ctx->ATIFragmentShader._Enabled | ||||
|              && !ctx->ShaderObjects._FragmentShaderPresent | ||||
|              && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT | ||||
|   | ||||
		Reference in New Issue
	
	Block a user