Compare commits
	
		
			245 Commits
		
	
	
		
			cros-mesa-
			...
			texman_0_1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 8ecd83f6cd | ||
|  | cff7e025ed | ||
|  | 3de9a9bd1d | ||
|  | e6cae6e6f6 | ||
|  | 9cf5945b83 | ||
|  | d6ddc33f07 | ||
|  | ec32d129b7 | ||
|  | cd41c27446 | ||
|  | af6a480117 | ||
|  | 14e9700621 | ||
|  | 7fb177c367 | ||
|  | d65cda4ce3 | ||
|  | 460a375d85 | ||
|  | c3c5652602 | ||
|  | e1998baef8 | ||
|  | 3e980901b0 | ||
|  | 14fe63a12b | ||
|  | fbd147c0b5 | ||
|  | 7b7c54e94c | ||
|  | 84dd9c8112 | ||
|  | bba85343e7 | ||
|  | 6484b373c3 | ||
|  | 245a3c54c7 | ||
|  | 1266e633cc | ||
|  | 86042f53f2 | ||
|  | 068062f997 | ||
|  | c62af8e3b7 | ||
|  | 8e5650d7f4 | ||
|  | 65f1cf2cbf | ||
|  | f04f5e990a | ||
|  | 1854ebe77e | ||
|  | 3500f2e3c4 | ||
|  | cfeefc9b81 | ||
|  | 3ad6adfb57 | ||
|  | 8a126f1166 | ||
|  | 6315aabcf2 | ||
|  | a8c2344364 | ||
|  | 2929b2569b | ||
|  | f14790d7b0 | ||
|  | 8fb2e61801 | ||
|  | b3c94f9d9d | ||
|  | 5b889f7f2d | ||
|  | 0f531b5b48 | ||
|  | c6482c0d41 | ||
|  | b71748efd1 | ||
|  | 1c4b9edc41 | ||
|  | 2b464d93d1 | ||
|  | 497f80ac34 | ||
|  | 2be748769b | ||
|  | 45a1083ee7 | ||
|  | 3a45baa70d | ||
|  | 0bc3a7ac2e | ||
|  | 08f0579176 | ||
|  | d689cd0715 | ||
|  | e957f39f67 | ||
|  | 416f09d3e6 | ||
|  | 40cc5d36fd | ||
|  | 62f9613dbc | ||
|  | 7f31255eb2 | ||
|  | 78382b4bbe | ||
|  | bd8e90857c | ||
|  | b7cc448ff8 | ||
|  | 0ea582acbe | ||
|  | 05c824db87 | ||
|  | 829f6909bd | ||
|  | 34f1ebc72f | ||
|  | c6e586ee0c | ||
|  | 9180d932c6 | ||
|  | 95df1b67a2 | ||
|  | bc400c3f30 | ||
|  | 3a3db0e9ec | ||
|  | 613e395ab8 | ||
|  | 86c5de8b85 | ||
|  | 44c8c42ab9 | ||
|  | 31a82a663c | ||
|  | dafdf6512e | ||
|  | 9caacb015a | ||
|  | 2887770534 | ||
|  | fb440c9f82 | ||
|  | 576c9c310f | ||
|  | ec1db9db1f | ||
|  | e1f70cf5e2 | ||
|  | a7cdbf5c38 | ||
|  | fe37adfde3 | ||
|  | 315396ac6c | ||
|  | a7252f42ae | ||
|  | bffc66109e | ||
|  | 0089c7f4ee | ||
|  | 54f435340b | ||
|  | 66d887d605 | ||
|  | c6dc5cc8ab | ||
|  | e0412bb726 | ||
|  | cc5cbd1bca | ||
|  | 93fbfa5781 | ||
|  | 30709caad6 | ||
|  | a647198f65 | ||
|  | 7ad6ea6ff2 | ||
|  | ceee2c45cd | ||
|  | 26dc161fde | ||
|  | b176ef05f2 | ||
|  | 6d6e7a08c7 | ||
|  | eb75ec2349 | ||
|  | 2a8bd4e329 | ||
|  | c247268499 | ||
|  | b2cb8920c2 | ||
|  | af4d93f256 | ||
|  | c8dd839acb | ||
|  | e43c3c38fb | ||
|  | 9194782fdc | ||
|  | ec36d5b537 | ||
|  | 6e5da1a860 | ||
|  | 21f6e8a2d0 | ||
|  | 18772c9e88 | ||
|  | 5df4283b53 | ||
|  | 6734bab3b2 | ||
|  | 0a5fea5f96 | ||
|  | 9b2762d7b9 | ||
|  | 571bf7a71b | ||
|  | 4ab3b9aa76 | ||
|  | 88c018ee47 | ||
|  | cead52ef68 | ||
|  | 9cf0ed6059 | ||
|  | 2c1c8dccf7 | ||
|  | b87f9f6056 | ||
|  | 427bf0171d | ||
|  | 98c5445c75 | ||
|  | 15ffb3bbab | ||
|  | 97b570b999 | ||
|  | e8e6374a16 | ||
|  | d9f31f16c0 | ||
|  | 1173198f51 | ||
|  | 01a56d23e6 | ||
|  | bf050799ac | ||
|  | 3697eca493 | ||
|  | de2b3506ea | ||
|  | bfbe2eb6e9 | ||
|  | 8bd395f601 | ||
|  | 735925d15b | ||
|  | 448a3456a9 | ||
|  | e176b11b74 | ||
|  | cdc8771893 | ||
|  | 789399d3f4 | ||
|  | dfa8624e83 | ||
|  | 36b64bbd4f | ||
|  | 651985f813 | ||
|  | 9f2b49a7b3 | ||
|  | 05c6361b0b | ||
|  | 9621817253 | ||
|  | 7e2e4a6b1a | ||
|  | 656c71ca3f | ||
|  | 6ce7055dcc | ||
|  | c848a65b5e | ||
|  | 1ff99fcd50 | ||
|  | 67342052d2 | ||
|  | ccf52b6784 | ||
|  | 78aa58c914 | ||
|  | 4291f24abd | ||
|  | f4211722f1 | ||
|  | 71380a1325 | ||
|  | 33e55c6a7d | ||
|  | cd32164cc6 | ||
|  | 7c1348ac8f | ||
|  | 2560061cfe | ||
|  | 0c047b8847 | ||
|  | c64a08c286 | ||
|  | bb409e88d8 | ||
|  | af69eefcba | ||
|  | d9c071adec | ||
|  | 833d19c21d | ||
|  | 7245757174 | ||
|  | 3d96cb7d48 | ||
|  | f565ab2dd5 | ||
|  | 7ad0c51f48 | ||
|  | fea684c533 | ||
|  | 4e8845fc0c | ||
|  | ffcc1cdb41 | ||
|  | afc90075ba | ||
|  | 79acea2708 | ||
|  | a12063a540 | ||
|  | 9826d83439 | ||
|  | 84f7ded925 | ||
|  | 59dd8ad752 | ||
|  | 4afd26982e | ||
|  | 17e4a7ea17 | ||
|  | 3d67655cce | ||
|  | b5d7c69884 | ||
|  | b6759e2be7 | ||
|  | af853b0da7 | ||
|  | 8d349798da | ||
|  | 4aea628194 | ||
|  | 008ddf628a | ||
|  | 716496f263 | ||
|  | b3b325e560 | ||
|  | 382ce985ac | ||
|  | 54b7eca7a0 | ||
|  | f74e06bf11 | ||
|  | 9c02649d18 | ||
|  | 2c34704e41 | ||
|  | 85d0041ff0 | ||
|  | 67ff8b354e | ||
|  | 08e7957571 | ||
|  | 9c1f7089d8 | ||
|  | 5381ac5f11 | ||
|  | a6f78d4eee | ||
|  | ae695e3566 | ||
|  | c82c3335e1 | ||
|  | f8246f504b | ||
|  | 499458bcdb | ||
|  | 37a53fd6a0 | ||
|  | 5ec38fb2ea | ||
|  | 11c0215bf8 | ||
|  | 6a13b6c346 | ||
|  | a103097ee5 | ||
|  | 7efad0d84c | ||
|  | 42c88cd072 | ||
|  | 2541c54e79 | ||
|  | 33529e3d8e | ||
|  | 84c1b82081 | ||
|  | a97a1439ae | ||
|  | 2fd2910010 | ||
|  | fbbda155e0 | ||
|  | a49c3c0fae | ||
|  | baf5998d59 | ||
|  | 4c5acef241 | ||
|  | 9839e272cf | ||
|  | b57e79ff14 | ||
|  | 43824acb4e | ||
|  | d8f509e749 | ||
|  | eb91c93c2e | ||
|  | 79de983b6f | ||
|  | fdb3acf016 | ||
|  | 2807d1f58a | ||
|  | 93f913926e | ||
|  | 33ca04f379 | ||
|  | 398cb30c72 | ||
|  | f67bb30314 | ||
|  | 4578d7b9f0 | ||
|  | dcdfc154c3 | ||
|  | 696ba32779 | ||
|  | dcfe55539f | ||
|  | ff84b1f1b2 | ||
|  | 3bca9c47f4 | ||
|  | d4d7fdb43b | ||
|  | d65dab5777 | ||
|  | 638ca019ef | 
| @@ -10,9 +10,6 @@ MESA_MAJOR=6 | ||||
| MESA_MINOR=5 | ||||
| MESA_TINY=0 | ||||
|  | ||||
| # external projects.  This should be useless now that we use libdrm. | ||||
| DRM_SOURCE_PATH=$(TOP)/../drm | ||||
|  | ||||
| # Compiler and flags | ||||
| CC = cc | ||||
| CXX = CC | ||||
|   | ||||
| @@ -9,11 +9,12 @@ CONFIG_NAME = linux-dri | ||||
| CC = gcc | ||||
| CXX = g++ | ||||
|  | ||||
| MKDEP = /usr/X11R6/bin/makedepend | ||||
| #MKDEP = /usr/X11R6/bin/makedepend | ||||
| #MKDEP = gcc -M | ||||
| #MKDEP_OPTIONS = -MF depend | ||||
|  | ||||
| OPT_FLAGS  = -g | ||||
| #OPT_FLAGS  = -g -march=pentium4 -fprefetch-loop-arrays | ||||
| OPT_FLAGS  = -O2  | ||||
| PIC_FLAGS  = -fPIC | ||||
|  | ||||
| # Add '-DGLX_USE_TLS' to ARCH_FLAGS to enable TLS support. | ||||
| @@ -22,6 +23,7 @@ ARCH_FLAGS ?= | ||||
| DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \ | ||||
| 	-D_BSD_SOURCE -D_GNU_SOURCE \ | ||||
| 	-DPTHREADS -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER \ | ||||
| 	-DDEBUG \ | ||||
| 	-DGLX_DIRECT_RENDERING -DHAVE_ALIAS | ||||
|  | ||||
| X11_INCLUDES = -I/usr/X11R6/include | ||||
| @@ -63,5 +65,7 @@ WINDOW_SYSTEM=dri | ||||
|  | ||||
| # gamma are missing because they have not been converted to use the new | ||||
| # interface. | ||||
| DRI_DIRS = i810 i830 i915 mach64 mga r128 r200 r300 radeon s3v \ | ||||
| DRI_DIRS = i915 mach64 mga r128 r200 r300 radeon s3v \ | ||||
| 	savage sis tdfx trident unichrome ffb | ||||
|  | ||||
| DRI_DIRS = i915  | ||||
|   | ||||
| @@ -2260,6 +2260,28 @@ typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pnam | ||||
|  | ||||
|  | ||||
|  | ||||
| #ifndef GL_EXT_framebuffer_blit | ||||
| #define GL_EXT_framebuffer_blit 1 | ||||
|  | ||||
| #define GL_READ_FRAMEBUFFER_EXT                0x8CA8 | ||||
| #define GL_DRAW_FRAMEBUFFER_EXT                0x8CA9 | ||||
| #define GL_DRAW_FRAMEBUFFER_BINDING_EXT        0x8CA6 | ||||
| #define GL_READ_FRAMEBUFFER_BINDING_EXT        0x8CAA | ||||
|  | ||||
| GLAPI void GLAPIENTRY | ||||
| glBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, | ||||
|                      GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, | ||||
|                      GLbitfield mask, GLenum filter); | ||||
|  | ||||
| typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) | ||||
|         (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, | ||||
|          GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, | ||||
|          GLbitfield mask, GLenum filter); | ||||
|  | ||||
| #endif /* GL_EXT_framebuffer_blit */ | ||||
|  | ||||
|  | ||||
|  | ||||
| #ifndef GL_EXT_packed_depth_stencil | ||||
| #define GL_EXT_packed_depth_stencil 1 | ||||
|  | ||||
|   | ||||
| @@ -20,11 +20,14 @@ PROGS = \ | ||||
| 	clearspd \ | ||||
| 	cubemap \ | ||||
| 	drawpix \ | ||||
| 	copypix \ | ||||
| 	drawpix_pbo \ | ||||
| 	fire \ | ||||
| 	fogcoord \ | ||||
| 	fplight \ | ||||
| 	gamma \ | ||||
| 	gears \ | ||||
| 	gearbox \ | ||||
| 	geartrain \ | ||||
| 	glinfo \ | ||||
| 	gloss \ | ||||
| @@ -51,7 +54,7 @@ PROGS = \ | ||||
| 	terrain \ | ||||
| 	tessdemo \ | ||||
| 	texcyl \ | ||||
| 	texdown \ | ||||
| 	texdown-pool \ | ||||
| 	texenv \ | ||||
| 	texobj \ | ||||
| 	trispd \ | ||||
| @@ -73,9 +76,8 @@ PROGS = \ | ||||
|  | ||||
| ##### TARGETS ##### | ||||
|  | ||||
| default: $(PROGS) | ||||
| default: readtex.o $(PROGS) | ||||
|  | ||||
| $(PROGS): readtex.o | ||||
|  | ||||
| readtex.c: $(TOP)/progs/util/readtex.c | ||||
| 	cp $< . | ||||
|   | ||||
							
								
								
									
										364
									
								
								progs/demos/copypix.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								progs/demos/copypix.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,364 @@ | ||||
|  | ||||
| /* | ||||
|  * glDrawPixels demo/test/benchmark | ||||
|  *  | ||||
|  * Brian Paul   September 25, 1997  This file is in the public domain. | ||||
|  */ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <math.h> | ||||
| #include <string.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| #include "readtex.h" | ||||
|  | ||||
| #define IMAGE_FILE "../images/girl.rgb" | ||||
|  | ||||
| static int ImgWidth, ImgHeight; | ||||
| static GLenum ImgFormat; | ||||
| static GLubyte *Image = NULL; | ||||
|  | ||||
| static int Xpos, Ypos; | ||||
| static int SkipPixels, SkipRows; | ||||
| static int DrawWidth, DrawHeight; | ||||
| static int Scissor = 0; | ||||
| static int Fog = 0; | ||||
| static GLfloat Zpos = -1.0; | ||||
| static float Xzoom, Yzoom; | ||||
| static GLboolean DrawFront = GL_FALSE; | ||||
| static GLboolean Dither = GL_TRUE; | ||||
|  | ||||
|  | ||||
| static void Reset( void ) | ||||
| { | ||||
|    Xpos = Ypos = 20; | ||||
|    DrawWidth = ImgWidth; | ||||
|    DrawHeight = ImgHeight; | ||||
|    SkipPixels = SkipRows = 0; | ||||
|    Scissor = 0; | ||||
|    Fog = 0; | ||||
|    Zpos = -1.0; | ||||
|    Xzoom = Yzoom = 1.0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Display( void ) | ||||
| { | ||||
|    glClear( GL_COLOR_BUFFER_BIT ); | ||||
|  | ||||
|    glRasterPos2i(10, 10); | ||||
|    glPixelZoom( 1, 1 ); | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|    glDisable(GL_FOG); | ||||
|    glDrawPixels(ImgWidth, ImgHeight, ImgFormat, GL_UNSIGNED_BYTE, Image); | ||||
|  | ||||
| #if 0 | ||||
|    glRasterPos2i(Xpos, Ypos); | ||||
| #else | ||||
|    /* This allows negative raster positions: */ | ||||
|    glRasterPos3f(0, 0, Zpos); | ||||
|    glBitmap(0, 0, 0, 0, Xpos, Ypos, NULL); | ||||
| #endif | ||||
|  | ||||
|    glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels); | ||||
|    glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows); | ||||
|  | ||||
|    glPixelZoom( Xzoom, Yzoom ); | ||||
|  | ||||
|    if (Scissor) | ||||
|       glEnable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    if (Fog) | ||||
|       glEnable(GL_FOG); | ||||
|  | ||||
|    glCopyPixels(10, 10, ImgWidth, ImgHeight, GL_COLOR); | ||||
|  | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|    glDisable(GL_FOG); | ||||
|  | ||||
|    if (DrawFront) | ||||
|       glFinish(); | ||||
|    else | ||||
|       glutSwapBuffers(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Benchmark( void ) | ||||
| { | ||||
|    int startTime, endTime; | ||||
|    int draws = 500; | ||||
|    double seconds, pixelsPerSecond; | ||||
|  | ||||
|    printf("Benchmarking...\n"); | ||||
|    /* GL set-up */ | ||||
|    glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels); | ||||
|    glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows); | ||||
|    glPixelZoom( Xzoom, Yzoom ); | ||||
|    if (Scissor) | ||||
|       glEnable(GL_SCISSOR_TEST); | ||||
|    if (Fog) | ||||
|       glEnable(GL_FOG); | ||||
|  | ||||
|    if (DrawFront) | ||||
|       glDrawBuffer(GL_FRONT); | ||||
|    else | ||||
|       glDrawBuffer(GL_BACK); | ||||
|  | ||||
|    /* Run timing test */ | ||||
|    draws = 0; | ||||
|    startTime = glutGet(GLUT_ELAPSED_TIME); | ||||
|    do { | ||||
|       glCopyPixels(10, 10, ImgWidth, ImgHeight, GL_COLOR); | ||||
|       draws++; | ||||
|       endTime = glutGet(GLUT_ELAPSED_TIME); | ||||
|    } while (endTime - startTime < 4000);   /* 4 seconds */ | ||||
|  | ||||
|    /* GL clean-up */ | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|    glDisable(GL_FOG); | ||||
|  | ||||
|    /* Results */ | ||||
|    seconds = (double) (endTime - startTime) / 1000.0; | ||||
|    pixelsPerSecond = draws * DrawWidth * DrawHeight / seconds; | ||||
|    printf("Result:  %d draws in %f seconds = %f pixels/sec\n", | ||||
|           draws, seconds, pixelsPerSecond); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Reshape( int width, int height ) | ||||
| { | ||||
|    glViewport( 0, 0, width, height ); | ||||
|    glMatrixMode( GL_PROJECTION ); | ||||
|    glLoadIdentity(); | ||||
|    glOrtho( 0.0, width, 0.0, height, 0.0, 2.0 ); | ||||
|    glMatrixMode( GL_MODELVIEW ); | ||||
|    glLoadIdentity(); | ||||
|  | ||||
|    glScissor(width/4, height/4, width/2, height/2); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Key( unsigned char key, int x, int y ) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case ' ': | ||||
|          Reset(); | ||||
|          break; | ||||
|       case 'd': | ||||
|          Dither = !Dither; | ||||
|          if (Dither) | ||||
|             glEnable(GL_DITHER); | ||||
|          else | ||||
|             glDisable(GL_DITHER); | ||||
|          break; | ||||
|       case 'w': | ||||
|          if (DrawWidth > 0) | ||||
|             DrawWidth--; | ||||
|          break; | ||||
|       case 'W': | ||||
|          DrawWidth++; | ||||
|          break; | ||||
|       case 'h': | ||||
|          if (DrawHeight > 0) | ||||
|             DrawHeight--; | ||||
|          break; | ||||
|       case 'H': | ||||
|          DrawHeight++; | ||||
|          break; | ||||
|       case 'p': | ||||
|          if (SkipPixels > 0) | ||||
|              SkipPixels--; | ||||
|          break; | ||||
|       case 'P': | ||||
|          SkipPixels++; | ||||
|          break; | ||||
|       case 'r': | ||||
|          if (SkipRows > 0) | ||||
|              SkipRows--; | ||||
|          break; | ||||
|       case 'R': | ||||
|          SkipRows++; | ||||
|          break; | ||||
|       case 's': | ||||
|          Scissor = !Scissor; | ||||
|          break; | ||||
|       case 'x': | ||||
|          Xzoom -= 0.1; | ||||
|          break; | ||||
|       case 'X': | ||||
|          Xzoom += 0.1; | ||||
|          break; | ||||
|       case 'y': | ||||
|          Yzoom -= 0.1; | ||||
|          break; | ||||
|       case 'Y': | ||||
|          Yzoom += 0.1; | ||||
|          break; | ||||
|       case 'z': | ||||
|          Zpos -= 0.1; | ||||
|          printf("RasterPos Z = %g\n", Zpos); | ||||
|          break; | ||||
|       case 'Z': | ||||
|          Zpos += 0.1; | ||||
|          printf("RasterPos Z = %g\n", Zpos); | ||||
|          break; | ||||
|       case 'b': | ||||
|          Benchmark(); | ||||
|          break; | ||||
|       case 'F': | ||||
|          Fog = !Fog; | ||||
|          printf("Fog %d\n", Fog); | ||||
|          break; | ||||
|       case 'f': | ||||
|          DrawFront = !DrawFront; | ||||
|          if (DrawFront) | ||||
|             glDrawBuffer(GL_FRONT); | ||||
|          else | ||||
|             glDrawBuffer(GL_BACK); | ||||
|          printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK"); | ||||
|          break; | ||||
|       case 27: | ||||
|          exit(0); | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void SpecialKey( int key, int x, int y ) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case GLUT_KEY_UP: | ||||
|          Ypos += 1; | ||||
|          break; | ||||
|       case GLUT_KEY_DOWN: | ||||
|          Ypos -= 1; | ||||
|          break; | ||||
|       case GLUT_KEY_LEFT: | ||||
|          Xpos -= 1; | ||||
|          break; | ||||
|       case GLUT_KEY_RIGHT: | ||||
|          Xpos += 1; | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Init( GLboolean ciMode, const char *filename ) | ||||
| { | ||||
|    static const GLfloat fogColor[4] = {0, 1, 0, 0}; | ||||
|  | ||||
|    printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); | ||||
|    printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|  | ||||
|    Image = LoadRGBImage( filename, &ImgWidth, &ImgHeight, &ImgFormat ); | ||||
|    if (!Image) { | ||||
|       printf("Couldn't read %s\n", filename); | ||||
|       exit(0); | ||||
|    } | ||||
|  | ||||
|    if (ciMode) { | ||||
|       /* Convert RGB image to grayscale */ | ||||
|       GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight ); | ||||
|       GLint i; | ||||
|       for (i=0; i<ImgWidth*ImgHeight; i++) { | ||||
|          int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2]; | ||||
|          indexImage[i] = gray / 3; | ||||
|       } | ||||
|       free(Image); | ||||
|       Image = indexImage; | ||||
|       ImgFormat = GL_COLOR_INDEX; | ||||
|  | ||||
|       for (i=0;i<255;i++) { | ||||
|          float g = i / 255.0; | ||||
|          glutSetColor(i, g, g, g); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    printf("Loaded %d by %d image\n", ImgWidth, ImgHeight ); | ||||
|  | ||||
|    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|    glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth); | ||||
|  | ||||
|    glFogi(GL_FOG_MODE, GL_LINEAR); | ||||
|    glFogf(GL_FOG_START, 0); | ||||
|    glFogf(GL_FOG_END, 2); | ||||
|    glFogfv(GL_FOG_COLOR, fogColor); | ||||
|  | ||||
|    Reset(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Usage(void) | ||||
| { | ||||
|    printf("Keys:\n"); | ||||
|    printf("       SPACE  Reset Parameters\n"); | ||||
|    printf("     Up/Down  Move image up/down\n"); | ||||
|    printf("  Left/Right  Move image left/right\n"); | ||||
|    printf("           x  Decrease X-axis PixelZoom\n"); | ||||
|    printf("           X  Increase X-axis PixelZoom\n"); | ||||
|    printf("           y  Decrease Y-axis PixelZoom\n"); | ||||
|    printf("           Y  Increase Y-axis PixelZoom\n"); | ||||
|    printf("           w  Decrease glDrawPixels width*\n"); | ||||
|    printf("           W  Increase glDrawPixels width*\n"); | ||||
|    printf("           h  Decrease glDrawPixels height*\n"); | ||||
|    printf("           H  Increase glDrawPixels height*\n"); | ||||
|    printf("           p  Decrease GL_UNPACK_SKIP_PIXELS*\n"); | ||||
|    printf("           P  Increase GL_UNPACK_SKIP_PIXELS*\n"); | ||||
|    printf("           r  Decrease GL_UNPACK_SKIP_ROWS*\n"); | ||||
|    printf("           R  Increase GL_UNPACK_SKIP_ROWS*\n"); | ||||
|    printf("           s  Toggle GL_SCISSOR_TEST\n"); | ||||
|    printf("           F  Toggle GL_FOG\n"); | ||||
|    printf("           z  Decrease RasterPos Z\n"); | ||||
|    printf("           Z  Increase RasterPos Z\n"); | ||||
|     | ||||
|    printf("           f  Toggle front/back buffer drawing\n"); | ||||
|    printf("           b  Benchmark test\n"); | ||||
|    printf("         ESC  Exit\n"); | ||||
|    printf("* Warning: no limits are imposed on these parameters so it's\n"); | ||||
|    printf("  possible to cause a segfault if you go too far.\n"); | ||||
| } | ||||
|  | ||||
|  | ||||
| int main( int argc, char *argv[] ) | ||||
| { | ||||
|    GLboolean ciMode = GL_FALSE; | ||||
|    const char *filename = IMAGE_FILE; | ||||
|    int i = 1; | ||||
|  | ||||
|    if (argc > i && strcmp(argv[i], "-ci")==0) { | ||||
|       ciMode = GL_TRUE; | ||||
|       i++; | ||||
|    } | ||||
|    if (argc > i) { | ||||
|       filename = argv[i]; | ||||
|    } | ||||
|  | ||||
|    glutInit( &argc, argv ); | ||||
|    glutInitWindowPosition( 0, 0 ); | ||||
|    glutInitWindowSize( 500, 400 ); | ||||
|  | ||||
|    if (ciMode) | ||||
|       glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE ); | ||||
|    else | ||||
|       glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE); | ||||
|  | ||||
|    glutCreateWindow(argv[0]); | ||||
|  | ||||
|    Init(ciMode, filename); | ||||
|    Usage(); | ||||
|  | ||||
|    glutReshapeFunc( Reshape ); | ||||
|    glutKeyboardFunc( Key ); | ||||
|    glutSpecialFunc( SpecialKey ); | ||||
|    glutDisplayFunc( Display ); | ||||
|  | ||||
|    glutMainLoop(); | ||||
|    return 0; | ||||
| } | ||||
							
								
								
									
										376
									
								
								progs/demos/drawpix_pbo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										376
									
								
								progs/demos/drawpix_pbo.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,376 @@ | ||||
|  | ||||
| /* | ||||
|  * glDrawPixels demo/test/benchmark | ||||
|  *  | ||||
|  * Brian Paul   September 25, 1997  This file is in the public domain. | ||||
|  */ | ||||
| #define GL_GLEXT_PROTOTYPES | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <math.h> | ||||
| #include <string.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| #include "readtex.h" | ||||
|  | ||||
| #define IMAGE_FILE "../images/tree2.rgba" | ||||
|  | ||||
| static int ImgWidth, ImgHeight; | ||||
| static GLenum ImgFormat; | ||||
| static GLenum ImgType = GL_UNSIGNED_BYTE; | ||||
| static GLubyte *Image = NULL; | ||||
|  | ||||
| static int Xpos, Ypos; | ||||
| static int SkipPixels, SkipRows; | ||||
| static int DrawWidth, DrawHeight; | ||||
| static int Scissor = 0; | ||||
| static int Fog = 0; | ||||
| static GLfloat Zpos = -1.0; | ||||
| static float Xzoom, Yzoom; | ||||
| static GLboolean DrawFront = GL_FALSE; | ||||
| static GLboolean Dither = GL_TRUE; | ||||
|  | ||||
|  | ||||
| static GLuint DrawPBO; | ||||
|  | ||||
|  | ||||
| static void Reset( void ) | ||||
| { | ||||
|    Xpos = Ypos = 20; | ||||
|    DrawWidth = ImgWidth; | ||||
|    DrawHeight = ImgHeight; | ||||
|    SkipPixels = SkipRows = 0; | ||||
|    Scissor = 0; | ||||
|    Fog = 0; | ||||
|    Zpos = -1.0; | ||||
|    Xzoom = Yzoom = 1.0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Display( void ) | ||||
| { | ||||
|    glClear( GL_COLOR_BUFFER_BIT ); | ||||
|  | ||||
| #if 0 | ||||
|    glRasterPos2i(Xpos, Ypos); | ||||
| #else | ||||
|    /* This allows negative raster positions: */ | ||||
|    glRasterPos3f(0, 0, Zpos); | ||||
|    glBitmap(0, 0, 0, 0, Xpos, Ypos, NULL); | ||||
| #endif | ||||
|  | ||||
|    glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels); | ||||
|    glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows); | ||||
|  | ||||
|    glPixelZoom( Xzoom, Yzoom ); | ||||
|  | ||||
|    if (Scissor) | ||||
|       glEnable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    if (Fog) | ||||
|       glEnable(GL_FOG); | ||||
|  | ||||
|    /*** Draw from the DrawPBO */ | ||||
|    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO); | ||||
|    glDrawPixels(DrawWidth, DrawHeight, ImgFormat, ImgType, NULL); | ||||
|    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
|  | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|    glDisable(GL_FOG); | ||||
|  | ||||
|    if (DrawFront) | ||||
|       glFinish(); | ||||
|    else | ||||
|       glutSwapBuffers(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Benchmark( void ) | ||||
| { | ||||
|    int startTime, endTime; | ||||
|    int draws = 500; | ||||
|    double seconds, pixelsPerSecond; | ||||
|  | ||||
|    printf("Benchmarking...\n"); | ||||
|    /* GL set-up */ | ||||
|    glPixelStorei(GL_UNPACK_SKIP_PIXELS, SkipPixels); | ||||
|    glPixelStorei(GL_UNPACK_SKIP_ROWS, SkipRows); | ||||
|    glPixelZoom( Xzoom, Yzoom ); | ||||
|    if (Scissor) | ||||
|       glEnable(GL_SCISSOR_TEST); | ||||
|    if (Fog) | ||||
|       glEnable(GL_FOG); | ||||
|  | ||||
|    if (DrawFront) | ||||
|       glDrawBuffer(GL_FRONT); | ||||
|    else | ||||
|       glDrawBuffer(GL_BACK); | ||||
|  | ||||
|    /* Run timing test */ | ||||
|    draws = 0; | ||||
|    startTime = glutGet(GLUT_ELAPSED_TIME); | ||||
|    do { | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO); | ||||
|       glDrawPixels(DrawWidth, DrawHeight, ImgFormat, ImgType, NULL); | ||||
|       glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); | ||||
|       draws++; | ||||
|       endTime = glutGet(GLUT_ELAPSED_TIME); | ||||
|    } while (endTime - startTime < 4000);   /* 4 seconds */ | ||||
|  | ||||
|    /* GL clean-up */ | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|    glDisable(GL_FOG); | ||||
|  | ||||
|    /* Results */ | ||||
|    seconds = (double) (endTime - startTime) / 1000.0; | ||||
|    pixelsPerSecond = draws * DrawWidth * DrawHeight / seconds; | ||||
|    printf("Result:  %d draws in %f seconds = %f pixels/sec\n", | ||||
|           draws, seconds, pixelsPerSecond); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Reshape( int width, int height ) | ||||
| { | ||||
|    glViewport( 0, 0, width, height ); | ||||
|    glMatrixMode( GL_PROJECTION ); | ||||
|    glLoadIdentity(); | ||||
|    glOrtho( 0.0, width, 0.0, height, 0.0, 2.0 ); | ||||
|    glMatrixMode( GL_MODELVIEW ); | ||||
|    glLoadIdentity(); | ||||
|  | ||||
|    glScissor(width/4, height/4, width/2, height/2); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Key( unsigned char key, int x, int y ) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case ' ': | ||||
|          Reset(); | ||||
|          break; | ||||
|       case 'd': | ||||
|          Dither = !Dither; | ||||
|          if (Dither) | ||||
|             glEnable(GL_DITHER); | ||||
|          else | ||||
|             glDisable(GL_DITHER); | ||||
|          break; | ||||
|       case 'w': | ||||
|          if (DrawWidth > 0) | ||||
|             DrawWidth--; | ||||
|          break; | ||||
|       case 'W': | ||||
|          DrawWidth++; | ||||
|          break; | ||||
|       case 'h': | ||||
|          if (DrawHeight > 0) | ||||
|             DrawHeight--; | ||||
|          break; | ||||
|       case 'H': | ||||
|          DrawHeight++; | ||||
|          break; | ||||
|       case 'p': | ||||
|          if (SkipPixels > 0) | ||||
|              SkipPixels--; | ||||
|          break; | ||||
|       case 'P': | ||||
|          SkipPixels++; | ||||
|          break; | ||||
|       case 'r': | ||||
|          if (SkipRows > 0) | ||||
|              SkipRows--; | ||||
|          break; | ||||
|       case 'R': | ||||
|          SkipRows++; | ||||
|          break; | ||||
|       case 's': | ||||
|          Scissor = !Scissor; | ||||
|          break; | ||||
|       case 'x': | ||||
|          Xzoom -= 0.1; | ||||
|          break; | ||||
|       case 'X': | ||||
|          Xzoom += 0.1; | ||||
|          break; | ||||
|       case 'y': | ||||
|          Yzoom -= 0.1; | ||||
|          break; | ||||
|       case 'Y': | ||||
|          Yzoom += 0.1; | ||||
|          break; | ||||
|       case 'z': | ||||
|          Zpos -= 0.1; | ||||
|          printf("RasterPos Z = %g\n", Zpos); | ||||
|          break; | ||||
|       case 'Z': | ||||
|          Zpos += 0.1; | ||||
|          printf("RasterPos Z = %g\n", Zpos); | ||||
|          break; | ||||
|       case 'b': | ||||
|          Benchmark(); | ||||
|          break; | ||||
|       case 'F': | ||||
|          Fog = !Fog; | ||||
|          printf("Fog %d\n", Fog); | ||||
|          break; | ||||
|       case 'f': | ||||
|          DrawFront = !DrawFront; | ||||
|          if (DrawFront) | ||||
|             glDrawBuffer(GL_FRONT); | ||||
|          else | ||||
|             glDrawBuffer(GL_BACK); | ||||
|          printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK"); | ||||
|          break; | ||||
|       case 27: | ||||
|          exit(0); | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void SpecialKey( int key, int x, int y ) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case GLUT_KEY_UP: | ||||
|          Ypos += 1; | ||||
|          break; | ||||
|       case GLUT_KEY_DOWN: | ||||
|          Ypos -= 1; | ||||
|          break; | ||||
|       case GLUT_KEY_LEFT: | ||||
|          Xpos -= 1; | ||||
|          break; | ||||
|       case GLUT_KEY_RIGHT: | ||||
|          Xpos += 1; | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Init( GLboolean ciMode, const char *filename ) | ||||
| { | ||||
|    static const GLfloat fogColor[4] = {0, 1, 0, 0}; | ||||
|  | ||||
|    printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); | ||||
|    printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|  | ||||
|    Image = LoadRGBImage( filename, &ImgWidth, &ImgHeight, &ImgFormat ); | ||||
|    if (!Image) { | ||||
|       printf("Couldn't read %s\n", filename); | ||||
|       exit(0); | ||||
|    } | ||||
|  | ||||
|    if (ciMode) { | ||||
|       /* Convert RGB image to grayscale */ | ||||
|       GLubyte *indexImage = (GLubyte *) malloc( ImgWidth * ImgHeight ); | ||||
|       GLint i; | ||||
|       for (i=0; i<ImgWidth*ImgHeight; i++) { | ||||
|          int gray = Image[i*3] + Image[i*3+1] + Image[i*3+2]; | ||||
|          indexImage[i] = gray / 3; | ||||
|       } | ||||
|       free(Image); | ||||
|       Image = indexImage; | ||||
|       ImgFormat = GL_COLOR_INDEX; | ||||
|  | ||||
|       for (i=0;i<255;i++) { | ||||
|          float g = i / 255.0; | ||||
|          glutSetColor(i, g, g, g); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    printf("Loaded %d by %d image\n", ImgWidth, ImgHeight ); | ||||
|  | ||||
|    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|    glPixelStorei(GL_UNPACK_ROW_LENGTH, ImgWidth); | ||||
|  | ||||
|  | ||||
|    /* put image into DrawPBO */ | ||||
|    glGenBuffersARB(1, &DrawPBO); | ||||
|    glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, DrawPBO); | ||||
|    glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT, | ||||
|                    ImgWidth * ImgHeight * 4, Image, GL_STATIC_DRAW); | ||||
|  | ||||
|  | ||||
|    glFogi(GL_FOG_MODE, GL_LINEAR); | ||||
|    glFogf(GL_FOG_START, 0); | ||||
|    glFogf(GL_FOG_END, 2); | ||||
|    glFogfv(GL_FOG_COLOR, fogColor); | ||||
|  | ||||
|    Reset(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void Usage(void) | ||||
| { | ||||
|    printf("Keys:\n"); | ||||
|    printf("       SPACE  Reset Parameters\n"); | ||||
|    printf("     Up/Down  Move image up/down\n"); | ||||
|    printf("  Left/Right  Move image left/right\n"); | ||||
|    printf("           x  Decrease X-axis PixelZoom\n"); | ||||
|    printf("           X  Increase X-axis PixelZoom\n"); | ||||
|    printf("           y  Decrease Y-axis PixelZoom\n"); | ||||
|    printf("           Y  Increase Y-axis PixelZoom\n"); | ||||
|    printf("           w  Decrease glDrawPixels width*\n"); | ||||
|    printf("           W  Increase glDrawPixels width*\n"); | ||||
|    printf("           h  Decrease glDrawPixels height*\n"); | ||||
|    printf("           H  Increase glDrawPixels height*\n"); | ||||
|    printf("           p  Decrease GL_UNPACK_SKIP_PIXELS*\n"); | ||||
|    printf("           P  Increase GL_UNPACK_SKIP_PIXELS*\n"); | ||||
|    printf("           r  Decrease GL_UNPACK_SKIP_ROWS*\n"); | ||||
|    printf("           R  Increase GL_UNPACK_SKIP_ROWS*\n"); | ||||
|    printf("           s  Toggle GL_SCISSOR_TEST\n"); | ||||
|    printf("           F  Toggle GL_FOG\n"); | ||||
|    printf("           z  Decrease RasterPos Z\n"); | ||||
|    printf("           Z  Increase RasterPos Z\n"); | ||||
|     | ||||
|    printf("           f  Toggle front/back buffer drawing\n"); | ||||
|    printf("           b  Benchmark test\n"); | ||||
|    printf("         ESC  Exit\n"); | ||||
|    printf("* Warning: no limits are imposed on these parameters so it's\n"); | ||||
|    printf("  possible to cause a segfault if you go too far.\n"); | ||||
| } | ||||
|  | ||||
|  | ||||
| int main( int argc, char *argv[] ) | ||||
| { | ||||
|    GLboolean ciMode = GL_FALSE; | ||||
|    const char *filename = IMAGE_FILE; | ||||
|    int i = 1; | ||||
|  | ||||
|    if (argc > i && strcmp(argv[i], "-ci")==0) { | ||||
|       ciMode = GL_TRUE; | ||||
|       i++; | ||||
|    } | ||||
|    if (argc > i) { | ||||
|       filename = argv[i]; | ||||
|    } | ||||
|  | ||||
|    glutInit( &argc, argv ); | ||||
|    glutInitWindowPosition( 0, 0 ); | ||||
|    glutInitWindowSize( 500, 400 ); | ||||
|  | ||||
|    if (ciMode) | ||||
|       glutInitDisplayMode( GLUT_INDEX | GLUT_DOUBLE ); | ||||
|    else | ||||
|       glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE); | ||||
|  | ||||
|    glutCreateWindow(argv[0]); | ||||
|  | ||||
|    Init(ciMode, filename); | ||||
|    Usage(); | ||||
|  | ||||
|    glutReshapeFunc( Reshape ); | ||||
|    glutKeyboardFunc( Key ); | ||||
|    glutSpecialFunc( SpecialKey ); | ||||
|    glutDisplayFunc( Display ); | ||||
|  | ||||
|    glutMainLoop(); | ||||
|    return 0; | ||||
| } | ||||
							
								
								
									
										486
									
								
								progs/demos/gearbox.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								progs/demos/gearbox.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,486 @@ | ||||
| /* | ||||
|  * Use glCopyTexSubImage2D to draw animated gears on the sides of a box. | ||||
|  * | ||||
|  * Brian Paul | ||||
|  * 27 January 2006 | ||||
|  */ | ||||
|  | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| #ifndef M_PI | ||||
| #define M_PI 3.14159265 | ||||
| #endif | ||||
|  | ||||
| static GLint WinWidth = 800, WinHeight = 500; | ||||
| static GLint TexWidth, TexHeight; | ||||
| static GLuint TexObj = 1; | ||||
| static GLenum IntFormat = GL_RGBA; | ||||
|  | ||||
| static GLboolean WireFrame = GL_FALSE; | ||||
|  | ||||
| static GLint T0 = 0; | ||||
| static GLint Frames = 0; | ||||
| static GLint Win = 0; | ||||
|  | ||||
| static GLfloat ViewRotX = 20.0, ViewRotY = 30.0, ViewRotZ = 0.0; | ||||
| static GLint Gear1, Gear2, Gear3; | ||||
| static GLfloat GearRot = 0.0; | ||||
| static GLfloat CubeRot = 0.0; | ||||
|  | ||||
|  | ||||
| /** | ||||
|   Draw a gear wheel.  You'll probably want to call this function when | ||||
|   building a display list since we do a lot of trig here. | ||||
|   | ||||
|   Input:  inner_radius - radius of hole at center | ||||
|           outer_radius - radius at center of teeth | ||||
|           width - width of gear | ||||
|           teeth - number of teeth | ||||
|           tooth_depth - depth of tooth | ||||
|  **/ | ||||
| static void | ||||
| gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, | ||||
|      GLint teeth, GLfloat tooth_depth) | ||||
| { | ||||
|   GLint i; | ||||
|   GLfloat r0, r1, r2; | ||||
|   GLfloat angle, da; | ||||
|   GLfloat u, v, len; | ||||
|  | ||||
|   r0 = inner_radius; | ||||
|   r1 = outer_radius - tooth_depth / 2.0; | ||||
|   r2 = outer_radius + tooth_depth / 2.0; | ||||
|  | ||||
|   da = 2.0 * M_PI / teeth / 4.0; | ||||
|  | ||||
|   glShadeModel(GL_FLAT); | ||||
|  | ||||
|   glNormal3f(0.0, 0.0, 1.0); | ||||
|  | ||||
|   /* draw front face */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i <= teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); | ||||
|     if (i < teeth) { | ||||
|       glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); | ||||
|       glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); | ||||
|     } | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   /* draw front sides of teeth */ | ||||
|   glBegin(GL_QUADS); | ||||
|   da = 2.0 * M_PI / teeth / 4.0; | ||||
|   for (i = 0; i < teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|  | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   glNormal3f(0.0, 0.0, -1.0); | ||||
|  | ||||
|   /* draw back face */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i <= teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); | ||||
|     if (i < teeth) { | ||||
|       glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); | ||||
|       glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); | ||||
|     } | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   /* draw back sides of teeth */ | ||||
|   glBegin(GL_QUADS); | ||||
|   da = 2.0 * M_PI / teeth / 4.0; | ||||
|   for (i = 0; i < teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|  | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
|   /* draw outward faces of teeth */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i < teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|  | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); | ||||
|     u = r2 * cos(angle + da) - r1 * cos(angle); | ||||
|     v = r2 * sin(angle + da) - r1 * sin(angle); | ||||
|     len = sqrt(u * u + v * v); | ||||
|     u /= len; | ||||
|     v /= len; | ||||
|     glNormal3f(v, -u, 0.0); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); | ||||
|     glNormal3f(cos(angle), sin(angle), 0.0); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); | ||||
|     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); | ||||
|     u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); | ||||
|     v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); | ||||
|     glNormal3f(v, -u, 0.0); | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); | ||||
|     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); | ||||
|     glNormal3f(cos(angle), sin(angle), 0.0); | ||||
|   } | ||||
|  | ||||
|   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); | ||||
|   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); | ||||
|  | ||||
|   glEnd(); | ||||
|  | ||||
|   glShadeModel(GL_SMOOTH); | ||||
|  | ||||
|   /* draw inside radius cylinder */ | ||||
|   glBegin(GL_QUAD_STRIP); | ||||
|   for (i = 0; i <= teeth; i++) { | ||||
|     angle = i * 2.0 * M_PI / teeth; | ||||
|     glNormal3f(-cos(angle), -sin(angle), 0.0); | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); | ||||
|     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); | ||||
|   } | ||||
|   glEnd(); | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| cleanup(void) | ||||
| { | ||||
|    glDeleteTextures(1, &TexObj); | ||||
|    glDeleteLists(Gear1, 1); | ||||
|    glDeleteLists(Gear2, 1); | ||||
|    glDeleteLists(Gear3, 1); | ||||
|    glutDestroyWindow(Win); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| DrawGears(void) | ||||
| { | ||||
|    if (WireFrame) { | ||||
|       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
|    } | ||||
|  | ||||
|    glPushMatrix(); | ||||
|       glRotatef(20/*ViewRotX*/, 1.0, 0.0, 0.0); | ||||
|       glRotatef(ViewRotY, 0.0, 1.0, 0.0); | ||||
|       glRotatef(ViewRotZ, 0.0, 0.0, 1.0); | ||||
|  | ||||
|       glPushMatrix(); | ||||
|          glTranslatef(-3.0, -2.0, 0.0); | ||||
|          glRotatef(GearRot, 0.0, 0.0, 1.0); | ||||
|          glCallList(Gear1); | ||||
|       glPopMatrix(); | ||||
|  | ||||
|       glPushMatrix(); | ||||
|          glTranslatef(3.1, -2.0, 0.0); | ||||
|          glRotatef(-2.0 * GearRot - 9.0, 0.0, 0.0, 1.0); | ||||
|          glCallList(Gear2); | ||||
|       glPopMatrix(); | ||||
|  | ||||
|       glPushMatrix(); | ||||
|          glTranslatef(-3.1, 4.2, 0.0); | ||||
|          glRotatef(-2.0 * GearRot - 25.0, 0.0, 0.0, 1.0); | ||||
|          glCallList(Gear3); | ||||
|       glPopMatrix(); | ||||
|  | ||||
|   glPopMatrix(); | ||||
|  | ||||
|   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| DrawCube(void) | ||||
| { | ||||
|    static const GLfloat texcoords[4][2] = { | ||||
|       { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } | ||||
|    }; | ||||
|    static const GLfloat vertices[4][2] = { | ||||
|       { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } | ||||
|    }; | ||||
|    static const GLfloat xforms[6][4] = { | ||||
|       {   0, 0, 1, 0 }, | ||||
|       {  90, 0, 1, 0 }, | ||||
|       { 180, 0, 1, 0 }, | ||||
|       { 270, 0, 1, 0 }, | ||||
|       {  90, 1, 0, 0 }, | ||||
|       { -90, 1, 0, 0 } | ||||
|    }; | ||||
|    static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 }; | ||||
|    GLint i, j; | ||||
|  | ||||
|    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat); | ||||
|    glEnable(GL_TEXTURE_2D); | ||||
|  | ||||
|    glPushMatrix(); | ||||
|       glRotatef(ViewRotX, 1.0, 0.0, 0.0); | ||||
|       glRotatef(15, 1, 0, 0); | ||||
|       glRotatef(CubeRot, 0, 1, 0); | ||||
|       glScalef(4, 4, 4); | ||||
|  | ||||
|       for (i = 0; i < 6; i++) { | ||||
|          glPushMatrix(); | ||||
|             glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]); | ||||
|             glTranslatef(0, 0, 1.1); | ||||
|             glBegin(GL_POLYGON); | ||||
|                glNormal3f(0, 0, 1); | ||||
|                for (j = 0; j < 4; j++) { | ||||
|                   glTexCoord2fv(texcoords[j]); | ||||
|                   glVertex2fv(vertices[j]); | ||||
|                } | ||||
|             glEnd(); | ||||
|          glPopMatrix(); | ||||
|       } | ||||
|    glPopMatrix(); | ||||
|  | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| draw(void) | ||||
| { | ||||
|    float ar; | ||||
|  | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|    glLoadIdentity(); | ||||
|    glTranslatef(0.0, 0.0, -40.0); | ||||
|  | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|    glClear(GL_DEPTH_BUFFER_BIT); | ||||
|    glEnable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    /* draw gears */ | ||||
|    glViewport(0, 0, TexWidth, TexHeight); | ||||
|    glScissor(0, 0, TexWidth, TexHeight); | ||||
|    glClearColor(0.5, 0.5, 0.8, 0.0); | ||||
|    glClearColor(1, 1, 1, 0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT); | ||||
|  | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 60.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|  | ||||
|    DrawGears(); | ||||
|  | ||||
|    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight); | ||||
|     | ||||
|    /* draw textured cube */ | ||||
|    glViewport(TexWidth, 0, WinWidth - TexWidth, WinHeight); | ||||
|    glScissor(TexWidth, 0, WinWidth - TexWidth, WinHeight); | ||||
|    glClearColor(0.5, 0.5, 0.8, 0.0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT); | ||||
|  | ||||
|    ar = (float) (WinWidth - TexWidth) / WinHeight; | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|  | ||||
|    DrawCube(); | ||||
|  | ||||
|    /* finish up */ | ||||
|    glutSwapBuffers(); | ||||
|  | ||||
|    Frames++; | ||||
|    { | ||||
|       GLint t = glutGet(GLUT_ELAPSED_TIME); | ||||
|       if (t - T0 >= 5000) { | ||||
|          GLfloat seconds = (t - T0) / 1000.0; | ||||
|          GLfloat fps = Frames / seconds; | ||||
|          printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); | ||||
|          T0 = t; | ||||
|          Frames = 0; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| idle(void) | ||||
| { | ||||
|   static double t0 = -1.; | ||||
|   double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|   if (t0 < 0.0) | ||||
|     t0 = t; | ||||
|   dt = t - t0; | ||||
|   t0 = t; | ||||
|  | ||||
|   GearRot += 70.0 * dt;  /* 70 degrees per second */ | ||||
|   GearRot = fmod(GearRot, 360.0); /* prevents eventual overflow */ | ||||
|  | ||||
|   CubeRot += 15.0 * dt; | ||||
|  | ||||
|   glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* change view angle, exit upon ESC */ | ||||
| static void | ||||
| key(unsigned char k, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (k) { | ||||
|    case 'w': | ||||
|       WireFrame = !WireFrame; | ||||
|       break; | ||||
|    case 'z': | ||||
|       ViewRotZ += 5.0; | ||||
|       break; | ||||
|    case 'Z': | ||||
|       ViewRotZ -= 5.0; | ||||
|       break; | ||||
|    case 27:  /* Escape */ | ||||
|       cleanup(); | ||||
|       exit(0); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
| /* change view angle */ | ||||
| static void | ||||
| special(int k, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (k) { | ||||
|    case GLUT_KEY_UP: | ||||
|       ViewRotX += 5.0; | ||||
|       break; | ||||
|    case GLUT_KEY_DOWN: | ||||
|       ViewRotX -= 5.0; | ||||
|       break; | ||||
|    case GLUT_KEY_LEFT: | ||||
|       ViewRotY += 5.0; | ||||
|       break; | ||||
|    case GLUT_KEY_RIGHT: | ||||
|       ViewRotY -= 5.0; | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* new window size or exposure */ | ||||
| static void | ||||
| reshape(int width, int height) | ||||
| { | ||||
|   WinWidth = width; | ||||
|   WinHeight = height; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| init(int argc, char *argv[]) | ||||
| { | ||||
|   static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; | ||||
|   static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; | ||||
|   static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; | ||||
|   static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; | ||||
|   GLint i; | ||||
|  | ||||
|   glLightfv(GL_LIGHT0, GL_POSITION, pos); | ||||
| #if 0 | ||||
|   glEnable(GL_CULL_FACE); | ||||
| #endif | ||||
|   glEnable(GL_LIGHTING); | ||||
|   glEnable(GL_LIGHT0); | ||||
|   glEnable(GL_DEPTH_TEST); | ||||
|  | ||||
|   /* make the gears */ | ||||
|   Gear1 = glGenLists(1); | ||||
|   glNewList(Gear1, GL_COMPILE); | ||||
|   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); | ||||
|   gear(1.0, 4.0, 1.0, 20, 0.7); | ||||
|   glEndList(); | ||||
|  | ||||
|   Gear2 = glGenLists(1); | ||||
|   glNewList(Gear2, GL_COMPILE); | ||||
|   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); | ||||
|   gear(0.5, 2.0, 2.0, 10, 0.7); | ||||
|   glEndList(); | ||||
|  | ||||
|   Gear3 = glGenLists(1); | ||||
|   glNewList(Gear3, GL_COMPILE); | ||||
|   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); | ||||
|   gear(1.3, 2.0, 0.5, 10, 0.7); | ||||
|   glEndList(); | ||||
|  | ||||
|   glEnable(GL_NORMALIZE); | ||||
|  | ||||
|   /* xxx make size dynamic */ | ||||
|   TexWidth = 256; | ||||
|   TexHeight = 256; | ||||
|  | ||||
|    glBindTexture(GL_TEXTURE_2D, TexObj); | ||||
|    glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0, | ||||
|                 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||||
|  | ||||
|   for ( i=1; i<argc; i++ ) { | ||||
|     if (strcmp(argv[i], "-info")==0) { | ||||
|       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|       printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION)); | ||||
|       printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR)); | ||||
|       printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void  | ||||
| visible(int vis) | ||||
| { | ||||
|   if (vis == GLUT_VISIBLE) | ||||
|     glutIdleFunc(idle); | ||||
|   else | ||||
|     glutIdleFunc(NULL); | ||||
| } | ||||
|  | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
|    glutInit(&argc, argv); | ||||
|    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); | ||||
|  | ||||
|    glutInitWindowSize(WinWidth, WinHeight); | ||||
|    Win = glutCreateWindow("gearbox"); | ||||
|    init(argc, argv); | ||||
|  | ||||
|    glutDisplayFunc(draw); | ||||
|    glutReshapeFunc(reshape); | ||||
|    glutKeyboardFunc(key); | ||||
|    glutSpecialFunc(special); | ||||
|    glutVisibilityFunc(visible); | ||||
|  | ||||
|    glutMainLoop(); | ||||
|    return 0;             /* ANSI C requires main to return int. */ | ||||
| } | ||||
| @@ -38,8 +38,8 @@ | ||||
| #include <GL/glut.h> | ||||
| 
 | ||||
| 
 | ||||
| static GLsizei MaxSize = 1024; | ||||
| static GLsizei TexWidth = 256, TexHeight = 256, TexBorder = 0; | ||||
| static GLsizei MaxSize = 2048; | ||||
| static GLsizei TexWidth = 1024, TexHeight = 1024, TexBorder = 0; | ||||
| static GLboolean ScaleAndBias = GL_FALSE; | ||||
| static GLboolean SubImage = GL_FALSE; | ||||
| static GLdouble DownloadRate = 0.0;  /* texels/sec */ | ||||
| @@ -47,6 +47,32 @@ static GLdouble DownloadRate = 0.0;  /* texels/sec */ | ||||
| static GLuint Mode = 0; | ||||
| 
 | ||||
| 
 | ||||
| /* Try and avoid L2 cache effects by cycling through a small number of
 | ||||
|  * textures. | ||||
|  *  | ||||
|  * At the initial size of 1024x1024x4 == 4mbyte, say 8 textures will | ||||
|  * keep us out of most caches at 32mb total. | ||||
|  * | ||||
|  * This turns into a fairly interesting question of what exactly you | ||||
|  * expect to be in cache in normal usage, and what you think should be | ||||
|  * outside.  There's no rules for this, no reason to favour one usage | ||||
|  * over another except what the application you care about happens to | ||||
|  * resemble most closely. | ||||
|  * | ||||
|  * - Should the client texture image be in L2 cache?  Has it just been | ||||
|  *   generated or read from disk? | ||||
|  * - Does the application really use >1 texture, or is it constantly  | ||||
|  *   updating one image in-place? | ||||
|  * | ||||
|  * Different answers will favour different texture upload mechanisms. | ||||
|  * To upload an image that is purely outside of cache, a DMA-based | ||||
|  * upload will probably win, whereas for small, in-cache textures, | ||||
|  * copying looks good. | ||||
|  */ | ||||
| #define NR_TEXOBJ 4 | ||||
| static GLuint TexObj[NR_TEXOBJ]; | ||||
| 
 | ||||
| 
 | ||||
| struct FormatRec { | ||||
|    GLenum Format; | ||||
|    GLenum Type; | ||||
| @@ -116,25 +142,57 @@ TypeStr(GLenum type) | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| /* On x86, there is a performance cliff for memcpy to texture memory
 | ||||
|  * for sources below 64 byte alignment.  We do our best with this in | ||||
|  * the driver, but it is better if the images are correctly aligned to | ||||
|  * start with: | ||||
|  */ | ||||
| #define ALIGN (1<<12) | ||||
| 
 | ||||
| static unsigned align(unsigned value, unsigned a) | ||||
| { | ||||
|    return (value + a - 1) & ~(a-1); | ||||
| } | ||||
| 
 | ||||
| static int MIN2(int a, int b) | ||||
| { | ||||
|    return a < b ? a : b; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| MeasureDownloadRate(void) | ||||
| { | ||||
|    const int w = TexWidth + 2 * TexBorder; | ||||
|    const int h = TexHeight + 2 * TexBorder; | ||||
|    const int bytes = w * h * BytesPerTexel(Format); | ||||
|    const int image_bytes = align(w * h * BytesPerTexel(Format), ALIGN); | ||||
|    const int bytes = image_bytes * NR_TEXOBJ; | ||||
|    GLubyte *orig_texImage, *orig_getImage; | ||||
|    GLubyte *texImage, *getImage; | ||||
|    GLdouble t0, t1, time; | ||||
|    int count; | ||||
|    int i; | ||||
|    int offset = 0; | ||||
|    GLdouble total = 0;		/* ints will tend to overflow */ | ||||
| 
 | ||||
|    texImage = (GLubyte *) malloc(bytes); | ||||
|    getImage = (GLubyte *) malloc(bytes); | ||||
|    if (!texImage || !getImage) { | ||||
|    printf("allocating %d bytes for %d %dx%d images\n", | ||||
| 	  bytes, NR_TEXOBJ, w, h); | ||||
| 
 | ||||
|    orig_texImage = (GLubyte *) malloc(bytes + ALIGN); | ||||
|    orig_getImage = (GLubyte *) malloc(image_bytes + ALIGN); | ||||
|    if (!orig_texImage || !orig_getImage) { | ||||
|       DownloadRate = 0.0; | ||||
|       return; | ||||
|    } | ||||
| 
 | ||||
|    printf("alloc %p %p\n", orig_texImage, orig_getImage); | ||||
| 
 | ||||
|    texImage = (GLubyte *)align((unsigned)orig_texImage, ALIGN); | ||||
|    getImage = (GLubyte *)align((unsigned)orig_getImage, ALIGN);    | ||||
| 
 | ||||
|    for (i = 1; !(((unsigned)texImage) & i); i<<=1) | ||||
|       ; | ||||
|    printf("texture image alignment: %d bytes (%p)\n", i, texImage); | ||||
|        | ||||
|    for (i = 0; i < bytes; i++) { | ||||
|       texImage[i] = i & 0xff; | ||||
|    } | ||||
| @@ -166,51 +224,80 @@ MeasureDownloadRate(void) | ||||
|    count = 0; | ||||
|    t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001; | ||||
|    do { | ||||
|       int img = count%NR_TEXOBJ; | ||||
|       GLubyte *img_ptr = texImage + img * image_bytes; | ||||
| 
 | ||||
|       glBindTexture(GL_TEXTURE_2D, TexObj[img]); | ||||
| 
 | ||||
|       if (SubImage && count > 0) { | ||||
|          glTexSubImage2D(GL_TEXTURE_2D, 0, -TexBorder, -TexBorder, w, h, | ||||
| 	 /* Only update a portion of the image each iteration.  This
 | ||||
| 	  * is presumably why you'd want to use texsubimage, otherwise | ||||
| 	  * you may as well just call teximage again. | ||||
| 	  * | ||||
| 	  * A bigger question is whether to use a pointer that moves | ||||
| 	  * with each call, ie does the incoming data come from L2 | ||||
| 	  * cache under normal circumstances, or is it pulled from | ||||
| 	  * uncached memory?   | ||||
| 	  *  | ||||
| 	  * There's a good argument to say L2 cache, ie you'd expect | ||||
| 	  * the data to have been recently generated.  It's possible | ||||
| 	  * that it could have come from a file read, which may or may | ||||
| 	  * not have gone through the cpu. | ||||
| 	  */ | ||||
|          glTexSubImage2D(GL_TEXTURE_2D, 0,  | ||||
| 			 -TexBorder,  | ||||
| 			 -TexBorder + offset * h/8,  | ||||
| 			 w,  | ||||
| 			 h/8, | ||||
|                          FormatTable[Format].Format, | ||||
|                          FormatTable[Format].Type, texImage); | ||||
|                          FormatTable[Format].Type,  | ||||
| #if 1 | ||||
| 			 texImage /* likely in L2$ */ | ||||
| #else | ||||
| 			 img_ptr + offset * bytes/8 /* unlikely in L2$ */ | ||||
| #endif | ||||
| 	    ); | ||||
| 	 offset += 1; | ||||
| 	 offset %= 8; | ||||
| 	 total += w * h / 8; | ||||
|       } | ||||
|       else { | ||||
|          glTexImage2D(GL_TEXTURE_2D, 0, | ||||
|                       FormatTable[Format].IntFormat, w, h, TexBorder, | ||||
|                       FormatTable[Format].Format, | ||||
|                       FormatTable[Format].Type, texImage); | ||||
|                       FormatTable[Format].Type,  | ||||
| 		      img_ptr); | ||||
| 	 total += w*h; | ||||
|       } | ||||
| 
 | ||||
| #if 1 | ||||
|       /* Render a texture, but not necessarily the one just uploaded.  
 | ||||
|        */ | ||||
| /*       glBindTexture(GL_TEXTURE_2D, TexObj[(img + NR_TEXOBJ/2)%NR_TEXOBJ]); */ | ||||
| 
 | ||||
|       /* draw a tiny polygon to force texture into texram */ | ||||
|       glBegin(GL_TRIANGLES); | ||||
|       glTexCoord2f(0, 0);     glVertex2f(1, 1); | ||||
|       glTexCoord2f(1, 0);     glVertex2f(3, 1); | ||||
|       glTexCoord2f(0.5, 1);   glVertex2f(2, 3); | ||||
|       glEnd(); | ||||
| /*       glFinish(); */ | ||||
| #endif | ||||
| 
 | ||||
|       t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001; | ||||
|       time = t1 - t0; | ||||
|       count++; | ||||
| /*       printf("total %f count %d\n", total, count); */ | ||||
|    } while (time < 3.0); | ||||
| 
 | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
| 
 | ||||
|    printf("w*h=%d  count=%d  time=%f\n", w*h, count, time); | ||||
|    DownloadRate = w * h * count / time; | ||||
|    printf("total texels=%f  time=%f\n", total, time); | ||||
|    DownloadRate = total / time; | ||||
| 
 | ||||
| #if 0 | ||||
|    if (!ScaleAndBias) { | ||||
|       /* verify texture readback */ | ||||
|       glGetTexImage(GL_TEXTURE_2D, 0, | ||||
|                     FormatTable[Format].Format, | ||||
|                     FormatTable[Format].Type, getImage); | ||||
|       for (i = 0; i < w * h; i++) { | ||||
|          if (texImage[i] != getImage[i]) { | ||||
|             printf("[%d] %d != %d\n", i, texImage[i], getImage[i]); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| #endif | ||||
| 
 | ||||
|    free(texImage); | ||||
|    free(getImage); | ||||
|    free(orig_texImage);  | ||||
|    free(orig_getImage);  | ||||
| 
 | ||||
|    { | ||||
|       GLint err = glGetError(); | ||||
| @@ -29,6 +29,7 @@ SOURCES = antialias.c \ | ||||
| 	dinoshade.c \ | ||||
| 	floattex.c \ | ||||
| 	fbotest1.c \ | ||||
| 	fbotest2.c \ | ||||
| 	fbotexture.c \ | ||||
| 	fog.c \ | ||||
| 	fogcoord.c \ | ||||
| @@ -47,6 +48,7 @@ SOURCES = antialias.c \ | ||||
| 	sharedtex.c \ | ||||
| 	stencilwrap.c \ | ||||
| 	stencil_wrap.c \ | ||||
| 	subtexrate.c \ | ||||
| 	tex1d.c \ | ||||
| 	texfilt.c \ | ||||
| 	texline.c \ | ||||
|   | ||||
							
								
								
									
										204
									
								
								progs/tests/fbotest2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								progs/tests/fbotest2.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | ||||
| /* | ||||
|  * Test GL_EXT_framebuffer_object | ||||
|  * | ||||
|  * Brian Paul | ||||
|  * 19 Mar 2006 | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #define GL_GLEXT_PROTOTYPES | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <math.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| static int Width = 400, Height = 400; | ||||
| static GLuint MyFB, ColorRb, DepthRb; | ||||
| static GLboolean Animate = GL_FALSE; | ||||
| static GLfloat Rotation = 0.0; | ||||
|  | ||||
|  | ||||
| static void | ||||
| CheckError(int line) | ||||
| { | ||||
|    GLenum err = glGetError(); | ||||
|    if (err) { | ||||
|       printf("fbotest1: GL Error 0x%x at line %d\n", (int) err, line); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Display( void ) | ||||
| { | ||||
|    GLubyte *buffer = malloc(Width * Height * 4); | ||||
|    GLenum status; | ||||
|  | ||||
|    printf("Drawing\n"); | ||||
|  | ||||
|    CheckError(__LINE__); | ||||
|  | ||||
|    /* draw to user framebuffer */ | ||||
|    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); | ||||
|    glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); | ||||
|    glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); | ||||
|  | ||||
|    status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | ||||
|    if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { | ||||
|       printf("fbotest1: Error: Framebuffer is incomplete!!!\n"); | ||||
|    } | ||||
|  | ||||
|    CheckError(__LINE__); | ||||
|  | ||||
|    glClearColor(0.5, 0.5, 1.0, 0.0); | ||||
|    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); | ||||
|  | ||||
|    glEnable(GL_DEPTH_TEST); | ||||
|    glEnable(GL_LIGHTING); | ||||
|    glEnable(GL_LIGHT0); | ||||
|  | ||||
|    glPushMatrix(); | ||||
|    glRotatef(30.0, 1, 0, 0); | ||||
|    glRotatef(Rotation, 0, 1, 0); | ||||
|    glutSolidTeapot(2.0); | ||||
|    glPopMatrix(); | ||||
|  | ||||
|    glDisable(GL_DEPTH_TEST); | ||||
|    glDisable(GL_LIGHTING); | ||||
|  | ||||
|    /* read from user framebuffer */ | ||||
|    glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); | ||||
|  | ||||
|    /* draw to window */ | ||||
|    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||||
|    glWindowPos2iARB(0, 0); | ||||
|    glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); | ||||
|  | ||||
|    free(buffer); | ||||
|    glutSwapBuffers(); | ||||
|    CheckError(__LINE__); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Reshape( int width, int height ) | ||||
| { | ||||
|    float ar = (float) width / (float) height; | ||||
|  | ||||
|    glViewport( 0, 0, width, height ); | ||||
|    glMatrixMode( GL_PROJECTION ); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum( -ar, ar, -1.0, 1.0, 5.0, 25.0 ); | ||||
|  | ||||
|    glMatrixMode( GL_MODELVIEW ); | ||||
|    glLoadIdentity(); | ||||
|    glTranslatef( 0.0, 0.0, -15.0 ); | ||||
|  | ||||
|    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb); | ||||
|    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height); | ||||
|    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRb); | ||||
|    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, | ||||
|                             width, height); | ||||
|  | ||||
|    Width = width; | ||||
|    Height = height; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| CleanUp(void) | ||||
| { | ||||
|    glDeleteFramebuffersEXT(1, &MyFB); | ||||
|    glDeleteRenderbuffersEXT(1, &ColorRb); | ||||
|    glDeleteRenderbuffersEXT(1, &DepthRb); | ||||
|    assert(!glIsFramebufferEXT(MyFB)); | ||||
|    assert(!glIsRenderbufferEXT(ColorRb)); | ||||
|    assert(!glIsRenderbufferEXT(DepthRb)); | ||||
|    exit(0); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Idle(void) | ||||
| { | ||||
|    Rotation = glutGet(GLUT_ELAPSED_TIME) * 0.1; | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Key( unsigned char key, int x, int y ) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|    case 'a': | ||||
|       Animate = !Animate; | ||||
|       if (Animate) | ||||
|          glutIdleFunc(Idle); | ||||
|       else | ||||
|          glutIdleFunc(NULL); | ||||
|       break; | ||||
|    case 27: | ||||
|       CleanUp(); | ||||
|       break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Init( void ) | ||||
| { | ||||
|    if (!glutExtensionSupported("GL_EXT_framebuffer_object")) { | ||||
|       printf("fbotest1: GL_EXT_framebuffer_object not found!\n"); | ||||
|       exit(0); | ||||
|    } | ||||
|    printf("fbotest1: GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|  | ||||
|    glGenFramebuffersEXT(1, &MyFB); | ||||
|    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); | ||||
|    assert(glIsFramebufferEXT(MyFB)); | ||||
|  | ||||
|    /* set color buffer */ | ||||
|    glGenRenderbuffersEXT(1, &ColorRb); | ||||
|    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ColorRb); | ||||
|    assert(glIsRenderbufferEXT(ColorRb)); | ||||
|    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, | ||||
|                                 GL_RENDERBUFFER_EXT, ColorRb); | ||||
|    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height); | ||||
|  | ||||
|    /* setup depth buffer */ | ||||
|    glGenRenderbuffersEXT(1, &DepthRb); | ||||
|    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRb); | ||||
|    assert(glIsRenderbufferEXT(DepthRb)); | ||||
|    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, | ||||
|                                 GL_RENDERBUFFER_EXT, DepthRb); | ||||
|    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, Width, Height); | ||||
|  | ||||
|    CheckError(__LINE__); | ||||
|  | ||||
|    /* restore to default */ | ||||
|    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||||
|    CheckError(__LINE__); | ||||
| } | ||||
|  | ||||
|  | ||||
| int | ||||
| main( int argc, char *argv[] ) | ||||
| { | ||||
|    glutInit( &argc, argv ); | ||||
|    glutInitWindowPosition( 0, 0 ); | ||||
|    glutInitWindowSize(Width, Height); | ||||
|    glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); | ||||
|    glutCreateWindow(argv[0]); | ||||
|    glutReshapeFunc( Reshape ); | ||||
|    glutKeyboardFunc( Key ); | ||||
|    glutDisplayFunc( Display ); | ||||
|    if (Animate) | ||||
|       glutIdleFunc(Idle); | ||||
|    Init(); | ||||
|    glutMainLoop(); | ||||
|    return 0; | ||||
| } | ||||
| @@ -17,6 +17,10 @@ | ||||
| #include <string.h> | ||||
| #include <math.h> | ||||
|  | ||||
| /* For debug */ | ||||
| #define DEPTH 1 | ||||
| #define STENCIL 1 | ||||
|  | ||||
|  | ||||
| static int Width = 400, Height = 400; | ||||
| static int TexWidth = 512, TexHeight = 512; | ||||
| @@ -76,10 +80,14 @@ RenderTexture(void) | ||||
|    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||||
|    CheckError(__LINE__); | ||||
|  | ||||
| #if DEPTH | ||||
|    glEnable(GL_DEPTH_TEST); | ||||
|  | ||||
| #if STENCIL | ||||
|    glEnable(GL_STENCIL_TEST); | ||||
|    glStencilFunc(GL_NEVER, 1, ~0); | ||||
|    glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE); | ||||
| #endif | ||||
|  | ||||
|    CheckError(__LINE__); | ||||
|  | ||||
| @@ -93,10 +101,13 @@ RenderTexture(void) | ||||
|    glEnd(); | ||||
|  | ||||
|    /* draw teapot where stencil != 1 */ | ||||
| #if STENCIL | ||||
|    glStencilFunc(GL_NOTEQUAL, 1, ~0); | ||||
|    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | ||||
| #endif | ||||
|  | ||||
|    CheckError(__LINE__); | ||||
| #endif | ||||
|  | ||||
| #if 0 | ||||
|    glBegin(GL_POLYGON); | ||||
| @@ -184,9 +195,13 @@ Reshape(int width, int height) | ||||
| static void | ||||
| CleanUp(void) | ||||
| { | ||||
| #if DEPTH | ||||
|    glDeleteRenderbuffersEXT(1, &DepthRB); | ||||
| #endif | ||||
| #if STENCIL | ||||
|    if (!UsePackedDepthStencil) | ||||
|       glDeleteRenderbuffersEXT(1, &StencilRB); | ||||
| #endif | ||||
|    glDeleteFramebuffersEXT(1, &MyFB); | ||||
|  | ||||
|    glDeleteTextures(1, &TexObj); | ||||
| @@ -253,6 +268,7 @@ Init(int argc, char *argv[]) | ||||
|    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i); | ||||
|    assert(i == MyFB); | ||||
|  | ||||
| #if DEPTH | ||||
|    /* make depth renderbuffer */ | ||||
|    glGenRenderbuffersEXT(1, &DepthRB); | ||||
|    assert(DepthRB); | ||||
| @@ -275,9 +291,11 @@ Init(int argc, char *argv[]) | ||||
|    /* attach DepthRB to MyFB */ | ||||
|    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, | ||||
|                                 GL_RENDERBUFFER_EXT, DepthRB); | ||||
| #endif | ||||
|  | ||||
|    CheckError(__LINE__); | ||||
|  | ||||
| #if STENCIL | ||||
|    if (UsePackedDepthStencil) { | ||||
|       /* DepthRb is a combined depth/stencil renderbuffer */ | ||||
|       glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | ||||
| @@ -303,7 +321,7 @@ Init(int argc, char *argv[]) | ||||
|    CheckError(__LINE__); | ||||
|    printf("Stencil renderbuffer size = %d bits\n", i); | ||||
|    assert(i > 0); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|    /* bind regular framebuffer */ | ||||
|    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
|  | ||||
| #include "../util/readtex.c"  /* a hack, I know */ | ||||
|  | ||||
| #define IMAGE_FILE "../images/girl.rgb" | ||||
| #define IMAGE_FILE "../images/tree2.rgba" | ||||
|  | ||||
| static int ImgWidth, ImgHeight; | ||||
| static GLenum ImgFormat; | ||||
| @@ -32,8 +32,8 @@ static GLboolean Benchmark = GL_FALSE; | ||||
| static GLuint DrawPBO, TempPBO; | ||||
|  | ||||
|  | ||||
| static GLenum ReadFormat = GL_RGBA; | ||||
| static GLenum ReadType = GL_UNSIGNED_BYTE; | ||||
| static GLenum ReadFormat = GL_BGRA; | ||||
| static GLenum ReadType = GL_UNSIGNED_INT_8_8_8_8_REV; | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										378
									
								
								progs/tests/subtexrate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								progs/tests/subtexrate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,378 @@ | ||||
| /* | ||||
|  * Measure glTexSubImage and glCopyTexSubImage speed | ||||
|  * | ||||
|  * Brian Paul | ||||
|  * 26 Jan 2006 | ||||
|  */ | ||||
|  | ||||
| #define GL_GLEXT_PROTOTYPES | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <math.h> | ||||
| #include <GL/glut.h> | ||||
|  | ||||
| static GLint WinWidth = 1024, WinHeight = 512; | ||||
| static GLint TexWidth = 512, TexHeight = 512; | ||||
|  | ||||
| static GLuint TexObj = 1; | ||||
|  | ||||
| static GLenum IntFormat = GL_RGBA; | ||||
| static GLenum ReadFormat = GL_BGRA; /* for glReadPixels */ | ||||
|  | ||||
| static GLboolean DrawQuad = GL_TRUE; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * draw teapot image, size TexWidth by TexHeight | ||||
|  */ | ||||
| static void | ||||
| DrawTestImage(void) | ||||
| { | ||||
|    GLfloat ar; | ||||
|  | ||||
|    glViewport(0, 0, TexWidth, TexHeight); | ||||
|    glScissor(0, 0, TexWidth, TexHeight); | ||||
|    glEnable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    glClearColor(0.5, 0.5, 0.5, 0.0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
|  | ||||
|    ar = (float) TexWidth / TexHeight; | ||||
|  | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|  | ||||
|    glEnable(GL_LIGHTING); | ||||
|    glEnable(GL_LIGHT0); | ||||
|    glEnable(GL_DEPTH_TEST); | ||||
|    glFrontFace(GL_CW); | ||||
|    glPushMatrix(); | ||||
|    glRotatef(45, 1, 0, 0); | ||||
|    glRotatef(45, 0, 1, 0); | ||||
|    glutSolidTeapot(2.3); | ||||
|    glPopMatrix(); | ||||
|    glFrontFace(GL_CCW); | ||||
|    glDisable(GL_DEPTH_TEST); | ||||
|    glDisable(GL_LIGHTING); | ||||
|  | ||||
|    glDisable(GL_SCISSOR_TEST); | ||||
|  | ||||
|    glViewport(0, 0, WinWidth, WinHeight); | ||||
|    glFinish(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Do glCopyTexSubImage2D call (update texture with framebuffer data) | ||||
|  * If doSubRect is true, do the copy in four pieces instead of all at once. | ||||
|  */ | ||||
| static void | ||||
| DoCopyTex(GLboolean doSubRect) | ||||
| { | ||||
|    if (doSubRect) { | ||||
|       /* copy in four parts */ | ||||
|       int w = TexWidth / 2, h = TexHeight / 2; | ||||
|       int x0 = 0, y0 = 0; | ||||
|       int x1 = w, y1 = h; | ||||
| #if 0 | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x0, y0, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x1, y0, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x0, y1, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x1, y1, w, h); | ||||
| #else | ||||
|       /* scramble */ | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, x1, y1, w, h);  | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, x0, y1, w, h);  | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, x1, y0, w, h); | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, x0, y0, w, h); | ||||
| #endif | ||||
|    } | ||||
|    else { | ||||
|       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TexWidth, TexHeight); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Do glTexSubImage2D (update texture w/ user data) | ||||
|  * If doSubRect, do update in four pieces, else all at once. | ||||
|  */ | ||||
| static void | ||||
| SubTex(GLboolean doSubRect, const GLubyte *image) | ||||
| { | ||||
|    if (doSubRect) { | ||||
|       /* four pieces */ | ||||
|       int w = TexWidth / 2, h = TexHeight / 2; | ||||
|       int x0 = 0, y0 = 0; | ||||
|       int x1 = w, y1 = h; | ||||
|       glPixelStorei(GL_UNPACK_ROW_LENGTH, TexWidth); | ||||
|       glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | ||||
|       glPixelStorei( GL_PACK_INVERT_MESA, GL_TRUE ); | ||||
|  | ||||
|        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);  | ||||
|        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y0); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y0, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x0); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y1, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|  | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_ROWS, y1); */ | ||||
| /*       glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1); */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, x1, y1, w, h, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|       glPixelStorei( GL_PACK_INVERT_MESA, GL_FALSE ); | ||||
|        | ||||
|    } | ||||
|    else { | ||||
|       /* all at once */ | ||||
|       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexWidth, TexHeight, | ||||
|                       ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Measure gl[Copy]TexSubImage rate. | ||||
|  * This actually also includes time to render a quad and SwapBuffers. | ||||
|  */ | ||||
| static void | ||||
| RunTest(GLboolean copyTex, GLboolean doSubRect) | ||||
| { | ||||
|    double t0, t1; | ||||
|    int iters = 0; | ||||
|    float copyRate, mbRate; | ||||
|    float rot = 0.0; | ||||
|    int bpp, r, g, b, a; | ||||
|    int w, h; | ||||
|    GLubyte *image = NULL; | ||||
|  | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &r); | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &g); | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &b); | ||||
|    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &a); | ||||
|    bpp = (r + g + b + a) / 8; | ||||
|  | ||||
|    if (!copyTex) { | ||||
|       /* read image from frame buffer */ | ||||
|       image = (GLubyte *) malloc(TexWidth * TexHeight * bpp); | ||||
|       glPixelStorei(GL_PACK_ALIGNMENT, 1); | ||||
|       glReadPixels(0, 0, TexWidth, TexHeight, | ||||
|                    ReadFormat, GL_UNSIGNED_BYTE, image); | ||||
|    } | ||||
|  | ||||
|    glEnable(GL_TEXTURE_2D); | ||||
|    glViewport(WinWidth / 2, 0, WinWidth / 2, WinHeight); | ||||
|  | ||||
|    t0 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|  | ||||
|    if (!DrawQuad) | ||||
|       glDrawBuffer(GL_FRONT); | ||||
|  | ||||
|    do { | ||||
|       if (copyTex) | ||||
|          /* Framebuffer -> Texture */ | ||||
|          DoCopyTex(doSubRect); | ||||
|       else { | ||||
|          /* Main Mem -> Texture */ | ||||
|          SubTex(doSubRect, image); | ||||
|       } | ||||
|  | ||||
|       /* draw textured quad */ | ||||
|       if (DrawQuad) { | ||||
|          glPushMatrix(); | ||||
|             glRotatef(rot, 0, 0, 1); | ||||
|             glTranslatef(1, 0, 0); | ||||
|             glBegin(GL_POLYGON); | ||||
|                glTexCoord2f(0, 0);  glVertex2f(-1, -1); | ||||
|                glTexCoord2f(1, 0);  glVertex2f( 1, -1); | ||||
|                glTexCoord2f(1, 1);  glVertex2f( 1,  1); | ||||
|                glTexCoord2f(0, 1);  glVertex2f(-1,  1); | ||||
|             glEnd(); | ||||
|          glPopMatrix(); | ||||
| 	 glutSwapBuffers(); | ||||
|       } | ||||
|       else { | ||||
| 	 /* Draw something tiny to ensure that the texture is really | ||||
| 	  * uploaded: | ||||
| 	  */ | ||||
|          glPushMatrix(); | ||||
|             glRotatef(rot, 0, 0, 1); | ||||
|             glTranslatef(1, 0, 0); | ||||
|             glBegin(GL_POLYGON); | ||||
|                glTexCoord2f(0, 0);  glVertex2f(-.01, -.01); | ||||
|                glTexCoord2f(.01, 0);  glVertex2f( .01, -.01); | ||||
|                glTexCoord2f(.01, .01);  glVertex2f( .01,  .01); | ||||
|                glTexCoord2f(0, .01);  glVertex2f(-.01,  .01); | ||||
|             glEnd(); | ||||
|          glPopMatrix(); | ||||
| 	 glFlush(); | ||||
|       } | ||||
|  | ||||
|       iters++; | ||||
|       rot += 2.0; | ||||
|  | ||||
|       t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|    } while (t1 - t0 < 2.0); | ||||
|  | ||||
|    /*  Make sure everything is done before taking the final timing: | ||||
|     */ | ||||
|    glFinish(); | ||||
|    t1 = glutGet(GLUT_ELAPSED_TIME) / 1000.0; | ||||
|     | ||||
|  | ||||
|    glDisable(GL_TEXTURE_2D); | ||||
|    if (image) | ||||
|       free(image); | ||||
|  | ||||
|    if (doSubRect) { | ||||
|       w = TexWidth / 2; | ||||
|       h = TexHeight / 2; | ||||
|       iters *= 4; | ||||
|    } | ||||
|    else { | ||||
|       w = TexWidth; | ||||
|       h = TexHeight; | ||||
|    } | ||||
|  | ||||
|    copyRate = iters / (t1 - t0); | ||||
|    mbRate = w * h * bpp * copyRate / (1024 * 1024); | ||||
|  | ||||
|    if (copyTex) | ||||
|       printf("glCopyTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp); | ||||
|    else | ||||
|       printf("glTexSubImage: %d x %d, %d Bpp:\n", w, h, bpp); | ||||
|    printf("   %d calls in %.2f = %.2f calls/sec, %.2f MB/s\n", | ||||
|           iters, t1-t0, copyRate, mbRate); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Draw(void) | ||||
| { | ||||
|    glClearColor(0.2, 0.2, 0.8, 0); | ||||
|    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||||
|  | ||||
|    DrawTestImage(); | ||||
|    if (!DrawQuad) { | ||||
|       glutSwapBuffers(); | ||||
|    } | ||||
|  | ||||
|    RunTest(GL_FALSE, GL_FALSE);  | ||||
|    RunTest(GL_FALSE, GL_TRUE);  | ||||
|    RunTest(GL_TRUE, GL_FALSE);  | ||||
|    RunTest(GL_TRUE, GL_TRUE); | ||||
|  | ||||
|    glutSwapBuffers();  | ||||
|  | ||||
| /*    printf("exiting\n"); */ | ||||
| /*    exit(0); */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Reshape(int width, int height) | ||||
| { | ||||
|    glViewport(0, 0, width, height); | ||||
|    glMatrixMode(GL_PROJECTION); | ||||
|    glLoadIdentity(); | ||||
|    glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); | ||||
|    glMatrixMode(GL_MODELVIEW); | ||||
|    glLoadIdentity(); | ||||
|    glTranslatef(0.0, 0.0, -15.0); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Key(unsigned char key, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case 27: | ||||
|          exit(0); | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| SpecialKey(int key, int x, int y) | ||||
| { | ||||
|    (void) x; | ||||
|    (void) y; | ||||
|    switch (key) { | ||||
|       case GLUT_KEY_UP: | ||||
|          break; | ||||
|       case GLUT_KEY_DOWN: | ||||
|          break; | ||||
|       case GLUT_KEY_LEFT: | ||||
|          break; | ||||
|       case GLUT_KEY_RIGHT: | ||||
|          break; | ||||
|    } | ||||
|    glutPostRedisplay(); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Init(void) | ||||
| { | ||||
|    /* create initial, empty teximage */ | ||||
|    glBindTexture(GL_TEXTURE_2D, TexObj); | ||||
|    glTexImage2D(GL_TEXTURE_2D, 0, IntFormat, TexWidth, TexHeight, 0, | ||||
|                 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
|    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| ParseArgs(int argc, char *argv[]) | ||||
| { | ||||
|    int i; | ||||
|    for (i = 1; i < argc; i++) { | ||||
|       if (strcmp(argv[i], "-nodraw") == 0) | ||||
|          DrawQuad = GL_FALSE; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
|    GLint mode = GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH; | ||||
|    glutInit(&argc, argv); | ||||
|  | ||||
|    ParseArgs(argc, argv); | ||||
|  | ||||
|    glutInitWindowPosition(0, 0); | ||||
|    glutInitWindowSize(WinWidth, WinHeight); | ||||
|    glutInitDisplayMode(mode); | ||||
|    glutCreateWindow(argv[0]); | ||||
|    glutReshapeFunc(Reshape); | ||||
|    glutKeyboardFunc(Key); | ||||
|    glutSpecialFunc(SpecialKey); | ||||
|    glutDisplayFunc(Draw); | ||||
|  | ||||
|    printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); | ||||
|    Init(); | ||||
|  | ||||
|    glutMainLoop(); | ||||
|    return 0; | ||||
| } | ||||
| @@ -687,4 +687,15 @@ extern int __glXGetInternalVersion(void); | ||||
| /* Get the unadjusted system time */ | ||||
| extern int __glXGetUST( int64_t * ust ); | ||||
|  | ||||
| /* KW: Temporary hacks to coalesce multiple opens of the same drm | ||||
|  * instance.  These should be renamed or moved to libdrm, or the | ||||
|  * behaviour of drmOpen/drmClose should change. | ||||
|  */ | ||||
| int drmOpenOnce(void *unused,  | ||||
| 		const char *BusID, | ||||
| 		int *newlyopened); | ||||
|  | ||||
| void drmCloseOnce(int fd); | ||||
|  | ||||
|  | ||||
| #endif /* !__GLX_client_h__ */ | ||||
|   | ||||
| @@ -702,6 +702,68 @@ static const __DRIinterfaceMethods interface_methods = { | ||||
|     glXGetMscRateOML, | ||||
| }; | ||||
|  | ||||
| #define DRM_MAX_FDS 16 | ||||
| static struct { | ||||
|    char *BusID; | ||||
|    int fd; | ||||
|    int refcount; | ||||
| } connection[DRM_MAX_FDS]; | ||||
|  | ||||
| static int nr_fds = 0; | ||||
|  | ||||
| int drmOpenOnce(void *unused,  | ||||
| 		const char *BusID, | ||||
| 		int *newlyopened) | ||||
| { | ||||
|    int i; | ||||
|    int fd; | ||||
|     | ||||
|    for (i = 0; i < nr_fds; i++) | ||||
|       if (strcmp(BusID, connection[i].BusID) == 0) { | ||||
| 	 connection[i].refcount++; | ||||
| 	 *newlyopened = 0; | ||||
| 	 return connection[i].fd; | ||||
|       } | ||||
|  | ||||
|    fd = drmOpen(unused, BusID); | ||||
|    if (fd <= 0 || nr_fds == DRM_MAX_FDS) | ||||
|       return fd; | ||||
|     | ||||
|    connection[nr_fds].BusID = strdup(BusID); | ||||
|    connection[nr_fds].fd = fd; | ||||
|    connection[nr_fds].refcount = 1; | ||||
|    *newlyopened = 1; | ||||
|  | ||||
|    fprintf(stderr, "saved connection %d for %s %d\n",  | ||||
| 	  nr_fds, connection[nr_fds].BusID,  | ||||
| 	  strcmp(BusID, connection[nr_fds].BusID)); | ||||
|  | ||||
|    nr_fds++; | ||||
|  | ||||
|    return fd;    | ||||
| } | ||||
|  | ||||
| void drmCloseOnce(int fd) | ||||
| { | ||||
|    int i; | ||||
|  | ||||
|     | ||||
|  | ||||
|    for (i = 0; i < nr_fds; i++) { | ||||
|       if (fd == connection[i].fd) { | ||||
| 	 if (--connection[i].refcount == 0) { | ||||
| 	    drmClose(connection[i].fd); | ||||
| 	    free(connection[i].BusID); | ||||
| 	     | ||||
| 	    if (i < --nr_fds)  | ||||
| 	       connection[i] = connection[nr_fds]; | ||||
|  | ||||
| 	    return; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Perform the required libGL-side initialization and call the client-side | ||||
| @@ -753,7 +815,8 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, | ||||
|     framebuffer.dev_priv = NULL; | ||||
|  | ||||
|     if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { | ||||
| 	fd = drmOpen(NULL,BusID); | ||||
|         int newlyopened; | ||||
| 	fd = drmOpenOnce(NULL,BusID, &newlyopened); | ||||
| 	Xfree(BusID); /* No longer needed */ | ||||
|  | ||||
| 	err_msg = "open DRM"; | ||||
| @@ -780,7 +843,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, | ||||
| 		} | ||||
|  | ||||
| 		err_msg = "XF86DRIAuthConnection"; | ||||
| 		if (XF86DRIAuthConnection(dpy, scrn, magic)) { | ||||
| 		if (!newlyopened || XF86DRIAuthConnection(dpy, scrn, magic)) { | ||||
| 		    char *driverName; | ||||
|  | ||||
| 		    /* | ||||
| @@ -884,7 +947,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc, | ||||
| 	} | ||||
|  | ||||
| 	if ( fd >= 0 ) { | ||||
| 	    (void)drmClose(fd); | ||||
| 	    (void)drmCloseOnce(fd); | ||||
| 	} | ||||
|  | ||||
| 	(void)XF86DRICloseConnection(dpy, scrn); | ||||
|   | ||||
| @@ -206,10 +206,15 @@ _mesa_init_driver_functions(struct dd_function_table *driver) | ||||
| #if FEATURE_EXT_framebuffer_object | ||||
|    driver->NewFramebuffer = _mesa_new_framebuffer; | ||||
|    driver->NewRenderbuffer = _mesa_new_soft_renderbuffer; | ||||
|    driver->RenderbufferTexture = _mesa_renderbuffer_texture; | ||||
|    driver->RenderTexture = _mesa_render_texture; | ||||
|    driver->FinishRenderTexture = _mesa_finish_render_texture; | ||||
|    driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; | ||||
| #endif | ||||
|  | ||||
| #if FEATURE_EXT_framebuffer_blit | ||||
|    driver->BlitFramebuffer = _swrast_BlitFramebuffer; | ||||
| #endif | ||||
|  | ||||
|    /* query objects */ | ||||
|    driver->NewQueryObject = _mesa_new_query_object; | ||||
|    driver->BeginQuery = NULL; | ||||
|   | ||||
| @@ -89,7 +89,7 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME) | ||||
| depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) | ||||
| 	touch depend | ||||
| 	$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \ | ||||
| 		> /dev/null  | ||||
| 		>& /dev/null  | ||||
|  | ||||
|  | ||||
| # Emacs tags | ||||
|   | ||||
| @@ -829,7 +829,7 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv | ||||
| 	(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX); | ||||
| 	(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize); | ||||
| 	_mesa_free(psp->pDevPriv); | ||||
| 	(void)drmClose(psp->fd); | ||||
| 	(void)drmCloseOnce(psp->fd); | ||||
| 	if ( psp->modes != NULL ) { | ||||
| 	    (*dri_interface->destroyContextModes)( psp->modes ); | ||||
| 	} | ||||
|   | ||||
| @@ -56,6 +56,8 @@ driNewRenderbuffer(GLenum format, GLvoid *addr, | ||||
|    driRenderbuffer *drb; | ||||
|  | ||||
|    assert(format == GL_RGBA || | ||||
|           format == GL_RGB5 || | ||||
|           format == GL_RGBA8 || | ||||
|           format == GL_DEPTH_COMPONENT16 || | ||||
|           format == GL_DEPTH_COMPONENT24 || | ||||
|           format == GL_DEPTH_COMPONENT32 || | ||||
| @@ -75,7 +77,7 @@ driNewRenderbuffer(GLenum format, GLvoid *addr, | ||||
|  | ||||
|       drb->Base.InternalFormat = format; | ||||
|  | ||||
|       if (format == GL_RGBA) { | ||||
|       if (format == GL_RGBA || format == GL_RGB5 || format == GL_RGBA8) { | ||||
|          /* Color */ | ||||
|          drb->Base._BaseFormat = GL_RGBA; | ||||
|          drb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
| @@ -94,7 +96,7 @@ driNewRenderbuffer(GLenum format, GLvoid *addr, | ||||
|       } | ||||
|       else { | ||||
|          /* Stencil */ | ||||
|          ASSERT(format == GL_STENCIL_INDEX8); | ||||
|          ASSERT(format == GL_STENCIL_INDEX8_EXT); | ||||
|          drb->Base._BaseFormat = GL_STENCIL_INDEX; | ||||
|          drb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
|       } | ||||
|   | ||||
| @@ -5,16 +5,6 @@ include $(TOP)/configs/current | ||||
| LIBNAME = i915_dri.so | ||||
|  | ||||
| DRIVER_SOURCES = \ | ||||
| 	i915_context.c \ | ||||
| 	i915_debug.c \ | ||||
| 	i915_fragprog.c \ | ||||
| 	i915_metaops.c \ | ||||
| 	i915_program.c \ | ||||
| 	i915_state.c \ | ||||
| 	i915_tex.c \ | ||||
| 	i915_texprog.c \ | ||||
| 	i915_texstate.c \ | ||||
| 	i915_vtbl.c \ | ||||
| 	i830_context.c \ | ||||
| 	i830_metaops.c \ | ||||
| 	i830_state.c \ | ||||
| @@ -22,16 +12,45 @@ DRIVER_SOURCES = \ | ||||
| 	i830_tex.c \ | ||||
| 	i830_texstate.c \ | ||||
| 	i830_vtbl.c \ | ||||
| 	intel_render.c \ | ||||
| 	intel_regions.c \ | ||||
| 	intel_buffer_objects.c \ | ||||
| 	intel_batchbuffer.c \ | ||||
| 	intel_mipmap_tree.c \ | ||||
| 	i915_tex_layout.c \ | ||||
| 	intel_tex_image.c \ | ||||
| 	intel_tex_subimage.c \ | ||||
| 	intel_tex_copy.c \ | ||||
| 	intel_tex_validate.c \ | ||||
| 	intel_tex_format.c \ | ||||
| 	intel_tex.c \ | ||||
| 	intel_pixel.c \ | ||||
| 	intel_pixel_copy.c \ | ||||
| 	intel_pixel_read.c \ | ||||
| 	intel_pixel_draw.c \ | ||||
| 	intel_buffers.c \ | ||||
| 	intel_blit.c \ | ||||
| 	i915_tex.c \ | ||||
| 	i915_texstate.c \ | ||||
| 	i915_context.c \ | ||||
| 	i915_debug.c \ | ||||
| 	i915_fragprog.c \ | ||||
| 	i915_metaops.c \ | ||||
| 	i915_program.c \ | ||||
| 	i915_state.c \ | ||||
| 	i915_texprog.c \ | ||||
| 	i915_vtbl.c \ | ||||
| 	intel_context.c \ | ||||
| 	intel_ioctl.c \ | ||||
| 	intel_pixel.c \ | ||||
| 	intel_render.c \ | ||||
| 	intel_screen.c \ | ||||
| 	intel_span.c \ | ||||
| 	intel_state.c \ | ||||
| 	intel_tex.c \ | ||||
| 	intel_tris.c  | ||||
| 	intel_tris.c \ | ||||
| 	intel_fbo.c \ | ||||
| 	intel_depthstencil.c \ | ||||
| 	intel_bufmgr.c | ||||
|  | ||||
|  | ||||
|  | ||||
| C_SOURCES = \ | ||||
| 	$(COMMON_SOURCES) \ | ||||
|   | ||||
| @@ -58,8 +58,8 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis, | ||||
| 			    void *sharedContextPrivate) | ||||
| { | ||||
|    struct dd_function_table functions; | ||||
|    i830ContextPtr i830 = (i830ContextPtr) CALLOC_STRUCT(i830_context); | ||||
|    intelContextPtr intel = &i830->intel; | ||||
|    struct i830_context *i830 = CALLOC_STRUCT(i830_context); | ||||
|    struct intel_context *intel = &i830->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    if (!i830) return GL_FALSE; | ||||
|  | ||||
| @@ -76,33 +76,14 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis, | ||||
|    intel->ctx.Const.MaxTextureImageUnits = I830_TEX_UNITS; | ||||
|    intel->ctx.Const.MaxTextureCoordUnits = I830_TEX_UNITS; | ||||
|  | ||||
|    intel->nr_heaps = 1; | ||||
|    intel->texture_heaps[0] =  | ||||
|       driCreateTextureHeap( 0, intel, | ||||
| 			    intel->intelScreen->tex.size, | ||||
| 			    12, | ||||
| 			    I830_NR_TEX_REGIONS, | ||||
| 			    intel->sarea->texList, | ||||
| 			    & intel->sarea->texAge, | ||||
| 			    & intel->swapped, | ||||
| 			    sizeof( struct i830_texture_object ), | ||||
| 			    (destroy_texture_object_t *)intelDestroyTexObj ); | ||||
|  | ||||
|    /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are tightly | ||||
|     * FIXME: packed, but they're not in Intel graphics hardware. | ||||
|    /* Advertise the full hardware capabilities.  The new memory | ||||
|     * manager should cope much better with overload situations: | ||||
|     */ | ||||
|    intel->ctx.Const.MaxTextureUnits = 1; | ||||
|    driCalculateMaxTextureLevels( intel->texture_heaps, | ||||
| 				 intel->nr_heaps, | ||||
| 				 &intel->ctx.Const, | ||||
| 				 4, | ||||
| 				 11, /* max 2D texture size is 2048x2048 */ | ||||
| 				 8,  /* max 3D texture size is 256^3 */ | ||||
| 				 10, /* max CUBE texture size is 1024x1024 */ | ||||
| 				 11, /* max RECT. supported */ | ||||
| 				 12, | ||||
| 				 GL_FALSE ); | ||||
|    intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS; | ||||
|    ctx->Const.MaxTextureLevels = 12; | ||||
|    ctx->Const.Max3DTextureLevels = 9; | ||||
|    ctx->Const.MaxCubeTextureLevels = 11; | ||||
|    ctx->Const.MaxTextureRectSize = (1<<11); | ||||
|    ctx->Const.MaxTextureUnits = I830_TEX_UNITS; | ||||
|  | ||||
|    _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,  | ||||
| 		       18 * sizeof(GLfloat) ); | ||||
| @@ -112,7 +93,7 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis, | ||||
|    driInitExtensions( ctx, i830_extensions, GL_FALSE ); | ||||
|  | ||||
|    i830InitState( i830 ); | ||||
|  | ||||
|    i830InitMetaFuncs( i830 ); | ||||
|  | ||||
|    _tnl_allow_vertex_fog( ctx, 1 );  | ||||
|    _tnl_allow_pixel_fog( ctx, 0 );  | ||||
|   | ||||
| @@ -39,6 +39,7 @@ | ||||
| #define I830_UPLOAD_CTX              0x1 | ||||
| #define I830_UPLOAD_BUFFERS          0x2 | ||||
| #define I830_UPLOAD_STIPPLE          0x4 | ||||
| #define I830_UPLOAD_INVARIENT        0x8 | ||||
| #define I830_UPLOAD_TEX(i)           (0x10<<(i)) | ||||
| #define I830_UPLOAD_TEXBLEND(i)      (0x100<<(i)) | ||||
| #define I830_UPLOAD_TEX_ALL          (0x0f0) | ||||
| @@ -48,17 +49,15 @@ | ||||
|  */ | ||||
| #define I830_DESTREG_CBUFADDR0 0 | ||||
| #define I830_DESTREG_CBUFADDR1 1 | ||||
| #define I830_DESTREG_CBUFADDR2 2 | ||||
| #define I830_DESTREG_DBUFADDR0 3 | ||||
| #define I830_DESTREG_DBUFADDR1 4 | ||||
| #define I830_DESTREG_DBUFADDR2 5 | ||||
| #define I830_DESTREG_DV0 6 | ||||
| #define I830_DESTREG_DV1 7 | ||||
| #define I830_DESTREG_SENABLE 8 | ||||
| #define I830_DESTREG_SR0 9 | ||||
| #define I830_DESTREG_SR1 10 | ||||
| #define I830_DESTREG_SR2 11 | ||||
| #define I830_DEST_SETUP_SIZE 12 | ||||
| #define I830_DESTREG_DBUFADDR0 2 | ||||
| #define I830_DESTREG_DBUFADDR1 3 | ||||
| #define I830_DESTREG_DV0 4 | ||||
| #define I830_DESTREG_DV1 5 | ||||
| #define I830_DESTREG_SENABLE 6 | ||||
| #define I830_DESTREG_SR0 7 | ||||
| #define I830_DESTREG_SR1 8 | ||||
| #define I830_DESTREG_SR2 9 | ||||
| #define I830_DEST_SETUP_SIZE 10 | ||||
|  | ||||
| #define I830_CTXREG_STATE1		0 | ||||
| #define I830_CTXREG_STATE2		1 | ||||
| @@ -84,14 +83,13 @@ | ||||
| #define I830_STP_SETUP_SIZE    2 | ||||
|  | ||||
| #define I830_TEXREG_TM0LI      0 /* load immediate 2 texture map n */ | ||||
| #define I830_TEXREG_TM0S0      1 | ||||
| #define I830_TEXREG_TM0S1      2 | ||||
| #define I830_TEXREG_TM0S2      3 | ||||
| #define I830_TEXREG_TM0S3      4 | ||||
| #define I830_TEXREG_TM0S4      5 | ||||
| #define I830_TEXREG_MCS	       6	/* _3DSTATE_MAP_COORD_SETS */ | ||||
| #define I830_TEXREG_CUBE       7	/* _3DSTATE_MAP_SUBE */ | ||||
| #define I830_TEX_SETUP_SIZE    8 | ||||
| #define I830_TEXREG_TM0S1      1 | ||||
| #define I830_TEXREG_TM0S2      2 | ||||
| #define I830_TEXREG_TM0S3      3 | ||||
| #define I830_TEXREG_TM0S4      4 | ||||
| #define I830_TEXREG_MCS	       5	/* _3DSTATE_MAP_COORD_SETS */ | ||||
| #define I830_TEXREG_CUBE       6	/* _3DSTATE_MAP_SUBE */ | ||||
| #define I830_TEX_SETUP_SIZE    7 | ||||
|  | ||||
| #define I830_TEXBLEND_SIZE	12	/* (4 args + op) * 2 + COLOR_FACTOR */ | ||||
|  | ||||
| @@ -110,6 +108,17 @@ struct i830_hw_state { | ||||
|    GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE]; | ||||
|    GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE]; | ||||
|    GLuint TexBlendWordsUsed[I830_TEX_UNITS]; | ||||
|  | ||||
|    struct intel_region *draw_region; | ||||
|    struct intel_region *depth_region; | ||||
|  | ||||
|    /* Regions aren't actually that appropriate here as the memory may | ||||
|     * be from a PBO or FBO.  Just use the buffer id.  Will have to do | ||||
|     * this for draw and depth for FBO's... | ||||
|     */ | ||||
|    GLuint tex_buffer[I830_TEX_UNITS]; | ||||
|    GLuint tex_offset[I830_TEX_UNITS]; | ||||
|     | ||||
|    GLuint emitted;		/* I810_UPLOAD_* */ | ||||
|    GLuint active; | ||||
| }; | ||||
| @@ -118,15 +127,12 @@ struct i830_context | ||||
| { | ||||
|    struct intel_context intel; | ||||
|     | ||||
|    GLuint lodbias_tm0s3[MAX_TEXTURE_UNITS]; | ||||
|    GLuint last_index; | ||||
|  | ||||
|    struct i830_hw_state meta, initial, state, *current; | ||||
| }; | ||||
|  | ||||
| typedef struct i830_context *i830ContextPtr; | ||||
| typedef struct i830_texture_object *i830TextureObjectPtr; | ||||
|  | ||||
| #define I830_CONTEXT(ctx)	((i830ContextPtr)(ctx)) | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -148,7 +154,7 @@ do {						\ | ||||
| /* i830_vtbl.c | ||||
|  */ | ||||
| extern void  | ||||
| i830InitVtbl( i830ContextPtr i830 ); | ||||
| i830InitVtbl( struct i830_context *i830 ); | ||||
|  | ||||
| /* i830_context.c | ||||
|  */ | ||||
| @@ -160,22 +166,19 @@ i830CreateContext( const __GLcontextModes *mesaVis, | ||||
| /* i830_tex.c, i830_texstate.c | ||||
|  */ | ||||
| extern void  | ||||
| i830UpdateTextureState( intelContextPtr intel ); | ||||
| i830UpdateTextureState( struct intel_context *intel ); | ||||
|  | ||||
| extern void  | ||||
| i830InitTextureFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| extern intelTextureObjectPtr | ||||
| i830AllocTexObj( struct gl_texture_object *tObj ); | ||||
|  | ||||
| /* i830_texblend.c | ||||
|  */ | ||||
| extern GLuint i830SetTexEnvCombine(i830ContextPtr i830, | ||||
| extern GLuint i830SetTexEnvCombine(struct i830_context *i830, | ||||
|     const struct gl_tex_env_combine_state * combine, GLint blendUnit, | ||||
|      GLuint texel_op, GLuint *state, const GLfloat *factor ); | ||||
|  | ||||
| extern void  | ||||
| i830EmitTextureBlend( i830ContextPtr i830 ); | ||||
| i830EmitTextureBlend( struct i830_context *i830 ); | ||||
|  | ||||
|  | ||||
| /* i830_state.c | ||||
| @@ -184,32 +187,25 @@ extern void | ||||
| i830InitStateFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| extern void  | ||||
| i830EmitState( i830ContextPtr i830 ); | ||||
| i830EmitState( struct i830_context *i830 ); | ||||
|  | ||||
| extern void  | ||||
| i830InitState( i830ContextPtr i830 ); | ||||
| i830InitState( struct i830_context *i830 ); | ||||
|  | ||||
| /* i830_metaops.c | ||||
|  */ | ||||
| extern GLboolean | ||||
| i830TryTextureReadPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *pack, | ||||
| 			  GLvoid *pixels ); | ||||
|  | ||||
| extern GLboolean | ||||
| i830TryTextureDrawPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  const GLvoid *pixels ); | ||||
|  | ||||
| extern void  | ||||
| i830ClearWithTris( intelContextPtr intel, GLbitfield mask, | ||||
| 		   GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); | ||||
| i830InitMetaFuncs( struct i830_context *i830 ); | ||||
|  | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.  These are better-typed than the | ||||
|  * macros used previously: | ||||
|  */ | ||||
| static INLINE struct i830_context * | ||||
| i830_context( GLcontext *ctx ) | ||||
| { | ||||
|    return (struct i830_context *)ctx; | ||||
| } | ||||
|  | ||||
| 	 | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -34,16 +34,18 @@ | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i830_context.h" | ||||
| #include "i830_reg.h" | ||||
|  | ||||
| /* A large amount of state doesn't need to be uploaded. | ||||
|  */ | ||||
| #define ACTIVE (I830_UPLOAD_TEXBLEND(0) |	\ | ||||
| 		I830_UPLOAD_STIPPLE |		\ | ||||
| #define ACTIVE (I830_UPLOAD_INVARIENT |         \ | ||||
| 		I830_UPLOAD_CTX |		\ | ||||
| 		I830_UPLOAD_BUFFERS |		\ | ||||
| 		I830_UPLOAD_STIPPLE |		\ | ||||
| 		I830_UPLOAD_TEXBLEND(0) |	\ | ||||
| 		I830_UPLOAD_TEX(0))		 | ||||
|  | ||||
|  | ||||
| @@ -54,20 +56,11 @@ do {						\ | ||||
|    i830->current->emitted &= ~ACTIVE;			\ | ||||
| } while (0) | ||||
|  | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void set_initial_state( i830ContextPtr i830 ) | ||||
| { | ||||
|    memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) ); | ||||
|    i830->meta.active = ACTIVE; | ||||
|    i830->meta.emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_no_depth_stencil_write( i830ContextPtr i830 ) | ||||
| static void set_no_stencil_write( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; | ||||
| @@ -75,6 +68,12 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 ) | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE; | ||||
|  | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
| static void set_no_depth_write( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE ) | ||||
|     */ | ||||
| @@ -86,25 +85,43 @@ static void set_no_depth_stencil_write( i830ContextPtr i830 ) | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
| /* Set depth unit to replace. | ||||
|  */ | ||||
| static void set_depth_replace( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE ) | ||||
|     * ctx->Driver.DepthMask( ctx, GL_TRUE ) | ||||
|     */ | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE; | ||||
|  | ||||
|    /* ctx->Driver.DepthFunc( ctx, GL_ALWAYS ) | ||||
|     */ | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK; | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC | | ||||
| 					  DEPTH_TEST_FUNC(COMPAREFUNC_ALWAYS)); | ||||
|  | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Set stencil unit to replace always with the reference value. | ||||
|  */ | ||||
| static void set_stencil_replace( i830ContextPtr i830, | ||||
| static void set_stencil_replace( struct intel_context *intel, | ||||
| 				 GLuint s_mask, | ||||
| 				 GLuint s_clear) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_TRUE ) | ||||
|     */ | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE; | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE; | ||||
|  | ||||
|    /* ctx->Driver.StencilMask( ctx, s_mask ) | ||||
|     */ | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; | ||||
| @@ -140,8 +157,10 @@ static void set_stencil_replace( i830ContextPtr i830, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_color_mask( i830ContextPtr i830, GLboolean state ) | ||||
| static void set_color_mask( struct intel_context *intel, GLboolean state ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    const GLuint mask = ((1 << WRITEMASK_RED_SHIFT) | | ||||
| 			(1 << WRITEMASK_GREEN_SHIFT) | | ||||
| 			(1 << WRITEMASK_BLUE_SHIFT) | | ||||
| @@ -161,8 +180,9 @@ static void set_color_mask( i830ContextPtr i830, GLboolean state ) | ||||
| /* Installs a one-stage passthrough texture blend pipeline.  Is there | ||||
|  * more that can be done to turn off texturing? | ||||
|  */ | ||||
| static void set_no_texture( i830ContextPtr i830 ) | ||||
| static void set_no_texture( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    static const struct gl_tex_env_combine_state comb = { | ||||
|       GL_NONE, GL_NONE, | ||||
|       { GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, }, | ||||
| @@ -181,13 +201,13 @@ static void set_no_texture( i830ContextPtr i830 ) | ||||
| /* Set up a single element blend stage for 'replace' texturing with no | ||||
|  * funny ops. | ||||
|  */ | ||||
| static void enable_texture_blend_replace( i830ContextPtr i830, | ||||
| 					  GLenum format ) | ||||
| static void set_texture_blend_replace( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    static const struct gl_tex_env_combine_state comb = { | ||||
|       GL_REPLACE, GL_REPLACE, | ||||
|       { GL_TEXTURE, 0, 0, }, { GL_TEXTURE, 0, 0, }, | ||||
|       { GL_SRC_COLOR, 0, 0 }, { GL_SRC_ALPHA, 0, 0 }, | ||||
|       { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, }, { GL_TEXTURE, GL_TEXTURE, GL_TEXTURE, }, | ||||
|       { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR }, { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA }, | ||||
|       0, 0, 1, 1 | ||||
|    }; | ||||
|  | ||||
| @@ -207,31 +227,90 @@ static void enable_texture_blend_replace( i830ContextPtr i830, | ||||
| /* Set up an arbitary piece of memory as a rectangular texture | ||||
|  * (including the front or back buffer). | ||||
|  */ | ||||
| static void set_tex_rect_source( i830ContextPtr i830, | ||||
| 				 GLuint offset, | ||||
| 				 GLuint width,  | ||||
| 				 GLuint height, | ||||
| 				 GLuint pitch, | ||||
| 				 GLuint textureFormat ) | ||||
| static GLboolean set_tex_rect_source( struct intel_context *intel, | ||||
| 				      GLuint buffer, | ||||
| 				      GLuint offset, | ||||
| 				      GLuint pitch, | ||||
| 				      GLuint height, | ||||
| 				      GLenum format, | ||||
| 				      GLenum type) | ||||
| { | ||||
|    GLint numLevels = 1; | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    GLuint *setup = i830->meta.Tex[0]; | ||||
|    GLint numLevels = 1; | ||||
|    GLuint textureFormat; | ||||
|    GLuint cpp; | ||||
|  | ||||
|    pitch *= i830->intel.intelScreen->cpp; | ||||
|    /* A full implementation of this would do the upload through | ||||
|     * glTexImage2d, and get all the conversion operations at that | ||||
|     * point.  We are restricted, but still at least have access to the | ||||
|     * fragment program swizzle. | ||||
|     */ | ||||
|    switch (format) { | ||||
|    case GL_BGRA: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       case GL_UNSIGNED_BYTE: | ||||
| 	 textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888); | ||||
| 	 cpp = 4; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_RGBA: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       case GL_UNSIGNED_BYTE: | ||||
| 	 textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888); | ||||
| 	 cpp = 4; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_BGR: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_SHORT_5_6_5_REV: | ||||
| 	 textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); | ||||
| 	 cpp = 2; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_RGB: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_SHORT_5_6_5: | ||||
| 	 textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); | ||||
| 	 cpp = 2; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
| /*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */ | ||||
| /* 	   __FUNCTION__, offset, width, height, pitch, textureFormat ); */ | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    i830->meta.tex_buffer[0] = buffer; | ||||
|    i830->meta.tex_offset[0] = offset; | ||||
|  | ||||
|    setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |  | ||||
| 			       (LOAD_TEXTURE_MAP0 << 0) | 4); | ||||
|    setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset); | ||||
|    setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) | | ||||
| 			       ((width - 1) << TM0S1_WIDTH_SHIFT) | | ||||
| 			       ((pitch - 1) << TM0S1_WIDTH_SHIFT) | | ||||
| 			       textureFormat); | ||||
|    setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));    | ||||
|    setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK; | ||||
|    setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK; | ||||
|    setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT; | ||||
|    setup[I830_TEXREG_TM0S2] = (((((pitch * cpp) / 4) - 1) << TM0S2_PITCH_SHIFT)  | | ||||
| 			       TM0S2_CUBE_FACE_ENA_MASK);    | ||||
|  | ||||
|    setup[I830_TEXREG_TM0S3] = ( (((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT) | | ||||
| 				(FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT) | | ||||
| 				(MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT) | | ||||
| 				(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT)); | ||||
|  | ||||
|    setup[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(0)); | ||||
|  | ||||
|    setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | | ||||
| 			     MAP_UNIT(0) | | ||||
| @@ -244,40 +323,17 @@ static void set_tex_rect_source( i830ContextPtr i830, | ||||
| 			     TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP)); | ||||
|  | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_TEX(0); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Select between front and back draw buffers. | ||||
|  */ | ||||
| static void set_draw_offset( i830ContextPtr i830, | ||||
| 			     GLuint offset ) | ||||
| { | ||||
|    i830->meta.Buffer[I830_DESTREG_CBUFADDR2] = offset; | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_BUFFERS; | ||||
| } | ||||
|  | ||||
| /* Setup an arbitary draw format, useful for targeting | ||||
|  * texture or agp memory. | ||||
|  */ | ||||
| static void set_draw_format( i830ContextPtr i830, | ||||
| 			     GLuint format, | ||||
| 			     GLuint depth_format) | ||||
| { | ||||
|    i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
| 					  DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
| 					  format | | ||||
| 					  DEPTH_IS_Z | | ||||
| 					  depth_format); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_vertex_format( i830ContextPtr i830 ) | ||||
| static void set_vertex_format( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    i830->meta.Ctx[I830_CTXREG_VF] =  (_3DSTATE_VFT0_CMD | | ||||
| 				      VFT0_TEX_COUNT(1) | | ||||
| 				      VFT0_DIFFUSE | | ||||
| 				      VFT0_SPEC | | ||||
| 				      VFT0_XYZW); | ||||
| 				      VFT0_XYZ); | ||||
|    i830->meta.Ctx[I830_CTXREG_VF2] = (_3DSTATE_VFT1_CMD | | ||||
| 				      VFT1_TEX0_FMT(TEXCOORDFMT_2D) | | ||||
| 				      VFT1_TEX1_FMT(TEXCOORDFMT_2D) |  | ||||
| @@ -287,446 +343,127 @@ static void set_vertex_format( i830ContextPtr i830 ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void draw_quad(i830ContextPtr i830,  | ||||
| 		      GLfloat x0, GLfloat x1, | ||||
| 		      GLfloat y0, GLfloat y1,  | ||||
| 		      GLubyte red, GLubyte green, | ||||
| 		      GLubyte blue, GLubyte alpha, | ||||
| 		      GLfloat s0, GLfloat s1, | ||||
| 		      GLfloat t0, GLfloat t1 ) | ||||
| static void meta_import_pixel_state( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint vertex_size = 8; | ||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i830->intel,  | ||||
| 						PRIM3D_TRIFAN,  | ||||
| 						4*vertex_size, | ||||
| 						vertex_size ); | ||||
|    intelVertex tmp; | ||||
|    int i; | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE1] = i830->state.Ctx[I830_CTXREG_STATE1]; | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE2] = i830->state.Ctx[I830_CTXREG_STATE2]; | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE3] = i830->state.Ctx[I830_CTXREG_STATE3]; | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE4] = i830->state.Ctx[I830_CTXREG_STATE4]; | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE5] = i830->state.Ctx[I830_CTXREG_STATE5]; | ||||
|    i830->meta.Ctx[I830_CTXREG_IALPHAB] = i830->state.Ctx[I830_CTXREG_IALPHAB]; | ||||
|    i830->meta.Ctx[I830_CTXREG_STENCILTST] = i830->state.Ctx[I830_CTXREG_STENCILTST]; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_1] = i830->state.Ctx[I830_CTXREG_ENABLES_1]; | ||||
|    i830->meta.Ctx[I830_CTXREG_ENABLES_2] = i830->state.Ctx[I830_CTXREG_ENABLES_2]; | ||||
|    i830->meta.Ctx[I830_CTXREG_AA] = i830->state.Ctx[I830_CTXREG_AA]; | ||||
|    i830->meta.Ctx[I830_CTXREG_FOGCOLOR] = i830->state.Ctx[I830_CTXREG_FOGCOLOR]; | ||||
|    i830->meta.Ctx[I830_CTXREG_BLENDCOLOR0] = i830->state.Ctx[I830_CTXREG_BLENDCOLOR0]; | ||||
|    i830->meta.Ctx[I830_CTXREG_BLENDCOLOR1] = i830->state.Ctx[I830_CTXREG_BLENDCOLOR1]; | ||||
|    i830->meta.Ctx[I830_CTXREG_MCSB0] = i830->state.Ctx[I830_CTXREG_MCSB0]; | ||||
|    i830->meta.Ctx[I830_CTXREG_MCSB1] = i830->state.Ctx[I830_CTXREG_MCSB1]; | ||||
|     | ||||
| /*    fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", */ | ||||
| /* 	   __FUNCTION__, */ | ||||
| /* 	   x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); */ | ||||
|  | ||||
|    i830->meta.Ctx[I830_CTXREG_STATE3] &= ~CULLMODE_MASK; | ||||
|    i830->meta.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE; | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_CTX; | ||||
|  | ||||
|  | ||||
|    /* initial vertex, left bottom */ | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.y = y0; | ||||
|    tmp.v.z = 1.0; | ||||
|    tmp.v.w = 1.0; | ||||
|    tmp.v.color.red = red; | ||||
|    tmp.v.color.green = green; | ||||
|    tmp.v.color.blue = blue; | ||||
|    tmp.v.color.alpha = alpha; | ||||
|    tmp.v.specular.red = 0; | ||||
|    tmp.v.specular.green = 0; | ||||
|    tmp.v.specular.blue = 0; | ||||
|    tmp.v.specular.alpha = 0; | ||||
|    tmp.v.u0 = s0; | ||||
|    tmp.v.v0 = t0; | ||||
|    for (i = 0 ; i < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right bottom */ | ||||
|    vb += 8; | ||||
|    tmp.v.x = x1; | ||||
|    tmp.v.u0 = s1; | ||||
|    for (i = 0 ; i < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right top */ | ||||
|    vb += 8; | ||||
|    tmp.v.y = y1; | ||||
|    tmp.v.v0 = t1; | ||||
|    for (i = 0 ; i < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* left top */ | ||||
|    vb += 8; | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.u0 = s0; | ||||
|    for (i = 0 ; i < 8 ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
| /*    fprintf(stderr, "%s: DV1: %x\n",  */ | ||||
| /* 	   __FUNCTION__, i830->meta.Buffer[I830_DESTREG_DV1]); */ | ||||
| } | ||||
|  | ||||
| void  | ||||
| i830ClearWithTris(intelContextPtr intel, GLbitfield mask, | ||||
| 		  GLboolean all, | ||||
| 		  GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( intel ); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    int x0, y0, x1, y1; | ||||
|  | ||||
|  | ||||
|    SET_STATE( i830, meta ); | ||||
|    set_initial_state( i830 ); | ||||
|    set_no_texture( i830 ); | ||||
|    set_vertex_format( i830 );  | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if(!all) { | ||||
|       x0 = cx; | ||||
|       y0 = cy; | ||||
|       x1 = x0 + cw; | ||||
|       y1 = y0 + ch; | ||||
|    } else { | ||||
|       x0 = 0; | ||||
|       y0 = 0; | ||||
|       x1 = x0 + dPriv->w; | ||||
|       y1 = y0 + dPriv->h; | ||||
|    } | ||||
|  | ||||
|    /* Don't do any clipping to screen - these are window coordinates. | ||||
|     * The active cliprects will be applied as for any other geometry. | ||||
|     */ | ||||
|  | ||||
|    if(mask & BUFFER_BIT_FRONT_LEFT) { | ||||
|       set_no_depth_stencil_write( i830 ); | ||||
|       set_color_mask( i830, GL_TRUE ); | ||||
|       set_draw_offset( i830, screen->front.offset ); | ||||
|       draw_quad(i830, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green, | ||||
| 		intel->clear_blue, intel->clear_alpha, | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if(mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       set_no_depth_stencil_write( i830 ); | ||||
|       set_color_mask( i830, GL_TRUE ); | ||||
|       set_draw_offset( i830, screen->back.offset ); | ||||
|  | ||||
|       draw_quad(i830, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green, | ||||
| 		intel->clear_blue, intel->clear_alpha, | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if(mask & BUFFER_BIT_STENCIL) { | ||||
|       set_stencil_replace( i830,  | ||||
| 			   intel->ctx.Stencil.WriteMask[0],  | ||||
| 			   intel->ctx.Stencil.Clear); | ||||
|  | ||||
|       set_color_mask( i830, GL_FALSE ); | ||||
|       set_draw_offset( i830, screen->front.offset ); | ||||
|       draw_quad( i830, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 ); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    SET_STATE( i830, state ); | ||||
|    i830->meta.Buffer[I830_DESTREG_SENABLE] = i830->state.Buffer[I830_DESTREG_SENABLE]; | ||||
|    i830->meta.Buffer[I830_DESTREG_SR1] = i830->state.Buffer[I830_DESTREG_SR1]; | ||||
|    i830->meta.Buffer[I830_DESTREG_SR2] = i830->state.Buffer[I830_DESTREG_SR2]; | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_BUFFERS; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| GLboolean | ||||
| i830TryTextureReadPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *pack, | ||||
| 			  GLvoid *pixels ) | ||||
| /* Select between front and back draw buffers. | ||||
|  */ | ||||
| static void meta_draw_region( struct intel_context *intel, | ||||
| 			      struct intel_region *draw_region, | ||||
| 			      struct intel_region *depth_region ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = i830->intel.intelScreen; | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|    __DRIdrawablePrivate *dPriv = i830->intel.driDrawable; | ||||
|    int textureFormat; | ||||
|    GLenum glTextureFormat; | ||||
|    int src_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; | ||||
|    int destOffset = intelAgpOffsetFromVirtual( &i830->intel, pixels); | ||||
|    int destFormat, depthFormat, destPitch; | ||||
|    drm_clip_rect_t tmp; | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    GLuint format; | ||||
|    GLuint depth_format = DEPTH_FRMT_16_FIXED; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|  | ||||
|    if (	ctx->_ImageTransferState || | ||||
| 	pack->SwapBytes || | ||||
| 	pack->LsbFirst || | ||||
| 	!pack->Invert) { | ||||
|       fprintf(stderr, "%s: check_color failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    switch (screen->fbFormat) { | ||||
|    case DV_PF_565: | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|       glTextureFormat = GL_RGB; | ||||
|       break; | ||||
|    case DV_PF_555: | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    case DV_PF_8888: | ||||
|       textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "%s: textureFormat failed %x\n", __FUNCTION__, | ||||
| 	      screen->fbFormat); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    switch (type) { | ||||
|    case GL_UNSIGNED_SHORT_5_6_5:  | ||||
|       if (format != GL_RGB) return GL_FALSE; | ||||
|       destFormat = COLR_BUF_RGB565;  | ||||
|       depthFormat = DEPTH_FRMT_16_FIXED; | ||||
|       destPitch = pitch * 2; | ||||
|       break; | ||||
|    case GL_UNSIGNED_INT_8_8_8_8_REV:  | ||||
|       if (format != GL_BGRA) return GL_FALSE; | ||||
|       destFormat = COLR_BUF_ARGB8888;  | ||||
|       depthFormat = DEPTH_FRMT_24_FIXED_8_OTHER; | ||||
|       destPitch = pitch * 4; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "%s: destFormat failed %s\n", __FUNCTION__, | ||||
| 	      _mesa_lookup_enum_by_nr(type)); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    destFormat |= (0x02<<24); | ||||
|  | ||||
| /*    fprintf(stderr, "type: %s destFormat: %x\n", */ | ||||
| /* 	   _mesa_lookup_enum_by_nr(type), */ | ||||
| /* 	   destFormat); */ | ||||
|  | ||||
|    intelFlush( ctx ); | ||||
|  | ||||
|    SET_STATE( i830, meta ); | ||||
|    set_initial_state( i830 ); | ||||
|    set_no_depth_stencil_write( i830 ); | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       intelWaitForIdle( intel ); /* required by GL */ | ||||
|  | ||||
|       if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 SET_STATE(i830, state); | ||||
| 	 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
| #if 0 | ||||
|       /* FIXME -- Just emit the correct state | ||||
|        */ | ||||
|       if (i830SetParam(i830->driFd, I830_SETPARAM_CBUFFER_PITCH,  | ||||
| 		      destPitch) != 0) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 SET_STATE(i830, state); | ||||
| 	 fprintf(stderr, "%s: setparam failed\n", __FUNCTION__); | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       /* Set the frontbuffer up as a large rectangular texture. | ||||
|        */ | ||||
|       set_tex_rect_source( i830,  | ||||
| 			   src_offset,  | ||||
| 			   screen->width,  | ||||
| 			   screen->height,  | ||||
| 			   screen->front.pitch,  | ||||
| 			   textureFormat );  | ||||
|    intel_region_release(intel, &i830->meta.draw_region); | ||||
|    intel_region_reference(&i830->meta.draw_region, draw_region); | ||||
|     | ||||
|     | ||||
|       enable_texture_blend_replace( i830, glTextureFormat );  | ||||
|    intel_region_release(intel, &i830->meta.depth_region);    | ||||
|    intel_region_reference(&i830->meta.depth_region, depth_region); | ||||
|  | ||||
|    /* XXX FBO: grab code from i915 meta_draw_region */ | ||||
|  | ||||
|       /* Set the 3d engine to draw into the agp memory | ||||
|        */ | ||||
|    /* XXX: 555 support? | ||||
|     */ | ||||
|    if (draw_region->cpp == 2) | ||||
|       format = DV_PF_565; | ||||
|    else | ||||
|       format = DV_PF_8888; | ||||
|  | ||||
|       set_draw_offset( i830, destOffset );  | ||||
|       set_draw_format( i830, destFormat, depthFormat );   | ||||
|  | ||||
|  | ||||
|       /* Draw a single quad, no cliprects: | ||||
|        */ | ||||
|       i830->intel.numClipRects = 1; | ||||
|       i830->intel.pClipRects = &tmp; | ||||
|       i830->intel.pClipRects[0].x1 = 0; | ||||
|       i830->intel.pClipRects[0].y1 = 0; | ||||
|       i830->intel.pClipRects[0].x2 = width; | ||||
|       i830->intel.pClipRects[0].y2 = height; | ||||
|  | ||||
|       draw_quad( i830,  | ||||
| 		 0, width, 0, height,  | ||||
| 		 0, 255, 0, 0,  | ||||
| 		 x, x+width, y, y+height ); | ||||
|  | ||||
|       intelWindowMoved( intel ); | ||||
|    if (depth_region) { | ||||
|       if (depth_region->cpp == 2) | ||||
| 	 depth_format = DEPTH_FRMT_16_FIXED; | ||||
|       else | ||||
| 	 depth_format = DEPTH_FRMT_24_FIXED_8_OTHER; | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( ctx ); /* required by GL */ | ||||
|  | ||||
|    SET_STATE( i830, state ); | ||||
|    return GL_TRUE; | ||||
|    i830->meta.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
| 					  DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
| 					  format | | ||||
| 					  DEPTH_IS_Z | | ||||
| 					  depth_format); | ||||
|  | ||||
|    i830->meta.emitted &= ~I830_UPLOAD_BUFFERS; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean | ||||
| i830TryTextureDrawPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  const GLvoid *pixels ) | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void install_meta_state( struct intel_context *intel ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    GLint pitch = unpack->RowLength ? unpack->RowLength : width; | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    int textureFormat; | ||||
|    GLenum glTextureFormat; | ||||
|    int dst_offset = i830->meta.Buffer[I830_DESTREG_CBUFADDR2]; | ||||
|    int src_offset = intelAgpOffsetFromVirtual( intel, pixels ); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    memcpy(&i830->meta, &i830->initial, sizeof(i830->meta) ); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    i830->meta.active = ACTIVE; | ||||
|    i830->meta.emitted = 0; | ||||
|  | ||||
|    /* Todo -- upload images that aren't in agp space, then texture | ||||
|     * from them.   | ||||
|     */ | ||||
|    SET_STATE(i830, meta); | ||||
|    set_vertex_format(intel); | ||||
|    set_no_texture(intel); | ||||
| } | ||||
|  | ||||
|    if ( !intelIsAgpMemory( intel, pixels, pitch*height ) ) { | ||||
|       fprintf(stderr, "%s: intelIsAgpMemory failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Todo -- don't want to clobber all the drawing state like we do | ||||
|     * for readpixels -- most of this state can be handled just fine. | ||||
|     */ | ||||
|    if (	ctx->_ImageTransferState || | ||||
| 	unpack->SwapBytes || | ||||
| 	unpack->LsbFirst || | ||||
| 	ctx->Color.AlphaEnabled ||  | ||||
| 	ctx->Depth.Test || | ||||
| 	ctx->Fog.Enabled || | ||||
| 	ctx->Scissor.Enabled || | ||||
| 	ctx->Stencil.Enabled || | ||||
| 	!ctx->Color.ColorMask[0] || | ||||
| 	!ctx->Color.ColorMask[1] || | ||||
| 	!ctx->Color.ColorMask[2] || | ||||
| 	!ctx->Color.ColorMask[3] || | ||||
| 	ctx->Color.ColorLogicOpEnabled || | ||||
| 	ctx->Texture._EnabledUnits) { | ||||
|       fprintf(stderr, "%s: other tests failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Todo -- remove these restrictions: | ||||
|     */ | ||||
|    if (ctx->Pixel.ZoomX != 1.0F || | ||||
|        ctx->Pixel.ZoomY != -1.0F) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|  | ||||
|    switch (type) { | ||||
|    case GL_UNSIGNED_SHORT_1_5_5_5_REV: | ||||
|       if (format != GL_BGRA) return GL_FALSE; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    case GL_UNSIGNED_SHORT_5_6_5:  | ||||
|       if (format != GL_RGB) return GL_FALSE; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|       glTextureFormat = GL_RGB; | ||||
|       break; | ||||
|    case GL_UNSIGNED_SHORT_8_8_MESA:  | ||||
|       if (format != GL_YCBCR_MESA) return GL_FALSE; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY  | ||||
| /*  		       | TM0S1_COLORSPACE_CONVERSION */ | ||||
| 	 ); | ||||
|       glTextureFormat = GL_YCBCR_MESA; | ||||
|       break; | ||||
|    case GL_UNSIGNED_SHORT_8_8_REV_MESA:  | ||||
|       if (format != GL_YCBCR_MESA) return GL_FALSE; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL  | ||||
| /* 		       | TM0S1_COLORSPACE_CONVERSION */ | ||||
| 	 ); | ||||
|       glTextureFormat = GL_YCBCR_MESA; | ||||
|       break; | ||||
|    case GL_UNSIGNED_INT_8_8_8_8_REV:  | ||||
|       if (format != GL_BGRA) return GL_FALSE; | ||||
|       textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|       glTextureFormat = GL_RGBA; | ||||
|       break; | ||||
|    default: | ||||
|       fprintf(stderr, "%s: destFormat failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intelFlush( ctx ); | ||||
|  | ||||
|    SET_STATE( i830, meta ); | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       intelWaitForIdle( intel ); /* required by GL */ | ||||
|  | ||||
|       y -= height;			/* cope with pixel zoom */ | ||||
|  | ||||
|       if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 SET_STATE(i830, state); | ||||
| 	 fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|  | ||||
|       set_initial_state( i830 ); | ||||
|  | ||||
|       /* Set the pixel image up as a rectangular texture. | ||||
|        */ | ||||
|       set_tex_rect_source( i830,  | ||||
| 			   src_offset,  | ||||
| 			   width,  | ||||
| 			   height,  | ||||
| 			   pitch, /* XXXX!!!! -- /2 sometimes */ | ||||
| 			   textureFormat );  | ||||
|     | ||||
|     | ||||
|       enable_texture_blend_replace( i830, glTextureFormat );  | ||||
|  | ||||
|     | ||||
|       /* Draw to the current draw buffer: | ||||
|        */ | ||||
|       set_draw_offset( i830, dst_offset ); | ||||
|  | ||||
|       /* Draw a quad, use regular cliprects | ||||
|        */ | ||||
| /*       fprintf(stderr, "x: %d y: %d width %d height %d\n", x, y, width, height); */ | ||||
|  | ||||
|       draw_quad( i830,  | ||||
| 		 x, x+width, y, y+height, | ||||
| 		 0, 255, 0, 0,  | ||||
| 		 0, width, 0, height ); | ||||
|  | ||||
|       intelWindowMoved( intel ); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( ctx ); /* required by GL */ | ||||
|     | ||||
| static void leave_meta_state( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    intel_region_release(intel, &i830->meta.draw_region); | ||||
|    intel_region_release(intel, &i830->meta.depth_region); | ||||
| /*    intel_region_release(intel, &i830->meta.tex_region[0]); */ | ||||
|    SET_STATE(i830, state); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void i830InitMetaFuncs( struct i830_context *i830 ) | ||||
| { | ||||
|    i830->intel.vtbl.install_meta_state = install_meta_state; | ||||
|    i830->intel.vtbl.leave_meta_state = leave_meta_state; | ||||
|    i830->intel.vtbl.meta_no_depth_write = set_no_depth_write; | ||||
|    i830->intel.vtbl.meta_no_stencil_write = set_no_stencil_write; | ||||
|    i830->intel.vtbl.meta_stencil_replace = set_stencil_replace; | ||||
|    i830->intel.vtbl.meta_depth_replace = set_depth_replace; | ||||
|    i830->intel.vtbl.meta_color_mask = set_color_mask; | ||||
|    i830->intel.vtbl.meta_no_texture = set_no_texture; | ||||
|    i830->intel.vtbl.meta_texture_blend_replace = set_texture_blend_replace; | ||||
|    i830->intel.vtbl.meta_tex_rect_source = set_tex_rect_source; | ||||
|    i830->intel.vtbl.meta_draw_region = meta_draw_region; | ||||
|    i830->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -407,10 +407,10 @@ | ||||
| #define LOGICOP_SET			0xf | ||||
| #define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00)) | ||||
| #define ENABLE_STENCIL_TEST_MASK	(1<<17) | ||||
| #define STENCIL_TEST_MASK(x)		((x)<<8) | ||||
| #define STENCIL_TEST_MASK(x)		(((x)&0xff)<<8) | ||||
| #define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff)) | ||||
| #define ENABLE_STENCIL_WRITE_MASK	(1<<16) | ||||
| #define STENCIL_WRITE_MASK(x)		(x) | ||||
| #define STENCIL_WRITE_MASK(x)		((x)&0xff) | ||||
|  | ||||
| /* _3DSTATE_MODES_5, p196 */ | ||||
| #define _3DSTATE_MODES_5_CMD		(CMD_3D|(0x0c<<24)) | ||||
|   | ||||
| @@ -36,6 +36,7 @@ | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_fbo.h" | ||||
|  | ||||
| #include "i830_context.h" | ||||
| #include "i830_reg.h" | ||||
| @@ -44,7 +45,7 @@ static void | ||||
| i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
|                         GLuint mask) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|  | ||||
|    mask = mask & 0xff; | ||||
| @@ -69,7 +70,7 @@ i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
| static void | ||||
| i830StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask); | ||||
| @@ -86,7 +87,7 @@ static void | ||||
| i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|                       GLenum zpass) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int fop, dfop, dpop; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -193,7 +194,7 @@ i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|  | ||||
| static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|    GLubyte refByte; | ||||
|    GLuint refInt; | ||||
| @@ -221,7 +222,7 @@ static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
|  */ | ||||
| static void i830EvalLogicOpBlendState(GLcontext *ctx) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
| @@ -245,7 +246,7 @@ static void i830EvalLogicOpBlendState(GLcontext *ctx) | ||||
|  | ||||
| static void i830BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    GLubyte r, g, b, a; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -268,7 +269,7 @@ static void i830BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
|  */ | ||||
| static void i830_set_blend_state( GLcontext * ctx ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int funcA; | ||||
|    int funcRGB; | ||||
|    int eqnA; | ||||
| @@ -406,7 +407,7 @@ static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, | ||||
|  | ||||
| static void i830DepthFunc(GLcontext *ctx, GLenum func) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int test = intel_translate_compare_func(func); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -420,7 +421,7 @@ static void i830DepthFunc(GLcontext *ctx, GLenum func) | ||||
|  | ||||
| static void i830DepthMask(GLcontext *ctx, GLboolean flag) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag); | ||||
| @@ -443,7 +444,7 @@ static void i830DepthMask(GLcontext *ctx, GLboolean flag) | ||||
|  */ | ||||
| static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    const GLubyte *m = mask; | ||||
|    GLubyte p[4]; | ||||
|    int i,j,k; | ||||
| @@ -496,15 +497,14 @@ static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| static void i830Scissor(GLcontext *ctx, GLint x, GLint y,  | ||||
| 			GLsizei w, GLsizei h) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = i830->intel.intelScreen; | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int x1, y1, x2, y2; | ||||
|  | ||||
|    if (!i830->intel.driDrawable) | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|  | ||||
|    x1 = x; | ||||
|    y1 = i830->intel.driDrawable->h - (y + h); | ||||
|    y1 = ctx->DrawBuffer->Height - (y + h); | ||||
|    x2 = x + w - 1; | ||||
|    y2 = y1 + h - 1; | ||||
|  | ||||
| @@ -512,16 +512,10 @@ static void i830Scissor(GLcontext *ctx, GLint x, GLint y, | ||||
|       fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__, | ||||
| 	      x, y, w, h); | ||||
|  | ||||
|    if (x1 < 0) x1 = 0; | ||||
|    if (y1 < 0) y1 = 0; | ||||
|    if (x2 < 0) x2 = 0; | ||||
|    if (y2 < 0) y2 = 0; | ||||
|  | ||||
|    if (x2 >= screen->width) x2 = screen->width-1; | ||||
|    if (y2 >= screen->height) y2 = screen->height-1; | ||||
|    if (x1 >= screen->width) x1 = screen->width-1; | ||||
|    if (y1 >= screen->height) y1 = screen->height-1; | ||||
|  | ||||
|    x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); | ||||
|    x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); | ||||
|    i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); | ||||
| @@ -530,7 +524,7 @@ static void i830Scissor(GLcontext *ctx, GLint x, GLint y, | ||||
|  | ||||
| static void i830LogicOp(GLcontext *ctx, GLenum opcode) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    int tmp = intel_translate_logic_op( opcode ); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -545,7 +539,7 @@ static void i830LogicOp(GLcontext *ctx, GLenum opcode) | ||||
|  | ||||
| static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    GLuint mode; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -573,7 +567,7 @@ static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
|  | ||||
| static void i830LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    struct i830_context *i830 = i830_context( ctx ); | ||||
|    int width; | ||||
|    int state5; | ||||
|  | ||||
| @@ -594,7 +588,7 @@ static void i830LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
|  | ||||
| static void i830PointSize(GLcontext *ctx, GLfloat size) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    GLint point_size = (int)size; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -616,7 +610,7 @@ static void i830ColorMask(GLcontext *ctx, | ||||
| 			  GLboolean r, GLboolean g, | ||||
| 			  GLboolean b, GLboolean a) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    struct i830_context *i830 = i830_context( ctx ); | ||||
|    GLuint tmp = 0; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -638,7 +632,7 @@ static void i830ColorMask(GLcontext *ctx, | ||||
|  | ||||
| static void update_specular( GLcontext *ctx ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    struct i830_context *i830 = i830_context( ctx ); | ||||
|  | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|    i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK; | ||||
| @@ -664,7 +658,7 @@ static void i830LightModelfv(GLcontext *ctx, GLenum pname, | ||||
|  */ | ||||
| static void i830ShadeModel(GLcontext *ctx, GLenum mode) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
|  | ||||
| @@ -690,7 +684,7 @@ static void i830ShadeModel(GLcontext *ctx, GLenum mode) | ||||
|  */ | ||||
| static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
| @@ -710,7 +704,7 @@ static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
|  | ||||
| static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|  | ||||
|    switch(cap) { | ||||
|    case GL_LIGHTING: | ||||
| @@ -806,20 +800,28 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|       break; | ||||
|  | ||||
|    case GL_STENCIL_TEST: | ||||
|       if (i830->intel.hw_stencil) { | ||||
| 	 I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|       { | ||||
|          GLboolean hw_stencil = GL_FALSE; | ||||
|          if (ctx->DrawBuffer) { | ||||
|             struct intel_renderbuffer *irbStencil | ||||
|                = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); | ||||
|             hw_stencil = (irbStencil && irbStencil->region); | ||||
|          } | ||||
|          if (hw_stencil) { | ||||
|             I830_STATECHANGE(i830, I830_UPLOAD_CTX); | ||||
|  | ||||
| 	 if (state) { | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST; | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE; | ||||
| 	 } else { | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE; | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; | ||||
| 	    i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE; | ||||
| 	 } | ||||
|       } else { | ||||
| 	 FALLBACK( &i830->intel, I830_FALLBACK_STENCIL, state ); | ||||
|             if (state) { | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE; | ||||
|             } else { | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; | ||||
|                i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE; | ||||
|             } | ||||
|          } else { | ||||
|             FALLBACK( &i830->intel, I830_FALLBACK_STENCIL, state ); | ||||
|          } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
| @@ -844,7 +846,7 @@ static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830_init_packets( i830ContextPtr i830 ) | ||||
| static void i830_init_packets( struct i830_context *i830 ) | ||||
| { | ||||
|    intelScreenPrivate *screen = i830->intel.intelScreen; | ||||
|  | ||||
| @@ -902,6 +904,7 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
| 					     DISABLE_COLOR_BLEND | | ||||
| 					     DISABLE_DEPTH_TEST); | ||||
|  | ||||
| #if 000 /* XXX all the stencil enable state is set in i830Enable(), right? */ | ||||
|    if (i830->intel.hw_stencil) { | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD | | ||||
| 						ENABLE_STENCIL_WRITE | | ||||
| @@ -911,7 +914,9 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
| 						/* set no color comps disabled */ | ||||
| 						ENABLE_COLOR_WRITE | | ||||
| 						ENABLE_DEPTH_WRITE); | ||||
|    } else { | ||||
|    } else | ||||
| #endif | ||||
|    { | ||||
|       i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD | | ||||
| 						DISABLE_STENCIL_WRITE | | ||||
| 						ENABLE_TEX_CACHE | | ||||
| @@ -1010,15 +1015,14 @@ static void i830_init_packets( i830ContextPtr i830 ) | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR1] =  | ||||
|       (BUF_3D_ID_DEPTH | | ||||
|        BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | | ||||
|        BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | /* XXX FBO fix */ | ||||
|        BUF_3D_USE_FENCE); | ||||
|    i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; | ||||
| /*    i830->state.Buffer[I830_DESTREG_DBUFADDR2] = screen->depth.offset; */ | ||||
|  | ||||
|  | ||||
|    i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; | ||||
|  | ||||
|    switch (screen->fbFormat) { | ||||
|    case DV_PF_555: | ||||
|    case DV_PF_565: | ||||
|       i830->state.Buffer[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
| 					      DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
| @@ -1068,7 +1072,7 @@ void i830InitStateFuncs( struct dd_function_table *functions ) | ||||
|    functions->StencilOpSeparate = i830StencilOpSeparate; | ||||
| } | ||||
|  | ||||
| void i830InitState( i830ContextPtr i830 ) | ||||
| void i830InitState( struct i830_context *i830 ) | ||||
| { | ||||
|    GLcontext *ctx = &i830->intel.ctx; | ||||
|  | ||||
| @@ -1080,7 +1084,8 @@ void i830InitState( i830ContextPtr i830 ) | ||||
|  | ||||
|    i830->current = &i830->state; | ||||
|    i830->state.emitted = 0; | ||||
|    i830->state.active = (I830_UPLOAD_TEXBLEND(0) | | ||||
|    i830->state.active = (I830_UPLOAD_INVARIENT | | ||||
| 			 I830_UPLOAD_TEXBLEND(0) | | ||||
| 			 I830_UPLOAD_STIPPLE | | ||||
| 			 I830_UPLOAD_CTX | | ||||
| 			 I830_UPLOAD_BUFFERS); | ||||
|   | ||||
| @@ -45,261 +45,12 @@ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Set the texture wrap modes. | ||||
|  *  | ||||
|  * The i830M (and related graphics cores) do not support GL_CLAMP.  The Intel | ||||
|  * drivers for "other operating systems" implement GL_CLAMP as | ||||
|  * GL_CLAMP_TO_EDGE, so the same is done here. | ||||
|  *  | ||||
|  * \param t Texture object whose wrap modes are to be set | ||||
|  * \param swrap Wrap mode for the \a s texture coordinate | ||||
|  * \param twrap Wrap mode for the \a t texture coordinate | ||||
|  */ | ||||
| static void i830SetTexWrapping(i830TextureObjectPtr tex, | ||||
| 			       GLenum swrap,  | ||||
| 			       GLenum twrap) | ||||
| { | ||||
|    tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK); | ||||
|  | ||||
|    switch( swrap ) { | ||||
|    case GL_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP); | ||||
|       break; | ||||
|    case GL_CLAMP: | ||||
|    case GL_CLAMP_TO_EDGE: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP); | ||||
|       break; | ||||
|    case GL_CLAMP_TO_BORDER: | ||||
|       tex->Setup[I830_TEXREG_MCS] |=  | ||||
| 			TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER); | ||||
|       break; | ||||
|    case GL_MIRRORED_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |=  | ||||
| 			TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR); | ||||
|       break; | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    switch( twrap ) { | ||||
|    case GL_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP); | ||||
|       break; | ||||
|    case GL_CLAMP: | ||||
|    case GL_CLAMP_TO_EDGE: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP); | ||||
|       break; | ||||
|    case GL_CLAMP_TO_BORDER: | ||||
|       tex->Setup[I830_TEXREG_MCS] |=  | ||||
| 			TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER); | ||||
|       break; | ||||
|    case GL_MIRRORED_REPEAT: | ||||
|       tex->Setup[I830_TEXREG_MCS] |= | ||||
| 			TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR); | ||||
|       break; | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Set the texture magnification and minification modes. | ||||
|  *  | ||||
|  * \param t Texture whose filter modes are to be set | ||||
|  * \param minf Texture minification mode | ||||
|  * \param magf Texture magnification mode | ||||
|  * \param bias LOD bias for this texture unit. | ||||
|  */ | ||||
|  | ||||
| static void i830SetTexFilter( i830TextureObjectPtr t, GLenum minf, GLenum magf, | ||||
| 			      GLfloat maxanisotropy ) | ||||
| { | ||||
|    int minFilt = 0, mipFilt = 0, magFilt = 0; | ||||
|  | ||||
|    if(INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if ( maxanisotropy > 1.0 ) { | ||||
|       minFilt = FILTER_ANISOTROPIC; | ||||
|       magFilt = FILTER_ANISOTROPIC; | ||||
|    } | ||||
|    else { | ||||
|       switch (minf) { | ||||
|       case GL_NEAREST: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_NONE; | ||||
| 	 break; | ||||
|       case GL_LINEAR: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_NONE; | ||||
| 	 break; | ||||
|       case GL_NEAREST_MIPMAP_NEAREST: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_LINEAR_MIPMAP_NEAREST: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_NEAREST_MIPMAP_LINEAR: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_LINEAR; | ||||
| 	 break; | ||||
|       case GL_LINEAR_MIPMAP_LINEAR: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_LINEAR; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 break; | ||||
|       } | ||||
|  | ||||
|       switch (magf) { | ||||
|       case GL_NEAREST: | ||||
| 	 magFilt = FILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_LINEAR: | ||||
| 	 magFilt = FILTER_LINEAR; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 break; | ||||
|       }   | ||||
|    } | ||||
|  | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_FILTER_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIP_FILTER_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAG_FILTER_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | | ||||
| 				   (mipFilt << TM0S3_MIP_FILTER_SHIFT) | | ||||
| 				   (magFilt << TM0S3_MAG_FILTER_SHIFT)); | ||||
| } | ||||
|  | ||||
| static void i830SetTexBorderColor(i830TextureObjectPtr t, GLubyte color[4]) | ||||
| { | ||||
|    if(INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|     t->Setup[I830_TEXREG_TM0S4] =  | ||||
|         INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Allocate space for and load the mesa images into the texture memory block. | ||||
|  * This will happen before drawing with a new texture, or drawing with a | ||||
|  * texture after it was swapped out or teximaged again. | ||||
|  */ | ||||
|  | ||||
| intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj ) | ||||
| { | ||||
|    i830TextureObjectPtr t = CALLOC_STRUCT( i830_texture_object ); | ||||
|    if ( !t )  | ||||
|       return NULL; | ||||
|  | ||||
|    texObj->DriverData = t; | ||||
|    t->intel.base.tObj = texObj; | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
|    make_empty_list( &t->intel.base ); | ||||
|  | ||||
|    t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */ | ||||
|    t->Setup[I830_TEXREG_TM0S0] = 0; | ||||
|    t->Setup[I830_TEXREG_TM0S1] = 0; | ||||
|    t->Setup[I830_TEXREG_TM0S2] = 0; | ||||
|    t->Setup[I830_TEXREG_TM0S3] = 0; | ||||
|    t->Setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | | ||||
| 				MAP_UNIT(0) | | ||||
| 				ENABLE_TEXCOORD_PARAMS | | ||||
| 				TEXCOORDS_ARE_NORMAL | | ||||
| 				TEXCOORDTYPE_CARTESIAN | | ||||
| 				ENABLE_ADDR_V_CNTL | | ||||
| 				TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) | | ||||
| 				ENABLE_ADDR_U_CNTL | | ||||
| 				TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP)); | ||||
|  | ||||
|     | ||||
|    i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT ); | ||||
|    i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter,  | ||||
| 		     texObj->MaxAnisotropy ); | ||||
|    i830SetTexBorderColor( t, texObj->_BorderChan ); | ||||
|  | ||||
|    return &t->intel; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830TexParameter( GLcontext *ctx, GLenum target, | ||||
| 			      struct gl_texture_object *tObj, | ||||
| 			      GLenum pname, const GLfloat *params ) | ||||
| { | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData; | ||||
|    if (!t) | ||||
|       return; | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_MIN_FILTER: | ||||
|    case GL_TEXTURE_MAG_FILTER: | ||||
|    case GL_TEXTURE_MAX_ANISOTROPY_EXT: | ||||
|       i830SetTexFilter( t, tObj->MinFilter, tObj->MagFilter, | ||||
| 			tObj->MaxAnisotropy); | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_WRAP_S: | ||||
|    case GL_TEXTURE_WRAP_T: | ||||
|       i830SetTexWrapping( t, tObj->WrapS, tObj->WrapT ); | ||||
|       break; | ||||
|    | ||||
|    case GL_TEXTURE_BORDER_COLOR: | ||||
|       i830SetTexBorderColor( t, tObj->_BorderChan ); | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_BASE_LEVEL: | ||||
|    case GL_TEXTURE_MAX_LEVEL: | ||||
|    case GL_TEXTURE_MIN_LOD: | ||||
|    case GL_TEXTURE_MAX_LOD: | ||||
|       /* The i830 and its successors can do a lot of this without | ||||
|        * reloading the textures.  A project for someone? | ||||
|        */ | ||||
|       intelFlush( ctx ); | ||||
|       driSwapOutTextureObject( (driTextureObject *) t ); | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830TexEnv( GLcontext *ctx, GLenum target,  | ||||
| 			GLenum pname, const GLfloat *param ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT( ctx ); | ||||
|    GLuint unit = ctx->Texture.CurrentUnit; | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_ENV_COLOR:  | ||||
| #if 0 | ||||
|    { | ||||
|       GLubyte r, g, b, a; | ||||
|       GLuint col; | ||||
|        | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(r, param[RCOMP]); | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(g, param[GCOMP]); | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(b, param[BCOMP]); | ||||
|       UNCLAMPED_FLOAT_TO_UBYTE(a, param[ACOMP]); | ||||
|  | ||||
|       col = ((a << 24) | (r << 16) | (g << 8) | b); | ||||
|  | ||||
|       if (col != i830->state.TexEnv[unit][I830_TEXENVREG_COL1]) { | ||||
| 	 I830_STATECHANGE(i830, I830_UPLOAD_TEXENV); | ||||
| 	 i830->state.TexEnv[unit][I830_TEXENVREG_COL1] = col; | ||||
|       } | ||||
|  | ||||
|       break; | ||||
|    } | ||||
| #endif | ||||
|    case GL_TEXTURE_ENV_MODE: | ||||
|    case GL_COMBINE_RGB: | ||||
|    case GL_COMBINE_ALPHA: | ||||
| @@ -320,13 +71,13 @@ static void i830TexEnv( GLcontext *ctx, GLenum target, | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_LOD_BIAS: { | ||||
|       struct i830_context *i830 = i830_context( ctx ); | ||||
|       GLuint unit = ctx->Texture.CurrentUnit; | ||||
|       int b = (int) ((*param) * 16.0); | ||||
|       if (b > 63) b = 63; | ||||
|       if (b < -64) b = -64; | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK; | ||||
|       i830->state.Tex[unit][I830_TEXREG_TM0S3] |=  | ||||
| 	 ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK); | ||||
|       i830->lodbias_tm0s3[unit] = ((b << TM0S3_LOD_BIAS_SHIFT) & TM0S3_LOD_BIAS_MASK); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
| @@ -341,5 +92,4 @@ static void i830TexEnv( GLcontext *ctx, GLenum target, | ||||
| void i830InitTextureFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->TexEnv                    = i830TexEnv; | ||||
|    functions->TexParameter              = i830TexParameter; | ||||
| } | ||||
|   | ||||
| @@ -101,7 +101,7 @@ static GLuint emit_factor( GLuint blendUnit, GLuint *state, GLuint count, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ GLuint GetTexelOp(GLint unit) | ||||
| static INLINE GLuint GetTexelOp(GLint unit) | ||||
| { | ||||
|    switch(unit) { | ||||
|    case 0: return TEXBLENDARG_TEXEL0; | ||||
| @@ -132,7 +132,7 @@ static __inline__ GLuint GetTexelOp(GLint unit) | ||||
|  * partial support for the extension? | ||||
|  */ | ||||
| GLuint | ||||
| i830SetTexEnvCombine(i830ContextPtr i830, | ||||
| i830SetTexEnvCombine(struct i830_context *i830, | ||||
| 		     const struct gl_tex_env_combine_state * combine, | ||||
| 		     GLint blendUnit, | ||||
| 		     GLuint texel_op, | ||||
| @@ -394,7 +394,7 @@ i830SetTexEnvCombine(i830ContextPtr i830, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit, | ||||
| static void emit_texblend( struct i830_context *i830, GLuint unit, GLuint blendUnit, | ||||
| 			   GLboolean last_stage ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit]; | ||||
| @@ -423,7 +423,7 @@ static void emit_texblend( i830ContextPtr i830, GLuint unit, GLuint blendUnit, | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), GL_TRUE); | ||||
| } | ||||
|  | ||||
| static void emit_passthrough( i830ContextPtr i830 ) | ||||
| static void emit_passthrough( struct i830_context *i830 ) | ||||
| { | ||||
|    GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz; | ||||
|    GLuint unit = 0; | ||||
| @@ -442,7 +442,7 @@ static void emit_passthrough( i830ContextPtr i830 ) | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), GL_TRUE); | ||||
| } | ||||
|  | ||||
| void i830EmitTextureBlend( i830ContextPtr i830 ) | ||||
| void i830EmitTextureBlend( struct i830_context *i830 ) | ||||
| { | ||||
|    GLcontext *ctx = &i830->intel.ctx; | ||||
|    GLuint unit, last_stage = 0, blendunit = 0; | ||||
|   | ||||
| @@ -38,441 +38,274 @@ | ||||
| #include "intel_screen.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i830_context.h" | ||||
| #include "i830_reg.h" | ||||
|  | ||||
| static const GLint initial_offsets[6][2] = { {0,0}, | ||||
| 				       {0,2}, | ||||
| 				       {1,0}, | ||||
| 				       {1,2}, | ||||
| 				       {1,1}, | ||||
| 				       {1,3} }; | ||||
|  | ||||
| static const GLint step_offsets[6][2] = { {0,2}, | ||||
| 				    {0,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,1}, | ||||
| 				    {-1,1} }; | ||||
|  | ||||
| #define I830_TEX_UNIT_ENABLED(unit)		(1<<unit) | ||||
|  | ||||
| static GLboolean i830SetTexImages( i830ContextPtr i830,  | ||||
| 				  struct gl_texture_object *tObj ) | ||||
| static GLuint translate_texture_format( GLuint mesa_format ) | ||||
| { | ||||
|    GLuint total_height, pitch, i, textureFormat; | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData; | ||||
|    const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; | ||||
|    GLint firstLevel, lastLevel, numLevels; | ||||
|  | ||||
|    switch( baseImage->TexFormat->MesaFormat ) { | ||||
|    switch (mesa_format) { | ||||
|    case MESA_FORMAT_L8: | ||||
|       t->intel.texelBytes = 1; | ||||
|       textureFormat = MAPSURF_8BIT | MT_8BIT_L8; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_8BIT | MT_8BIT_L8; | ||||
|    case MESA_FORMAT_I8: | ||||
|       t->intel.texelBytes = 1; | ||||
|       textureFormat = MAPSURF_8BIT | MT_8BIT_I8; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_8BIT | MT_8BIT_I8; | ||||
|    case MESA_FORMAT_A8: | ||||
|       t->intel.texelBytes = 1; | ||||
|       textureFormat = MAPSURF_8BIT | MT_8BIT_I8; /* Kludge -- check with conform, glean */ | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */ | ||||
|    case MESA_FORMAT_AL88: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_AY88; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_AY88; | ||||
|    case MESA_FORMAT_RGB565: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_RGB565; | ||||
|    case MESA_FORMAT_ARGB1555: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_ARGB1555; | ||||
|    case MESA_FORMAT_ARGB4444: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_16BIT | MT_16BIT_ARGB4444; | ||||
|    case MESA_FORMAT_ARGB8888: | ||||
|       t->intel.texelBytes = 4; | ||||
|       textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|       break; | ||||
|  | ||||
|       return MAPSURF_32BIT | MT_32BIT_ARGB8888; | ||||
|    case MESA_FORMAT_YCBCR_REV: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL |  | ||||
| 		       TM0S1_COLORSPACE_CONVERSION); | ||||
|       break; | ||||
|  | ||||
|       return (MAPSURF_422 | MT_422_YCRCB_NORMAL); | ||||
|    case MESA_FORMAT_YCBCR: | ||||
|       t->intel.texelBytes = 2; | ||||
|       textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */ | ||||
| 		       TM0S1_COLORSPACE_CONVERSION); | ||||
|       break; | ||||
|  | ||||
|       return (MAPSURF_422 | MT_422_YCRCB_SWAPY); | ||||
|    case MESA_FORMAT_RGB_FXT1: | ||||
|    case MESA_FORMAT_RGBA_FXT1: | ||||
|      t->intel.texelBytes = 2; | ||||
|      textureFormat = MAPSURF_COMPRESSED | MT_COMPRESS_FXT1; | ||||
|      break; | ||||
|  | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); | ||||
|    case MESA_FORMAT_RGBA_DXT1: | ||||
|    case MESA_FORMAT_RGB_DXT1: | ||||
|      /*  | ||||
|       * DXTn pitches are Width/4 * blocksize in bytes  | ||||
|       * for DXT1: blocksize=8 so Width/4*8 = Width * 2  | ||||
|       * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4 | ||||
|       */ | ||||
|      t->intel.texelBytes = 2; | ||||
|      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); | ||||
|      break; | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); | ||||
|    case MESA_FORMAT_RGBA_DXT3: | ||||
|      t->intel.texelBytes = 4; | ||||
|      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); | ||||
|      break; | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); | ||||
|    case MESA_FORMAT_RGBA_DXT5: | ||||
|      t->intel.texelBytes = 4; | ||||
|      textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); | ||||
|      break; | ||||
|  | ||||
|       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); | ||||
|    default: | ||||
|       fprintf(stderr, "%s: bad image format\n", __FUNCTION__); | ||||
|       fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, | ||||
| 	      mesa_format); | ||||
|       abort(); | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    /* Compute which mipmap levels we really want to send to the hardware. | ||||
|     * This depends on the base image size, GL_TEXTURE_MIN_LOD, | ||||
|     * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. | ||||
|     * Yes, this looks overly complicated, but it's all needed. | ||||
|     */ | ||||
|    driCalculateTextureFirstLastLevel( (driTextureObject *) t ); | ||||
|  | ||||
|  | ||||
|    /* Figure out the amount of memory required to hold all the mipmap | ||||
|     * levels.  Choose the smallest pitch to accomodate the largest | ||||
|     * mipmap: | ||||
|     */ | ||||
|    firstLevel = t->intel.base.firstLevel; | ||||
|    lastLevel = t->intel.base.lastLevel; | ||||
|    numLevels = lastLevel - firstLevel + 1; | ||||
|  | ||||
|  | ||||
|    /* All images must be loaded at this pitch.  Count the number of | ||||
|     * lines required: | ||||
|     */ | ||||
|    switch (tObj->Target) { | ||||
|    case GL_TEXTURE_CUBE_MAP: { | ||||
|       const GLuint dim = tObj->Image[0][firstLevel]->Width; | ||||
|       GLuint face; | ||||
|  | ||||
|       pitch = dim * t->intel.texelBytes; | ||||
|       pitch *= 2;		/* double pitch for cube layouts */ | ||||
|       pitch = (pitch + 3) & ~3; | ||||
|        | ||||
|       total_height = dim * 4; | ||||
|  | ||||
|       for ( face = 0 ; face < 6 ; face++) { | ||||
| 	 GLuint x = initial_offsets[face][0] * dim; | ||||
| 	 GLuint y = initial_offsets[face][1] * dim; | ||||
| 	 GLuint d = dim; | ||||
| 	  | ||||
| 	 t->intel.base.dirty_images[face] = ~0; | ||||
|  | ||||
| 	 assert(tObj->Image[face][firstLevel]->Width == dim); | ||||
| 	 assert(tObj->Image[face][firstLevel]->Height == dim); | ||||
|  | ||||
| 	 for (i = 0; i < numLevels; i++) { | ||||
| 	    t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; | ||||
| 	    if (!t->intel.image[face][i].image) { | ||||
| 	       fprintf(stderr, "no image %d %d\n", face, i); | ||||
| 	       break;		/* can't happen */ | ||||
| 	    } | ||||
| 	  | ||||
| 	    t->intel.image[face][i].offset =  | ||||
| 	       y * pitch + x * t->intel.texelBytes; | ||||
| 	    t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; | ||||
|  | ||||
| 	    d >>= 1; | ||||
| 	    x += step_offsets[face][0] * d; | ||||
| 	    y += step_offsets[face][1] * d; | ||||
| 	 } | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    default: | ||||
|       pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; | ||||
|       pitch = (pitch + 3) & ~3; | ||||
|       t->intel.base.dirty_images[0] = ~0; | ||||
|  | ||||
|       for ( total_height = i = 0 ; i < numLevels ; i++ ) { | ||||
| 	 t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; | ||||
| 	 if (!t->intel.image[0][i].image)  | ||||
| 	    break; | ||||
| 	  | ||||
| 	 t->intel.image[0][i].offset = total_height * pitch; | ||||
| 	 t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; | ||||
| 	 if (t->intel.image[0][i].image->IsCompressed) | ||||
| 	 { | ||||
| 	   if (t->intel.image[0][i].image->Height > 4) | ||||
| 	     total_height += t->intel.image[0][i].image->Height/4; | ||||
| 	   else | ||||
| 	     total_height += 1; | ||||
| 	 } | ||||
| 	 else | ||||
| 	   total_height += MAX2(2, t->intel.image[0][i].image->Height); | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    t->intel.Pitch = pitch; | ||||
|    t->intel.base.totalSize = total_height*pitch; | ||||
|    t->intel.max_level = i-1; | ||||
|    t->Setup[I830_TEXREG_TM0S1] =  | ||||
|       (((tObj->Image[0][firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) | | ||||
|        ((tObj->Image[0][firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) | | ||||
|        textureFormat); | ||||
|    t->Setup[I830_TEXREG_TM0S2] =  | ||||
|       (((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | | ||||
|       TM0S2_CUBE_FACE_ENA_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK; | ||||
|    t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT; | ||||
|    t->intel.dirty = I830_UPLOAD_TEX_ALL; | ||||
|  | ||||
|    return intelUploadTexImages( &i830->intel, &t->intel, 0 ); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i830_import_tex_unit( i830ContextPtr i830,  | ||||
| 			   i830TextureObjectPtr t, | ||||
| 			   GLuint unit ) | ||||
| { | ||||
|    if(INTEL_DEBUG&DEBUG_TEXTURE) | ||||
|       fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); | ||||
|     | ||||
|    if (i830->intel.CurrentTexObj[unit])  | ||||
|       i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit); | ||||
|  | ||||
|    i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t; | ||||
|    t->intel.base.bound |= (1 << unit); | ||||
|  | ||||
|    I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) ); | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |  | ||||
| 					       (LOAD_TEXTURE_MAP0 << unit) | 4); | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | | ||||
| 					       t->intel.TextureOffset); | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S1] = t->Setup[I830_TEXREG_TM0S1]; | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S2] = t->Setup[I830_TEXREG_TM0S2]; | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S3] &= TM0S3_LOD_BIAS_MASK; | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S3] |= (t->Setup[I830_TEXREG_TM0S3] & | ||||
| 						~TM0S3_LOD_BIAS_MASK); | ||||
|  | ||||
|    i830->state.Tex[unit][I830_TEXREG_TM0S4] = t->Setup[I830_TEXREG_TM0S4]; | ||||
|    i830->state.Tex[unit][I830_TEXREG_MCS] = (t->Setup[I830_TEXREG_MCS] &  | ||||
| 					     ~MAP_UNIT_MASK);    | ||||
|    i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE]; | ||||
|    i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit); | ||||
|  | ||||
|    t->intel.dirty &= ~I830_UPLOAD_TEX(unit); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) | ||||
|  | ||||
| /* The i915 (and related graphics cores) do not support GL_CLAMP.  The | ||||
|  * Intel drivers for "other operating systems" implement GL_CLAMP as | ||||
|  * GL_CLAMP_TO_EDGE, so the same is done here. | ||||
|  */ | ||||
| static GLuint translate_wrap_mode( GLenum wrap ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; | ||||
|    struct gl_texture_object *tObj = texUnit->_Current; | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; | ||||
|    switch( wrap ) { | ||||
|    case GL_REPEAT:  | ||||
|       return TEXCOORDMODE_WRAP; | ||||
|    case GL_CLAMP:   | ||||
|    case GL_CLAMP_TO_EDGE:  | ||||
|       return TEXCOORDMODE_CLAMP; /* not really correct */ | ||||
|    case GL_CLAMP_TO_BORDER:  | ||||
|       return TEXCOORDMODE_CLAMP_BORDER; | ||||
|    case GL_MIRRORED_REPEAT:  | ||||
|       return TEXCOORDMODE_MIRROR; | ||||
|    default:  | ||||
|       return TEXCOORDMODE_WRAP; | ||||
|    } | ||||
| } | ||||
|  | ||||
|    if (0) fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Fallback if there's a texture border */ | ||||
|    if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { | ||||
|       fprintf(stderr, "Texture border\n"); | ||||
|       return GL_FALSE; | ||||
| /* Recalculate all state from scratch.  Perhaps not the most | ||||
|  * efficient, but this has gotten complex enough that we need | ||||
|  * something which is understandable and reliable. | ||||
|  */ | ||||
| static GLboolean i830_update_tex_unit( struct intel_context *intel, | ||||
| 				       GLuint unit,  | ||||
| 				       GLuint ss3 ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(tObj); | ||||
|    struct gl_texture_image *firstImage; | ||||
|    GLuint *state = i830->state.Tex[unit]; | ||||
|  | ||||
|    memset(state, 0, sizeof(state)); | ||||
|  | ||||
|    if (!intel_finalize_mipmap_tree(intel, unit)) | ||||
|       return GL_FALSE;    | ||||
|  | ||||
|    /* Get first image here, since intelObj->firstLevel will get set in | ||||
|     * the intel_finalize_mipmap_tree() call above. | ||||
|     */ | ||||
|    firstImage = tObj->Image[0][intelObj->firstLevel]; | ||||
|  | ||||
|    i830->state.tex_buffer[unit] = intelObj->mt->region->buffer; | ||||
|    i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt, 0, | ||||
| 							     intelObj->firstLevel);  | ||||
|  | ||||
|  | ||||
|    state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |  | ||||
| 			       (LOAD_TEXTURE_MAP0 << unit) | 4); | ||||
|  | ||||
| /*    state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */ | ||||
| /* 			       t->intel.TextureOffset); */ | ||||
|  | ||||
|  | ||||
|    state[I830_TEXREG_TM0S1] =   | ||||
|       (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) | | ||||
|        ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | | ||||
|        translate_texture_format( firstImage->TexFormat->MesaFormat)); | ||||
|  | ||||
|    state[I830_TEXREG_TM0S2] =  | ||||
|       (((((intelObj->mt->pitch * intelObj->mt->cpp) / 4) - 1) << TM0S2_PITCH_SHIFT) | | ||||
|        TM0S2_CUBE_FACE_ENA_MASK); | ||||
|  | ||||
|    { | ||||
|       if (tObj->Target == GL_TEXTURE_CUBE_MAP) | ||||
| 	 state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) | | ||||
| 				    CUBE_NEGX_ENABLE |  | ||||
| 				    CUBE_POSX_ENABLE |  | ||||
| 				    CUBE_NEGY_ENABLE |  | ||||
| 				    CUBE_POSY_ENABLE |  | ||||
| 				    CUBE_NEGZ_ENABLE |  | ||||
| 				    CUBE_POSZ_ENABLE); | ||||
|       else | ||||
| 	 state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit)); | ||||
|    } | ||||
|  | ||||
|    /* Upload teximages (not pipelined) | ||||
|     */ | ||||
|    if (t->intel.base.dirty_images[0]) { | ||||
|       if (!i830SetTexImages( i830, tObj )) { | ||||
|  | ||||
|  | ||||
|  | ||||
|    { | ||||
|       GLuint minFilt, mipFilt, magFilt; | ||||
|  | ||||
|       switch (tObj->MinFilter) { | ||||
|       case GL_NEAREST: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_NONE; | ||||
| 	 break; | ||||
|       case GL_LINEAR: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_NONE; | ||||
| 	 break; | ||||
|       case GL_NEAREST_MIPMAP_NEAREST: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_LINEAR_MIPMAP_NEAREST: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_NEAREST; | ||||
| 	 break; | ||||
|       case GL_NEAREST_MIPMAP_LINEAR: | ||||
| 	 minFilt = FILTER_NEAREST; | ||||
| 	 mipFilt = MIPFILTER_LINEAR; | ||||
| 	 break; | ||||
|       case GL_LINEAR_MIPMAP_LINEAR: | ||||
| 	 minFilt = FILTER_LINEAR; | ||||
| 	 mipFilt = MIPFILTER_LINEAR; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       if ( tObj->MaxAnisotropy > 1.0 ) { | ||||
| 	 minFilt = FILTER_ANISOTROPIC;  | ||||
| 	 magFilt = FILTER_ANISOTROPIC; | ||||
|       } | ||||
|       else { | ||||
| 	 switch (tObj->MagFilter) { | ||||
| 	 case GL_NEAREST: | ||||
| 	    magFilt = FILTER_NEAREST; | ||||
| 	    break; | ||||
| 	 case GL_LINEAR: | ||||
| 	    magFilt = FILTER_LINEAR; | ||||
| 	    break; | ||||
| 	 default: | ||||
| 	    return GL_FALSE; | ||||
| 	 }   | ||||
|       } | ||||
|  | ||||
|       state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit]; | ||||
|  | ||||
| #if 0  | ||||
|       /* YUV conversion: | ||||
|        */ | ||||
|       if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || | ||||
| 	  firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) | ||||
| 	 state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION; | ||||
| #endif | ||||
|  | ||||
|       state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -  | ||||
| 				    intelObj->firstLevel)*4) << TM0S3_MIN_MIP_SHIFT; | ||||
|  | ||||
|       state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | | ||||
| 				   (mipFilt << TM0S3_MIP_FILTER_SHIFT) | | ||||
| 				   (magFilt << TM0S3_MAG_FILTER_SHIFT)); | ||||
|    } | ||||
|  | ||||
|    /* Update state if this is a different texture object to last | ||||
|     * time. | ||||
|     */ | ||||
|    if (i830->intel.CurrentTexObj[unit] != &t->intel ||  | ||||
|        (t->intel.dirty & I830_UPLOAD_TEX(unit))) { | ||||
|       i830_import_tex_unit( i830, t, unit); | ||||
|    { | ||||
|       GLenum ws = tObj->WrapS; | ||||
|       GLenum wt = tObj->WrapT; | ||||
|        | ||||
|  | ||||
|       /* 3D textures not available on i830 | ||||
|        */ | ||||
|       if (tObj->Target == GL_TEXTURE_3D) | ||||
| 	 return GL_FALSE; | ||||
| 	      | ||||
|       state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | | ||||
| 				MAP_UNIT(unit) | | ||||
| 				ENABLE_TEXCOORD_PARAMS | | ||||
| 				ss3 | | ||||
| 				ENABLE_ADDR_V_CNTL | | ||||
| 				TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt)) | | ||||
| 				ENABLE_ADDR_U_CNTL | | ||||
| 				TEXCOORD_ADDR_U_MODE(translate_wrap_mode(ws))); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0], | ||||
| 						  tObj->_BorderChan[1], | ||||
| 						  tObj->_BorderChan[2], | ||||
| 						  tObj->_BorderChan[3]); | ||||
|     | ||||
|  | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS]; | ||||
|  | ||||
|    mcs &= ~TEXCOORDS_ARE_NORMAL; | ||||
|    mcs |= TEXCOORDS_ARE_IN_TEXELUNITS; | ||||
|  | ||||
|    if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) | ||||
|        || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) { | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_MCS] = mcs; | ||||
|       i830->state.Tex[unit][I830_TEXREG_CUBE] = 0; | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS]; | ||||
|  | ||||
|    mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS; | ||||
|    mcs |= TEXCOORDS_ARE_NORMAL; | ||||
|  | ||||
|    if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) | ||||
|        || (0 != i830->state.Tex[unit][I830_TEXREG_CUBE])) { | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_MCS] = mcs; | ||||
|       i830->state.Tex[unit][I830_TEXREG_CUBE] = 0; | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|   | ||||
| static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; | ||||
|    struct gl_texture_object *tObj = texUnit->_Current; | ||||
|    i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; | ||||
|    GLuint mcs = i830->state.Tex[unit][I830_TEXREG_MCS]; | ||||
|    const GLuint cube = CUBE_NEGX_ENABLE | CUBE_POSX_ENABLE | ||||
|      | CUBE_NEGY_ENABLE | CUBE_POSY_ENABLE | ||||
|      | CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE; | ||||
|    GLuint face; | ||||
|  | ||||
|    mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS; | ||||
|    mcs |= TEXCOORDS_ARE_NORMAL; | ||||
|  | ||||
|    if ((mcs != i830->state.Tex[unit][I830_TEXREG_MCS]) | ||||
|        || (cube != i830->state.Tex[unit][I830_TEXREG_CUBE])) { | ||||
|       I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); | ||||
|       i830->state.Tex[unit][I830_TEXREG_MCS] = mcs; | ||||
|       i830->state.Tex[unit][I830_TEXREG_CUBE] = cube; | ||||
|    } | ||||
|  | ||||
|    /* Upload teximages (not pipelined) | ||||
|    /* memcmp was already disabled, but definitely won't work as the | ||||
|     * region might now change and that wouldn't be detected: | ||||
|     */ | ||||
|    if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] || | ||||
|         t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] || | ||||
|         t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) { | ||||
|       i830SetTexImages( i830, tObj ); | ||||
|    } | ||||
|    I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) ); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|    /* upload (per face) */ | ||||
|    for (face = 0; face < 6; face++) { | ||||
|       if (t->intel.base.dirty_images[face]) { | ||||
| 	 if (!intelUploadTexImages( &i830->intel, &t->intel, face )) { | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
|  | ||||
|  | ||||
|  | ||||
| void i830UpdateTextureState( struct intel_context *intel ) | ||||
| { | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    GLboolean ok = GL_TRUE; | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0 ; i < I830_TEX_UNITS && ok ; i++) { | ||||
|       switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) { | ||||
|       case TEXTURE_1D_BIT: | ||||
|       case TEXTURE_2D_BIT: | ||||
|       case TEXTURE_CUBE_BIT: | ||||
| 	 ok = i830_update_tex_unit( intel, i, TEXCOORDS_ARE_NORMAL ); | ||||
| 	 break; | ||||
|       case TEXTURE_RECT_BIT: | ||||
| 	 ok = i830_update_tex_unit( intel, i, TEXCOORDS_ARE_IN_TEXELUNITS ); | ||||
| 	 break; | ||||
|       case 0:  | ||||
| 	 if (i830->state.active & I830_UPLOAD_TEX(i))  | ||||
| 	    I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), GL_FALSE); | ||||
| 	 break; | ||||
|       case TEXTURE_3D_BIT: | ||||
|       default: | ||||
| 	 ok = GL_FALSE; | ||||
| 	 break; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean disable_tex( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(ctx); | ||||
|  | ||||
|    /* This is happening too often.  I need to conditionally send diffuse | ||||
|     * state to the card.  Perhaps a diffuse dirty flag of some kind. | ||||
|     * Will need to change this logic if more than 2 texture units are | ||||
|     * used.  We need to only do this up to the last unit enabled, or unit | ||||
|     * one if nothing is enabled. | ||||
|     */ | ||||
|  | ||||
|    if ( i830->intel.CurrentTexObj[unit] != NULL ) { | ||||
|       /* The old texture is no longer bound to this texture unit. | ||||
|        * Mark it as such. | ||||
|        */ | ||||
|  | ||||
|       i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0); | ||||
|       i830->intel.CurrentTexObj[unit] = NULL; | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; | ||||
|  | ||||
|    if (texUnit->_ReallyEnabled && | ||||
|        INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    switch(texUnit->_ReallyEnabled) { | ||||
|    case TEXTURE_1D_BIT: | ||||
|    case TEXTURE_2D_BIT: | ||||
|       return (enable_tex_common( ctx, unit ) && | ||||
| 	      enable_tex_2d( ctx, unit )); | ||||
|    case TEXTURE_RECT_BIT: | ||||
|       return (enable_tex_common( ctx, unit ) && | ||||
| 	      enable_tex_rect( ctx, unit )); | ||||
|    case TEXTURE_CUBE_BIT: | ||||
|       return (enable_tex_common( ctx, unit ) && | ||||
| 	      enable_tex_cube( ctx, unit )); | ||||
|    case 0: | ||||
|       return disable_tex( ctx, unit ); | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void i830UpdateTextureState( intelContextPtr intel ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLboolean ok; | ||||
|  | ||||
|    if (0) fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    I830_ACTIVESTATE(i830, I830_UPLOAD_TEX_ALL, GL_FALSE); | ||||
|  | ||||
|    ok = (i830UpdateTexUnit( ctx, 0 ) && | ||||
| 	 i830UpdateTexUnit( ctx, 1 ) && | ||||
| 	 i830UpdateTexUnit( ctx, 2 ) && | ||||
| 	 i830UpdateTexUnit( ctx, 3 )); | ||||
|  | ||||
|    FALLBACK( intel, I830_FALLBACK_TEXTURE, !ok ); | ||||
|  | ||||
|    if (ok) | ||||
| @@ -481,3 +314,8 @@ void i830UpdateTextureState( intelContextPtr intel ) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -30,11 +30,12 @@ | ||||
| #include "i830_reg.h" | ||||
|  | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "tnl/t_context.h" | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
| static GLboolean i830_check_vertex_size( struct intel_context *intel, | ||||
| 					 GLuint expected ); | ||||
|  | ||||
| #define SZ_TO_HW(sz)  ((sz-2)&0x3) | ||||
| @@ -59,10 +60,10 @@ do {									\ | ||||
| #define VRTX_TEX_SET_FMT(n, x)          ((x)<<((n)*2)) | ||||
| #define TEXBIND_SET(n, x) 		((x)<<((n)*4)) | ||||
|  | ||||
| static void i830_render_start( intelContextPtr intel ) | ||||
| static void i830_render_start( struct intel_context *intel ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|    GLuint index = tnl->render_inputs; | ||||
| @@ -163,6 +164,7 @@ static void i830_render_start( intelContextPtr intel ) | ||||
|        v2 != i830->state.Ctx[I830_CTXREG_VF2] || | ||||
|        mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] || | ||||
|        index != i830->last_index) { | ||||
|       int k; | ||||
|      | ||||
|       I830_STATECHANGE( i830, I830_UPLOAD_CTX ); | ||||
|  | ||||
| @@ -182,14 +184,15 @@ static void i830_render_start( intelContextPtr intel ) | ||||
|       i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1; | ||||
|       i830->last_index = index; | ||||
|  | ||||
|       assert(i830_check_vertex_size( intel, intel->vertex_size )); | ||||
|       k = i830_check_vertex_size( intel, intel->vertex_size ); | ||||
|       assert(k); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void i830_reduced_primitive_state( intelContextPtr intel, | ||||
| static void i830_reduced_primitive_state( struct intel_context *intel, | ||||
| 					  GLenum rprim ) | ||||
| { | ||||
|     i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|     struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|     GLuint st1 = i830->state.Stipple[I830_STPREG_ST1]; | ||||
|  | ||||
|     st1 &= ~ST1_ENABLE; | ||||
| @@ -217,10 +220,10 @@ static void i830_reduced_primitive_state( intelContextPtr intel, | ||||
| /* Pull apart the vertex format registers and figure out how large a | ||||
|  * vertex is supposed to be.  | ||||
|  */ | ||||
| static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
| static GLboolean i830_check_vertex_size( struct intel_context *intel, | ||||
| 					 GLuint expected ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    int vft0 = i830->current->Ctx[I830_CTXREG_VF]; | ||||
|    int vft1 = i830->current->Ctx[I830_CTXREG_VF2]; | ||||
|    int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT; | ||||
| @@ -257,16 +260,11 @@ static GLboolean i830_check_vertex_size( intelContextPtr intel, | ||||
|    return sz == expected; | ||||
| } | ||||
|  | ||||
| static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
| static void i830_emit_invarient_state( struct intel_context *intel ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH( 200 ); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(0)); | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(1)); | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(2)); | ||||
|    OUT_BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(3)); | ||||
|    BEGIN_BATCH(200, 0); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); | ||||
|    OUT_BATCH(0); | ||||
| @@ -330,13 +328,6 @@ static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
| 	     TRI_FAN_PROVOKE_VRTX(2) |  | ||||
| 	     TRI_STRIP_PROVOKE_VRTX(2)); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD |  | ||||
| 	     DISABLE_SCISSOR_RECT); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); | ||||
|    OUT_BATCH(0); | ||||
|    OUT_BATCH(0); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM); | ||||
|    OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE); | ||||
|  | ||||
| @@ -355,18 +346,20 @@ static void i830_emit_invarient_state( intelContextPtr intel ) | ||||
| #define emit( intel, state, size )			\ | ||||
| do {							\ | ||||
|    int k;						\ | ||||
|    BEGIN_BATCH( size / sizeof(GLuint));			\ | ||||
|    for (k = 0 ; k < size / sizeof(GLuint) ; k++)	\ | ||||
|    BEGIN_BATCH(size / sizeof(GLuint), 0);		\ | ||||
|    for (k = 0 ; k < size / sizeof(GLuint) ; k++) {	\ | ||||
|       if (0) _mesa_printf("  0x%08x\n", state[k]);		\ | ||||
|       OUT_BATCH(state[k]);				\ | ||||
|    }							\ | ||||
|    ADVANCE_BATCH();					\ | ||||
| } while (0); | ||||
| } while (0) | ||||
|  | ||||
|  | ||||
| /* Push the state into the sarea and/or texture memory. | ||||
|  */ | ||||
| static void i830_emit_state( intelContextPtr intel ) | ||||
| static void i830_emit_state( struct intel_context *intel ) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    struct i830_hw_state *state = i830->current; | ||||
|    int i; | ||||
|    GLuint dirty; | ||||
| @@ -374,29 +367,79 @@ static void i830_emit_state( intelContextPtr intel ) | ||||
|  | ||||
|    dirty = state->active & ~state->emitted; | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_INVARIENT) { | ||||
|       if (INTEL_DEBUG & DEBUG_STATE)  | ||||
| 	 fprintf(stderr, "I830_UPLOAD_INVARIENT:\n");  | ||||
|       i830_emit_invarient_state( intel ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_CTX) { | ||||
|       if (VERBOSE) fprintf(stderr, "I830_UPLOAD_CTX:\n");  | ||||
|       if (INTEL_DEBUG & DEBUG_STATE)  | ||||
| 	 fprintf(stderr, "I830_UPLOAD_CTX:\n");  | ||||
|       emit( i830, state->Ctx, sizeof(state->Ctx) ); | ||||
|  | ||||
|    } | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_BUFFERS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");  | ||||
|       emit( i830, state->Buffer, sizeof(state->Buffer) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE)  | ||||
| 	 fprintf(stderr, "I830_UPLOAD_BUFFERS:\n");  | ||||
|       BEGIN_BATCH(I830_DEST_SETUP_SIZE+2, 0); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]); | ||||
|       OUT_RELOC(state->draw_region->buffer, DRM_MM_TT|DRM_MM_WRITE, 0); | ||||
|  | ||||
|       if (state->depth_region) { | ||||
| 	 OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]); | ||||
| 	 OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]); | ||||
| 	 OUT_RELOC(state->depth_region->buffer, DRM_MM_TT |DRM_MM_WRITE, 0); | ||||
|       } | ||||
|  | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_DV0]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_DV1]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SENABLE]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SR0]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SR1]); | ||||
|       OUT_BATCH(state->Buffer[I830_DESTREG_SR2]); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I830_UPLOAD_STIPPLE) { | ||||
|       if (VERBOSE) fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");  | ||||
|       if (INTEL_DEBUG & DEBUG_STATE)  | ||||
| 	 fprintf(stderr, "I830_UPLOAD_STIPPLE:\n");  | ||||
|       emit( i830, state->Stipple, sizeof(state->Stipple) ); | ||||
|    } | ||||
|  | ||||
|    for (i = 0; i < I830_TEX_UNITS; i++) { | ||||
|       if ((dirty & I830_UPLOAD_TEX(i))) {  | ||||
|  	 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);  | ||||
| 	 emit( i830, state->Tex[i], sizeof(state->Tex[i]));  | ||||
|  	 if (INTEL_DEBUG & DEBUG_STATE) | ||||
| 	    fprintf(stderr, "I830_UPLOAD_TEX(%d):\n", i);  | ||||
|  | ||||
| 	 BEGIN_BATCH(I830_TEX_SETUP_SIZE+1, 0); | ||||
| 	 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0LI]); | ||||
|  | ||||
| 	 if (state->tex_buffer[i]) { | ||||
| 	    OUT_RELOC(state->tex_buffer[i], | ||||
| 		      DRM_MM_TT|DRM_MM_READ, | ||||
| 		      state->tex_offset[i] | TM0S0_USE_FENCE); | ||||
| 	 } | ||||
| 	 else { | ||||
| 	    assert(i == 0); | ||||
| 	    assert(state == &i830->meta); | ||||
| 	    OUT_BATCH(0); | ||||
| 	 } | ||||
|  | ||||
| 	 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S1]); | ||||
| 	 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S2]); | ||||
| 	 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S3]); | ||||
| 	 OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]); | ||||
| 	 OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]); | ||||
| 	 OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]); | ||||
|       }  | ||||
|  | ||||
|       if (dirty & I830_UPLOAD_TEXBLEND(i)) { | ||||
| 	 if (VERBOSE) fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d):\n", i);  | ||||
| 	 if (INTEL_DEBUG & DEBUG_STATE)  | ||||
| 	    fprintf(stderr, "I830_UPLOAD_TEXBLEND(%d): %d words\n", i, | ||||
| 		    state->TexBlendWordsUsed[i]);  | ||||
| 	 emit( i830, state->TexBlend[i],  | ||||
| 	       state->TexBlendWordsUsed[i] * 4 ); | ||||
|       } | ||||
| @@ -405,52 +448,54 @@ static void i830_emit_state( intelContextPtr intel ) | ||||
|    state->emitted |= dirty; | ||||
| } | ||||
|  | ||||
| static void i830_destroy_context( intelContextPtr intel ) | ||||
| static void i830_destroy_context( struct intel_context *intel ) | ||||
| { | ||||
|    _tnl_free_vertices(&intel->ctx); | ||||
| } | ||||
|  | ||||
| static void i830_set_draw_offset( intelContextPtr intel, int offset ) | ||||
| static void i830_set_draw_region( struct intel_context *intel,  | ||||
| 				  struct intel_region *draw_region, | ||||
| 				  struct intel_region *depth_region) | ||||
| { | ||||
|    i830ContextPtr i830 = I830_CONTEXT(intel); | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|  | ||||
|    intel_region_release(intel, &i830->state.draw_region); | ||||
|    intel_region_release(intel, &i830->state.depth_region); | ||||
|    intel_region_reference(&i830->state.draw_region, draw_region); | ||||
|    intel_region_reference(&i830->state.depth_region, depth_region); | ||||
|  | ||||
|    /* XXX FBO: Need code from i915_set_draw_region() */ | ||||
|  | ||||
|    I830_STATECHANGE( i830, I830_UPLOAD_BUFFERS ); | ||||
|    i830->state.Buffer[I830_DESTREG_CBUFADDR2] = offset; | ||||
| } | ||||
|  | ||||
| /* This isn't really handled at the moment. | ||||
|  */ | ||||
| static void i830_lost_hardware( intelContextPtr intel ) | ||||
| static void i830_lost_hardware( struct intel_context *intel ) | ||||
| { | ||||
|    I830_CONTEXT(intel)->state.emitted = 0; | ||||
|    struct i830_context *i830 = i830_context(&intel->ctx); | ||||
|    i830->state.emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void i830_emit_flush( intelContextPtr intel ) | ||||
| static GLuint i830_flush_cmd( void ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH(2); | ||||
|    OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE );  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
|    return MI_FLUSH | FLUSH_MAP_CACHE;  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void i830InitVtbl( i830ContextPtr i830 ) | ||||
| void i830InitVtbl( struct i830_context *i830 ) | ||||
| { | ||||
|    i830->intel.vtbl.alloc_tex_obj = i830AllocTexObj; | ||||
|    i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; | ||||
|    i830->intel.vtbl.clear_with_tris = i830ClearWithTris; | ||||
|    i830->intel.vtbl.destroy = i830_destroy_context; | ||||
|    i830->intel.vtbl.emit_invarient_state = i830_emit_invarient_state; | ||||
|    i830->intel.vtbl.emit_state = i830_emit_state; | ||||
|    i830->intel.vtbl.lost_hardware = i830_lost_hardware; | ||||
|    i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state; | ||||
|    i830->intel.vtbl.set_draw_offset = i830_set_draw_offset; | ||||
|    i830->intel.vtbl.set_draw_region = i830_set_draw_region; | ||||
|    i830->intel.vtbl.update_texture_state = i830UpdateTextureState; | ||||
|    i830->intel.vtbl.emit_flush = i830_emit_flush; | ||||
|    i830->intel.vtbl.flush_cmd = i830_flush_cmd; | ||||
|    i830->intel.vtbl.render_start = i830_render_start; | ||||
| } | ||||
|   | ||||
| @@ -41,6 +41,10 @@ | ||||
| #include "utils.h" | ||||
| #include "i915_reg.h" | ||||
|  | ||||
| #include "intel_bufmgr.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| /*************************************** | ||||
|  * Mesa's Driver Functions | ||||
|  ***************************************/ | ||||
| @@ -65,7 +69,7 @@ static void i915InvalidateState( GLcontext *ctx, GLuint new_state ) | ||||
|    _ac_InvalidateState( ctx, new_state ); | ||||
|    _tnl_InvalidateState( ctx, new_state ); | ||||
|    _tnl_invalidate_vertex_state( ctx, new_state ); | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= new_state; | ||||
|    intel_context(ctx)->NewGLState |= new_state; | ||||
|  | ||||
|    /* Todo: gather state values under which tracked parameters become | ||||
|     * invalidated, add callbacks for things like | ||||
| @@ -99,13 +103,16 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
| 			    void *sharedContextPrivate) | ||||
| { | ||||
|    struct dd_function_table functions; | ||||
|    i915ContextPtr i915 = (i915ContextPtr) CALLOC_STRUCT(i915_context); | ||||
|    intelContextPtr intel = &i915->intel; | ||||
|    struct i915_context *i915 = (struct i915_context *) CALLOC_STRUCT(i915_context); | ||||
|    struct intel_context *intel = &i915->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|    if (!i915) return GL_FALSE; | ||||
|  | ||||
|    _mesa_printf( "\ntexmem branch (i915, drop3)\n\n"); | ||||
|     | ||||
|    i915InitVtbl( i915 ); | ||||
|    i915InitMetaFuncs( i915 ); | ||||
|  | ||||
|    i915InitDriverFunctions( &functions ); | ||||
|  | ||||
| @@ -119,48 +126,28 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
|    ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS; | ||||
|    ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS; | ||||
|  | ||||
|    intel->nr_heaps = 1; | ||||
|    intel->texture_heaps[0] =  | ||||
|       driCreateTextureHeap( 0, intel, | ||||
| 			    intel->intelScreen->tex.size, | ||||
| 			    12, | ||||
| 			    I830_NR_TEX_REGIONS, | ||||
| 			    intel->sarea->texList, | ||||
| 			    & intel->sarea->texAge, | ||||
| 			    & intel->swapped, | ||||
| 			    sizeof( struct i915_texture_object ), | ||||
| 			    (destroy_texture_object_t *)intelDestroyTexObj ); | ||||
|  | ||||
|    /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are | ||||
|     * tightly packed, but they're not in Intel graphics | ||||
|     * hardware. | ||||
|    /* Advertise the full hardware capabilities.  The new memory | ||||
|     * manager should cope much better with overload situations: | ||||
|     */ | ||||
|    ctx->Const.MaxTextureUnits = 1; | ||||
|    driCalculateMaxTextureLevels( intel->texture_heaps, | ||||
| 				 intel->nr_heaps, | ||||
| 				 &intel->ctx.Const, | ||||
| 				 4, | ||||
| 				 11, /* max 2D texture size is 2048x2048 */ | ||||
| 				 8,  /* 3D texture */ | ||||
| 				 11, /* cube texture. */ | ||||
| 				 11, /* rect texture */ | ||||
| 				 12, | ||||
| 				 GL_FALSE ); | ||||
|    ctx->Const.MaxTextureLevels = 12; | ||||
|    ctx->Const.Max3DTextureLevels = 9; | ||||
|    ctx->Const.MaxCubeTextureLevels = 12; | ||||
|    ctx->Const.MaxTextureRectSize = (1<<11); | ||||
|    ctx->Const.MaxTextureUnits = I915_TEX_UNITS; | ||||
|  | ||||
|    /* GL_ARB_fragment_program limits - don't think Mesa actually | ||||
|     * validates programs against these, and in any case one ARB | ||||
|     * instruction can translate to more than one HW instruction, so | ||||
|     * we'll still have to check and fallback each time. | ||||
|     */ | ||||
|     | ||||
|     */    | ||||
|    ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */ | ||||
|    ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN; | ||||
|    ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN; | ||||
|    ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN +  | ||||
| 						I915_MAX_TEX_INSN); | ||||
| 						       I915_MAX_TEX_INSN); | ||||
|    ctx->Const.FragmentProgram.MaxNativeTexIndirections = I915_MAX_TEX_INDIRECT; | ||||
|    ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */ | ||||
|  | ||||
|   | ||||
| @@ -43,6 +43,8 @@ | ||||
| #define I915_UPLOAD_PROGRAM          0x8 | ||||
| #define I915_UPLOAD_CONSTANTS        0x10 | ||||
| #define I915_UPLOAD_FOG              0x20 | ||||
| #define I915_UPLOAD_INVARIENT        0x40 | ||||
| #define I915_UPLOAD_DEFAULTS         0x80 | ||||
| #define I915_UPLOAD_TEX(i)           (0x00010000<<(i)) | ||||
| #define I915_UPLOAD_TEX_ALL          (0x00ff0000) | ||||
| #define I915_UPLOAD_TEX_0_SHIFT      16 | ||||
| @@ -52,10 +54,8 @@ | ||||
|  */ | ||||
| #define I915_DESTREG_CBUFADDR0 0 | ||||
| #define I915_DESTREG_CBUFADDR1 1 | ||||
| #define I915_DESTREG_CBUFADDR2 2 | ||||
| #define I915_DESTREG_DBUFADDR0 3 | ||||
| #define I915_DESTREG_DBUFADDR1 4 | ||||
| #define I915_DESTREG_DBUFADDR2 5 | ||||
| #define I915_DESTREG_DV0 6 | ||||
| #define I915_DESTREG_DV1 7 | ||||
| #define I915_DESTREG_SENABLE 8 | ||||
| @@ -86,7 +86,6 @@ | ||||
| #define I915_STPREG_ST1        1 | ||||
| #define I915_STP_SETUP_SIZE    2 | ||||
|  | ||||
| #define I915_TEXREG_MS2        0 | ||||
| #define I915_TEXREG_MS3        1 | ||||
| #define I915_TEXREG_MS4        2 | ||||
| #define I915_TEXREG_SS2        3 | ||||
| @@ -94,6 +93,15 @@ | ||||
| #define I915_TEXREG_SS4        5 | ||||
| #define I915_TEX_SETUP_SIZE    6 | ||||
|  | ||||
| #define I915_DEFREG_C0    0 | ||||
| #define I915_DEFREG_C1    1 | ||||
| #define I915_DEFREG_S0    2 | ||||
| #define I915_DEFREG_S1    3 | ||||
| #define I915_DEFREG_Z0    4 | ||||
| #define I915_DEFREG_Z1    5 | ||||
| #define I915_DEF_SETUP_SIZE    6 | ||||
|  | ||||
|  | ||||
| #define I915_MAX_CONSTANT      32 | ||||
| #define I915_CONSTANT_SIZE     (2+(4*I915_MAX_CONSTANT)) | ||||
|  | ||||
| @@ -163,8 +171,6 @@ struct i915_fragment_program { | ||||
|    GLuint nr_params; | ||||
|        | ||||
|  | ||||
|  | ||||
|  | ||||
|    /* Helpers for i915_texprog.c: | ||||
|     */ | ||||
|    GLuint src_texture;		/* Reg containing sampled texture color, | ||||
| @@ -185,13 +191,6 @@ struct i915_fragment_program { | ||||
|  | ||||
|  | ||||
|  | ||||
| struct i915_texture_object | ||||
| { | ||||
|    struct intel_texture_object intel; | ||||
|    GLenum lastTarget; | ||||
|    GLboolean refs_border_color; | ||||
|    GLuint Setup[I915_TEX_SETUP_SIZE]; | ||||
| }; | ||||
|  | ||||
| #define I915_TEX_UNITS 8 | ||||
|  | ||||
| @@ -201,11 +200,27 @@ struct i915_hw_state { | ||||
|    GLuint Buffer[I915_DEST_SETUP_SIZE]; | ||||
|    GLuint Stipple[I915_STP_SETUP_SIZE]; | ||||
|    GLuint Fog[I915_FOG_SETUP_SIZE]; | ||||
|    GLuint Defaults[I915_DEF_SETUP_SIZE]; | ||||
|    GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE]; | ||||
|    GLuint Constant[I915_CONSTANT_SIZE]; | ||||
|    GLuint ConstantSize; | ||||
|    GLuint Program[I915_PROGRAM_SIZE]; | ||||
|    GLuint ProgramSize; | ||||
|     | ||||
|    /* Region pointers for relocation:  | ||||
|     */ | ||||
|    struct intel_region *draw_region; | ||||
|    struct intel_region *depth_region; | ||||
| /*    struct intel_region *tex_region[I915_TEX_UNITS]; */ | ||||
|  | ||||
|    /* Regions aren't actually that appropriate here as the memory may | ||||
|     * be from a PBO or FBO.  Just use the buffer id.  Will have to do | ||||
|     * this for draw and depth for FBO's... | ||||
|     */ | ||||
|    GLuint tex_buffer[I915_TEX_UNITS]; | ||||
|    GLuint tex_offset[I915_TEX_UNITS]; | ||||
|     | ||||
|  | ||||
|    GLuint active;		/* I915_UPLOAD_* */ | ||||
|    GLuint emitted;		/* I915_UPLOAD_* */ | ||||
| }; | ||||
| @@ -220,6 +235,8 @@ struct i915_context | ||||
|  | ||||
|    GLuint last_ReallyEnabled; | ||||
|    GLuint vertex_fog; | ||||
|    GLuint lodbias_ss2[MAX_TEXTURE_UNITS]; | ||||
|  | ||||
|  | ||||
|    struct i915_fragment_program tex_program; | ||||
|    struct i915_fragment_program *current_program; | ||||
| @@ -228,24 +245,14 @@ struct i915_context | ||||
| }; | ||||
|  | ||||
|  | ||||
| typedef struct i915_context *i915ContextPtr; | ||||
| typedef struct i915_texture_object *i915TextureObjectPtr; | ||||
|  | ||||
| #define I915_CONTEXT(ctx)	((i915ContextPtr)(ctx)) | ||||
|  | ||||
|  | ||||
|  | ||||
| #define I915_STATECHANGE(i915, flag)					\ | ||||
| do {									\ | ||||
|    if (0) fprintf(stderr, "I915_STATECHANGE %x in %s\n", flag, __FUNCTION__);	\ | ||||
|    INTEL_FIREVERTICES( &(i915)->intel );					\ | ||||
|    (i915)->state.emitted &= ~(flag);					\ | ||||
| } while (0) | ||||
|  | ||||
| #define I915_ACTIVESTATE(i915, flag, mode)			\ | ||||
| do {								\ | ||||
|    if (0) fprintf(stderr, "I915_ACTIVESTATE %x %d in %s\n",	\ | ||||
| 		  flag, mode, __FUNCTION__);			\ | ||||
|    INTEL_FIREVERTICES( &(i915)->intel );				\ | ||||
|    if (mode)							\ | ||||
|       (i915)->state.active |= (flag);				\ | ||||
| @@ -257,7 +264,13 @@ do {								\ | ||||
| /*====================================================================== | ||||
|  * i915_vtbl.c | ||||
|  */ | ||||
| extern void i915InitVtbl( i915ContextPtr i915 ); | ||||
| extern void i915InitVtbl( struct i915_context *i915 ); | ||||
|  | ||||
| extern void | ||||
| i915_state_draw_region(struct intel_context *intel,  | ||||
|                        struct i915_hw_state *state, | ||||
|                        struct intel_region *color_region, | ||||
|                        struct intel_region *depth_region); | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -294,7 +307,7 @@ extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis, | ||||
| /*====================================================================== | ||||
|  * i915_texprog.c | ||||
|  */ | ||||
| extern void i915ValidateTextureProgram( i915ContextPtr i915 ); | ||||
| extern void i915ValidateTextureProgram( struct i915_context *i915 ); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
| @@ -308,44 +321,43 @@ extern void i915_print_ureg( const char *msg, GLuint ureg ); | ||||
|  * i915_state.c | ||||
|  */ | ||||
| extern void i915InitStateFunctions( struct dd_function_table *functions ); | ||||
| extern void i915InitState( i915ContextPtr i915 ); | ||||
| extern void i915InitState( struct i915_context *i915 ); | ||||
| extern void i915_update_fog( GLcontext *ctx ); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_tex.c | ||||
|  */ | ||||
| extern void i915UpdateTextureState( intelContextPtr intel ); | ||||
| extern void i915UpdateTextureState( struct intel_context *intel ); | ||||
| extern void i915InitTextureFuncs( struct dd_function_table *functions ); | ||||
| extern intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ); | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_metaops.c | ||||
|  */ | ||||
| extern GLboolean | ||||
| i915TryTextureReadPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *pack, | ||||
| 			  GLvoid *pixels ); | ||||
|  | ||||
| extern GLboolean | ||||
| i915TryTextureDrawPixels( GLcontext *ctx, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLenum format, GLenum type, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  const GLvoid *pixels ); | ||||
|  | ||||
| extern void  | ||||
| i915ClearWithTris( intelContextPtr intel, GLbitfield mask, | ||||
| 		   GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch); | ||||
| void i915InitMetaFuncs( struct i915_context *i915 ); | ||||
|  | ||||
|  | ||||
| /*====================================================================== | ||||
|  * i915_fragprog.c | ||||
|  */ | ||||
| extern void i915ValidateFragmentProgram( i915ContextPtr i915 ); | ||||
| extern void i915ValidateFragmentProgram( struct i915_context *i915 ); | ||||
| extern void i915InitFragProgFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.  These are better-typed than the | ||||
|  * macros used previously: | ||||
|  */ | ||||
| static INLINE struct i915_context * | ||||
| i915_context( GLcontext *ctx ) | ||||
| { | ||||
|    return (struct i915_context *)ctx; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #define I915_CONTEXT(ctx)	i915_context(ctx) | ||||
|  | ||||
|  | ||||
| 	 | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -806,7 +806,7 @@ static void check_wpos( struct i915_fragment_program *p ) | ||||
|  | ||||
| static void translate_program( struct i915_fragment_program *p ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(p->ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(p->ctx); | ||||
|     | ||||
|    i915_init_program( i915, p ); | ||||
|    check_wpos( p );  | ||||
| @@ -840,7 +840,7 @@ static void i915BindProgram( GLcontext *ctx, | ||||
| 			    struct program *prog ) | ||||
| { | ||||
|    if (target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *)prog; | ||||
|  | ||||
|       if (i915->current_program == p)  | ||||
| @@ -896,7 +896,7 @@ static void i915DeleteProgram( GLcontext *ctx, | ||||
| 			      struct program *prog ) | ||||
| { | ||||
|    if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) { | ||||
|       i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|       struct i915_fragment_program *p = (struct i915_fragment_program *)prog; | ||||
|        | ||||
|       if (i915->current_program == p)  | ||||
| @@ -940,10 +940,10 @@ static void i915ProgramStringNotify( GLcontext *ctx, | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
| void i915ValidateFragmentProgram( struct i915_context *i915 ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|  | ||||
| @@ -1028,6 +1028,7 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
|  | ||||
|    if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || | ||||
|        s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { | ||||
|       int k; | ||||
|      | ||||
|       I915_STATECHANGE( i915, I915_UPLOAD_CTX ); | ||||
|  | ||||
| @@ -1044,7 +1045,8 @@ void i915ValidateFragmentProgram( i915ContextPtr i915 ) | ||||
|       i915->state.Ctx[I915_CTXREG_LIS2] = s2; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] = s4; | ||||
|  | ||||
|       assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size )); | ||||
|       k = intel->vtbl.check_vertex_size( intel, intel->vertex_size ); | ||||
|       assert(k); | ||||
|    } | ||||
|  | ||||
|    if (!p->params_uptodate)  | ||||
|   | ||||
| @@ -34,44 +34,45 @@ | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i915_context.h" | ||||
| #include "i915_reg.h" | ||||
|  | ||||
| /* A large amount of state doesn't need to be uploaded. | ||||
| /* We touch almost everything: | ||||
|  */ | ||||
| #define ACTIVE (I915_UPLOAD_PROGRAM | 		\ | ||||
| 		I915_UPLOAD_STIPPLE |		\ | ||||
| #define ACTIVE (I915_UPLOAD_INVARIENT | 	\ | ||||
| 		I915_UPLOAD_CTX |		\ | ||||
| 		I915_UPLOAD_BUFFERS |		\ | ||||
| 		I915_UPLOAD_STIPPLE |		\ | ||||
|                 I915_UPLOAD_PROGRAM | 		\ | ||||
|                 I915_UPLOAD_FOG | 		\ | ||||
| 		I915_UPLOAD_TEX(0))		 | ||||
|  | ||||
| #define SET_STATE( i915, STATE )			\ | ||||
| #define SET_STATE( i915, STATE )		\ | ||||
| do {						\ | ||||
|    i915->current->emitted &= ~ACTIVE;		\ | ||||
|    i915->current = &i915->STATE;			\ | ||||
|    i915->current = &i915->STATE;		\ | ||||
|    i915->current->emitted &= ~ACTIVE;		\ | ||||
| } while (0) | ||||
|  | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void set_initial_state( i915ContextPtr i915 ) | ||||
| { | ||||
|    memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) ); | ||||
|    i915->meta.active = ACTIVE; | ||||
|    i915->meta.emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_no_depth_stencil_write( i915ContextPtr i915 ) | ||||
| static void meta_no_stencil_write( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_STENCIL_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |  | ||||
| 				       S5_STENCIL_WRITE_ENABLE); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
| static void meta_no_depth_write( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE | | ||||
| @@ -80,12 +81,33 @@ static void set_no_depth_stencil_write( i915ContextPtr i915 ) | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
| static void meta_depth_replace( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_TRUE ) | ||||
|     * ctx->Driver.DepthMask( ctx, GL_TRUE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] |= (S6_DEPTH_TEST_ENABLE | | ||||
| 					S6_DEPTH_WRITE_ENABLE); | ||||
|  | ||||
|    /* ctx->Driver.DepthFunc( ctx, GL_REPLACE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK; | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] |=  | ||||
|       COMPAREFUNC_ALWAYS << S6_DEPTH_TEST_FUNC_SHIFT; | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Set stencil unit to replace always with the reference value. | ||||
|  */ | ||||
| static void set_stencil_replace( i915ContextPtr i915, | ||||
| static void meta_stencil_replace( struct intel_context *intel, | ||||
| 				 GLuint s_mask, | ||||
| 				 GLuint s_clear) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint op = STENCILOP_REPLACE; | ||||
|    GLuint func = COMPAREFUNC_ALWAYS; | ||||
|  | ||||
| @@ -94,13 +116,6 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |  | ||||
| 				      S5_STENCIL_WRITE_ENABLE); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.Enable( ctx, GL_DEPTH_TEST, GL_FALSE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] &= ~(S6_DEPTH_TEST_ENABLE | | ||||
| 				       S6_DEPTH_WRITE_ENABLE); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.StencilMask( ctx, s_mask ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; | ||||
| @@ -108,7 +123,6 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | | ||||
| 					STENCIL_WRITE_MASK(s_mask)); | ||||
|  | ||||
|  | ||||
|    /* ctx->Driver.StencilOp( ctx, GL_REPLACE, GL_REPLACE, GL_REPLACE ) | ||||
|     */ | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK | | ||||
| @@ -137,8 +151,9 @@ static void set_stencil_replace( i915ContextPtr i915, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
| static void meta_color_mask( struct intel_context *intel, GLboolean state ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    const GLuint mask = (S5_WRITEDISABLE_RED | | ||||
| 			S5_WRITEDISABLE_GREEN | | ||||
| 			S5_WRITEDISABLE_BLUE | | ||||
| @@ -159,6 +174,28 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void meta_import_pixel_state( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    memcpy(i915->meta.Fog, i915->state.Fog, I915_FOG_SETUP_SIZE * 4); | ||||
|     | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS5] = i915->state.Ctx[I915_CTXREG_LIS5]; | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS6] = i915->state.Ctx[I915_CTXREG_LIS6]; | ||||
|    i915->meta.Ctx[I915_CTXREG_STATE4] = i915->state.Ctx[I915_CTXREG_STATE4]; | ||||
|    i915->meta.Ctx[I915_CTXREG_BLENDCOLOR1] = i915->state.Ctx[I915_CTXREG_BLENDCOLOR1]; | ||||
|    i915->meta.Ctx[I915_CTXREG_IAB] = i915->state.Ctx[I915_CTXREG_IAB]; | ||||
|  | ||||
|    i915->meta.Buffer[I915_DESTREG_SENABLE] = i915->state.Buffer[I915_DESTREG_SENABLE]; | ||||
|    i915->meta.Buffer[I915_DESTREG_SR1] = i915->state.Buffer[I915_DESTREG_SR1]; | ||||
|    i915->meta.Buffer[I915_DESTREG_SR2] = i915->state.Buffer[I915_DESTREG_SR2]; | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_FOG; | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #define REG( type, nr ) (((type)<<5)|(nr)) | ||||
|  | ||||
| @@ -210,8 +247,10 @@ static void set_color_mask( i915ContextPtr i915, GLboolean state ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void set_no_texture( i915ContextPtr i915 ) | ||||
| static void meta_no_texture( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    static const GLuint prog[] = { | ||||
|       _3DSTATE_PIXEL_SHADER_PROGRAM, | ||||
|  | ||||
| @@ -240,9 +279,10 @@ static void set_no_texture( i915ContextPtr i915 ) | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_PROGRAM; | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| static void enable_texture_blend_replace( i915ContextPtr i915 ) | ||||
| static void meta_texture_blend_replace( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    static const GLuint prog[] = { | ||||
|       _3DSTATE_PIXEL_SHADER_PROGRAM, | ||||
|  | ||||
| @@ -285,78 +325,126 @@ static void enable_texture_blend_replace( i915ContextPtr i915 ) | ||||
| /* Set up an arbitary piece of memory as a rectangular texture | ||||
|  * (including the front or back buffer). | ||||
|  */ | ||||
| static void set_tex_rect_source( i915ContextPtr i915, | ||||
| 				 GLuint offset, | ||||
| 				 GLuint width,  | ||||
| 				 GLuint height, | ||||
| 				 GLuint pitch, | ||||
| 				 GLuint textureFormat ) | ||||
| static GLboolean meta_tex_rect_source( struct intel_context *intel, | ||||
| 				       GLuint buffer, | ||||
| 				       GLuint offset,  | ||||
| 				       GLuint pitch, | ||||
| 				       GLuint height, | ||||
| 				       GLenum format, | ||||
| 				       GLenum type) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint unit = 0; | ||||
|    GLint numLevels = 1; | ||||
|    GLuint *state = i915->meta.Tex[0]; | ||||
|    GLuint textureFormat; | ||||
|    GLuint cpp; | ||||
|  | ||||
|    pitch *= i915->intel.intelScreen->cpp; | ||||
|    /* A full implementation of this would do the upload through | ||||
|     * glTexImage2d, and get all the conversion operations at that | ||||
|     * point.  We are restricted, but still at least have access to the | ||||
|     * fragment program swizzle. | ||||
|     */ | ||||
|    switch (format) { | ||||
|    case GL_BGRA: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       case GL_UNSIGNED_BYTE: | ||||
| 	 textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888); | ||||
| 	 cpp = 4; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_RGBA: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_INT_8_8_8_8_REV: | ||||
|       case GL_UNSIGNED_BYTE: | ||||
| 	 textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888); | ||||
| 	 cpp = 4; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_BGR: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_SHORT_5_6_5_REV: | ||||
| 	 textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); | ||||
| 	 cpp = 2; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|    case GL_RGB: | ||||
|       switch (type) { | ||||
|       case GL_UNSIGNED_SHORT_5_6_5: | ||||
| 	 textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565); | ||||
| 	 cpp = 2; | ||||
| 	 break; | ||||
|       default: | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       break; | ||||
|  | ||||
| /*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */ | ||||
| /* 	   __FUNCTION__, offset, width, height, pitch, textureFormat ); */ | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if ((pitch * cpp) & 3) { | ||||
|       _mesa_printf("%s: texture is not dword pitch\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
| /*    intel_region_release(intel, &i915->meta.tex_region[0]); */ | ||||
| /*    intel_region_reference(&i915->meta.tex_region[0], region); */ | ||||
|    i915->meta.tex_buffer[0] = buffer; | ||||
|    i915->meta.tex_offset[0] = offset; | ||||
|  | ||||
|    state[I915_TEXREG_MS2] = offset; | ||||
|    state[I915_TEXREG_MS3] = (((height - 1) << MS3_HEIGHT_SHIFT) | | ||||
| 			    ((width - 1) << MS3_WIDTH_SHIFT) | | ||||
| 			    textureFormat | | ||||
| 			    MS3_USE_FENCE_REGS); | ||||
| 			     ((pitch - 1) << MS3_WIDTH_SHIFT) | | ||||
| 			     textureFormat | | ||||
| 			     MS3_USE_FENCE_REGS); | ||||
|  | ||||
|    state[I915_TEXREG_MS4] = ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |  | ||||
| 			    MS4_CUBE_FACE_ENA_MASK | | ||||
| 			    ((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT)); | ||||
|    state[I915_TEXREG_MS4] = (((((pitch * cpp) / 4) - 1) << MS4_PITCH_SHIFT) |  | ||||
| 			     MS4_CUBE_FACE_ENA_MASK | | ||||
| 			     ((((numLevels-1) * 4)) << MS4_MAX_LOD_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS2] = ((FILTER_NEAREST << SS2_MIN_FILTER_SHIFT) | | ||||
| 			    (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | | ||||
| 			    (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT)); | ||||
| 			     (MIPFILTER_NONE << SS2_MIP_FILTER_SHIFT) | | ||||
| 			     (FILTER_NEAREST << SS2_MAG_FILTER_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS3] = ((TEXCOORDMODE_WRAP << SS3_TCX_ADDR_MODE_SHIFT) | | ||||
| 			    (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) | | ||||
| 			    (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) | | ||||
| 			    (unit<<SS3_TEXTUREMAP_INDEX_SHIFT)); | ||||
| 			     (TEXCOORDMODE_WRAP << SS3_TCY_ADDR_MODE_SHIFT) | | ||||
| 			     (TEXCOORDMODE_WRAP << SS3_TCZ_ADDR_MODE_SHIFT) | | ||||
| 			     (unit<<SS3_TEXTUREMAP_INDEX_SHIFT)); | ||||
|  | ||||
|    state[I915_TEXREG_SS4] = 0; | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_TEX(0); | ||||
|    return GL_TRUE; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* Select between front and back draw buffers. | ||||
|  | ||||
| /** | ||||
|  * Set the color and depth drawing region for meta ops. | ||||
|  */ | ||||
| static void set_draw_offset( i915ContextPtr i915, | ||||
| 			     GLuint offset ) | ||||
| static void meta_draw_region( struct intel_context *intel, | ||||
| 			      struct intel_region *color_region, | ||||
| 			      struct intel_region *depth_region ) | ||||
| { | ||||
|    i915->meta.Buffer[I915_DESTREG_CBUFADDR2] = offset; | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    i915_state_draw_region(intel, &i915->meta, color_region, depth_region); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| /* Setup an arbitary draw format, useful for targeting texture or agp | ||||
|  * memory. | ||||
|  */ | ||||
| static void set_draw_format( i915ContextPtr i915, | ||||
| 			     GLuint format, | ||||
| 			     GLuint depth_format) | ||||
| { | ||||
|    i915->meta.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
| 					DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
| 					format | | ||||
| 					LOD_PRECLAMP_OGL | | ||||
| 					TEX_DEFAULT_COLOR_OGL | | ||||
| 					depth_format); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_BUFFERS; | ||||
| /*    fprintf(stderr, "%s: DV1: %x\n",  */ | ||||
| /* 	   __FUNCTION__, i915->meta.Buffer[I915_DESTREG_DV1]); */ | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void set_vertex_format( i915ContextPtr i915 ) | ||||
| static void set_vertex_format( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS2] =  | ||||
|       (S2_TEXCOORD_FMT(0, TEXCOORDFMT_2D) | | ||||
|        S2_TEXCOORD_FMT(1, TEXCOORDFMT_NOT_PRESENT) |  | ||||
| @@ -371,146 +459,52 @@ static void set_vertex_format( i915ContextPtr i915 ) | ||||
|  | ||||
|    i915->meta.Ctx[I915_CTXREG_LIS4] |=  | ||||
|       (S4_VFMT_COLOR | | ||||
|        S4_VFMT_SPEC_FOG | | ||||
|        S4_VFMT_XYZW); | ||||
|        S4_VFMT_XYZ); | ||||
|  | ||||
|    i915->meta.emitted &= ~I915_UPLOAD_CTX; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| static void draw_quad(i915ContextPtr i915,  | ||||
| 		      GLfloat x0, GLfloat x1, | ||||
| 		      GLfloat y0, GLfloat y1,  | ||||
| 		      GLubyte red, GLubyte green, | ||||
| 		      GLubyte blue, GLubyte alpha, | ||||
| 		      GLfloat s0, GLfloat s1, | ||||
| 		      GLfloat t0, GLfloat t1 ) | ||||
|  | ||||
| /* Operations where the 3D engine is decoupled temporarily from the | ||||
|  * current GL state and used for other purposes than simply rendering | ||||
|  * incoming triangles. | ||||
|  */ | ||||
| static void install_meta_state( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint vertex_size = 8; | ||||
|    GLuint *vb = intelEmitInlinePrimitiveLocked( &i915->intel,  | ||||
| 						PRIM3D_TRIFAN,  | ||||
| 						4 * vertex_size, | ||||
| 						vertex_size ); | ||||
|    intelVertex tmp; | ||||
|    int i; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    memcpy(&i915->meta, &i915->initial, sizeof(i915->meta) ); | ||||
|    i915->meta.active = ACTIVE; | ||||
|    i915->meta.emitted = 0; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: %f,%f-%f,%f 0x%x%x%x%x %f,%f-%f,%f\n", | ||||
| 	      __FUNCTION__, | ||||
| 	      x0,y0,x1,y1,red,green,blue,alpha,s0,t0,s1,t1); | ||||
|  | ||||
|  | ||||
|    /* initial vertex, left bottom */ | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.y = y0; | ||||
|    tmp.v.z = 1.0; | ||||
|    tmp.v.w = 1.0;  | ||||
|    tmp.v.color.red = red; | ||||
|    tmp.v.color.green = green; | ||||
|    tmp.v.color.blue = blue; | ||||
|    tmp.v.color.alpha = alpha; | ||||
|    tmp.v.specular.red = 0; | ||||
|    tmp.v.specular.green = 0; | ||||
|    tmp.v.specular.blue = 0; | ||||
|    tmp.v.specular.alpha = 0; | ||||
|    tmp.v.u0 = s0; | ||||
|    tmp.v.v0 = t0; | ||||
|  | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right bottom */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.x = x1; | ||||
|    tmp.v.u0 = s1; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* right top */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.y = y1; | ||||
|    tmp.v.v0 = t1; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|  | ||||
|    /* left top */ | ||||
|    vb += vertex_size; | ||||
|    tmp.v.x = x0; | ||||
|    tmp.v.u0 = s0; | ||||
|    for (i = 0 ; i < vertex_size ; i++) | ||||
|       vb[i] = tmp.ui[i]; | ||||
|    SET_STATE(i915, meta); | ||||
|    set_vertex_format(intel); | ||||
|    meta_no_texture(intel); | ||||
| } | ||||
|  | ||||
| void  | ||||
| i915ClearWithTris(intelContextPtr intel, GLbitfield mask, | ||||
| 		  GLboolean all, | ||||
| 		  GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| static void leave_meta_state( struct intel_context *intel ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( intel ); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    int x0, y0, x1, y1; | ||||
|  | ||||
|    SET_STATE( i915, meta );  | ||||
|    set_initial_state( i915 );  | ||||
|    set_no_texture( i915 );  | ||||
|    set_vertex_format( i915 );  | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    if(!all) { | ||||
|       x0 = cx; | ||||
|       y0 = cy; | ||||
|       x1 = x0 + cw; | ||||
|       y1 = y0 + ch; | ||||
|    } else { | ||||
|       x0 = 0; | ||||
|       y0 = 0; | ||||
|       x1 = x0 + dPriv->w; | ||||
|       y1 = y0 + dPriv->h; | ||||
|    } | ||||
|  | ||||
|    /* Don't do any clipping to screen - these are window coordinates. | ||||
|     * The active cliprects will be applied as for any other geometry. | ||||
|     */ | ||||
|  | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) {  | ||||
|       set_no_depth_stencil_write( i915 ); | ||||
|       set_color_mask( i915, GL_TRUE ); | ||||
|       set_draw_offset( i915, screen->front.offset ); | ||||
|  | ||||
|       draw_quad(i915, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green,  | ||||
|  		intel->clear_blue, intel->clear_alpha,  | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       set_no_depth_stencil_write( i915 ); | ||||
|       set_color_mask( i915, GL_TRUE ); | ||||
|       set_draw_offset( i915, screen->back.offset ); | ||||
|  | ||||
|       draw_quad(i915, x0, x1, y0, y1, | ||||
| 		intel->clear_red, intel->clear_green, | ||||
| 		intel->clear_blue, intel->clear_alpha, | ||||
| 		0, 0, 0, 0); | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       set_stencil_replace( i915,  | ||||
| 			   intel->ctx.Stencil.WriteMask[0],  | ||||
| 			   intel->ctx.Stencil.Clear); | ||||
|        | ||||
|       set_color_mask( i915, GL_FALSE ); | ||||
|       set_draw_offset( i915, screen->front.offset ); /* could be either? */ | ||||
|  | ||||
|       draw_quad( i915, x0, x1, y0, y1, 0, 0, 0, 0, 0, 0, 0, 0 ); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
|    SET_STATE( i915, state ); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    intel_region_release(intel, &i915->meta.draw_region); | ||||
|    intel_region_release(intel, &i915->meta.depth_region); | ||||
| /*    intel_region_release(intel, &i915->meta.tex_region[0]); */ | ||||
|    SET_STATE(i915, state); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void i915InitMetaFuncs( struct i915_context *i915 ) | ||||
| { | ||||
|    i915->intel.vtbl.install_meta_state = install_meta_state; | ||||
|    i915->intel.vtbl.leave_meta_state = leave_meta_state; | ||||
|    i915->intel.vtbl.meta_no_depth_write = meta_no_depth_write; | ||||
|    i915->intel.vtbl.meta_no_stencil_write = meta_no_stencil_write; | ||||
|    i915->intel.vtbl.meta_stencil_replace = meta_stencil_replace; | ||||
|    i915->intel.vtbl.meta_depth_replace = meta_depth_replace; | ||||
|    i915->intel.vtbl.meta_color_mask = meta_color_mask; | ||||
|    i915->intel.vtbl.meta_no_texture = meta_no_texture; | ||||
|    i915->intel.vtbl.meta_texture_blend_replace = meta_texture_blend_replace; | ||||
|    i915->intel.vtbl.meta_tex_rect_source = meta_tex_rect_source; | ||||
|    i915->intel.vtbl.meta_draw_region = meta_draw_region; | ||||
|    i915->intel.vtbl.meta_import_pixel_state = meta_import_pixel_state; | ||||
| } | ||||
|   | ||||
| @@ -144,7 +144,8 @@ GLuint i915_emit_arith( struct i915_fragment_program *p, | ||||
|    GLuint nr_const = 0; | ||||
|  | ||||
|    assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); | ||||
|    assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); | ||||
|    dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); | ||||
|    assert(dest); | ||||
|  | ||||
|    if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) c[nr_const++] = 0; | ||||
|    if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) c[nr_const++] = 1; | ||||
| @@ -202,7 +203,8 @@ GLuint i915_emit_texld( struct i915_fragment_program *p, | ||||
| 			  GLuint op ) | ||||
| { | ||||
|    assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); | ||||
|    assert(dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); | ||||
|    dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); | ||||
|    assert(dest); | ||||
|  | ||||
|    if (GET_UREG_TYPE(coord) != REG_TYPE_T) { | ||||
|       p->nr_tex_indirect++; | ||||
| @@ -358,7 +360,7 @@ void i915_program_error( struct i915_fragment_program *p, const char *msg ) | ||||
|    p->error = 1; | ||||
| } | ||||
|  | ||||
| void i915_init_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
| void i915_init_program( struct i915_context *i915, struct i915_fragment_program *p ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT( ctx ); | ||||
| @@ -431,7 +433,7 @@ void i915_fini_program( struct i915_fragment_program *p ) | ||||
|    p->declarations[0] |= program_size + decl_size - 2; | ||||
| } | ||||
|  | ||||
| void i915_upload_program( i915ContextPtr i915, struct i915_fragment_program *p ) | ||||
| void i915_upload_program( struct i915_context *i915, struct i915_fragment_program *p ) | ||||
| { | ||||
|    GLuint program_size = p->csr - p->program; | ||||
|    GLuint decl_size = p->decl - p->declarations; | ||||
|   | ||||
| @@ -84,7 +84,7 @@ | ||||
|  | ||||
| /* One neat thing about the UREG representation:   | ||||
|  */ | ||||
| static __inline int swizzle( int reg, int x, int y, int z, int w ) | ||||
| static INLINE int swizzle( int reg, int x, int y, int z, int w ) | ||||
| { | ||||
|    return ((reg & ~UREG_XYZW_CHANNEL_MASK) | | ||||
| 	   CHANNEL_SRC( GET_CHANNEL_SRC( reg, x ), 0 ) | | ||||
| @@ -95,7 +95,7 @@ static __inline int swizzle( int reg, int x, int y, int z, int w ) | ||||
|  | ||||
| /* Another neat thing about the UREG representation:   | ||||
|  */ | ||||
| static __inline int negate( int reg, int x, int y, int z, int w ) | ||||
| static INLINE int negate( int reg, int x, int y, int z, int w ) | ||||
| { | ||||
|    return reg ^ (((x&1)<<UREG_CHANNEL_X_NEGATE_SHIFT)| | ||||
| 		 ((y&1)<<UREG_CHANNEL_Y_NEGATE_SHIFT)| | ||||
| @@ -149,10 +149,10 @@ extern GLuint i915_emit_param4fv( struct i915_fragment_program *p, | ||||
| extern void i915_program_error( struct i915_fragment_program *p, | ||||
|                                 const char *msg ); | ||||
|  | ||||
| extern void i915_init_program( i915ContextPtr i915, | ||||
| extern void i915_init_program( struct i915_context *i915, | ||||
| 			      struct i915_fragment_program *p ); | ||||
|  | ||||
| extern void i915_upload_program( i915ContextPtr i915,  | ||||
| extern void i915_upload_program( struct i915_context *i915,  | ||||
| 				struct i915_fragment_program *p ); | ||||
|  | ||||
| extern void i915_fini_program( struct i915_fragment_program *p ); | ||||
|   | ||||
| @@ -435,10 +435,10 @@ | ||||
| #define LOGICOP_MASK			(0xf<<18) | ||||
| #define MODE4_ENABLE_STENCIL_TEST_MASK	((1<<17)|(0xff00)) | ||||
| #define ENABLE_STENCIL_TEST_MASK	(1<<17) | ||||
| #define STENCIL_TEST_MASK(x)		((x)<<8) | ||||
| #define STENCIL_TEST_MASK(x)		(((x)&0xff)<<8) | ||||
| #define MODE4_ENABLE_STENCIL_WRITE_MASK	((1<<16)|(0x00ff)) | ||||
| #define ENABLE_STENCIL_WRITE_MASK	(1<<16) | ||||
| #define STENCIL_WRITE_MASK(x)		(x) | ||||
| #define STENCIL_WRITE_MASK(x)		((x)&0xff) | ||||
|  | ||||
| /* _3DSTATE_MODES_5, p220 */ | ||||
| #define _3DSTATE_MODES_5_CMD		(CMD_3D|(0x0c<<24)) | ||||
| @@ -824,10 +824,14 @@ | ||||
| #define ST1_ENABLE               (1<<16) | ||||
| #define ST1_MASK                 (0xffff) | ||||
|  | ||||
| #define _3DSTATE_DEFAULT_Z          ((0x3<<29)|(0x1d<<24)|(0x98<<16)) | ||||
| #define _3DSTATE_DEFAULT_DIFFUSE    ((0x3<<29)|(0x1d<<24)|(0x99<<16)) | ||||
| #define _3DSTATE_DEFAULT_SPECULAR   ((0x3<<29)|(0x1d<<24)|(0x9a<<16)) | ||||
|  | ||||
| #define MI_FLUSH           ((0<<29)|(4<<23)) | ||||
| #define FLUSH_MAP_CACHE    (1<<0) | ||||
| #define FLUSH_RENDER_CACHE (1<<1) | ||||
|  | ||||
| #define MI_FLUSH                   ((0<<29)|(4<<23)) | ||||
| #define FLUSH_MAP_CACHE            (1<<0) | ||||
| #define INHIBIT_FLUSH_RENDER_CACHE (1<<2) | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -36,6 +36,7 @@ | ||||
|  | ||||
| #include "texmem.h" | ||||
|  | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
|  | ||||
| @@ -48,7 +49,7 @@ static void | ||||
| i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
|                         GLuint mask) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func( func ); | ||||
|  | ||||
|    mask = mask & 0xff; | ||||
| @@ -73,7 +74,7 @@ i915StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref, | ||||
| static void | ||||
| i915StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask); | ||||
| @@ -91,7 +92,7 @@ static void | ||||
| i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|                       GLenum zpass) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int fop = intel_translate_stencil_op(fail);  | ||||
|    int dfop = intel_translate_stencil_op(zfail);  | ||||
|    int dpop = intel_translate_stencil_op(zpass); | ||||
| @@ -116,7 +117,7 @@ i915StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail, | ||||
|  | ||||
| static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func( func ); | ||||
|    GLubyte refByte; | ||||
|  | ||||
| @@ -137,7 +138,7 @@ static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) | ||||
|  */ | ||||
| static void i915EvalLogicOpBlendState(GLcontext *ctx) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
| @@ -157,7 +158,7 @@ static void i915EvalLogicOpBlendState(GLcontext *ctx) | ||||
|  | ||||
| static void i915BlendColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLubyte r, g, b, a; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -194,7 +195,7 @@ static GLuint translate_blend_equation( GLenum mode ) | ||||
|  | ||||
| static void i915UpdateBlendState( GLcontext *ctx ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &  | ||||
| 		 ~(IAB_SRC_FACTOR_MASK | | ||||
| 		   IAB_DST_FACTOR_MASK | | ||||
| @@ -261,7 +262,7 @@ static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB, | ||||
|  | ||||
| static void i915DepthFunc(GLcontext *ctx, GLenum func) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int test = intel_translate_compare_func( func ); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -274,7 +275,7 @@ static void i915DepthFunc(GLcontext *ctx, GLenum func) | ||||
|  | ||||
| static void i915DepthMask(GLcontext *ctx, GLboolean flag) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
|       fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag); | ||||
| @@ -295,7 +296,7 @@ static void i915DepthMask(GLcontext *ctx, GLboolean flag) | ||||
|  */ | ||||
| static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    const GLubyte *m = mask; | ||||
|    GLubyte p[4]; | ||||
|    int i,j,k; | ||||
| @@ -348,15 +349,14 @@ static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask ) | ||||
| static void i915Scissor(GLcontext *ctx, GLint x, GLint y,  | ||||
| 			GLsizei w, GLsizei h) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = i915->intel.intelScreen; | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int x1, y1, x2, y2; | ||||
|  | ||||
|    if (!i915->intel.driDrawable) | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|  | ||||
|    x1 = x; | ||||
|    y1 = i915->intel.driDrawable->h - (y + h); | ||||
|    y1 = ctx->DrawBuffer->Height - (y + h); | ||||
|    x2 = x + w - 1; | ||||
|    y2 = y1 + h - 1; | ||||
|  | ||||
| @@ -364,16 +364,10 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y, | ||||
|       fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__, | ||||
| 	      x, y, w, h); | ||||
|  | ||||
|    if (x1 < 0) x1 = 0; | ||||
|    if (y1 < 0) y1 = 0; | ||||
|    if (x2 < 0) x2 = 0; | ||||
|    if (y2 < 0) y2 = 0; | ||||
|  | ||||
|    if (x2 >= screen->width) x2 = screen->width-1; | ||||
|    if (y2 >= screen->height) y2 = screen->height-1; | ||||
|    if (x1 >= screen->width) x1 = screen->width-1; | ||||
|    if (y1 >= screen->height) y1 = screen->height-1; | ||||
|  | ||||
|    x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); | ||||
|    x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); | ||||
|    y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); | ||||
|  | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); | ||||
|    i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); | ||||
| @@ -382,7 +376,7 @@ static void i915Scissor(GLcontext *ctx, GLint x, GLint y, | ||||
|  | ||||
| static void i915LogicOp(GLcontext *ctx, GLenum opcode) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int tmp = intel_translate_logic_op(opcode); | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -397,7 +391,7 @@ static void i915LogicOp(GLcontext *ctx, GLenum opcode) | ||||
|  | ||||
| static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLuint mode; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -425,7 +419,7 @@ static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused) | ||||
|  | ||||
| static void i915LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    struct i915_context *i915 = I915_CONTEXT( ctx ); | ||||
|    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK; | ||||
|    int width; | ||||
|  | ||||
| @@ -444,7 +438,7 @@ static void i915LineWidth( GLcontext *ctx, GLfloat widthf ) | ||||
|  | ||||
| static void i915PointSize(GLcontext *ctx, GLfloat size) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK; | ||||
|    GLint point_size = (int)size; | ||||
|  | ||||
| @@ -469,7 +463,7 @@ static void i915ColorMask(GLcontext *ctx, | ||||
| 			 GLboolean r, GLboolean g, | ||||
| 			 GLboolean b, GLboolean a) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    struct i915_context *i915 = I915_CONTEXT( ctx ); | ||||
|    GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK; | ||||
|  | ||||
|    if (INTEL_DEBUG&DEBUG_DRI) | ||||
| @@ -490,7 +484,7 @@ static void update_specular( GLcontext *ctx ) | ||||
| { | ||||
|    /* A hack to trigger the rebuild of the fragment program. | ||||
|     */ | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= _NEW_TEXTURE; | ||||
|    intel_context(ctx)->NewGLState |= _NEW_TEXTURE; | ||||
|    I915_CONTEXT(ctx)->tex_program.translated = 0;  | ||||
| } | ||||
|  | ||||
| @@ -507,7 +501,7 @@ static void i915LightModelfv(GLcontext *ctx, GLenum pname, | ||||
|  | ||||
| static void i915ShadeModel(GLcontext *ctx, GLenum mode) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|  | ||||
|    if (mode == GL_SMOOTH) { | ||||
| @@ -526,7 +520,7 @@ static void i915ShadeModel(GLcontext *ctx, GLenum mode) | ||||
|  */ | ||||
| void i915_update_fog( GLcontext *ctx ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|    GLenum mode; | ||||
|    GLboolean enabled; | ||||
|    GLboolean try_pixel_fog; | ||||
| @@ -619,7 +613,7 @@ void i915_update_fog( GLcontext *ctx ) | ||||
|  | ||||
| static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_FOG_COORDINATE_SOURCE_EXT:  | ||||
| @@ -671,7 +665,7 @@ static void i915Hint(GLcontext *ctx, GLenum target, GLenum state) | ||||
|  | ||||
| static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(ctx); | ||||
|    struct i915_context *i915 = I915_CONTEXT(ctx); | ||||
|  | ||||
|    switch(cap) { | ||||
|    case GL_TEXTURE_2D: | ||||
| @@ -699,7 +693,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|  | ||||
|       /* Logicop doesn't seem to work at 16bpp: | ||||
|        */ | ||||
|       if (i915->intel.intelScreen->cpp == 2) | ||||
|       if (i915->intel.intelScreen->cpp == 2) /* XXX FBO fix */ | ||||
| 	 FALLBACK( &i915->intel, I915_FALLBACK_LOGICOP, state ); | ||||
|       break; | ||||
|  | ||||
| @@ -750,16 +744,24 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
|       break; | ||||
|  | ||||
|    case GL_STENCIL_TEST: | ||||
|       if (i915->intel.hw_stencil) { | ||||
| 	 I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
| 	 if (state) | ||||
| 	    i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | | ||||
| 						S5_STENCIL_WRITE_ENABLE); | ||||
| 	 else | ||||
| 	    i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |  | ||||
| 						 S5_STENCIL_WRITE_ENABLE); | ||||
|       } else { | ||||
| 	 FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state ); | ||||
|       { | ||||
|          GLboolean hw_stencil = GL_FALSE; | ||||
|          if (ctx->DrawBuffer) { | ||||
|             struct intel_renderbuffer *irbStencil | ||||
|                = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); | ||||
|             hw_stencil = (irbStencil && irbStencil->region); | ||||
|          } | ||||
|          if (hw_stencil) { | ||||
|             I915_STATECHANGE(i915, I915_UPLOAD_CTX); | ||||
|             if (state) | ||||
|                i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE | | ||||
|                                                    S5_STENCIL_WRITE_ENABLE); | ||||
|             else | ||||
|                i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |  | ||||
|                                                     S5_STENCIL_WRITE_ENABLE); | ||||
|          } else { | ||||
|             FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state ); | ||||
|          } | ||||
|       } | ||||
|       break; | ||||
|  | ||||
| @@ -785,7 +787,7 @@ static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_init_packets( i915ContextPtr i915 ) | ||||
| static void i915_init_packets( struct i915_context *i915 ) | ||||
| { | ||||
|    intelScreenPrivate *screen = i915->intel.intelScreen; | ||||
|  | ||||
| @@ -808,7 +810,7 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] = 0; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS5] = 0; | ||||
|  | ||||
|       if (screen->cpp == 2) | ||||
|       if (screen->cpp == 2) /* XXX FBO fix */ | ||||
| 	 i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; | ||||
|  | ||||
|  | ||||
| @@ -823,7 +825,6 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
| 					   ENABLE_STENCIL_WRITE_MASK | | ||||
| 					   STENCIL_WRITE_MASK(0xff)); | ||||
|  | ||||
|  | ||||
|       i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | | ||||
| 					IAB_MODIFY_ENABLE | | ||||
| 					IAB_MODIFY_FUNC | | ||||
| @@ -857,24 +858,24 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|    { | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); | ||||
|       i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */ | ||||
|       i915->state.Buffer[I915_DESTREG_CBUFADDR1] =  | ||||
| 	 (BUF_3D_ID_COLOR_BACK |  | ||||
| 	  BUF_3D_PITCH(screen->front.pitch * screen->cpp) | | ||||
| 	  BUF_3D_PITCH(screen->front.pitch * screen->cpp) | /* XXX FBO fix */ | ||||
| 	  BUF_3D_USE_FENCE); | ||||
|  | ||||
|  | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */ | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR1] =  | ||||
| 	 (BUF_3D_ID_DEPTH | | ||||
| 	  BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | | ||||
| 	  BUF_3D_PITCH(screen->depth.pitch * screen->cpp) | /* XXX FBO fix */ | ||||
| 	  BUF_3D_USE_FENCE); | ||||
|       i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depth.offset; | ||||
|  | ||||
|  | ||||
|       i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; | ||||
|  | ||||
|       /* XXX FBO: remove this?  Also get set in i915_set_draw_region() */ | ||||
| #if 0 /* seems we don't need this */ | ||||
|       switch (screen->fbFormat) { | ||||
|       case DV_PF_555: | ||||
|       case DV_PF_565: | ||||
| 	 i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
| 					       DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
| @@ -893,6 +894,8 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
| 					       DEPTH_FRMT_24_FIXED_8_OTHER); | ||||
| 	 break; | ||||
|       } | ||||
| #endif | ||||
|  | ||||
|       i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | | ||||
| 						DISABLE_SCISSOR_RECT); | ||||
|       i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD; | ||||
| @@ -901,13 +904,27 @@ static void i915_init_packets( i915ContextPtr i915 ) | ||||
|    } | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
|    { | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_DEFAULTS); | ||||
|       i915->state.Default[I915_DEFREG_C0] = _3DSTATE_DEFAULT_DIFFUSE; | ||||
|       i915->state.Default[I915_DEFREG_C1] = 0; | ||||
|       i915->state.Default[I915_DEFREG_S0] = _3DSTATE_DEFAULT_SPECULAR; | ||||
|       i915->state.Default[I915_DEFREG_S1] = 0; | ||||
|       i915->state.Default[I915_DEFREG_Z0] = _3DSTATE_DEFAULT_Z; | ||||
|       i915->state.Default[I915_DEFREG_Z1] = 0; | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|    /* These will be emitted every at the head of every buffer, unless | ||||
|     * we get hardware contexts working. | ||||
|     */ | ||||
|    i915->state.active = (I915_UPLOAD_PROGRAM |  | ||||
| 			I915_UPLOAD_STIPPLE |  | ||||
| 			I915_UPLOAD_CTX |  | ||||
| 			I915_UPLOAD_BUFFERS); | ||||
| 			 I915_UPLOAD_STIPPLE |  | ||||
| 			 I915_UPLOAD_CTX |  | ||||
| 			 I915_UPLOAD_BUFFERS | | ||||
| 			 I915_UPLOAD_INVARIENT); | ||||
| } | ||||
|  | ||||
| void i915InitStateFunctions( struct dd_function_table *functions ) | ||||
| @@ -937,7 +954,7 @@ void i915InitStateFunctions( struct dd_function_table *functions ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915InitState( i915ContextPtr i915 ) | ||||
| void i915InitState( struct i915_context *i915 ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|  | ||||
|   | ||||
| @@ -45,76 +45,10 @@ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Allocate space for and load the mesa images into the texture memory block. | ||||
|  * This will happen before drawing with a new texture, or drawing with a | ||||
|  * texture after it was swapped out or teximaged again. | ||||
|  */ | ||||
|  | ||||
| intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ) | ||||
| { | ||||
|    i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object ); | ||||
|    if ( !t )  | ||||
|       return NULL; | ||||
|  | ||||
|    texObj->DriverData = t; | ||||
|    t->intel.base.tObj = texObj; | ||||
|    t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|    make_empty_list( &t->intel.base ); | ||||
|    return &t->intel; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915TexParameter( GLcontext *ctx, GLenum target, | ||||
| 			     struct gl_texture_object *tObj, | ||||
| 			     GLenum pname, const GLfloat *params ) | ||||
| { | ||||
|    i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; | ||||
|   | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_MIN_FILTER: | ||||
|    case GL_TEXTURE_MAG_FILTER: | ||||
|    case GL_TEXTURE_MAX_ANISOTROPY_EXT: | ||||
|    case GL_TEXTURE_WRAP_S: | ||||
|    case GL_TEXTURE_WRAP_T: | ||||
|    case GL_TEXTURE_WRAP_R: | ||||
|    case GL_TEXTURE_BORDER_COLOR: | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_COMPARE_MODE: | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|    case GL_TEXTURE_COMPARE_FUNC: | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_BASE_LEVEL: | ||||
|    case GL_TEXTURE_MAX_LEVEL: | ||||
|    case GL_TEXTURE_MIN_LOD: | ||||
|    case GL_TEXTURE_MAX_LOD: | ||||
|       /* The i915 and its successors can do a lot of this without | ||||
|        * reloading the textures.  A project for someone? | ||||
|        */ | ||||
|       intelFlush( ctx ); | ||||
|       driSwapOutTextureObject( (driTextureObject *) t ); | ||||
|       t->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915TexEnv( GLcontext *ctx, GLenum target,  | ||||
| 			GLenum pname, const GLfloat *param ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT( ctx ); | ||||
|    GLuint unit = ctx->Texture.CurrentUnit; | ||||
|    struct i915_context *i915 = I915_CONTEXT( ctx ); | ||||
|  | ||||
|    switch (pname) { | ||||
|    case GL_TEXTURE_ENV_COLOR: 	/* Should be a tracked param */ | ||||
| @@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | ||||
|       break; | ||||
|  | ||||
|    case GL_TEXTURE_LOD_BIAS: { | ||||
|       int b = (int) ((*param) * 16.0); | ||||
|       GLuint unit = ctx->Texture.CurrentUnit; | ||||
|       GLint b = (int) ((*param) * 16.0); | ||||
|       if (b > 255) b = 255; | ||||
|       if (b < -256) b = -256; | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); | ||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK; | ||||
|       i915->state.Tex[unit][I915_TEXREG_SS2] |=  | ||||
| 	 ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); | ||||
|       i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
| @@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, | ||||
|  | ||||
|  | ||||
| static void i915BindTexture( GLcontext *ctx, GLenum target, | ||||
| 			    struct gl_texture_object *texObj ) | ||||
|                              struct gl_texture_object *texobj ) | ||||
| { | ||||
|    i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData; | ||||
|  | ||||
|    if (tex->lastTarget != texObj->Target) { | ||||
|       tex->intel.dirty = I915_UPLOAD_TEX_ALL; | ||||
|       tex->lastTarget = texObj->Target; | ||||
|    } | ||||
|  | ||||
|    /* Need this if image format changes between bound textures. | ||||
|     * Could try and shortcircuit by checking for differences in | ||||
|     * state between incoming and outgoing textures: | ||||
| @@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->BindTexture = i915BindTexture; | ||||
|    functions->TexEnv = i915TexEnv; | ||||
|    functions->TexParameter = i915TexParameter; | ||||
| } | ||||
|   | ||||
							
								
								
									
										338
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										338
									
								
								src/mesa/drivers/dri/i915/i915_tex_layout.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,338 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| /* Code to layout images in a mipmap tree for i915 and i945 | ||||
|  * respectively. | ||||
|  */ | ||||
|  | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "macros.h" | ||||
|  | ||||
| static GLint initial_offsets[6][2] = { {0,0}, | ||||
| 				       {0,2}, | ||||
| 				       {1,0}, | ||||
| 				       {1,2}, | ||||
| 				       {1,1}, | ||||
| 				       {1,3} }; | ||||
|  | ||||
|  | ||||
| static GLint step_offsets[6][2] = { {0,2}, | ||||
| 				    {0,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,2}, | ||||
| 				    {-1,1}, | ||||
| 				    {-1,1} }; | ||||
|  | ||||
| static GLuint minify( GLuint d ) | ||||
| { | ||||
|    return MAX2(1, d>>1); | ||||
| } | ||||
|  | ||||
| GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt ) | ||||
| { | ||||
|    GLint i; | ||||
|  | ||||
|    switch (mt->target) { | ||||
|    case GL_TEXTURE_CUBE_MAP: { | ||||
|       const GLuint dim = mt->width0; | ||||
|       GLuint face; | ||||
|  | ||||
|       /* double pitch for cube layouts */ | ||||
|       mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = dim * 4; | ||||
|        | ||||
|       for ( face = 0 ; face < 6 ; face++) { | ||||
| 	 GLuint x = initial_offsets[face][0] * dim; | ||||
| 	 GLuint y = initial_offsets[face][1] * dim; | ||||
| 	 GLuint d = dim; | ||||
| 	  | ||||
| 	 for (i = mt->first_level; i <= mt->last_level; i++) { | ||||
| 	    intel_miptree_set_image_offset(mt, face, i, | ||||
| 					   x, y, | ||||
| 					   d, d, 1); | ||||
|  | ||||
| 	    if (d == 0) | ||||
| 	       _mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n", | ||||
| 			    face, i, mt->first_level, mt->last_level); | ||||
|  | ||||
| 	    d >>= 1; | ||||
| 	    x += step_offsets[face][0] * d; | ||||
| 	    y += step_offsets[face][1] * d; | ||||
| 	 } | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    case GL_TEXTURE_3D: { | ||||
|       GLuint width  = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|       GLuint depth  = mt->depth0; | ||||
|  | ||||
|       /* Calculate the size of a single slice.  | ||||
|        */ | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       /* XXX: hardware expects/requires 9 levels at minimum. | ||||
|        */ | ||||
|       for ( i = mt->first_level ; i <= MAX2(8, mt->last_level) ; i++ ) { | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					0, mt->total_height, | ||||
| 					width, height, depth); | ||||
|  | ||||
| 	 mt->total_height += MAX2(2, height); | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
| 	 depth  = minify(depth); | ||||
|       } | ||||
|  | ||||
|       /* Fixup depth_image_stride:  | ||||
|        */ | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	 mt->offset[0][i].depth_image_stride = mt->total_height * mt->pitch * mt->cpp; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* Multiply slice size by texture depth for total size.  It's | ||||
|        * remarkable how wasteful of memory the i915 texture layouts | ||||
|        * are.  They are largely fixed in the i945. | ||||
|        */ | ||||
|       mt->total_height *= mt->depth0; | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    default: { | ||||
|       GLuint width  = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|  | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					0, mt->total_height, | ||||
| 					width, height, 1); | ||||
|  | ||||
| 	 if (mt->compressed) | ||||
| 	    mt->total_height += MAX2(1, height/4); | ||||
| 	 else | ||||
| 	    mt->total_height += MAX2(2, height); | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    } | ||||
|    DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,  | ||||
| 		mt->pitch,  | ||||
| 		mt->total_height, | ||||
| 		mt->cpp, | ||||
| 		mt->pitch * mt->total_height * mt->cpp ); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt ) | ||||
| { | ||||
|    GLint i; | ||||
|  | ||||
|    switch (mt->target) { | ||||
|    case GL_TEXTURE_CUBE_MAP: { | ||||
|       const GLuint dim = mt->width0; | ||||
|       GLuint face; | ||||
|  | ||||
|       /* Depending on the size of the largest images, pitch can be | ||||
|        * determined either by the old-style packing of cubemap faces, | ||||
|        * or the final row of 4x4, 2x2 and 1x1 faces below this.  | ||||
|        */ | ||||
|       if (dim > 32)  | ||||
| 	 mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp; | ||||
|       else  | ||||
| 	 mt->pitch = 14 * 8;  | ||||
|  | ||||
|       mt->total_height = dim * 4 + 4; | ||||
|  | ||||
|        | ||||
|       for ( face = 0 ; face < 6 ; face++) { | ||||
| 	 GLuint x = initial_offsets[face][0] * dim; | ||||
| 	 GLuint y = initial_offsets[face][1] * dim; | ||||
| 	 GLuint d = dim; | ||||
| 	  | ||||
| 	 if (dim == 4 && face >= 4) { | ||||
| 	    y = mt->total_height - 4; | ||||
| 	    x = (face - 4) * 8; | ||||
| 	 } | ||||
| 	 else if (dim < 4) { | ||||
| 	    y = mt->total_height - 4; | ||||
| 	    x = face * 8; | ||||
| 	 } | ||||
|  | ||||
| 	 for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	    intel_miptree_set_image_offset(mt, face, i, | ||||
| 					   x, y, | ||||
| 					   d, d, 1); | ||||
|  | ||||
| 	    d >>= 1; | ||||
| 	     | ||||
| 	    switch (d) { | ||||
| 	    case 4: | ||||
| 	       switch (face) { | ||||
| 	       case FACE_POS_X: | ||||
| 	       case FACE_NEG_X: | ||||
| 		  x += step_offsets[face][0] * d; | ||||
| 		  y += step_offsets[face][1] * d; | ||||
| 		  break; | ||||
| 	       case FACE_POS_Y: | ||||
| 	       case FACE_NEG_Y: | ||||
| 		  y += 12; | ||||
| 		  x -= 8; | ||||
| 		  break; | ||||
| 	       case FACE_POS_Z: | ||||
| 	       case FACE_NEG_Z: | ||||
| 		  y = mt->total_height - 4; | ||||
| 		  x = (face - 4) * 8; | ||||
| 		  break; | ||||
| 	       } | ||||
|  | ||||
| 	    case 2: | ||||
| 	       y = mt->total_height - 4; | ||||
| 	       x = 16 + face * 8; | ||||
| 	       break; | ||||
|  | ||||
| 	    case 1: | ||||
| 	       x += 48; | ||||
| 	       break; | ||||
| 	        | ||||
| 	    default: | ||||
| 	       x += step_offsets[face][0] * d; | ||||
| 	       y += step_offsets[face][1] * d; | ||||
| 	       break; | ||||
| 	    } | ||||
| 	 } | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    case GL_TEXTURE_3D: { | ||||
|       GLuint width  = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|       GLuint depth = mt->depth0; | ||||
|       GLuint depth_pack_pitch; | ||||
|       GLuint depth_packing = 0; | ||||
|  | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       depth_pack_pitch = mt->pitch * mt->cpp; | ||||
|  | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
|  | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					0, mt->total_height, | ||||
| 					width, height, depth); | ||||
|  | ||||
|  | ||||
|  | ||||
| 	 mt->total_height += MAX2(2, height) * MAX2((depth >> depth_packing), 1); | ||||
|  | ||||
| 	 /* When alignment dominates, can't increase depth packing? | ||||
| 	  * Or does pitch grow???  What are the alignment constraints, | ||||
| 	  * anyway? | ||||
| 	  */ | ||||
| 	 if (depth_pack_pitch > 4) { | ||||
| 	    depth_packing++; | ||||
| 	    depth_pack_pitch >>= 2; /* KW: is this right?? */ | ||||
| 	 } | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
| 	 depth  = minify(depth); | ||||
|  | ||||
| 	 /* XXX: Not sure how 3d textures work on i945 - where did | ||||
| 	  * t->depth_pitch get set in the old code.  Did it ever work? | ||||
| 	  * Fix up later. | ||||
| 	  */ | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    case GL_TEXTURE_1D: | ||||
|    case GL_TEXTURE_2D: | ||||
|    case GL_TEXTURE_RECTANGLE_ARB: { | ||||
|       GLuint x = 0; | ||||
|       GLuint y = 0; | ||||
|       GLuint width = mt->width0; | ||||
|       GLuint height = mt->height0; | ||||
|  | ||||
|       mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp; | ||||
|       mt->total_height = 0; | ||||
|  | ||||
|       for ( i = mt->first_level ; i <= mt->last_level ; i++ ) { | ||||
| 	 intel_miptree_set_image_offset(mt, 0, i, | ||||
| 					x, y, | ||||
| 					width, height, 1); | ||||
|  | ||||
| 	  | ||||
| 	 /* LPT change: step right after second mipmap. | ||||
| 	  */ | ||||
| 	 if (i == 1)  | ||||
| 	    x += mt->pitch / 2; | ||||
| 	 else { | ||||
| 	    GLuint img_height; | ||||
| 	  | ||||
| 	    if (mt->compressed) | ||||
| 	       img_height = MAX2(1, height/4); | ||||
| 	    else | ||||
| 	       img_height = MAX2(2, height); | ||||
|  | ||||
| 	    y += img_height; | ||||
| 	 } | ||||
|  | ||||
| 	 /* Because the images are packed better, the final offset | ||||
| 	  * might not be the maximal one: | ||||
| 	  */ | ||||
| 	 mt->total_height = MAX2(mt->total_height, y); | ||||
|  | ||||
| 	 width  = minify(width); | ||||
| 	 height = minify(height); | ||||
|       } | ||||
|       break; | ||||
|    } | ||||
|    default: | ||||
|       _mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()"); | ||||
|    } | ||||
|     | ||||
|    DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,  | ||||
| 		mt->pitch,  | ||||
| 		mt->total_height, | ||||
| 		mt->cpp, | ||||
| 		mt->pitch * mt->total_height * mt->cpp ); | ||||
| 		 | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| @@ -536,7 +536,7 @@ static void emit_program_fini( struct i915_fragment_program *p ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915EmitTextureProgram( i915ContextPtr i915 ) | ||||
| static void i915EmitTextureProgram( struct i915_context *i915 ) | ||||
| { | ||||
|    GLcontext *ctx = &i915->intel.ctx; | ||||
|    struct i915_fragment_program *p = &i915->tex_program; | ||||
| @@ -570,9 +570,9 @@ static void i915EmitTextureProgram( i915ContextPtr i915 ) | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915ValidateTextureProgram( i915ContextPtr i915 ) | ||||
| void i915ValidateTextureProgram( struct i915_context *i915 ) | ||||
| { | ||||
|    intelContextPtr intel = &i915->intel; | ||||
|    struct intel_context *intel = &i915->intel; | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
| @@ -639,7 +639,8 @@ void i915ValidateTextureProgram( i915ContextPtr i915 ) | ||||
|     */ | ||||
|    if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || | ||||
|        s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { | ||||
|      | ||||
|       int k; | ||||
|  | ||||
|       I915_STATECHANGE( i915, I915_UPLOAD_CTX ); | ||||
|  | ||||
|       i915->tex_program.translated = 0; | ||||
| @@ -657,7 +658,8 @@ void i915ValidateTextureProgram( i915ContextPtr i915 ) | ||||
|       i915->state.Ctx[I915_CTXREG_LIS2] = s2; | ||||
|       i915->state.Ctx[I915_CTXREG_LIS4] = s4; | ||||
|  | ||||
|       assert(intel->vtbl.check_vertex_size( intel, intel->vertex_size )); | ||||
|       k = intel->vtbl.check_vertex_size( intel, intel->vertex_size ); | ||||
|       assert(k); | ||||
|    } | ||||
|  | ||||
|    if (!i915->tex_program.translated || | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -37,14 +37,16 @@ | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "i915_reg.h" | ||||
| #include "i915_context.h" | ||||
|  | ||||
| static void i915_render_start( intelContextPtr intel ) | ||||
| static void i915_render_start( struct intel_context *intel ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|  | ||||
|    if (ctx->FragmentProgram._Active)  | ||||
|       i915ValidateFragmentProgram( i915 ); | ||||
| @@ -53,42 +55,42 @@ static void i915_render_start( intelContextPtr intel ) | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_reduced_primitive_state( intelContextPtr intel, | ||||
| static void i915_reduced_primitive_state( struct intel_context *intel, | ||||
| 					  GLenum rprim ) | ||||
| { | ||||
|     i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|     GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; | ||||
|  | ||||
|     st1 &= ~ST1_ENABLE; | ||||
|    st1 &= ~ST1_ENABLE; | ||||
|  | ||||
|     switch (rprim) { | ||||
|     case GL_TRIANGLES: | ||||
|        if (intel->ctx.Polygon.StippleFlag && | ||||
| 	   intel->hw_stipple) | ||||
| 	  st1 |= ST1_ENABLE; | ||||
|        break; | ||||
|     case GL_LINES: | ||||
|     case GL_POINTS: | ||||
|     default: | ||||
|        break; | ||||
|     } | ||||
|    switch (rprim) { | ||||
|    case GL_TRIANGLES: | ||||
|       if (intel->ctx.Polygon.StippleFlag && | ||||
| 	  intel->hw_stipple) | ||||
| 	 st1 |= ST1_ENABLE; | ||||
|       break; | ||||
|    case GL_LINES: | ||||
|    case GL_POINTS: | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|     i915->intel.reduced_primitive = rprim; | ||||
|    i915->intel.reduced_primitive = rprim; | ||||
|  | ||||
|     if (st1 != i915->state.Stipple[I915_STPREG_ST1]) { | ||||
|        I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); | ||||
|        i915->state.Stipple[I915_STPREG_ST1] = st1; | ||||
|     } | ||||
|    if (st1 != i915->state.Stipple[I915_STPREG_ST1]) { | ||||
|       I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); | ||||
|       i915->state.Stipple[I915_STPREG_ST1] = st1; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Pull apart the vertex format registers and figure out how large a | ||||
|  * vertex is supposed to be.  | ||||
|  */ | ||||
| static GLboolean i915_check_vertex_size( intelContextPtr intel, | ||||
| static GLboolean i915_check_vertex_size( struct intel_context *intel, | ||||
| 					 GLuint expected ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    int lis2 = i915->current->Ctx[I915_CTXREG_LIS2]; | ||||
|    int lis4 = i915->current->Ctx[I915_CTXREG_LIS4]; | ||||
|    int i, sz = 0; | ||||
| @@ -132,11 +134,11 @@ static GLboolean i915_check_vertex_size( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
| static void i915_emit_invarient_state( struct intel_context *intel ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH( 200 ); | ||||
|    BEGIN_BATCH( 200, 0 ); | ||||
|  | ||||
|    OUT_BATCH(_3DSTATE_AA_CMD | | ||||
| 	     AA_LINE_ECAAR_WIDTH_ENABLE | | ||||
| @@ -204,21 +206,15 @@ static void i915_emit_invarient_state( intelContextPtr intel ) | ||||
| } | ||||
|  | ||||
|  | ||||
| #define emit( intel, state, size )			\ | ||||
| do {							\ | ||||
|    int k;						\ | ||||
|    BEGIN_BATCH( (size) / sizeof(GLuint));		\ | ||||
|    for (k = 0 ; k < (size) / sizeof(GLuint) ; k++)	\ | ||||
|       OUT_BATCH((state)[k]);				\ | ||||
|    ADVANCE_BATCH();					\ | ||||
| } while (0); | ||||
| #define emit(intel, state, size )		     \ | ||||
|    intel_batchbuffer_data(intel->batch, state, size, 0 ) | ||||
|  | ||||
|  | ||||
| /* Push the state into the sarea and/or texture memory. | ||||
|  */ | ||||
| static void i915_emit_state( intelContextPtr intel ) | ||||
| static void i915_emit_state( struct intel_context *intel ) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    struct i915_hw_state *state = i915->current; | ||||
|    int i; | ||||
|    GLuint dirty; | ||||
| @@ -233,27 +229,51 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
|    dirty = state->active & ~state->emitted; | ||||
|  | ||||
|  | ||||
|    if (VERBOSE)  | ||||
|    if (INTEL_DEBUG & DEBUG_STATE)  | ||||
|       fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_INVARIENT) { | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_INVARIENT:\n");  | ||||
|       i915_emit_invarient_state( intel ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_CTX) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CTX:\n");  | ||||
|       emit( i915, state->Ctx, sizeof(state->Ctx) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CTX:\n");  | ||||
|       emit(intel, state->Ctx, sizeof(state->Ctx) ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_BUFFERS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");  | ||||
|       emit( i915, state->Buffer, sizeof(state->Buffer) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");  | ||||
|       BEGIN_BATCH(I915_DEST_SETUP_SIZE+2, 0); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); | ||||
|       OUT_RELOC(state->draw_region->buffer, DRM_MM_TT|DRM_MM_WRITE, | ||||
|                 state->draw_region->draw_offset); | ||||
|  | ||||
|       if (state->depth_region) { | ||||
|          OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); | ||||
|          OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); | ||||
|          OUT_RELOC(state->depth_region->buffer, DRM_MM_TT|DRM_MM_WRITE, | ||||
|                    state->depth_region->draw_offset); | ||||
|       } | ||||
|  | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); | ||||
|       OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_STIPPLE) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");  | ||||
|       emit( i915, state->Stipple, sizeof(state->Stipple) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_STIPPLE:\n");  | ||||
|       emit(intel, state->Stipple, sizeof(state->Stipple) ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_FOG) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_FOG:\n");  | ||||
|       emit( i915, state->Fog, sizeof(state->Fog) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_FOG:\n");  | ||||
|       emit(intel, state->Fog, sizeof(state->Fog) ); | ||||
|    } | ||||
|  | ||||
|    /* Combine all the dirty texture state into a single command to | ||||
| @@ -266,18 +286,29 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
| 	 if (dirty & I915_UPLOAD_TEX(i))  | ||||
| 	    nr++; | ||||
|  | ||||
|       BEGIN_BATCH(2+nr*3); | ||||
|       BEGIN_BATCH(2+nr*3, 0); | ||||
|       OUT_BATCH(_3DSTATE_MAP_STATE | (3*nr)); | ||||
|       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); | ||||
|       for (i = 0 ; i < I915_TEX_UNITS ; i++) | ||||
| 	 if (dirty & I915_UPLOAD_TEX(i)) { | ||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS2]); | ||||
|  | ||||
| 	    if (state->tex_buffer[i]) { | ||||
| 	       OUT_RELOC(state->tex_buffer[i], | ||||
| 			 DRM_MM_TT|DRM_MM_READ, | ||||
| 			 state->tex_offset[i]); | ||||
| 	    } | ||||
| 	    else { | ||||
| 	       assert(i == 0); | ||||
| 	       assert(state == &i915->meta); | ||||
| 	       OUT_BATCH(0); | ||||
| 	    } | ||||
|  | ||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); | ||||
| 	    OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); | ||||
| 	 } | ||||
|       ADVANCE_BATCH(); | ||||
|  | ||||
|       BEGIN_BATCH(2+nr*3); | ||||
|       BEGIN_BATCH(2+nr*3, 0); | ||||
|       OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3*nr)); | ||||
|       OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); | ||||
|       for (i = 0 ; i < I915_TEX_UNITS ; i++) | ||||
| @@ -290,64 +321,132 @@ static void i915_emit_state( intelContextPtr intel ) | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_CONSTANTS) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");  | ||||
|       emit( i915, state->Constant, state->ConstantSize * sizeof(GLuint) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n");  | ||||
|       emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint) ); | ||||
|    } | ||||
|  | ||||
|    if (dirty & I915_UPLOAD_PROGRAM) { | ||||
|       if (VERBOSE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");  | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) fprintf(stderr, "I915_UPLOAD_PROGRAM:\n");  | ||||
|  | ||||
|       assert((state->Program[0] & 0x1ff)+2 == state->ProgramSize); | ||||
|        | ||||
|       emit( i915, state->Program, state->ProgramSize * sizeof(GLuint) ); | ||||
|       if (VERBOSE) | ||||
|       emit(intel, state->Program, state->ProgramSize * sizeof(GLuint) ); | ||||
|       if (INTEL_DEBUG & DEBUG_STATE) | ||||
| 	 i915_disassemble_program( state->Program, state->ProgramSize ); | ||||
|    } | ||||
|  | ||||
|    state->emitted |= dirty; | ||||
| } | ||||
|  | ||||
| static void i915_destroy_context( intelContextPtr intel ) | ||||
| static void i915_destroy_context( struct intel_context *intel ) | ||||
| { | ||||
|    _tnl_free_vertices(&intel->ctx); | ||||
| } | ||||
|  | ||||
| static void i915_set_draw_offset( intelContextPtr intel, int offset ) | ||||
|  | ||||
| /** | ||||
|  * Set the drawing regions for the color and depth/stencil buffers. | ||||
|  * This involves setting the pitch, cpp and buffer ID/location. | ||||
|  * Also set pixel format for color and Z rendering | ||||
|  * Used for setting both regular and meta state. | ||||
|  */ | ||||
| void | ||||
| i915_state_draw_region(struct intel_context *intel,  | ||||
|                        struct i915_hw_state *state, | ||||
|                        struct intel_region *color_region, | ||||
|                        struct intel_region *depth_region) | ||||
| { | ||||
|    i915ContextPtr i915 = I915_CONTEXT(intel); | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    GLuint value; | ||||
|  | ||||
|    ASSERT(state == &i915->state || state == &i915->meta); | ||||
|  | ||||
|    if (state->draw_region != color_region) { | ||||
|       intel_region_release(intel, &state->draw_region); | ||||
|       intel_region_reference(&state->draw_region, color_region); | ||||
|    } | ||||
|    if (state->depth_region != depth_region) { | ||||
|       intel_region_release(intel, &state->depth_region); | ||||
|       intel_region_reference(&state->depth_region, depth_region); | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * Set stride/cpp values | ||||
|     */ | ||||
|    if (color_region) { | ||||
|       state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       state->Buffer[I915_DESTREG_CBUFADDR1] =  | ||||
|          (BUF_3D_ID_COLOR_BACK |  | ||||
|           BUF_3D_PITCH(color_region->pitch * color_region->cpp) | | ||||
|           BUF_3D_USE_FENCE); | ||||
|    } | ||||
|  | ||||
|    if (depth_region) { | ||||
|       state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; | ||||
|       state->Buffer[I915_DESTREG_DBUFADDR1] =  | ||||
| 	 (BUF_3D_ID_DEPTH | | ||||
| 	  BUF_3D_PITCH(depth_region->pitch * depth_region->cpp) | | ||||
| 	  BUF_3D_USE_FENCE); | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * Compute/set I915_DESTREG_DV1 value | ||||
|     */ | ||||
|    value = (DSTORG_HORT_BIAS(0x8) | /* .5 */ | ||||
|             DSTORG_VERT_BIAS(0x8) | /* .5 */ | ||||
|             LOD_PRECLAMP_OGL | | ||||
|             TEX_DEFAULT_COLOR_OGL); | ||||
|    if (color_region && color_region->cpp == 4) { | ||||
|       value |= DV_PF_8888; | ||||
|    } | ||||
|    else { | ||||
|       value |= (DITHER_FULL_ALWAYS | DV_PF_565); | ||||
|    } | ||||
|    if (depth_region && depth_region->cpp == 4) { | ||||
|       value |= DEPTH_FRMT_24_FIXED_8_OTHER; | ||||
|    } | ||||
|    else { | ||||
|       value |= DEPTH_FRMT_16_FIXED; | ||||
|    } | ||||
|    state->Buffer[I915_DESTREG_DV1] = value; | ||||
|  | ||||
|    I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); | ||||
|    i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset; | ||||
| } | ||||
|  | ||||
| static void i915_lost_hardware( intelContextPtr intel ) | ||||
| { | ||||
|    I915_CONTEXT(intel)->state.emitted = 0; | ||||
| } | ||||
|  | ||||
| static void i915_emit_flush( intelContextPtr intel ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    BEGIN_BATCH(2); | ||||
|    OUT_BATCH( MI_FLUSH | FLUSH_MAP_CACHE | FLUSH_RENDER_CACHE );  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915InitVtbl( i915ContextPtr i915 ) | ||||
| static void | ||||
| i915_set_draw_region(struct intel_context *intel,  | ||||
|                      struct intel_region *color_region, | ||||
|                      struct intel_region *depth_region) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    i915_state_draw_region(intel, &i915->state, color_region, depth_region); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void i915_lost_hardware( struct intel_context *intel ) | ||||
| { | ||||
|    struct i915_context *i915 = i915_context(&intel->ctx); | ||||
|    i915->state.emitted = 0; | ||||
| } | ||||
|  | ||||
| static GLuint i915_flush_cmd( void ) | ||||
| { | ||||
|    return MI_FLUSH | FLUSH_MAP_CACHE; | ||||
| } | ||||
|  | ||||
|  | ||||
| void i915InitVtbl( struct i915_context *i915 ) | ||||
| { | ||||
|    i915->intel.vtbl.alloc_tex_obj = i915AllocTexObj; | ||||
|    i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; | ||||
|    i915->intel.vtbl.clear_with_tris = i915ClearWithTris; | ||||
|    i915->intel.vtbl.destroy = i915_destroy_context; | ||||
|    i915->intel.vtbl.emit_invarient_state = i915_emit_invarient_state; | ||||
|    i915->intel.vtbl.emit_state = i915_emit_state; | ||||
|    i915->intel.vtbl.lost_hardware = i915_lost_hardware; | ||||
|    i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state; | ||||
|    i915->intel.vtbl.render_start = i915_render_start; | ||||
|    i915->intel.vtbl.set_draw_offset = i915_set_draw_offset; | ||||
|    i915->intel.vtbl.set_draw_region = i915_set_draw_region; | ||||
|    i915->intel.vtbl.update_texture_state = i915UpdateTextureState; | ||||
|    i915->intel.vtbl.emit_flush = i915_emit_flush; | ||||
|    i915->intel.vtbl.flush_cmd = i915_flush_cmd; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
| @@ -25,664 +25,270 @@ | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "context.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "intel_reg.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * Performance monitoring functions | ||||
| /* Relocations in kernel space: | ||||
|  *    - pass dma buffer seperately | ||||
|  *    - memory manager knows how to patch | ||||
|  *    - pass list of dependent buffers | ||||
|  *    - pass relocation list | ||||
|  * | ||||
|  * Either: | ||||
|  *    - get back an offset for buffer to fire | ||||
|  *    - memory manager knows how to fire buffer | ||||
|  * | ||||
|  * Really want the buffer to be AGP and pinned. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| static void intel_fill_box( intelContextPtr intel, | ||||
| 			    GLshort x, GLshort y, | ||||
| 			    GLshort w, GLshort h, | ||||
| 			    GLubyte r, GLubyte g, GLubyte b ) | ||||
| /* Cliprect fence: The highest fence protecting a dma buffer | ||||
|  * containing explicit cliprect information.  Like the old drawable | ||||
|  * lock but irq-driven.  X server must wait for this fence to expire | ||||
|  * before changing cliprects [and then doing sw rendering?].  For | ||||
|  * other dma buffers, the scheduler will grab current cliprect info | ||||
|  * and mix into buffer.  X server must hold the lock while changing | ||||
|  * cliprects???  Make per-drawable.  Need cliprects in shared memory | ||||
|  * -- beats storing them with every cmd buffer in the queue. | ||||
|  * | ||||
|  * ==> X server must wait for this fence to expire before touching the | ||||
|  * framebuffer with new cliprects. | ||||
|  * | ||||
|  * ==> Cliprect-dependent buffers associated with a | ||||
|  * cliprect-timestamp.  All of the buffers associated with a timestamp | ||||
|  * must go to hardware before any buffer with a newer timestamp. | ||||
|  * | ||||
|  * ==> Dma should be queued per-drawable for correct X/GL | ||||
|  * synchronization.  Or can fences be used for this? | ||||
|  * | ||||
|  * Applies to: Blit operations, metaops, X server operations -- X | ||||
|  * server automatically waits on its own dma to complete before | ||||
|  * modifying cliprects ??? | ||||
|  */				 | ||||
|  | ||||
| static void intel_dump_batchbuffer( GLuint offset, | ||||
| 				    GLuint *ptr, | ||||
| 				    GLuint count ) | ||||
| { | ||||
|    intelEmitFillBlitLocked( intel,  | ||||
| 			    intel->intelScreen->cpp, | ||||
| 			    intel->intelScreen->back.pitch, | ||||
| 			    intel->intelScreen->front.offset, | ||||
| 			    x, y, w, h, | ||||
| 			    INTEL_PACKCOLOR(intel->intelScreen->fbFormat, | ||||
| 					    r,g,b,0xff)); | ||||
| } | ||||
|  | ||||
| static void intel_draw_performance_boxes( intelContextPtr intel ) | ||||
| { | ||||
|    /* Purple box for page flipping | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_FLIP )  | ||||
|       intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 ); | ||||
|  | ||||
|    /* Red box if we have to wait for idle at any point | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_WAIT )  | ||||
|       intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 ); | ||||
|  | ||||
|    /* Blue box: lost context? | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT )  | ||||
|       intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 ); | ||||
|  | ||||
|    /* Yellow box for texture swaps | ||||
|     */ | ||||
|    if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD )  | ||||
|       intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 ); | ||||
|  | ||||
|    /* Green box if hardware never idles (as far as we can tell) | ||||
|     */ | ||||
|    if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) )  | ||||
|       intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 ); | ||||
|  | ||||
|  | ||||
|    /* Draw bars indicating number of buffers allocated  | ||||
|     * (not a great measure, easily confused) | ||||
|     */ | ||||
| #if 0 | ||||
|    if (intel->dma_used) { | ||||
|       int bar = intel->dma_used / 10240; | ||||
|       if (bar > 100) bar = 100; | ||||
|       if (bar < 1) bar = 1; | ||||
|       intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 ); | ||||
|       intel->dma_used = 0; | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    intel->perf_boxes = 0; | ||||
|    int i; | ||||
|    fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count/4); | ||||
|    for (i = 0; i < count/4; i += 4)  | ||||
|       fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",  | ||||
| 	      offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); | ||||
|    fprintf(stderr, "END BATCH\n\n\n"); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static int bad_prim_vertex_nr( int primitive, int nr ) | ||||
| static void intel_batchbuffer_reset( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    switch (primitive & PRIM3D_MASK) { | ||||
|    case PRIM3D_POINTLIST: | ||||
|       return nr < 1; | ||||
|    case PRIM3D_LINELIST: | ||||
|       return (nr & 1) || nr == 0; | ||||
|    case PRIM3D_LINESTRIP: | ||||
|       return nr < 2; | ||||
|    case PRIM3D_TRILIST: | ||||
|    case PRIM3D_RECTLIST: | ||||
|       return nr % 3 || nr == 0; | ||||
|    case PRIM3D_POLY: | ||||
|    case PRIM3D_TRIFAN: | ||||
|    case PRIM3D_TRISTRIP: | ||||
|    case PRIM3D_TRISTRIP_RVRSE: | ||||
|       return nr < 3; | ||||
|    default: | ||||
|       return 1; | ||||
|    }	 | ||||
|    bmBufferData(batch->bm, | ||||
| 		batch->buffer, | ||||
| 		BATCH_SZ, | ||||
| 		NULL, | ||||
| 		0); | ||||
| 		 | ||||
|    if (!batch->list)  | ||||
|       batch->list = bmNewBufferList(); | ||||
|  | ||||
|    drmMMClearBufList(batch->list); | ||||
|    batch->list_count = 0; | ||||
|    batch->nr_relocs = 0; | ||||
|    batch->flags = 0; | ||||
|  | ||||
|    bmAddBuffer( batch->bm, | ||||
| 	        batch->list, | ||||
| 		batch->buffer, | ||||
| 		DRM_MM_TT, | ||||
| 		NULL, | ||||
| 		&batch->offset[batch->list_count++]); | ||||
|  | ||||
|    batch->map = bmMapBuffer(batch->bm, batch->buffer, DRM_MM_WRITE); | ||||
|    batch->ptr = batch->map; | ||||
| } | ||||
|  | ||||
| static void intel_flush_inline_primitive( GLcontext *ctx ) | ||||
| /*====================================================================== | ||||
|  * Public functions | ||||
|  */ | ||||
| struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    GLuint used = intel->batch.ptr - intel->prim.start_ptr; | ||||
|    GLuint vertcount; | ||||
|    struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1); | ||||
|  | ||||
|    assert(intel->prim.primitive != ~0); | ||||
|    batch->intel = intel; | ||||
|    batch->bm = intel->bm; | ||||
|  | ||||
|    if (1) { | ||||
|       /* Check vertex size against the vertex we're specifying to | ||||
|        * hardware.  If it's wrong, ditch the primitive. | ||||
|        */  | ||||
|       if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size ))  | ||||
| 	 goto do_discard; | ||||
|    bmGenBuffers(intel->bm, 1, &batch->buffer, BM_BATCHBUFFER); | ||||
|    batch->last_fence = bmInitFence(batch->bm); | ||||
|    intel_batchbuffer_reset( batch ); | ||||
|    return batch; | ||||
| } | ||||
|  | ||||
|       vertcount = (used - 4)/ (intel->vertex_size * 4); | ||||
| void intel_batchbuffer_free( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    if (batch->map) | ||||
|       bmUnmapBuffer(batch->bm, batch->buffer); | ||||
|     | ||||
|    free(batch); | ||||
| } | ||||
|  | ||||
|       if (!vertcount) | ||||
| 	 goto do_discard; | ||||
| /* TODO: Push this whole function into bufmgr. | ||||
|  */ | ||||
| static void do_flush_locked( struct intel_batchbuffer *batch, | ||||
| 			     GLuint used, | ||||
| 			     GLboolean ignore_cliprects, | ||||
| 			     GLboolean allow_unlock) | ||||
| { | ||||
|    GLuint *ptr; | ||||
|    GLuint i; | ||||
|  | ||||
|    bmValidateBufferList( batch->bm,  | ||||
| 			 batch->list, | ||||
| 			 DRM_MM_TT ); | ||||
|  | ||||
|    /* Apply the relocations.  This nasty map indicates to me that the | ||||
|     * whole task should be done internally by the memory manager, and | ||||
|     * that dma buffers probably need to be pinned within agp space. | ||||
|     */ | ||||
|    ptr = (GLuint *)bmMapBuffer(batch->bm, batch->buffer, DRM_MM_WRITE); | ||||
|  | ||||
|     | ||||
|    for (i = 0; i < batch->nr_relocs; i++) { | ||||
|       struct buffer_reloc *r = &batch->reloc[i]; | ||||
|        | ||||
|       if (vertcount * intel->vertex_size * 4 != used - 4) { | ||||
| 	 fprintf(stderr, "vertex size confusion %d %d\n", used,  | ||||
| 		 intel->vertex_size * vertcount * 4); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|  | ||||
|       if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) { | ||||
| 	 fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive, | ||||
| 		 vertcount); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|       assert(r->elem < batch->list_count); | ||||
|       ptr[r->offset/4] = batch->offset[r->elem] + r->delta; | ||||
|    } | ||||
|  | ||||
|    if (used < 8) | ||||
|       goto do_discard; | ||||
|    if (INTEL_DEBUG & DEBUG_DMA) | ||||
|       intel_dump_batchbuffer( 0, ptr, used ); | ||||
|  | ||||
|    *(int *)intel->prim.start_ptr = (_3DPRIMITIVE |  | ||||
| 				    intel->prim.primitive | | ||||
| 				    (used/4-2)); | ||||
|  | ||||
|    goto finished; | ||||
|    bmUnmapBuffer(batch->bm, batch->buffer); | ||||
|     | ||||
|  do_discard: | ||||
|    intel->batch.ptr -= used; | ||||
|    intel->batch.space += used; | ||||
|    assert(intel->batch.space >= 0); | ||||
|  | ||||
|  finished: | ||||
|    intel->prim.primitive = ~0; | ||||
|    intel->prim.start_ptr = 0; | ||||
|    intel->prim.flush = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Emit a primitive referencing vertices in a vertex buffer. | ||||
|  */ | ||||
| void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %x\n", __FUNCTION__, prim); | ||||
|  | ||||
|  | ||||
|    /* Finish any in-progress primitive: | ||||
|    /* Fire the batch buffer, which was uploaded above: | ||||
|     */ | ||||
|    INTEL_FIREVERTICES( intel ); | ||||
|     | ||||
|    /* Emit outstanding state: | ||||
|     */ | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|     | ||||
|    /* Make sure there is some space in this buffer: | ||||
|     */ | ||||
|    if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) | ||||
|       intelFlushBatch(intel, GL_TRUE);  | ||||
|  | ||||
|  | ||||
| #if 1 | ||||
|    if (((int)intel->batch.ptr) & 0x4) { | ||||
|       BEGIN_BATCH(1); | ||||
|       OUT_BATCH(0); | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|    intel_batch_ioctl(batch->intel,  | ||||
| 		     batch->offset[0], | ||||
| 		     used, | ||||
| 		     ignore_cliprects, | ||||
| 		     allow_unlock); | ||||
| #endif | ||||
|  | ||||
|    /* Emit a slot which will be filled with the inline primitive | ||||
|     * command later. | ||||
|     */ | ||||
|    BEGIN_BATCH(2); | ||||
|    OUT_BATCH( 0 ); | ||||
|  | ||||
|    intel->prim.start_ptr = batch_ptr; | ||||
|    intel->prim.primitive = prim; | ||||
|    intel->prim.flush = intel_flush_inline_primitive; | ||||
|  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelRestartInlinePrimitive( intelContextPtr intel ) | ||||
| { | ||||
|    GLuint prim = intel->prim.primitive; | ||||
|  | ||||
|    intel_flush_inline_primitive( &intel->ctx ); | ||||
|    if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */ | ||||
|    intelStartInlinePrimitive( intel, prim ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelWrapInlinePrimitive( intelContextPtr intel ) | ||||
| { | ||||
|    GLuint prim = intel->prim.primitive; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    intel_flush_inline_primitive( &intel->ctx ); | ||||
|    intelFlushBatch(intel, GL_TRUE); | ||||
|    intelStartInlinePrimitive( intel, prim ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Emit a primitive with space for inline vertices. | ||||
|  */ | ||||
| GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  | ||||
| 				       int primitive, | ||||
| 				       int dwords, | ||||
| 				       int vertex_size ) | ||||
| { | ||||
|    GLuint *tmp = 0; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords); | ||||
|  | ||||
|    /* Emit outstanding state: | ||||
|     */ | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|  | ||||
|  | ||||
|    if (1) { | ||||
|       int used = dwords * 4; | ||||
|       int vertcount; | ||||
|  | ||||
|       /* Check vertex size against the vertex we're specifying to | ||||
|        * hardware.  If it's wrong, ditch the primitive. | ||||
|        */  | ||||
|       if (!intel->vtbl.check_vertex_size( intel, vertex_size ))  | ||||
| 	 goto do_discard; | ||||
|  | ||||
|       vertcount = dwords / vertex_size; | ||||
|        | ||||
|       if (dwords % vertex_size) { | ||||
| 	 fprintf(stderr, "did not request a whole number of vertices\n"); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|  | ||||
|       if (bad_prim_vertex_nr( primitive, vertcount )) { | ||||
| 	 fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount); | ||||
| 	 goto do_discard; | ||||
|       } | ||||
|  | ||||
|       if (used < 8) | ||||
| 	 goto do_discard; | ||||
|    } | ||||
|  | ||||
|    /* Emit 3D_PRIMITIVE commands: | ||||
|     */ | ||||
|    BEGIN_BATCH(1 + dwords); | ||||
|    OUT_BATCH( _3DPRIMITIVE |  | ||||
| 	      primitive | | ||||
| 	      (dwords-1) ); | ||||
|  | ||||
|    tmp = (GLuint *)batch_ptr; | ||||
|    batch_ptr += dwords * 4; | ||||
|  | ||||
|    ADVANCE_BATCH(); | ||||
|  | ||||
|  do_discard: | ||||
|    return tmp; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Copy the back buffer to the front buffer.  | ||||
|  */ | ||||
| void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )  | ||||
| { | ||||
|    intelContextPtr intel; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|  | ||||
|    intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *pbox = dPriv->pClipRects; | ||||
|       int pitch = intelScreen->front.pitch; | ||||
|       int cpp = intelScreen->cpp; | ||||
|       int i; | ||||
|       GLuint CMD, BR13; | ||||
|       BATCH_LOCALS; | ||||
|  | ||||
|       switch(cpp) { | ||||
|       case 2:  | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); | ||||
| 	 CMD = XY_SRC_COPY_BLT_CMD; | ||||
| 	 break; | ||||
|       case 4: | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25); | ||||
| 	 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 		XY_SRC_COPY_BLT_WRITE_RGB); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); | ||||
| 	 CMD = XY_SRC_COPY_BLT_CMD; | ||||
| 	 break; | ||||
|       } | ||||
|  | ||||
|       if (0) | ||||
| 	 intel_draw_performance_boxes( intel ); | ||||
|  | ||||
|       for (i = 0 ; i < nbox; i++, pbox++)  | ||||
|       { | ||||
| 	 if (pbox->x1 > pbox->x2 || | ||||
| 	     pbox->y1 > pbox->y2 || | ||||
| 	     pbox->x2 > intelScreen->width || | ||||
| 	     pbox->y2 > intelScreen->height) | ||||
| 	    continue; | ||||
|    batch->last_fence = bmFenceBufferList(batch->bm, batch->list); | ||||
|    if (!batch->intel->last_swap_fence_retired) { | ||||
|       int retired; | ||||
|       drmFence dFence = {0,batch->intel->last_swap_fence}; | ||||
|   | ||||
| 	 BEGIN_BATCH( 8); | ||||
| 	 OUT_BATCH( CMD ); | ||||
| 	 OUT_BATCH( BR13 ); | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( (pbox->y2 << 16) | pbox->x2 ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_BATCH( intelScreen->front.offset ); | ||||
| 	 else | ||||
| 	    OUT_BATCH( intelScreen->back.offset );			 | ||||
|  | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( BR13 & 0xffff ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_BATCH( intelScreen->back.offset );			 | ||||
| 	 else | ||||
| 	    OUT_BATCH( intelScreen->front.offset ); | ||||
|  | ||||
| 	 ADVANCE_BATCH(); | ||||
|      /*FIXME: Temporary fix for fence ageing | ||||
|       * | ||||
|       */ | ||||
|       if (!drmTestFence(batch->intel->driFd, dFence, 0, &retired)) { | ||||
| 	 batch->intel->last_swap_fence_retired = retired;  | ||||
|       } | ||||
|    } | ||||
|    intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    }	   | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelEmitFillBlitLocked( intelContextPtr intel, | ||||
| 			      GLuint cpp, | ||||
| 			      GLshort dst_pitch, | ||||
| 			      GLuint dst_offset, | ||||
| 			      GLshort x, GLshort y,  | ||||
| 			      GLshort w, GLshort h, | ||||
| 			      GLuint color ) | ||||
| GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    GLuint BR13, CMD; | ||||
|    BATCH_LOCALS; | ||||
|    struct intel_context *intel = batch->intel; | ||||
|    GLuint used = batch->ptr - batch->map; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|    if (used == 0)  | ||||
|       return batch->last_fence; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24); | ||||
|       CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | | ||||
| 	     XY_COLOR_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    /* Add the MI_BATCH_BUFFER_END.  Always add an MI_FLUSH - this is a | ||||
|     * performance drain that we would like to avoid. | ||||
|     */ | ||||
|    if (used & 4) { | ||||
|       ((int *)batch->ptr)[0] = intel->vtbl.flush_cmd(); | ||||
|       ((int *)batch->ptr)[1] = 0; | ||||
|       ((int *)batch->ptr)[2] = MI_BATCH_BUFFER_END; | ||||
|       used += 12; | ||||
|    } | ||||
|    else { | ||||
|       ((int *)batch->ptr)[0] = intel->vtbl.flush_cmd() ;  | ||||
|       ((int *)batch->ptr)[1] = MI_BATCH_BUFFER_END; | ||||
|       used += 8; | ||||
|    } | ||||
|  | ||||
|    BEGIN_BATCH( 6); | ||||
|    OUT_BATCH( CMD ); | ||||
|    OUT_BATCH( BR13 ); | ||||
|    OUT_BATCH( (y << 16) | x ); | ||||
|    OUT_BATCH( ((y+h) << 16) | (x+w) ); | ||||
|    OUT_BATCH( dst_offset ); | ||||
|    OUT_BATCH( color ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|    bmUnmapBuffer(batch->bm, batch->buffer); | ||||
|    batch->ptr = NULL; | ||||
|    batch->map = NULL; | ||||
|  | ||||
|  | ||||
| /* Copy BitBlt | ||||
|  */ | ||||
| void intelEmitCopyBlitLocked( intelContextPtr intel, | ||||
| 			      GLuint cpp, | ||||
| 			      GLshort src_pitch, | ||||
| 			      GLuint  src_offset, | ||||
| 			      GLshort dst_pitch, | ||||
| 			      GLuint  dst_offset, | ||||
| 			      GLshort src_x, GLshort src_y, | ||||
| 			      GLshort dst_x, GLshort dst_y, | ||||
| 			      GLshort w, GLshort h ) | ||||
| { | ||||
|    GLuint CMD, BR13; | ||||
|    int dst_y2 = dst_y + h; | ||||
|    int dst_x2 = dst_x + w; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    src_pitch *= cpp; | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = dst_pitch | (0xCC << 16) | (1<<24); | ||||
|       CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 	     XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (dst_y2 < dst_y || | ||||
|        dst_x2 < dst_x) { | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    BEGIN_BATCH( 12); | ||||
|    OUT_BATCH( CMD ); | ||||
|    OUT_BATCH( BR13 ); | ||||
|    OUT_BATCH( (dst_y << 16) | dst_x ); | ||||
|    OUT_BATCH( (dst_y2 << 16) | dst_x2 ); | ||||
|    OUT_BATCH( dst_offset );	 | ||||
|    OUT_BATCH( (src_y << 16) | src_x ); | ||||
|    OUT_BATCH( src_pitch ); | ||||
|    OUT_BATCH( src_offset );  | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all, | ||||
| 		      GLint cx1, GLint cy1, GLint cw, GLint ch) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|    GLuint clear_depth, clear_color; | ||||
|    GLint cx, cy; | ||||
|    GLint pitch = intelScreen->front.pitch; | ||||
|    GLint cpp = intelScreen->cpp; | ||||
|    GLint i; | ||||
|    GLuint BR13, CMD, D_CMD; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|     | ||||
|    clear_color = intel->ClearColor; | ||||
|    clear_depth = 0; | ||||
|  | ||||
|    if (flags & BUFFER_BIT_DEPTH) { | ||||
|       clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth); | ||||
|    } | ||||
|  | ||||
|    if (flags & BUFFER_BIT_STENCIL) { | ||||
|       clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; | ||||
|    } | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 2:  | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); | ||||
|       D_CMD = CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | | ||||
| 	     XY_COLOR_BLT_WRITE_ALPHA |  | ||||
| 	     XY_COLOR_BLT_WRITE_RGB); | ||||
|       D_CMD = XY_COLOR_BLT_CMD; | ||||
|       if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB; | ||||
|       if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA; | ||||
|       break; | ||||
|    default: | ||||
|       BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); | ||||
|       D_CMD = CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    /* TODO: Just pass the relocation list and dma buffer up to the | ||||
|     * kernel. | ||||
|     */ | ||||
|    if (!intel->locked) | ||||
|    { | ||||
|       /* flip top to bottom */ | ||||
|       cy = intel->driDrawable->h-cy1-ch; | ||||
|       cx = cx1 + intel->drawX; | ||||
|       cy += intel->drawY; | ||||
|       assert(!(batch->flags & INTEL_BATCH_NO_CLIPRECTS)); | ||||
|  | ||||
|       /* adjust for page flipping */ | ||||
|       if ( intel->sarea->pf_current_page == 1 ) { | ||||
| 	 GLuint tmp = flags; | ||||
|  | ||||
| 	 flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); | ||||
| 	 if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT; | ||||
| 	 if ( tmp & BUFFER_BIT_BACK_LEFT )  flags |= BUFFER_BIT_FRONT_LEFT; | ||||
|       } | ||||
|  | ||||
|       for (i = 0 ; i < intel->numClipRects ; i++)  | ||||
|       { 	  | ||||
| 	 drm_clip_rect_t *box = &intel->pClipRects[i];	  | ||||
| 	 drm_clip_rect_t b; | ||||
|  | ||||
| 	 if (!all) { | ||||
| 	    GLint x = box[i].x1; | ||||
| 	    GLint y = box[i].y1; | ||||
| 	    GLint w = box[i].x2 - x; | ||||
| 	    GLint h = box[i].y2 - y; | ||||
|  | ||||
| 	    if (x < cx) w -= cx - x, x = cx;  | ||||
| 	    if (y < cy) h -= cy - y, y = cy; | ||||
| 	    if (x + w > cx + cw) w = cx + cw - x; | ||||
| 	    if (y + h > cy + ch) h = cy + ch - y; | ||||
| 	    if (w <= 0) continue; | ||||
| 	    if (h <= 0) continue; | ||||
|  | ||||
| 	    b.x1 = x; | ||||
| 	    b.y1 = y; | ||||
| 	    b.x2 = x + w; | ||||
| 	    b.y2 = y + h;       | ||||
| 	 } else { | ||||
| 	    b = *box; | ||||
| 	 } | ||||
|  | ||||
|  | ||||
| 	 if (b.x1 > b.x2 || | ||||
| 	     b.y1 > b.y2 || | ||||
| 	     b.x2 > intelScreen->width || | ||||
| 	     b.y2 > intelScreen->height) | ||||
| 	    continue; | ||||
|  | ||||
| 	 if ( flags & BUFFER_BIT_FRONT_LEFT ) {	     | ||||
| 	    BEGIN_BATCH( 6);	     | ||||
| 	    OUT_BATCH( CMD ); | ||||
| 	    OUT_BATCH( BR13 ); | ||||
| 	    OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
| 	    OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
| 	    OUT_BATCH( intelScreen->front.offset ); | ||||
| 	    OUT_BATCH( clear_color ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 } | ||||
|  | ||||
| 	 if ( flags & BUFFER_BIT_BACK_LEFT ) { | ||||
| 	    BEGIN_BATCH( 6);  | ||||
| 	    OUT_BATCH( CMD ); | ||||
| 	    OUT_BATCH( BR13 ); | ||||
| 	    OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
| 	    OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
| 	    OUT_BATCH( intelScreen->back.offset ); | ||||
| 	    OUT_BATCH( clear_color ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 } | ||||
|  | ||||
| 	 if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) { | ||||
| 	    BEGIN_BATCH( 6); | ||||
| 	    OUT_BATCH( D_CMD ); | ||||
| 	    OUT_BATCH( BR13 ); | ||||
| 	    OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
| 	    OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
| 	    OUT_BATCH( intelScreen->depth.offset ); | ||||
| 	    OUT_BATCH( clear_depth ); | ||||
| 	    ADVANCE_BATCH(); | ||||
| 	 }       | ||||
|       } | ||||
|    } | ||||
|    intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelDestroyBatchBuffer( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    if (intel->alloc.ptr) { | ||||
|       intelFreeAGP( intel, intel->alloc.ptr ); | ||||
|       intel->alloc.ptr = 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitBatchBuffer( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    if (!intel->intelScreen->allow_batchbuffer || getenv("INTEL_NO_BATCH")) { | ||||
|       intel->alloc.size = 8 * 1024; | ||||
|       intel->alloc.ptr = malloc( intel->alloc.size ); | ||||
|       intel->alloc.offset = 0; | ||||
|       LOCK_HARDWARE(intel); | ||||
|       do_flush_locked(batch, used, GL_FALSE, GL_TRUE); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|    } | ||||
|    else { | ||||
|       switch (intel->intelScreen->deviceID) { | ||||
|       case PCI_CHIP_I865_G: | ||||
| 	 /* HW bug?  Seems to crash if batchbuffer crosses 4k boundary. | ||||
| 	  */ | ||||
| 	 intel->alloc.size = 8 * 1024;  | ||||
| 	 break; | ||||
|       default: | ||||
| 	 /* This is the smallest amount of memory the kernel deals with. | ||||
| 	  * We'd ideally like to make this smaller. | ||||
| 	  */ | ||||
| 	 intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity; | ||||
| 	 break; | ||||
|       } | ||||
|  | ||||
|       intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size ); | ||||
|       if (intel->alloc.ptr) | ||||
| 	 intel->alloc.offset =  | ||||
| 	    intelAgpOffsetFromVirtual( intel, intel->alloc.ptr ); | ||||
|       GLboolean ignore_cliprects = !(batch->flags & INTEL_BATCH_CLIPRECTS); | ||||
|       do_flush_locked(batch, used, ignore_cliprects, GL_FALSE); | ||||
|    } | ||||
|  | ||||
|    if (!intel->alloc.ptr) { | ||||
|       FALLBACK(intel, INTEL_FALLBACK_NO_BATCHBUFFER, 1); | ||||
|    } | ||||
|    else { | ||||
|       intel->prim.flush = 0; | ||||
|       intel->vtbl.emit_invarient_state( intel ); | ||||
|  | ||||
|       /* Make sure this gets to the hardware, even if we have no cliprects: | ||||
|        */ | ||||
|       LOCK_HARDWARE( intel ); | ||||
|       intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE ); | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|    } | ||||
|    /* Reset the buffer: | ||||
|     */ | ||||
|    intel_batchbuffer_reset( batch ); | ||||
|    return batch->last_fence; | ||||
| } | ||||
|  | ||||
| void intel_batchbuffer_finish( struct intel_batchbuffer *batch ) | ||||
| {    | ||||
|    bmFinishFence(batch->bm,  | ||||
| 		 intel_batchbuffer_flush(batch)); | ||||
| } | ||||
|     | ||||
|  | ||||
| /*  This is the only way buffers get added to the validate list. | ||||
|  */ | ||||
| GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch, | ||||
| 					GLuint buffer, | ||||
| 					GLuint flags, | ||||
| 					GLuint delta ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    assert(batch->nr_relocs <= MAX_RELOCS); | ||||
|  | ||||
|    i = bmScanBufferList(batch->bm, batch->list, buffer); | ||||
|    if (i == -1) { | ||||
|       i = batch->list_count;  | ||||
|       bmAddBuffer(batch->bm, | ||||
| 		  batch->list, | ||||
| 		  buffer, | ||||
| 		  flags, | ||||
| 		  NULL, | ||||
| 		  &batch->offset[batch->list_count++]); | ||||
|    } | ||||
|  | ||||
|    { | ||||
|       struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++]; | ||||
|       r->offset = batch->ptr - batch->map; | ||||
|       r->delta = delta; | ||||
|       r->elem = i; | ||||
|    } | ||||
|  | ||||
|    batch->ptr += 4; | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intel_batchbuffer_data(struct intel_batchbuffer *batch, | ||||
| 			    const void *data, | ||||
| 			    GLuint bytes, | ||||
| 			    GLuint flags) | ||||
| { | ||||
|    assert((bytes & 3) == 0); | ||||
|    intel_batchbuffer_require_space(batch, bytes, flags); | ||||
|    __memcpy(batch->ptr, data, bytes); | ||||
|    batch->ptr += bytes; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,123 +1,124 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BATCHBUFFER_H | ||||
| #define INTEL_BATCHBUFFER_H | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "mtypes.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
| struct intel_context; | ||||
|  | ||||
| #define BATCH_SZ 4096 | ||||
| #define BATCH_RESERVED 16 | ||||
|  | ||||
| #define MAX_RELOCS 100 | ||||
|  | ||||
| #define INTEL_BATCH_NO_CLIPRECTS 0x1 | ||||
| #define INTEL_BATCH_CLIPRECTS    0x2 | ||||
|  | ||||
| struct buffer_reloc { | ||||
|    GLuint offset; | ||||
|    GLuint elem;			/* elem in buffer list, not buffer id */ | ||||
|    GLuint delta;		/* not needed? */ | ||||
| }; | ||||
|  | ||||
| struct intel_batchbuffer { | ||||
|    struct bufmgr *bm; | ||||
|    struct intel_context *intel; | ||||
|  | ||||
|    GLuint buffer; | ||||
|    GLuint last_fence; | ||||
|    GLuint flags; | ||||
|  | ||||
|    /* In progress: | ||||
|     */ | ||||
|    unsigned long offset[MAX_RELOCS]; | ||||
|    struct _drmMMBufList *list;    | ||||
|    GLuint list_count; | ||||
|    GLubyte *map; | ||||
|    GLubyte *ptr;  | ||||
|  | ||||
|    struct buffer_reloc reloc[MAX_RELOCS]; | ||||
|    GLuint nr_relocs; | ||||
| }; | ||||
|  | ||||
| struct intel_batchbuffer *intel_batchbuffer_alloc( struct intel_context *intel ); | ||||
|  | ||||
| void intel_batchbuffer_free( struct intel_batchbuffer *batch ); | ||||
|  | ||||
|  | ||||
| #define BATCH_LOCALS	GLubyte *batch_ptr; | ||||
| void intel_batchbuffer_finish( struct intel_batchbuffer *batch ); | ||||
|  | ||||
| /* #define VERBOSE 0 */ | ||||
| #ifndef VERBOSE | ||||
| extern int VERBOSE; | ||||
| #endif | ||||
| GLuint intel_batchbuffer_flush( struct intel_batchbuffer *batch ); | ||||
|  | ||||
|  | ||||
| #define BEGIN_BATCH(n)							\ | ||||
| do {									\ | ||||
|    if (VERBOSE) fprintf(stderr, 					\ | ||||
| 			"BEGIN_BATCH(%d) in %s, %d dwords free\n",	\ | ||||
| 			(n), __FUNCTION__, intel->batch.space/4);	\ | ||||
|    if (intel->batch.space < (n)*4)					\ | ||||
|       intelFlushBatch(intel, GL_TRUE);					\ | ||||
|    batch_ptr = intel->batch.ptr;					\ | ||||
| } while (0) | ||||
| /* Unlike bmBufferData, this currently requires the buffer be mapped. | ||||
|  * Consider it a convenience function wrapping multple | ||||
|  * intel_buffer_dword() calls. | ||||
|  */ | ||||
| void intel_batchbuffer_data(struct intel_batchbuffer *batch, | ||||
| 			    const void *data, | ||||
| 			    GLuint bytes, | ||||
| 			    GLuint flags); | ||||
|  | ||||
| #define OUT_BATCH(n)					\ | ||||
| do {							\ | ||||
|    *(GLuint *)batch_ptr = (n);				\ | ||||
|    if (VERBOSE) fprintf(stderr, " -- %08x at %s/%d\n", (n), __FILE__, __LINE__);	\ | ||||
|    batch_ptr += 4;					\ | ||||
| } while (0) | ||||
| void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, | ||||
| 				   GLuint bytes); | ||||
|  | ||||
| #define ADVANCE_BATCH()						\ | ||||
| do {								\ | ||||
|    if (VERBOSE) fprintf(stderr, "ADVANCE_BATCH()\n");		\ | ||||
|    intel->batch.space -= (batch_ptr - intel->batch.ptr);	\ | ||||
|    intel->batch.ptr = batch_ptr;				\ | ||||
|    assert(intel->batch.space >= 0);				\ | ||||
| } while(0) | ||||
| GLboolean intel_batchbuffer_emit_reloc( struct intel_batchbuffer *batch, | ||||
| 					GLuint buffer, | ||||
| 					GLuint flags, | ||||
| 					GLuint offset ); | ||||
|  | ||||
| extern void intelInitBatchBuffer( GLcontext *ctx ); | ||||
| extern void intelDestroyBatchBuffer( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ); | ||||
| extern void intelWrapInlinePrimitive( intelContextPtr intel ); | ||||
| extern void intelRestartInlinePrimitive( intelContextPtr intel ); | ||||
| extern GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,  | ||||
| 					      int primitive, int dwords, | ||||
| 					      int vertex_size); | ||||
| extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv ); | ||||
| extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 			     GLint cx1, GLint cy1, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelEmitCopyBlitLocked( intelContextPtr intel, | ||||
| 				     GLuint cpp, | ||||
| 				     GLshort src_pitch, | ||||
| 				     GLuint  src_offset, | ||||
| 				     GLshort dst_pitch, | ||||
| 				     GLuint  dst_offset, | ||||
| 				     GLshort srcx, GLshort srcy, | ||||
| 				     GLshort dstx, GLshort dsty, | ||||
| 				     GLshort w, GLshort h ); | ||||
|  | ||||
| extern void intelEmitFillBlitLocked( intelContextPtr intel, | ||||
| 				     GLuint cpp, | ||||
| 				     GLshort dst_pitch, | ||||
| 				     GLuint dst_offset, | ||||
| 				     GLshort x, GLshort y,  | ||||
| 				     GLshort w, GLshort h, | ||||
| 				     GLuint color ); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static __inline GLuint *intelExtendInlinePrimitive( intelContextPtr intel,  | ||||
| 						GLuint dwords ) | ||||
| /* Inline functions - might actually be better off with these | ||||
|  * non-inlined.  Certainly better off switching all command packets to | ||||
|  * be passed as structs rather than dwords, but that's a little bit of | ||||
|  * work... | ||||
|  */ | ||||
| static INLINE GLuint  | ||||
| intel_batchbuffer_space( struct intel_batchbuffer *batch ) | ||||
| { | ||||
|    GLuint sz = dwords * sizeof(GLuint); | ||||
|    GLuint *ptr; | ||||
|  | ||||
|    if (intel->batch.space < sz) { | ||||
|       intelWrapInlinePrimitive( intel ); | ||||
| /*       assert(intel->batch.space >= sz); */ | ||||
|    } | ||||
|  | ||||
| /*    assert(intel->prim.primitive != ~0); */ | ||||
|    ptr = (GLuint *)intel->batch.ptr; | ||||
|    intel->batch.ptr += sz; | ||||
|    intel->batch.space -= sz; | ||||
|  | ||||
|    return ptr; | ||||
|    return (BATCH_SZ - BATCH_RESERVED) - (batch->ptr - batch->map); | ||||
| } | ||||
|  | ||||
|  | ||||
| static INLINE void  | ||||
| intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, | ||||
| 			     GLuint dword) | ||||
| { | ||||
|    assert(batch->map); | ||||
|    assert(intel_batchbuffer_space(batch) >= 4); | ||||
|    *(GLuint *)(batch->ptr) = dword; | ||||
|    batch->ptr += 4; | ||||
| } | ||||
|  | ||||
| static INLINE void  | ||||
| intel_batchbuffer_require_space(struct intel_batchbuffer *batch, | ||||
| 				GLuint sz, | ||||
| 				GLuint flags) | ||||
| { | ||||
|    assert(sz < BATCH_SZ - 8); | ||||
|    if (intel_batchbuffer_space(batch) < sz || | ||||
|        (batch->flags != 0 && flags != 0 && batch->flags != flags)) | ||||
|       intel_batchbuffer_flush(batch); | ||||
|     | ||||
|    batch->flags |= flags; | ||||
| } | ||||
|  | ||||
| /* Here are the crusty old macros, to be removed: | ||||
|  */ | ||||
| #define BATCH_LOCALS  | ||||
|  | ||||
| #define BEGIN_BATCH(n, flags) do {				\ | ||||
|    assert(!intel->prim.flush);					\ | ||||
|    intel_batchbuffer_require_space(intel->batch, (n)*4, flags);	\ | ||||
| } while (0) | ||||
|  | ||||
| #define OUT_BATCH(d)  intel_batchbuffer_emit_dword(intel->batch, d) | ||||
|  | ||||
| #define OUT_RELOC(buf,flags,delta) do { 				\ | ||||
|    assert((delta) >= 0);							\ | ||||
|    intel_batchbuffer_emit_reloc(intel->batch, buf, flags, delta);	\ | ||||
| } while (0) | ||||
|  | ||||
| #define ADVANCE_BATCH() do { } while(0) | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										444
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										444
									
								
								src/mesa/drivers/dri/i915/intel_blit.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,444 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "context.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_reg.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Copy the back color buffer to the front color buffer.  | ||||
|  * Used for SwapBuffers(). | ||||
|  */ | ||||
| void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )  | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    struct intel_context *intel; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|  | ||||
|    /* We need a rendering context in order to issue the blit cmd. | ||||
|     * Use the current context. | ||||
|     * XXX need to fix this someday. | ||||
|     */ | ||||
|    if (!ctx) { | ||||
|       _mesa_problem(NULL, "No current context in intelCopyBuffer()"); | ||||
|       return; | ||||
|    } | ||||
|    intel = (struct intel_context *) ctx; | ||||
|  | ||||
|    /* FIXME: Temporary fix for fence ageing. | ||||
|     *  | ||||
|     */ | ||||
|  | ||||
|    if (!intel->last_swap_fence_retired) { | ||||
|       bmFinishFence(intel->bm, intel->last_swap_fence); | ||||
|    } | ||||
|  | ||||
|    /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets | ||||
|     * should work regardless. | ||||
|     */ | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable && | ||||
|        intel->driDrawable->numClipRects) | ||||
|    { | ||||
|       const intelScreenPrivate *intelScreen = intel->intelScreen; | ||||
|       struct gl_framebuffer *fb | ||||
|          = (struct gl_framebuffer *) dPriv->driverPrivate; | ||||
|       const struct intel_region *frontRegion | ||||
|          = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); | ||||
|       const struct intel_region *backRegion | ||||
|          = intel_get_rb_region(fb, BUFFER_BACK_LEFT); | ||||
|       const int nbox = dPriv->numClipRects; | ||||
|       const drm_clip_rect_t *pbox = dPriv->pClipRects; | ||||
|       const int pitch = frontRegion->pitch; | ||||
|       const int cpp = frontRegion->cpp; | ||||
|       int BR13, CMD; | ||||
|       int i; | ||||
|  | ||||
|       ASSERT(fb); | ||||
|       ASSERT(fb->Name == 0); /* Not a user-created FBO */ | ||||
|       ASSERT(frontRegion); | ||||
|       ASSERT(backRegion); | ||||
|       ASSERT(frontRegion->pitch == backRegion->pitch); | ||||
|       ASSERT(frontRegion->cpp == backRegion->cpp); | ||||
|  | ||||
|       if (cpp == 2) { | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24); | ||||
| 	 CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       }  | ||||
|       else { | ||||
| 	 BR13 = (pitch * cpp) | (0xCC << 16) | (1<<24) | (1<<25); | ||||
| 	 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 		XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       } | ||||
|  | ||||
|       for (i = 0 ; i < nbox; i++, pbox++)  | ||||
|       { | ||||
| 	 if (pbox->x1 > pbox->x2 || | ||||
| 	     pbox->y1 > pbox->y2 || | ||||
| 	     pbox->x2 > intelScreen->width || | ||||
| 	     pbox->y2 > intelScreen->height) | ||||
| 	    continue; | ||||
|   | ||||
| 	 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); | ||||
| 	 OUT_BATCH( CMD ); | ||||
| 	 OUT_BATCH( BR13 ); | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( (pbox->y2 << 16) | pbox->x2 ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_RELOC( frontRegion->buffer, DRM_MM_TT|DRM_MM_WRITE, 0 ); | ||||
| 	 else | ||||
| 	    OUT_RELOC( backRegion->buffer, DRM_MM_TT|DRM_MM_WRITE, 0 );  | ||||
| 	 OUT_BATCH( (pbox->y1 << 16) | pbox->x1 ); | ||||
| 	 OUT_BATCH( BR13 & 0xffff ); | ||||
|  | ||||
| 	 if (intel->sarea->pf_current_page == 0)  | ||||
| 	    OUT_RELOC( backRegion->buffer, DRM_MM_TT|DRM_MM_READ, 0 );  | ||||
| 	 else | ||||
| 	    OUT_RELOC( frontRegion->buffer, DRM_MM_TT|DRM_MM_READ, 0 ); | ||||
|  | ||||
| 	 ADVANCE_BATCH(); | ||||
|       } | ||||
|  | ||||
|       intel->last_swap_fence = intel_batchbuffer_flush( intel->batch ); | ||||
|       intel->last_swap_fence_retired = GL_FALSE; | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelEmitFillBlit( struct intel_context *intel, | ||||
| 			GLuint cpp, | ||||
| 			GLshort dst_pitch, | ||||
| 			GLuint dst_buffer, | ||||
| 			GLuint dst_offset, | ||||
| 			GLshort x, GLshort y,  | ||||
| 			GLshort w, GLshort h, | ||||
| 			GLuint color ) | ||||
| { | ||||
|    GLuint BR13, CMD; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24); | ||||
|       CMD = XY_COLOR_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | | ||||
| 	     XY_COLOR_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); | ||||
|    OUT_BATCH( CMD ); | ||||
|    OUT_BATCH( BR13 ); | ||||
|    OUT_BATCH( (y << 16) | x ); | ||||
|    OUT_BATCH( ((y+h) << 16) | (x+w) ); | ||||
|    OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset ); | ||||
|    OUT_BATCH( color ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Copy BitBlt | ||||
|  */ | ||||
| void intelEmitCopyBlit( struct intel_context *intel, | ||||
| 			GLuint cpp, | ||||
| 			GLshort src_pitch, | ||||
| 			GLuint  src_buffer, | ||||
| 			GLuint  src_offset, | ||||
| 			GLshort dst_pitch, | ||||
| 			GLuint  dst_buffer, | ||||
| 			GLuint  dst_offset, | ||||
| 			GLshort src_x, GLshort src_y, | ||||
| 			GLshort dst_x, GLshort dst_y, | ||||
| 			GLshort w, GLshort h ) | ||||
| { | ||||
|    GLuint CMD, BR13; | ||||
|    int dst_y2 = dst_y + h; | ||||
|    int dst_x2 = dst_x + w; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|  | ||||
|    DBG("%s src:buf(%d)/%d+%d %d,%d dst:buf(%d)/%d+%d %d,%d sz:%dx%d\n", | ||||
|        __FUNCTION__, | ||||
|        src_buffer, src_pitch, src_offset, src_x, src_y, | ||||
|        dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, | ||||
|        w,h); | ||||
|  | ||||
|    src_pitch *= cpp; | ||||
|    dst_pitch *= cpp; | ||||
|  | ||||
|    switch(cpp) { | ||||
|    case 1:  | ||||
|    case 2:  | ||||
|    case 3:  | ||||
|       BR13 = (((GLint)dst_pitch)&0xffff) | (0xCC << 16) | (1<<24); | ||||
|       CMD = XY_SRC_COPY_BLT_CMD; | ||||
|       break; | ||||
|    case 4: | ||||
|       BR13 = (((GLint)dst_pitch)&0xffff) | (0xCC << 16) | (1<<24) | (1<<25); | ||||
|       CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||||
| 	     XY_SRC_COPY_BLT_WRITE_RGB); | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (dst_y2 < dst_y || | ||||
|        dst_x2 < dst_x) { | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* Initial y values don't seem to work with negative pitches.  If | ||||
|     * we adjust the offsets manually (below), it seems to work fine. | ||||
|     * | ||||
|     * On the other hand, if we always adjust, the hardware doesn't | ||||
|     * know which blit directions to use, so overlapping copypixels get | ||||
|     * the wrong result. | ||||
|     */ | ||||
|    if ( dst_pitch > 0 &&  | ||||
| 	src_pitch > 0) { | ||||
|       BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); | ||||
|       OUT_BATCH( CMD ); | ||||
|       OUT_BATCH( BR13 ); | ||||
|       OUT_BATCH( (dst_y << 16) | dst_x ); | ||||
|       OUT_BATCH( (dst_y2 << 16) | dst_x2 ); | ||||
|       OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset );	 | ||||
|       OUT_BATCH( (src_y << 16) | src_x ); | ||||
|       OUT_BATCH( ((GLint)src_pitch&0xffff) ); | ||||
|       OUT_RELOC( src_buffer, DRM_MM_TT|DRM_MM_READ, src_offset );  | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
|    else { | ||||
|       BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); | ||||
|       OUT_BATCH( CMD ); | ||||
|       OUT_BATCH( BR13 ); | ||||
|       OUT_BATCH( (0 << 16) | dst_x ); | ||||
|       OUT_BATCH( (h << 16) | dst_x2 ); | ||||
|       OUT_RELOC( dst_buffer, DRM_MM_TT|DRM_MM_WRITE, dst_offset + dst_y * dst_pitch );	 | ||||
|       OUT_BATCH( (0 << 16) | src_x ); | ||||
|       OUT_BATCH( ((GLint)src_pitch&0xffff) ); | ||||
|       OUT_RELOC( src_buffer, DRM_MM_TT|DRM_MM_READ, src_offset + src_y * src_pitch );  | ||||
|       ADVANCE_BATCH(); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Use blitting to clear the renderbuffers named by 'flags'. | ||||
|  * Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferMask field | ||||
|  * since that might include software renderbuffers or renderbuffers | ||||
|  * which we're clearing with triangles. | ||||
|  * \param mask  bitmask of BUFFER_BIT_* values indicating buffers to clear | ||||
|  */ | ||||
| void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
|                         GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    GLuint clear_depth; | ||||
|    GLbitfield skipBuffers = 0; | ||||
|    BATCH_LOCALS; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_DRI) | ||||
|       _mesa_printf("%s %x\n", __FUNCTION__, mask); | ||||
|  | ||||
|    /* | ||||
|     * Compute values for clearing the buffers. | ||||
|     */ | ||||
|    clear_depth = 0; | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear); | ||||
|    } | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; | ||||
|    } | ||||
|  | ||||
|    /* If clearing both depth and stencil, skip BUFFER_BIT_STENCIL in | ||||
|     * the loop below. | ||||
|     */ | ||||
|    if ((mask & BUFFER_BIT_DEPTH) && (mask & BUFFER_BIT_STENCIL)) { | ||||
|       skipBuffers = BUFFER_BIT_STENCIL; | ||||
|    } | ||||
|  | ||||
|    /* XXX Move this flush/lock into the following conditional? */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->numClipRects) | ||||
|    { | ||||
|       drm_clip_rect_t clear; | ||||
|       int i; | ||||
|  | ||||
|       if (intel->ctx.DrawBuffer->Name == 0) { | ||||
|          /* clearing a window */ | ||||
|  | ||||
|          /* flip top to bottom */ | ||||
|          clear.x1 = cx + intel->drawX; | ||||
|          clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch; | ||||
|          clear.x2 = clear.x1 + cw; | ||||
|          clear.y2 = clear.y1 + ch; | ||||
|  | ||||
|          /* adjust for page flipping */ | ||||
|          if ( intel->sarea->pf_current_page == 1 ) { | ||||
|             const GLuint tmp = mask; | ||||
|             mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); | ||||
|             if ( tmp & BUFFER_BIT_FRONT_LEFT ) mask |= BUFFER_BIT_BACK_LEFT; | ||||
|             if ( tmp & BUFFER_BIT_BACK_LEFT )  mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|          } | ||||
|       } | ||||
|       else { | ||||
|          /* clearing FBO */ | ||||
|          ASSERT(intel->numClipRects == 1); | ||||
|          ASSERT(intel->pClipRects == &intel->fboRect); | ||||
|          clear.x1 = cx; | ||||
|          clear.y1 = intel->ctx.DrawBuffer->Height - cy - ch; | ||||
|          clear.x2 = clear.y1 + cw; | ||||
|          clear.y2 = clear.y1 + ch; | ||||
|          /* no change to mask */ | ||||
|       } | ||||
|  | ||||
|       for (i = 0 ; i < intel->numClipRects ; i++)  | ||||
|       { 	  | ||||
| 	 const drm_clip_rect_t *box = &intel->pClipRects[i];	  | ||||
| 	 drm_clip_rect_t b; | ||||
|          GLuint buf; | ||||
|          GLuint clearMask = mask; /* use copy, since we modify it below */ | ||||
|  | ||||
| 	 if (!all) { | ||||
| 	    intel_intersect_cliprects(&b, &clear, box); | ||||
| 	 } else { | ||||
| 	    b = *box; | ||||
| 	 } | ||||
|  | ||||
| 	 if (0) | ||||
| 	    _mesa_printf("clear %d,%d..%d,%d, mask %x\n",  | ||||
| 			 b.x1, b.y1, | ||||
| 			 b.x2, b.y2,  | ||||
| 			 mask); | ||||
|  | ||||
|          /* Loop over all renderbuffers */ | ||||
|          for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) { | ||||
|             const GLbitfield bufBit = 1 << buf; | ||||
|             if ((clearMask & bufBit) && !(bufBit & skipBuffers)) { | ||||
|                /* OK, clear this renderbuffer */ | ||||
|                const struct intel_renderbuffer *irb | ||||
|                   = intel_renderbuffer(ctx->DrawBuffer-> | ||||
|                                        Attachment[buf].Renderbuffer); | ||||
|                GLuint clearVal; | ||||
|                GLint pitch, cpp; | ||||
|                GLuint BR13, CMD; | ||||
|  | ||||
|                ASSERT(irb); | ||||
|                ASSERT(irb->region); | ||||
|  | ||||
|                pitch = irb->region->pitch; | ||||
|                cpp = irb->region->cpp; | ||||
|  | ||||
|                /* Setup the blit command */ | ||||
|                if (cpp == 4) { | ||||
|                   BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24) | (1<<25); | ||||
|                   if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) { | ||||
|                      CMD = XY_COLOR_BLT_CMD; | ||||
|                      if (clearMask & BUFFER_BIT_DEPTH) | ||||
|                         CMD |= XY_COLOR_BLT_WRITE_RGB; | ||||
|                      if (clearMask & BUFFER_BIT_STENCIL) | ||||
|                         CMD |= XY_COLOR_BLT_WRITE_ALPHA; | ||||
|                   } | ||||
|                   else { | ||||
|                      /* clearing RGBA */ | ||||
|                      CMD = (XY_COLOR_BLT_CMD | | ||||
|                             XY_COLOR_BLT_WRITE_ALPHA |  | ||||
|                             XY_COLOR_BLT_WRITE_RGB); | ||||
|                   } | ||||
|                } | ||||
|                else { | ||||
|                   ASSERT(cpp == 2 || cpp == 0); | ||||
|                   BR13 = (0xF0 << 16) | (pitch * cpp) | (1<<24); | ||||
|                   CMD = XY_COLOR_BLT_CMD; | ||||
|                } | ||||
|  | ||||
|                if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) { | ||||
|                   clearVal = clear_depth; | ||||
|                } | ||||
|                else { | ||||
|                   clearVal = (cpp == 4) | ||||
|                      ? intel->ClearColor8888 : intel->ClearColor565; | ||||
|                } | ||||
|                /* | ||||
|                _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n", | ||||
|                            buf, irb->Base.Name); | ||||
|                */ | ||||
|                BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); | ||||
|                OUT_BATCH( CMD ); | ||||
|                OUT_BATCH( BR13 ); | ||||
|                OUT_BATCH( (b.y1 << 16) | b.x1 ); | ||||
|                OUT_BATCH( (b.y2 << 16) | b.x2 ); | ||||
|                OUT_RELOC( irb->region->buffer, DRM_MM_TT|DRM_MM_WRITE, | ||||
|                           irb->region->draw_offset ); | ||||
|                OUT_BATCH( clearVal ); | ||||
|                ADVANCE_BATCH(); | ||||
|                clearMask &= ~bufBit; /* turn off bit, for faster loop exit */ | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|       intel_batchbuffer_flush( intel->batch ); | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										60
									
								
								src/mesa/drivers/dri/i915/intel_blit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/mesa/drivers/dri/i915/intel_blit.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BLIT_H | ||||
| #define INTEL_BLIT_H | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
| extern void intelCopyBuffer( const __DRIdrawablePrivate *dpriv ); | ||||
| extern void intelClearWithBlit(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 			     GLint cx1, GLint cy1, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelEmitCopyBlit( struct intel_context *intel, | ||||
| 			       GLuint cpp, | ||||
| 			       GLshort src_pitch, | ||||
| 			       GLuint  src_buffer, | ||||
| 			       GLuint  src_offset, | ||||
| 			       GLshort dst_pitch, | ||||
| 			       GLuint  dst_buffer, | ||||
| 			       GLuint  dst_offset, | ||||
| 			       GLshort srcx, GLshort srcy, | ||||
| 			       GLshort dstx, GLshort dsty, | ||||
| 			       GLshort w, GLshort h ); | ||||
|  | ||||
| extern void intelEmitFillBlit( struct intel_context *intel, | ||||
| 			       GLuint cpp, | ||||
| 			       GLshort dst_pitch, | ||||
| 			       GLuint dst_buffer, | ||||
| 			       GLuint dst_offset, | ||||
| 			       GLshort x, GLshort y,  | ||||
| 			       GLshort w, GLshort h, | ||||
| 			       GLuint color ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										201
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,201 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include "imports.h" | ||||
| #include "mtypes.h" | ||||
| #include "bufferobj.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * There is some duplication between mesa's bufferobjects and our | ||||
|  * bufmgr buffers.  Both have an integer handle and a hashtable to | ||||
|  * lookup an opaque structure.  It would be nice if the handles and | ||||
|  * internal structure where somehow shared. | ||||
|  */ | ||||
| static struct gl_buffer_object *intel_bufferobj_alloc( GLcontext *ctx,  | ||||
| 						       GLuint name,  | ||||
| 						       GLenum target ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *obj = MALLOC_STRUCT(intel_buffer_object); | ||||
|  | ||||
|    _mesa_initialize_buffer_object(&obj->Base, name, target); | ||||
|  | ||||
|    /* XXX:  We generate our own handle, which is different to 'name' above. | ||||
|     */ | ||||
|    bmGenBuffers(intel->bm, 1, &obj->buffer, 0); | ||||
|  | ||||
|    return &obj->Base; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Deallocate/free a vertex/pixel buffer object. | ||||
|  * Called via glDeleteBuffersARB(). | ||||
|  */ | ||||
| static void intel_bufferobj_free( GLcontext *ctx,  | ||||
| 				  struct gl_buffer_object *obj ) | ||||
| {  | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|  | ||||
|    if (intel_obj->buffer)  | ||||
|       bmDeleteBuffers( intel->bm, 1, &intel_obj->buffer ); | ||||
|    | ||||
|    _mesa_free(intel_obj); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Allocate space for and store data in a buffer object.  Any data that was | ||||
|  * previously stored in the buffer object is lost.  If data is NULL, | ||||
|  * memory will be allocated, but no copy will occur. | ||||
|  * Called via glBufferDataARB(). | ||||
|  */ | ||||
| static void intel_bufferobj_data( GLcontext *ctx,  | ||||
| 				  GLenum target,  | ||||
| 				  GLsizeiptrARB size, | ||||
| 				  const GLvoid *data,  | ||||
| 				  GLenum usage, | ||||
| 				  struct gl_buffer_object *obj ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    /* XXX: do something useful with 'usage' (eg. populate flags | ||||
|     * argument below) | ||||
|     */ | ||||
|    assert(intel_obj); | ||||
|  | ||||
|    obj->Size = size; | ||||
|    obj->Usage = usage; | ||||
|  | ||||
|    bmBufferData(intel->bm, intel_obj->buffer, size, data, 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Replace data in a subrange of buffer object.  If the data range | ||||
|  * specified by size + offset extends beyond the end of the buffer or | ||||
|  * if data is NULL, no copy is performed. | ||||
|  * Called via glBufferSubDataARB(). | ||||
|  */ | ||||
| static void intel_bufferobj_subdata( GLcontext *ctx,  | ||||
| 				     GLenum target,  | ||||
| 				     GLintptrARB offset, | ||||
| 				     GLsizeiptrARB size,  | ||||
| 				     const GLvoid * data, | ||||
| 				     struct gl_buffer_object * obj ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|    bmBufferSubData(intel->bm, intel_obj->buffer, offset, size, data); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glGetBufferSubDataARB(). | ||||
|  */ | ||||
| static void intel_bufferobj_get_subdata( GLcontext *ctx,  | ||||
| 					 GLenum target,  | ||||
| 					 GLintptrARB offset, | ||||
| 					 GLsizeiptrARB size,  | ||||
| 					 GLvoid * data, | ||||
| 					 struct gl_buffer_object * obj ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|    bmBufferGetSubData(intel->bm, intel_obj->buffer, offset, size, data); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glMapBufferARB(). | ||||
|  */ | ||||
| static void *intel_bufferobj_map( GLcontext *ctx,  | ||||
| 				  GLenum target,  | ||||
| 				  GLenum access, | ||||
| 				  struct gl_buffer_object *obj ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    /* XXX: Translate access to flags arg below: | ||||
|     */ | ||||
|    assert(intel_obj); | ||||
|    obj->Pointer = bmMapBuffer(intel->bm, intel_obj->buffer, 0); | ||||
|    return obj->Pointer; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glMapBufferARB(). | ||||
|  */ | ||||
| static GLboolean intel_bufferobj_unmap( GLcontext *ctx, | ||||
| 					GLenum target, | ||||
| 					struct gl_buffer_object *obj ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_buffer_object *intel_obj = intel_buffer_object(obj); | ||||
|  | ||||
|    assert(intel_obj); | ||||
|    assert(obj->Pointer); | ||||
|    bmUnmapBuffer(intel->bm, intel_obj->buffer); | ||||
|    obj->Pointer = NULL; | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| GLuint intel_bufferobj_buffer( const struct intel_buffer_object *intel_obj ) | ||||
| { | ||||
|    return intel_obj->buffer; | ||||
| }   | ||||
|  | ||||
| void intel_bufferobj_init( struct intel_context *intel ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|    ctx->Driver.NewBufferObject = intel_bufferobj_alloc; | ||||
|    ctx->Driver.DeleteBuffer = intel_bufferobj_free; | ||||
|    ctx->Driver.BufferData = intel_bufferobj_data; | ||||
|    ctx->Driver.BufferSubData = intel_bufferobj_subdata; | ||||
|    ctx->Driver.GetBufferSubData = intel_bufferobj_get_subdata; | ||||
|    ctx->Driver.MapBuffer = intel_bufferobj_map; | ||||
|    ctx->Driver.UnmapBuffer = intel_bufferobj_unmap; | ||||
| } | ||||
							
								
								
									
										70
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/mesa/drivers/dri/i915/intel_buffer_objects.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
|  /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BUFFEROBJ_H | ||||
| #define INTEL_BUFFEROBJ_H | ||||
|  | ||||
| #include "mtypes.h" | ||||
|  | ||||
| struct intel_context; | ||||
| struct gl_buffer_object; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object. | ||||
|  */ | ||||
| struct intel_buffer_object { | ||||
|    struct gl_buffer_object Base; | ||||
|    GLuint buffer;   /* the low-level buffer manager's buffer handle */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* Get the bm buffer associated with a GL bufferobject: | ||||
|  */ | ||||
| GLuint intel_bufferobj_buffer( const struct intel_buffer_object *obj ); | ||||
|  | ||||
| /* Hook the bufferobject implementation into mesa:  | ||||
|  */ | ||||
| void intel_bufferobj_init( struct intel_context *intel ); | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Are the obj->Name tests necessary?  Unfortunately yes, mesa | ||||
|  * allocates a couple of gl_buffer_object structs statically, and | ||||
|  * the Name == 0 test is the only way to identify them and avoid | ||||
|  * casting them erroneously to our structs. | ||||
|  */ | ||||
| static INLINE struct intel_buffer_object * | ||||
| intel_buffer_object( struct gl_buffer_object *obj ) | ||||
| { | ||||
|    if (obj->Name) | ||||
|       return (struct intel_buffer_object *)obj; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										730
									
								
								src/mesa/drivers/dri/i915/intel_buffers.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										730
									
								
								src/mesa/drivers/dri/i915/intel_buffers.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,730 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_depthstencil.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "context.h" | ||||
| #include "framebuffer.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * XXX move this into a new dri/common/cliprects.c file. | ||||
|  */ | ||||
| GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst, | ||||
| 				     const drm_clip_rect_t *a, | ||||
| 				     const drm_clip_rect_t *b ) | ||||
| { | ||||
|    GLint bx = b->x1; | ||||
|    GLint by = b->y1; | ||||
|    GLint bw = b->x2 - bx; | ||||
|    GLint bh = b->y2 - by; | ||||
|  | ||||
|    if (bx < a->x1) bw -= a->x1 - bx, bx = a->x1; | ||||
|    if (by < a->y1) bh -= a->y1 - by, by = a->y1; | ||||
|    if (bx + bw > a->x2) bw = a->x2 - bx; | ||||
|    if (by + bh > a->y2) bh = a->y2 - by; | ||||
|    if (bw <= 0) return GL_FALSE; | ||||
|    if (bh <= 0) return GL_FALSE; | ||||
|  | ||||
|    dst->x1 = bx; | ||||
|    dst->y1 = by; | ||||
|    dst->x2 = bx + bw; | ||||
|    dst->y2 = by + bh; | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Return pointer to current color drawing region, or NULL. | ||||
|  */ | ||||
| struct intel_region *intel_drawbuf_region( struct intel_context *intel ) | ||||
| { | ||||
|    struct intel_renderbuffer *irbColor = | ||||
|       intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]); | ||||
|    if (irbColor) | ||||
|       return irbColor->region; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Return pointer to current color reading region, or NULL. | ||||
|  */ | ||||
| struct intel_region *intel_readbuf_region( struct intel_context *intel ) | ||||
| { | ||||
|    struct intel_renderbuffer *irb | ||||
|       = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); | ||||
|    if (irb) | ||||
|       return irb->region; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intelBufferSize(GLframebuffer *buffer, | ||||
| 			    GLuint *width,  | ||||
| 			    GLuint *height) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    /* Need to lock to make sure the driDrawable is uptodate.  This | ||||
|     * information is used to resize Mesa's software buffers, so it has | ||||
|     * to be correct. | ||||
|     */ | ||||
|    /* XXX This isn't 100% correct, the given buffer might not be | ||||
|     * bound to the current context! | ||||
|     */ | ||||
|    LOCK_HARDWARE(intel); | ||||
|    if (intel->driDrawable) { | ||||
|       *width = intel->driDrawable->w; | ||||
|       *height = intel->driDrawable->h; | ||||
|    } | ||||
|    else { | ||||
|       *width = 0; | ||||
|       *height = 0; | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Update the following fields for rendering to a user-created FBO: | ||||
|  *   intel->numClipRects | ||||
|  *   intel->pClipRects | ||||
|  *   intel->drawX | ||||
|  *   intel->drawY | ||||
|  */ | ||||
| static void intelSetRenderbufferClipRects( struct intel_context *intel ) | ||||
| { | ||||
|    assert(intel->ctx.DrawBuffer->Width > 0); | ||||
|    assert(intel->ctx.DrawBuffer->Height > 0); | ||||
|    intel->fboRect.x1 = 0; | ||||
|    intel->fboRect.y1 = 0; | ||||
|    intel->fboRect.x2 = intel->ctx.DrawBuffer->Width; | ||||
|    intel->fboRect.y2 = intel->ctx.DrawBuffer->Height; | ||||
|    intel->numClipRects = 1; | ||||
|    intel->pClipRects = &intel->fboRect; | ||||
|    intel->drawX = 0; | ||||
|    intel->drawY = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * As above, but for rendering to front buffer of a window. | ||||
|  * \sa intelSetRenderbufferClipRects | ||||
|  */ | ||||
| static void intelSetFrontClipRects( struct intel_context *intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    intel->numClipRects = dPriv->numClipRects; | ||||
|    intel->pClipRects = dPriv->pClipRects; | ||||
|    intel->drawX = dPriv->x; | ||||
|    intel->drawY = dPriv->y; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * As above, but for rendering to back buffer of a window. | ||||
|  */ | ||||
| static void intelSetBackClipRects( struct intel_context *intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { | ||||
|       /* use the front clip rects */ | ||||
|       intel->numClipRects = dPriv->numClipRects; | ||||
|       intel->pClipRects = dPriv->pClipRects; | ||||
|       intel->drawX = dPriv->x; | ||||
|       intel->drawY = dPriv->y; | ||||
|    } else { | ||||
|       /* use the back clip rects */ | ||||
|       intel->numClipRects = dPriv->numBackClipRects; | ||||
|       intel->pClipRects = dPriv->pBackClipRects; | ||||
|       intel->drawX = dPriv->backX; | ||||
|       intel->drawY = dPriv->backY; | ||||
|        | ||||
|       if (dPriv->numBackClipRects == 1 && | ||||
| 	  dPriv->x == dPriv->backX && | ||||
| 	  dPriv->y == dPriv->backY) { | ||||
|        | ||||
| 	 /* Repeat the calculation of the back cliprect dimensions here | ||||
| 	  * as early versions of dri.a in the Xserver are incorrect.  Try | ||||
| 	  * very hard not to restrict future versions of dri.a which | ||||
| 	  * might eg. allocate truly private back buffers. | ||||
| 	  */ | ||||
| 	 int x1, y1; | ||||
| 	 int x2, y2; | ||||
| 	  | ||||
| 	 x1 = dPriv->x; | ||||
| 	 y1 = dPriv->y;       | ||||
| 	 x2 = dPriv->x + dPriv->w; | ||||
| 	 y2 = dPriv->y + dPriv->h; | ||||
| 	  | ||||
| 	 if (x1 < 0) x1 = 0; | ||||
| 	 if (y1 < 0) y1 = 0; | ||||
| 	 if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width; | ||||
| 	 if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height; | ||||
|  | ||||
| 	 if (x1 == dPriv->pBackClipRects[0].x1 && | ||||
| 	     y1 == dPriv->pBackClipRects[0].y1) { | ||||
|  | ||||
| 	    dPriv->pBackClipRects[0].x2 = x2; | ||||
| 	    dPriv->pBackClipRects[0].y2 = y2; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * This will be called whenever the currently bound window is moved/resized. | ||||
|  * XXX: actually, it seems to NOT be called when the window is only moved (BP). | ||||
|  */ | ||||
| void intelWindowMoved( struct intel_context *intel ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|    if (!intel->ctx.DrawBuffer) { | ||||
|       /* when would this happen? -BP */ | ||||
|       intelSetFrontClipRects( intel ); | ||||
|    } | ||||
|    else if (intel->ctx.DrawBuffer->Name != 0) { | ||||
|       /* drawing to user-created FBO - do nothing */ | ||||
|       /* Cliprects would be set from intelDrawBuffer() */ | ||||
|    } | ||||
|    else { | ||||
|       /* drawing to a window */ | ||||
|       switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) { | ||||
|       case BUFFER_BIT_FRONT_LEFT: | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
| 	 break; | ||||
|       case BUFFER_BIT_BACK_LEFT: | ||||
| 	 intelSetBackClipRects( intel ); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* this update Mesa's notion of window size */ | ||||
|    if (ctx->WinSysDrawBuffer) { | ||||
|       _mesa_resize_framebuffer(ctx, ctx->WinSysDrawBuffer, | ||||
|                                intel->driDrawable->w, intel->driDrawable->h); | ||||
|    } | ||||
|  | ||||
|    /* Update hardware scissor */ | ||||
|    ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
|                         ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* A true meta version of this would be very simple and additionally | ||||
|  * machine independent.  Maybe we'll get there one day. | ||||
|  */ | ||||
| static void intelClearWithTris(struct intel_context *intel,  | ||||
| 			       GLbitfield mask, | ||||
| 			       GLboolean all, | ||||
| 			       GLint cx, GLint cy,  | ||||
| 			       GLint cw, GLint ch) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    drm_clip_rect_t clear; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_DRI) | ||||
|       _mesa_printf("%s 0x%x\n", __FUNCTION__, mask); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* XXX FBO: was: intel->driDrawable->numClipRects */ | ||||
|    if (intel->numClipRects) { | ||||
|       GLuint buf; | ||||
|  | ||||
|       intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|       /* note: regardless of 'all', cx, cy, cw, ch are correct */ | ||||
|       clear.x1 = cx; | ||||
|       clear.y1 = cy; | ||||
|       clear.x2 = cx + cw; | ||||
|       clear.y2 = cy + ch; | ||||
|  | ||||
|       /* Back and stencil cliprects are the same.  Try and do both | ||||
|        * buffers at once: | ||||
|        */ | ||||
|       if (mask & (BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH)) {  | ||||
|          struct intel_region *backRegion | ||||
|             = intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT); | ||||
|          struct intel_region *depthRegion | ||||
|             = intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH); | ||||
|          const GLuint clearColor = (backRegion && backRegion->cpp == 4) | ||||
|             ? intel->ClearColor8888 : intel->ClearColor565; | ||||
|  | ||||
| 	 intel->vtbl.meta_draw_region(intel, backRegion, depthRegion ); | ||||
|  | ||||
| 	 if (mask & BUFFER_BIT_BACK_LEFT) | ||||
| 	    intel->vtbl.meta_color_mask(intel, GL_TRUE ); | ||||
| 	 else | ||||
| 	    intel->vtbl.meta_color_mask(intel, GL_FALSE ); | ||||
|  | ||||
| 	 if (mask & BUFFER_BIT_STENCIL)  | ||||
| 	    intel->vtbl.meta_stencil_replace( intel,  | ||||
| 					      intel->ctx.Stencil.WriteMask[0],  | ||||
| 					      intel->ctx.Stencil.Clear); | ||||
| 	 else | ||||
| 	    intel->vtbl.meta_no_stencil_write(intel); | ||||
|  | ||||
| 	 if (mask & BUFFER_BIT_DEPTH)  | ||||
| 	    intel->vtbl.meta_depth_replace( intel ); | ||||
| 	 else | ||||
| 	    intel->vtbl.meta_no_depth_write(intel); | ||||
|        | ||||
| 	 /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the | ||||
| 	  * drawing origin may not be correctly emitted. | ||||
| 	  */ | ||||
| 	 intel_meta_draw_quad(intel,  | ||||
| 			      clear.x1, clear.x2,  | ||||
| 			      clear.y1, clear.y2,  | ||||
| 			      intel->ctx.Depth.Clear, | ||||
| 			      clearColor,  | ||||
| 			      0, 0, 0, 0); /* texcoords */ | ||||
|  | ||||
|          mask &= ~(BUFFER_BIT_BACK_LEFT|BUFFER_BIT_STENCIL|BUFFER_BIT_DEPTH); | ||||
|       } | ||||
|  | ||||
|       /* clear the remaining (color) renderbuffers */ | ||||
|       for (buf = 0; buf < BUFFER_COUNT && mask; buf++) { | ||||
|          const GLuint bufBit = 1 << buf; | ||||
|          if (mask & bufBit) { | ||||
|             struct intel_renderbuffer *irbColor = | ||||
|                intel_renderbuffer(ctx->DrawBuffer-> | ||||
|                                   Attachment[buf].Renderbuffer); | ||||
|             GLuint color = (irbColor->region->cpp == 4) | ||||
|                ? intel->ClearColor8888 : intel->ClearColor565; | ||||
|  | ||||
|             ASSERT(irbColor); | ||||
|  | ||||
|             intel->vtbl.meta_no_depth_write(intel); | ||||
|             intel->vtbl.meta_no_stencil_write(intel); | ||||
|             intel->vtbl.meta_color_mask(intel, GL_TRUE ); | ||||
|             intel->vtbl.meta_draw_region(intel, irbColor->region, NULL); | ||||
|  | ||||
|             /* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the | ||||
|              * drawing origin may not be correctly emitted. | ||||
|              */ | ||||
|             intel_meta_draw_quad(intel,  | ||||
|                                  clear.x1, clear.x2,  | ||||
|                                  clear.y1, clear.y2,  | ||||
|                                  0, /* depth clear val */ | ||||
|                                  color, | ||||
|                                  0, 0, 0, 0); /* texcoords */ | ||||
|  | ||||
|             mask &= ~bufBit; | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       intel->vtbl.leave_meta_state( intel ); | ||||
|       intel_batchbuffer_flush( intel->batch ); | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called by ctx->Driver.Clear. | ||||
|  */ | ||||
| static void intelClear(GLcontext *ctx,  | ||||
| 		       GLbitfield mask,  | ||||
| 		       GLboolean all, | ||||
| 		       GLint cx, GLint cy,  | ||||
| 		       GLint cw, GLint ch) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); | ||||
|    GLbitfield tri_mask = 0; | ||||
|    GLbitfield blit_mask = 0; | ||||
|    GLbitfield swrast_mask = 0; | ||||
|    GLuint i; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* HW color buffers (front, back, aux, generic FBO, etc) */ | ||||
|    if (colorMask == ~0) { | ||||
|       /* clear all R,G,B,A */ | ||||
|       /* XXX FBO: need to check if colorbuffers are software RBOs! */ | ||||
|       blit_mask |= (mask & BUFFER_BITS_COLOR); | ||||
|    } | ||||
|    else { | ||||
|       /* glColorMask in effect */ | ||||
|       tri_mask |= (mask & BUFFER_BITS_COLOR); | ||||
|    } | ||||
|  | ||||
|    /* HW stencil */ | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       const struct intel_region *stencilRegion | ||||
|          = intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL); | ||||
|       if (stencilRegion) { | ||||
|          /* have hw stencil */ | ||||
|          if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { | ||||
|             /* not clearing all stencil bits, so use triangle clearing */ | ||||
|             tri_mask |= BUFFER_BIT_STENCIL; | ||||
|          }  | ||||
|          else { | ||||
|             /* clearing all stencil bits, use blitting */ | ||||
|             blit_mask |= BUFFER_BIT_STENCIL; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* HW depth */ | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       /* clear depth with whatever method is used for stencil (see above) */ | ||||
|       if (tri_mask & BUFFER_BIT_STENCIL) | ||||
| 	 tri_mask |= BUFFER_BIT_DEPTH; | ||||
|       else  | ||||
| 	 blit_mask |= BUFFER_BIT_DEPTH; | ||||
|    } | ||||
|  | ||||
|    /* SW fallback clearing */ | ||||
|    swrast_mask = mask & ~tri_mask & ~blit_mask; | ||||
|  | ||||
|    for (i = 0; i < BUFFER_COUNT; i++) { | ||||
|       GLuint bufBit = 1 << i; | ||||
|       if ((blit_mask | tri_mask) & bufBit) { | ||||
|          if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) { | ||||
|             blit_mask &= ~bufBit; | ||||
|             tri_mask &= ~bufBit; | ||||
|             swrast_mask |= bufBit; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    intelFlush( ctx ); /* XXX intelClearWithBlit also does this */ | ||||
|  | ||||
|    if (blit_mask) | ||||
|       intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch ); | ||||
|  | ||||
|    if (tri_mask)  | ||||
|       intelClearWithTris( intel, tri_mask, all, cx, cy, cw, ch); | ||||
|  | ||||
|    if (swrast_mask) | ||||
|       _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Flip the front & back buffers | ||||
|  */ | ||||
| static void intelPageFlip( const __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
| #if 0 | ||||
|    struct intel_context *intel; | ||||
|    int tmp, ret; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|  | ||||
|    intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (dPriv->pClipRects) { | ||||
|       *(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0]; | ||||
|       intel->sarea->nbox = 1; | ||||
|    } | ||||
|  | ||||
|    ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);  | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    tmp = intel->sarea->last_enqueue; | ||||
|    intelRefillBatchLocked( intel ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|  | ||||
|    intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer ); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelSwapBuffers( __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
|    if (dPriv->driverPrivate) { | ||||
|       const struct gl_framebuffer *fb | ||||
|          = (struct gl_framebuffer *) dPriv->driverPrivate; | ||||
|       if (fb->Visual.doubleBufferMode) { | ||||
|          GET_CURRENT_CONTEXT(ctx); | ||||
|          if (ctx && ctx->DrawBuffer == fb) { | ||||
|             _mesa_notifySwapBuffers( ctx );  /* flush pending rendering */ | ||||
|          } | ||||
| 	 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */ | ||||
| 	    intelPageFlip( dPriv ); | ||||
| 	 } else { | ||||
| 	    intelCopyBuffer( dPriv ); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       _mesa_problem(NULL, | ||||
|                     "dPriv has no gl_framebuffer pointer in intelSwapBuffers"); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Update the hardware state for drawing into a window or framebuffer object. | ||||
|  * | ||||
|  * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other | ||||
|  * places within the driver. | ||||
|  * | ||||
|  * Basically, this needs to be called any time the current framebuffer | ||||
|  * changes, the renderbuffers change, or we need to draw into different | ||||
|  * color buffers. | ||||
|  */ | ||||
| void | ||||
| intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *colorRegion, *depthRegion = NULL; | ||||
|    struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; | ||||
|    int front = 0; /* drawing to front color buffer? */ | ||||
|   | ||||
|    if (!fb) { | ||||
|       /* this can happen during the initial context initialization */ | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* Do this here, note core Mesa, since this function is called from | ||||
|     * many places within the driver. | ||||
|     */ | ||||
|    if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { | ||||
|       /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ | ||||
|       _mesa_update_framebuffer(ctx); | ||||
|       /* this updates the DrawBuffer's Width/Height if it's a FBO */ | ||||
|       _mesa_update_draw_buffer_bounds(ctx); | ||||
|    } | ||||
|  | ||||
|    if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { | ||||
|       /* this may occur when we're called by glBindFrameBuffer() during | ||||
|        * the process of someone setting up renderbuffers, etc. | ||||
|        */ | ||||
|       _mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n"); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (fb->Name) | ||||
|       intel_validate_paired_depth_stencil(ctx, fb); | ||||
|  | ||||
|    /* | ||||
|     * How many color buffers are we drawing into? | ||||
|     */ | ||||
|    if (fb->_NumColorDrawBuffers[0] != 1 | ||||
| #if 0 | ||||
|        /* XXX FBO temporary - always use software rendering */ | ||||
|        || 1 | ||||
| #endif | ||||
|     ) { | ||||
|       /* writing to 0 or 2 or 4 color buffers */ | ||||
|       /*_mesa_debug(ctx, "Software rendering\n");*/ | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE ); | ||||
|       front = 1; /* might not have back color buffer */ | ||||
|    } | ||||
|    else { | ||||
|       /* draw to exactly one color buffer */ | ||||
|       /*_mesa_debug(ctx, "Hardware rendering\n");*/ | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) { | ||||
|          front = 1; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|     * Get the intel_renderbuffer for the colorbuffer we're drawing into. | ||||
|     * And set up cliprects. | ||||
|     */ | ||||
|    if (fb->Name == 0) { | ||||
|       /* drawing to window system buffer */ | ||||
|       if (intel->sarea->pf_current_page == 1 ) { | ||||
|          /* page flipped back/front */ | ||||
|          front ^= 1; | ||||
|       } | ||||
|       if (front) { | ||||
|          intelSetFrontClipRects( intel ); | ||||
|          colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); | ||||
|       } | ||||
|       else { | ||||
|          intelSetBackClipRects( intel ); | ||||
|          colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT); | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* drawing to user-created FBO */ | ||||
|       struct intel_renderbuffer *irb; | ||||
|       intelSetRenderbufferClipRects(intel); | ||||
|       irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]); | ||||
|       colorRegion = (irb && irb->region) ? irb->region : NULL; | ||||
|    } | ||||
|  | ||||
|    if (!colorRegion) { | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE ); | ||||
|    } | ||||
|    else { | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|    } | ||||
|  | ||||
|    /*** | ||||
|     *** Get depth buffer region and check if we need a software fallback. | ||||
|     *** Note that the depth buffer is usually a DEPTH_STENCIL buffer. | ||||
|     ***/ | ||||
|    if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) { | ||||
|       irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped); | ||||
|       if (irbDepth->region) { | ||||
|          FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); | ||||
|          depthRegion = irbDepth->region; | ||||
|       } | ||||
|       else { | ||||
|          FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE); | ||||
|          depthRegion = NULL; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* not using depth buffer */ | ||||
|       FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); | ||||
|       depthRegion = NULL; | ||||
|    } | ||||
|  | ||||
|    /*** | ||||
|     *** Stencil buffer | ||||
|     *** This can only be hardware accelerated if we're using a | ||||
|     *** combined DEPTH_STENCIL buffer (for now anyway). | ||||
|     ***/ | ||||
|    if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) { | ||||
|       irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped); | ||||
|       if (irbStencil && irbStencil->region) { | ||||
|          ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|          FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); | ||||
|          /* need to re-compute stencil hw state */ | ||||
|          ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); | ||||
|          if (!depthRegion) | ||||
|             depthRegion = irbStencil->region; | ||||
|       } | ||||
|       else { | ||||
|          FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE); | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */ | ||||
|       FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); | ||||
|       /* need to re-compute stencil hw state */ | ||||
|       ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /** | ||||
|     ** Release old regions, reference new regions | ||||
|     **/ | ||||
| #if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */ | ||||
|    if (intel->draw_region != colorRegion) { | ||||
|       intel_region_release(intel, &intel->draw_region); | ||||
|       intel_region_reference(&intel->draw_region, colorRegion); | ||||
|    } | ||||
|    if (intel->depth_region != depthRegion) { | ||||
|       intel_region_release(intel, &intel->depth_region); | ||||
|       intel_region_reference(&intel->depth_region, depthRegion); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    intel->vtbl.set_draw_region( intel, colorRegion, depthRegion ); | ||||
|  | ||||
|    /* update viewport since it depends on window size */ | ||||
|    ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, | ||||
|                         ctx->Viewport.Width, ctx->Viewport.Height); | ||||
|  | ||||
|    /* Update hardware scissor */ | ||||
|    ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
|                         ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelDrawBuffer(GLcontext *ctx, GLenum mode) | ||||
| { | ||||
|    intel_draw_buffer(ctx, ctx->DrawBuffer); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void  | ||||
| intelReadBuffer( GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    if (ctx->ReadBuffer == ctx->DrawBuffer) { | ||||
|       /* This will update FBO completeness status. | ||||
|        * A framebuffer will be incomplete if the GL_READ_BUFFER setting | ||||
|        * refers to a missing renderbuffer.  Calling glReadBuffer can set | ||||
|        * that straight and can make the drawing buffer complete. | ||||
|        */ | ||||
|       intel_draw_buffer(ctx, ctx->DrawBuffer); | ||||
|    } | ||||
|    /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc) | ||||
|     * reference ctx->ReadBuffer and do appropriate state checks. | ||||
|     */ | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitBufferFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->Clear = intelClear; | ||||
|    functions->GetBufferSize = intelBufferSize; | ||||
|    functions->ResizeBuffers = _mesa_resize_framebuffer; | ||||
|    functions->DrawBuffer = intelDrawBuffer; | ||||
|    functions->ReadBuffer = intelReadBuffer; | ||||
| } | ||||
							
								
								
									
										58
									
								
								src/mesa/drivers/dri/i915/intel_buffers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/mesa/drivers/dri/i915/intel_buffers.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_BUFFERS_H | ||||
| #define INTEL_BUFFERS_H | ||||
|  | ||||
|  | ||||
| struct intel_context; | ||||
|  | ||||
|  | ||||
| extern GLboolean | ||||
| intel_intersect_cliprects(drm_clip_rect_t *dest, | ||||
|                           const drm_clip_rect_t *a, | ||||
|                           const drm_clip_rect_t *b); | ||||
|  | ||||
| extern struct intel_region * | ||||
| intel_readbuf_region(struct intel_context *intel); | ||||
|  | ||||
| extern struct intel_region * | ||||
| intel_drawbuf_region(struct intel_context *intel); | ||||
|  | ||||
| extern void | ||||
| intelSwapBuffers( __DRIdrawablePrivate *dPriv); | ||||
|  | ||||
| extern void | ||||
| intelWindowMoved(struct intel_context *intel); | ||||
|  | ||||
| extern void | ||||
| intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb); | ||||
|  | ||||
| extern void | ||||
| intelInitBufferFuncs(struct dd_function_table *functions); | ||||
|  | ||||
| #endif /* INTEL_BUFFERS_H */ | ||||
							
								
								
									
										453
									
								
								src/mesa/drivers/dri/i915/intel_bufmgr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										453
									
								
								src/mesa/drivers/dri/i915/intel_bufmgr.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,453 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,  | ||||
|  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  | ||||
|  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  | ||||
|  * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
| #include "hash.h" | ||||
| #include "simple_list.h" | ||||
| #include "mm.h" | ||||
| #include "imports.h" | ||||
| #include "glthread.h" | ||||
| #include <sys/ioctl.h> | ||||
| #include <unistd.h> | ||||
| #include <drm.h> | ||||
|  | ||||
| struct _mesa_HashTable; | ||||
|  | ||||
| /* The buffer manager is really part of the gl_shared_state struct. | ||||
|  * TODO: Organize for the bufmgr to be created/deleted with the shared | ||||
|  * state and stored within the DriverData of that struct.  Currently | ||||
|  * there are no mesa callbacks for this. | ||||
|  */ | ||||
|  | ||||
| #define BM_MAX 16 | ||||
| static struct bufmgr | ||||
| { | ||||
|    _glthread_Mutex mutex;	/**< for thread safety */ | ||||
|    int driFd; | ||||
|    int refcount; | ||||
|    struct _mesa_HashTable *hash; | ||||
|  | ||||
|    unsigned buf_nr;			/* for generating ids */ | ||||
|    drmMMPool batchPool; | ||||
|    drmFence initFence; | ||||
| } bufmgr_pool[BM_MAX]; | ||||
|  | ||||
| static int nr_bms; | ||||
|  | ||||
| #define LOCK(bm) _glthread_LOCK_MUTEX(bm->mutex) | ||||
| #define UNLOCK(bm) _glthread_UNLOCK_MUTEX(bm->mutex) | ||||
|  | ||||
| static void | ||||
| bmError(int val, const char *file, const char *function, int line) | ||||
| { | ||||
|    _mesa_printf("Fatal video memory manager error \"%s\".\n" | ||||
| 		"Check kernel logs or set the LIBGL_DEBUG\n" | ||||
| 		"environment variable to \"verbose\" for more info.\n" | ||||
| 		"Detected in file %s, line %d, function %s.\n", | ||||
| 		strerror(-val), file, line, function); | ||||
| #ifndef NDEBUG | ||||
|    exit(-1); | ||||
| #else | ||||
|    abort(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #define BM_CKFATAL(val)					       \ | ||||
|   do{							       \ | ||||
|     int tstVal = (val);					       \ | ||||
|     if (tstVal) 					       \ | ||||
|       bmError(tstVal, __FILE__, __FUNCTION__, __LINE__);       \ | ||||
|   } while(0); | ||||
|  | ||||
| /*********************************************************************** | ||||
|  * Public functions | ||||
|  */ | ||||
|  | ||||
| /* The initialization functions are skewed in the fake implementation. | ||||
|  * This call would be to attach to an existing manager, rather than to | ||||
|  * create a local one. | ||||
|  */ | ||||
|  | ||||
| struct bufmgr * | ||||
| bm_intel_Attach(struct intel_context *intel) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0; i < nr_bms; i++) | ||||
|       if (bufmgr_pool[i].driFd == intel->driFd) { | ||||
| 	 bufmgr_pool[i].refcount++; | ||||
| 	 _mesa_printf("retrieive old bufmgr for fd %d\n", | ||||
| 		      bufmgr_pool[i].driFd); | ||||
| 	 return &bufmgr_pool[i]; | ||||
|       } | ||||
|  | ||||
|    if (nr_bms < BM_MAX) { | ||||
|       struct bufmgr *bm = &bufmgr_pool[nr_bms++]; | ||||
|  | ||||
|       _mesa_printf("create new bufmgr for fd %d\n", intel->driFd); | ||||
|       bm->driFd = intel->driFd; | ||||
|       bm->hash = _mesa_NewHashTable(); | ||||
|       bm->refcount = 1; | ||||
|       _glthread_INIT_MUTEX(bm->mutex); | ||||
|  | ||||
|       drmGetLock(bm->driFd, intel->hHWContext, 0); | ||||
|       BM_CKFATAL(drmMMAllocBufferPool(bm->driFd, mmPoolRing, 0, | ||||
| 				      DRM_MM_TT | DRM_MM_NO_EVICT | | ||||
| 				      DRM_MM_READ | DRM_MM_EXE | | ||||
| 				      BM_BATCHBUFFER, 1024 * 1024, 4096, | ||||
| 				      &bm->batchPool)); | ||||
|  | ||||
|        | ||||
|       BM_CKFATAL(drmEmitFence(bm->driFd, 0, &bm->initFence)); | ||||
|       drmUnlock(bm->driFd, intel->hHWContext); | ||||
|       return bm; | ||||
|    } | ||||
|  | ||||
|    _mesa_printf("failed to create new bufmgr for fd %d\n", intel->driFd); | ||||
|    return NULL; | ||||
| } | ||||
|  | ||||
| void | ||||
| bmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers, unsigned flags) | ||||
| { | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       unsigned i; | ||||
|       unsigned bFlags = | ||||
| 	    (flags) ? flags : DRM_MM_TT | DRM_MM_VRAM | DRM_MM_SYSTEM; | ||||
|  | ||||
|       for (i = 0; i < n; i++) { | ||||
| 	 drmMMBuf *buf = calloc(sizeof(*buf), 1); | ||||
|  | ||||
| 	 BM_CKFATAL(drmMMInitBuffer(bm->driFd, bFlags, 12, buf)); | ||||
| 	 buf->client_priv = ++bm->buf_nr; | ||||
| 	 buffers[i] = buf->client_priv; | ||||
| 	 _mesa_HashInsert(bm->hash, buffers[i], buf); | ||||
|       } | ||||
|    } | ||||
|    UNLOCK(bm); | ||||
| } | ||||
|  | ||||
| void | ||||
| bmSetShared(struct bufmgr *bm, unsigned buffer, unsigned flags, | ||||
| 	    unsigned long offset, void *virtual) | ||||
| { | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|       assert(buf); | ||||
|  | ||||
|       buf->flags = DRM_MM_NO_EVICT | DRM_MM_SHARED | ||||
| 	    | DRM_MM_WRITE | DRM_MM_READ; | ||||
|       buf->flags |= flags & DRM_MM_MEMTYPE_MASK; | ||||
|       buf->offset = offset; | ||||
|       buf->virtual = virtual; | ||||
|       BM_CKFATAL(drmMMAllocBuffer(bm->driFd, 0, NULL, 0, buf)); | ||||
|    } | ||||
|    UNLOCK(bm); | ||||
| } | ||||
|  | ||||
| void | ||||
| bmDeleteBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers) | ||||
| { | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       unsigned i; | ||||
|  | ||||
|       for (i = 0; i < n; i++) { | ||||
| 	 drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffers[i]); | ||||
|  | ||||
| 	 if (buf) { | ||||
| 	    BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf)); | ||||
|  | ||||
| 	    _mesa_HashRemove(bm->hash, buffers[i]); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
|    UNLOCK(bm); | ||||
| } | ||||
|  | ||||
| /* If buffer size changes, free and reallocate.  Otherwise update in | ||||
|  * place. | ||||
|  */ | ||||
|  | ||||
| void | ||||
| bmBufferData(struct bufmgr *bm, | ||||
| 	     unsigned buffer, unsigned size, const void *data, unsigned flags) | ||||
| { | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|       DBG("bmBufferData %d sz 0x%x data: %p\n", buffer, size, data); | ||||
|  | ||||
|       assert(buf); | ||||
|       assert(!buf->mapped); | ||||
|  | ||||
|       if (buf->flags & BM_BATCHBUFFER) { | ||||
| 	 BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf)); | ||||
| 	 BM_CKFATAL(drmMMAllocBuffer | ||||
| 		    (bm->driFd, size, &bm->batchPool, 1, buf)); | ||||
|       } else if (!(buf->flags & DRM_MM_SHARED)) { | ||||
|  | ||||
| 	 if (buf->block && (buf->size < size || drmBufIsBusy(bm->driFd, buf))) { | ||||
| 	    BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf)); | ||||
| 	 } | ||||
| 	 if (!buf->block) { | ||||
| 	    BM_CKFATAL(drmMMAllocBuffer(bm->driFd, size, NULL, 0, buf)); | ||||
| 	 } | ||||
|  | ||||
|       } | ||||
|  | ||||
|       if (data != NULL) { | ||||
|  | ||||
| 	 memcpy(drmMMMapBuffer(bm->driFd, buf), data, size); | ||||
| 	 drmMMUnmapBuffer(bm->driFd, buf); | ||||
|  | ||||
|       } | ||||
|    } | ||||
|    UNLOCK(bm); | ||||
| } | ||||
|  | ||||
| /* Update the buffer in place, in whatever space it is currently resident: | ||||
|  */ | ||||
| void | ||||
| bmBufferSubData(struct bufmgr *bm, | ||||
| 		unsigned buffer, | ||||
| 		unsigned offset, unsigned size, const void *data) | ||||
| { | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|       DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size); | ||||
|  | ||||
|       assert(buf); | ||||
|       drmBufWaitBusy(bm->driFd, buf); | ||||
|  | ||||
|       if (size) { | ||||
| 	 memcpy((unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset, | ||||
|                 data, size); | ||||
| 	 drmMMUnmapBuffer(bm->driFd, buf); | ||||
|       } | ||||
|    } | ||||
|    UNLOCK(bm); | ||||
| } | ||||
|  | ||||
| /* Extract data from the buffer: | ||||
|  */ | ||||
| void | ||||
| bmBufferGetSubData(struct bufmgr *bm, | ||||
| 		   unsigned buffer, | ||||
| 		   unsigned offset, unsigned size, void *data) | ||||
| { | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|       DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size); | ||||
|  | ||||
|       assert(buf); | ||||
|       drmBufWaitBusy(bm->driFd, buf); | ||||
|  | ||||
|       if (size) { | ||||
| 	 memcpy(data, | ||||
|                 (unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset, | ||||
|                 size); | ||||
| 	 drmMMUnmapBuffer(bm->driFd, buf); | ||||
|       } | ||||
|    } | ||||
|    UNLOCK(bm); | ||||
| } | ||||
|  | ||||
| /* Return a pointer to whatever space the buffer is currently resident in: | ||||
|  */ | ||||
| void * | ||||
| bmMapBuffer(struct bufmgr *bm, unsigned buffer, unsigned flags) | ||||
| { | ||||
|    void *retval; | ||||
|  | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|       DBG("bmMapBuffer %d\n", buffer); | ||||
|       DBG("Map: Block is 0x%x\n", &buf->block); | ||||
|  | ||||
|       assert(buf); | ||||
|       /* assert(!buf->mapped); */ | ||||
|       retval = drmMMMapBuffer(bm->driFd, buf); | ||||
|    } | ||||
|    UNLOCK(bm); | ||||
|  | ||||
|    return retval; | ||||
| } | ||||
|  | ||||
| void | ||||
| bmUnmapBuffer(struct bufmgr *bm, unsigned buffer) | ||||
| { | ||||
|    LOCK(bm); | ||||
|    { | ||||
|       drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|       if (!buf) | ||||
| 	 goto out; | ||||
|  | ||||
|       DBG("bmUnmapBuffer %d\n", buffer); | ||||
|  | ||||
|       drmMMUnmapBuffer(bm->driFd, buf); | ||||
|    } | ||||
|  out: | ||||
|    UNLOCK(bm); | ||||
| } | ||||
|  | ||||
| /* Build the list of buffers to validate.  Note that the buffer list | ||||
|  * isn't a shared structure so we don't need mutexes when manipulating | ||||
|  * it.   | ||||
|  * | ||||
|  * XXX: need refcounting for drmMMBuf structs so that they can't be | ||||
|  * deleted while on these lists. | ||||
|  */ | ||||
| struct _drmMMBufList * | ||||
| bmNewBufferList(void) | ||||
| { | ||||
|    return drmMMInitListHead(); | ||||
| } | ||||
|  | ||||
| int | ||||
| bmAddBuffer(struct bufmgr *bm, | ||||
| 	    struct _drmMMBufList *list, | ||||
| 	    unsigned buffer, | ||||
| 	    unsigned flags, | ||||
| 	    unsigned *memtype_return, unsigned long *offset_return) | ||||
| { | ||||
|    drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|    assert(buf); | ||||
|    return drmMMBufListAdd(list, buf, 0, flags, memtype_return, offset_return); | ||||
| } | ||||
|  | ||||
| void | ||||
| bmFreeBufferList(struct _drmMMBufList *list) | ||||
| { | ||||
|    drmMMFreeBufList(list); | ||||
| } | ||||
|  | ||||
| int | ||||
| bmScanBufferList(struct bufmgr *bm, | ||||
| 		 struct _drmMMBufList *list, unsigned buffer) | ||||
| { | ||||
|    drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer); | ||||
|  | ||||
|    assert(buf); | ||||
|    return drmMMScanBufList(list, buf); | ||||
| } | ||||
|  | ||||
| /* To be called prior to emitting commands to hardware which reference | ||||
|  * these buffers.  The buffer_usage list provides information on where | ||||
|  * the buffers should be placed and whether their contents need to be | ||||
|  * preserved on copying.  The offset and pool data elements are return | ||||
|  * values from this function telling the driver exactly where the | ||||
|  * buffers are currently located. | ||||
|  */ | ||||
|  | ||||
| int | ||||
| bmValidateBufferList(struct bufmgr *bm, | ||||
| 		     struct _drmMMBufList *list, unsigned flags) | ||||
| { | ||||
|    BM_CKFATAL(drmMMValidateBuffers(bm->driFd, list)); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
| /* After commands are emitted but before unlocking, this must be | ||||
|  * called so that the buffer manager can correctly age the buffers. | ||||
|  * The buffer manager keeps track of the list of validated buffers, so | ||||
|  * already knows what to apply the fence to. | ||||
|  * | ||||
|  * The buffer manager knows how to emit and test fences directly | ||||
|  * through the drm and without callbacks or whatever into the driver. | ||||
|  */ | ||||
| unsigned | ||||
| bmFenceBufferList(struct bufmgr *bm, struct _drmMMBufList *list) | ||||
| { | ||||
|    drmFence fence; | ||||
|  | ||||
|    BM_CKFATAL(drmMMFenceBuffers(bm->driFd, list)); | ||||
|    BM_CKFATAL(drmEmitFence(bm->driFd, 0, &fence)); | ||||
|  | ||||
|    return fence.fenceSeq; | ||||
| } | ||||
|  | ||||
| /* This functionality is used by the buffer manager, not really sure | ||||
|  * if we need to be exposing it in this way, probably libdrm will | ||||
|  * offer equivalent calls. | ||||
|  * | ||||
|  * For now they can stay, but will likely change/move before final: | ||||
|  */ | ||||
| unsigned | ||||
| bmSetFence(struct bufmgr *bm) | ||||
| { | ||||
|    drmFence dFence; | ||||
|  | ||||
|    BM_CKFATAL(drmEmitFence(bm->driFd, 0, &dFence)); | ||||
|  | ||||
|    return dFence.fenceSeq; | ||||
| } | ||||
|  | ||||
| int | ||||
| bmTestFence(struct bufmgr *bm, unsigned fence) | ||||
| { | ||||
|    drmFence dFence; | ||||
|    int retired; | ||||
|  | ||||
|    dFence.fenceType = 0; | ||||
|    dFence.fenceSeq = fence; | ||||
|    BM_CKFATAL(drmTestFence(bm->driFd, dFence, 0, &retired)); | ||||
|    return retired; | ||||
| } | ||||
|  | ||||
| void | ||||
| bmFinishFence(struct bufmgr *bm, unsigned fence) | ||||
| { | ||||
|    drmFence dFence; | ||||
|    dFence.fenceType = 0; | ||||
|    dFence.fenceSeq = fence; | ||||
|    BM_CKFATAL(drmWaitFence(bm->driFd, dFence)); | ||||
|    bm->initFence = dFence; | ||||
| } | ||||
|  | ||||
| unsigned | ||||
| bmInitFence(struct bufmgr *bm) | ||||
| { | ||||
|    return bm->initFence.fenceSeq; | ||||
| } | ||||
							
								
								
									
										132
									
								
								src/mesa/drivers/dri/i915/intel_bufmgr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/mesa/drivers/dri/i915/intel_bufmgr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||||
|  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,  | ||||
|  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR  | ||||
|  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  | ||||
|  * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef BUFMGR_H | ||||
| #define BUFMGR_H | ||||
|  | ||||
| #include "intel_context.h" | ||||
|  | ||||
| /* Note that this is destined to be external to Mesa, so don't use GL | ||||
|  * types like GLuint, etc. | ||||
|  */ | ||||
|  | ||||
| /* The buffer manager context.  Opaque. | ||||
|  */ | ||||
| struct bufmgr; | ||||
|  | ||||
| struct bufmgr *bm_intel_Attach(struct intel_context *intel); | ||||
|  | ||||
| #define BM_BATCHBUFFER      0x10000000	/* for map - pointer will be accessed | ||||
| 					 * without dri lock */ | ||||
|  | ||||
| /* Stick closely to ARB_vbo semantics - they're well defined and | ||||
|  * understood, and drivers can just pass the calls through without too | ||||
|  * much thunking. | ||||
|  */ | ||||
| void bmGenBuffers(struct bufmgr *, unsigned n, unsigned *buffers, | ||||
| 		  unsigned flags); | ||||
|  | ||||
| void bmDeleteBuffers(struct bufmgr *, unsigned n, unsigned *buffers); | ||||
|  | ||||
| /* The driver has more intimate knowledge of the hardare than a GL | ||||
|  * client would, so flags here is more proscriptive than the usage | ||||
|  * values in the ARB_vbo interface: | ||||
|  */ | ||||
| void bmBufferData(struct bufmgr *, | ||||
| 		  unsigned buffer, | ||||
| 		  unsigned size, const void *data, unsigned flags); | ||||
|  | ||||
| void bmBufferSubData(struct bufmgr *, | ||||
| 		     unsigned buffer, | ||||
| 		     unsigned offset, unsigned size, const void *data); | ||||
|  | ||||
| void bmBufferGetSubData(struct bufmgr *, | ||||
| 			unsigned buffer, | ||||
| 			unsigned offset, unsigned size, void *data); | ||||
|  | ||||
| void *bmMapBuffer(struct bufmgr *, unsigned buffer, unsigned access); | ||||
|  | ||||
| void bmUnmapBuffer(struct bufmgr *, unsigned buffer); | ||||
|  | ||||
| /* To be called prior to emitting commands to hardware which reference | ||||
|  * these buffers.   | ||||
|  * | ||||
|  * NewBufferList() and AddBuffer() build up a list of buffers to be | ||||
|  * validated.  The buffer list provides information on where the | ||||
|  * buffers should be placed and whether their contents need to be | ||||
|  * preserved on copying.  The offset data elements are return values | ||||
|  * from this function telling the driver exactly where the buffers are | ||||
|  * currently located. | ||||
|  * | ||||
|  * ValidateBufferList() performs the actual validation and returns the | ||||
|  * buffer pools and offsets within the pools. | ||||
|  * | ||||
|  * FenceBufferList() must be called to set fences and other | ||||
|  * housekeeping before unlocking after a successful call to | ||||
|  * ValidateBufferList(). The buffer manager knows how to emit and test | ||||
|  * fences directly through the drm and without callbacks to the | ||||
|  * driver. | ||||
|  */ | ||||
| struct _drmMMBufList *bmNewBufferList(void); | ||||
|  | ||||
| int bmAddBuffer(struct bufmgr *bm, | ||||
| 		struct _drmMMBufList *list, | ||||
| 		unsigned buffer, | ||||
| 		unsigned flags, | ||||
| 		unsigned *pool_return, unsigned long *offset_return); | ||||
|  | ||||
| int bmValidateBufferList(struct bufmgr *, | ||||
| 			 struct _drmMMBufList *, unsigned flags); | ||||
|  | ||||
| unsigned bmFenceBufferList(struct bufmgr *, struct _drmMMBufList *); | ||||
|  | ||||
| void bmFreeBufferList(struct _drmMMBufList *); | ||||
|  | ||||
| int bmScanBufferList(struct bufmgr *bm, | ||||
| 		     struct _drmMMBufList *list, unsigned buffer); | ||||
|  | ||||
| /* This functionality is used by the buffer manager, not really sure | ||||
|  * if we need to be exposing it in this way, probably libdrm will | ||||
|  * offer equivalent calls. | ||||
|  * | ||||
|  * For now they can stay, but will likely change/move before final: | ||||
|  */ | ||||
| unsigned bmSetFence(struct bufmgr *); | ||||
| int bmTestFence(struct bufmgr *, unsigned fence); | ||||
| void bmFinishFence(struct bufmgr *, unsigned fence); | ||||
| unsigned bmInitFence(struct bufmgr *bm); | ||||
| void bmSetShared(struct bufmgr *bm, unsigned buffer, | ||||
| 		 unsigned flags, unsigned long offset, void *virtual); | ||||
|  | ||||
| extern int INTEL_DEBUG; | ||||
|  | ||||
| #define DEBUG_BUFMGR 0x2000 | ||||
|  | ||||
| #define DBG(...)  do { if (INTEL_DEBUG & DEBUG_BUFMGR) _mesa_printf(__VA_ARGS__); } while(0) | ||||
|  | ||||
| #endif | ||||
| @@ -47,13 +47,20 @@ | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| #include "i830_dri.h" | ||||
| #include "i830_common.h" | ||||
|  | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_span.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "intel_fbo.h" | ||||
|  | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
| #include "utils.h" | ||||
| #ifndef INTEL_DEBUG | ||||
| @@ -72,27 +79,20 @@ int INTEL_DEBUG = (0); | ||||
| #define need_GL_EXT_blend_minmax | ||||
| #define need_GL_EXT_cull_vertex | ||||
| #define need_GL_EXT_fog_coord | ||||
| #define need_GL_EXT_framebuffer_object | ||||
| #define need_GL_EXT_multi_draw_arrays | ||||
| #define need_GL_EXT_secondary_color | ||||
| #define need_GL_NV_vertex_program | ||||
| #include "extension_helper.h" | ||||
|  | ||||
| #ifndef VERBOSE | ||||
| int VERBOSE = 0; | ||||
| #endif | ||||
|  | ||||
| #if DEBUG_LOCKING | ||||
| char *prevLockFile; | ||||
| int prevLockLine; | ||||
| #endif | ||||
| #define DRIVER_DATE                     "20060329" | ||||
|  | ||||
| /*************************************** | ||||
|  * Mesa's Driver Functions | ||||
|  ***************************************/ | ||||
| _glthread_Mutex lockMutex; | ||||
| static GLboolean lockMutexInit = GL_FALSE; | ||||
|  | ||||
| #define DRIVER_DATE                     "20050225" | ||||
|  | ||||
| const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
| static const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
| { | ||||
|    const char * chipset; | ||||
|    static char buffer[128]; | ||||
| @@ -103,7 +103,7 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
|       break; | ||||
|        | ||||
|    case GL_RENDERER: | ||||
|       switch (INTEL_CONTEXT(ctx)->intelScreen->deviceID) { | ||||
|       switch (intel_context(ctx)->intelScreen->deviceID) { | ||||
|       case PCI_CHIP_845_G: | ||||
| 	 chipset = "Intel(R) 845G"; break; | ||||
|       case PCI_CHIP_I830_M: | ||||
| @@ -130,27 +130,6 @@ const GLubyte *intelGetString( GLcontext *ctx, GLenum name ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelBufferSize(GLframebuffer *buffer, | ||||
| 			   GLuint *width, GLuint *height) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    /* Need to lock to make sure the driDrawable is uptodate.  This | ||||
|     * information is used to resize Mesa's software buffers, so it has | ||||
|     * to be correct. | ||||
|     */ | ||||
|    LOCK_HARDWARE(intel); | ||||
|    if (intel->driDrawable) { | ||||
|       *width = intel->driDrawable->w; | ||||
|       *height = intel->driDrawable->h; | ||||
|    } | ||||
|    else { | ||||
|       *width = 0; | ||||
|       *height = 0; | ||||
|    } | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Extension strings exported by the intel driver. | ||||
| @@ -173,6 +152,7 @@ const struct dri_extension card_extensions[] = | ||||
|     { "GL_ARB_texture_mirrored_repeat",    NULL }, | ||||
|     { "GL_ARB_texture_rectangle",          NULL }, | ||||
|     { "GL_ARB_vertex_buffer_object",       GL_ARB_vertex_buffer_object_functions }, | ||||
|     { "GL_ARB_pixel_buffer_object",        NULL }, | ||||
|     { "GL_ARB_vertex_program",             GL_ARB_vertex_program_functions }, | ||||
|     { "GL_ARB_window_pos",                 GL_ARB_window_pos_functions }, | ||||
|     { "GL_EXT_blend_color",                GL_EXT_blend_color_functions }, | ||||
| @@ -182,7 +162,11 @@ const struct dri_extension card_extensions[] = | ||||
|     { "GL_EXT_blend_subtract",             NULL }, | ||||
|     { "GL_EXT_cull_vertex",                GL_EXT_cull_vertex_functions }, | ||||
|     { "GL_EXT_fog_coord",                  GL_EXT_fog_coord_functions }, | ||||
|     { "GL_EXT_framebuffer_object",         GL_EXT_framebuffer_object_functions }, | ||||
|     { "GL_EXT_multi_draw_arrays",          GL_EXT_multi_draw_arrays_functions }, | ||||
| #if 1 /* XXX FBO temporary? */ | ||||
|     { "GL_EXT_packed_depth_stencil",       NULL }, | ||||
| #endif | ||||
|     { "GL_EXT_secondary_color",            GL_EXT_secondary_color_functions }, | ||||
|     { "GL_EXT_stencil_wrap",               NULL }, | ||||
|     { "GL_EXT_texture_edge_clamp",         NULL }, | ||||
| @@ -197,7 +181,7 @@ const struct dri_extension card_extensions[] = | ||||
|     { "GL_NV_blend_square",                NULL }, | ||||
|     { "GL_NV_vertex_program",              GL_NV_vertex_program_functions }, | ||||
|     { "GL_NV_vertex_program1_1",           NULL }, | ||||
|     { "GL_SGIS_generate_mipmap",           NULL }, | ||||
| /*     { "GL_SGIS_generate_mipmap",           NULL }, */ | ||||
|     { NULL,                                NULL } | ||||
| }; | ||||
|  | ||||
| @@ -237,6 +221,7 @@ static const struct dri_debug_control debug_control[] = | ||||
|     { "sync",  DEBUG_SYNC }, | ||||
|     { "sleep", DEBUG_SLEEP }, | ||||
|     { "pix",   DEBUG_PIXEL }, | ||||
|     { "buf",   DEBUG_BUFMGR }, | ||||
|     { NULL,    0 } | ||||
| }; | ||||
|  | ||||
| @@ -248,7 +233,32 @@ static void intelInvalidateState( GLcontext *ctx, GLuint new_state ) | ||||
|    _ac_InvalidateState( ctx, new_state ); | ||||
|    _tnl_InvalidateState( ctx, new_state ); | ||||
|    _tnl_invalidate_vertex_state( ctx, new_state ); | ||||
|    INTEL_CONTEXT(ctx)->NewGLState |= new_state; | ||||
|    intel_context(ctx)->NewGLState |= new_state; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelFlush( GLcontext *ctx ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|  | ||||
|    if (intel->Fallback) | ||||
|       _swrast_flush( ctx ); | ||||
|  | ||||
|    INTEL_FIREVERTICES( intel ); | ||||
|  | ||||
|    if (intel->batch->map != intel->batch->ptr) | ||||
|       intel_batchbuffer_flush( intel->batch ); | ||||
|  | ||||
|    /* XXX: Need to do an MI_FLUSH here.  Actually, the bufmgr_fake.c | ||||
|     * code will have done one already. | ||||
|     */ | ||||
| } | ||||
|  | ||||
| void intelFinish( GLcontext *ctx )  | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    intelFlush( ctx ); | ||||
|    bmFinishFence( intel->bm, intel->batch->last_fence ); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -257,10 +267,7 @@ void intelInitDriverFunctions( struct dd_function_table *functions ) | ||||
|    _mesa_init_driver_functions( functions ); | ||||
|  | ||||
|    functions->Flush = intelFlush; | ||||
|    functions->Clear = intelClear; | ||||
|    functions->Finish = intelFinish; | ||||
|    functions->GetBufferSize = intelBufferSize; | ||||
|    functions->ResizeBuffers = _mesa_resize_framebuffer; | ||||
|    functions->GetString = intelGetString; | ||||
|    functions->UpdateState = intelInvalidateState; | ||||
|    functions->CopyColorTable = _swrast_CopyColorTable; | ||||
| @@ -271,11 +278,12 @@ void intelInitDriverFunctions( struct dd_function_table *functions ) | ||||
|    intelInitTextureFuncs( functions ); | ||||
|    intelInitPixelFuncs( functions ); | ||||
|    intelInitStateFuncs( functions ); | ||||
|    intelInitBufferFuncs( functions ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| GLboolean intelInitContext( intelContextPtr intel, | ||||
| GLboolean intelInitContext( struct intel_context *intel, | ||||
| 			    const __GLcontextModes *mesaVis, | ||||
| 			    __DRIcontextPrivate *driContextPriv, | ||||
| 			    void *sharedContextPrivate, | ||||
| @@ -299,9 +307,10 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    intel->driScreen = sPriv; | ||||
|    intel->sarea = saPriv; | ||||
|  | ||||
|  | ||||
|    (void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) ); | ||||
|    make_empty_list( & intel->swapped ); | ||||
|    if (!lockMutexInit) { | ||||
|       lockMutexInit = GL_TRUE; | ||||
|       _glthread_INIT_MUTEX(lockMutex); | ||||
|    } | ||||
|  | ||||
|    ctx->Const.MaxTextureMaxAnisotropy = 2.0; | ||||
|  | ||||
| @@ -317,6 +326,8 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    ctx->Const.MaxPointSizeAA = 3.0; | ||||
|    ctx->Const.PointSizeGranularity = 1.0; | ||||
|  | ||||
|    ctx->Const.MaxColorAttachments = 4; /* XXX FBO: review this */ | ||||
|  | ||||
|    /* Initialize the software rasterizer and helper modules. */ | ||||
|    _swrast_CreateContext( ctx ); | ||||
|    _ac_CreateContext( ctx ); | ||||
| @@ -336,23 +347,16 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|    intel->driFd = sPriv->fd; | ||||
|    intel->driHwLock = (drmLock *) &sPriv->pSAREA->lock; | ||||
|  | ||||
|    intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; | ||||
|    intel->hw_stipple = 1; | ||||
|  | ||||
|    /* XXX FBO: this doesn't seem to be used anywhere */ | ||||
|    switch(mesaVis->depthBits) { | ||||
|    case 0:			/* what to do in this case? */ | ||||
|    case 16: | ||||
|       intel->depth_scale = 1.0/0xffff; | ||||
|       intel->polygon_offset_scale = 1.0/0xffff; | ||||
|       intel->depth_clear_mask = ~0; | ||||
|       intel->ClearDepth = 0xffff; | ||||
|       break; | ||||
|    case 24: | ||||
|       intel->depth_scale = 1.0/0xffffff; | ||||
|       intel->polygon_offset_scale = 2.0/0xffffff; /* req'd to pass glean */ | ||||
|       intel->depth_clear_mask = 0x00ffffff; | ||||
|       intel->stencil_clear_mask = 0xff000000; | ||||
|       intel->ClearDepth = 0x00ffffff; | ||||
|       break; | ||||
|    default: | ||||
|       assert(0);  | ||||
| @@ -371,7 +375,65 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|  | ||||
|    _math_matrix_ctr (&intel->ViewportMatrix); | ||||
|  | ||||
|    driInitExtensions( ctx, card_extensions, GL_TRUE ); | ||||
|    /* Disable imaging extension until convolution is working in | ||||
|     * teximage paths: | ||||
|     */ | ||||
|    driInitExtensions( ctx, card_extensions,  | ||||
| /* 		      GL_TRUE, */ | ||||
| 		      GL_FALSE); | ||||
|  | ||||
|  | ||||
|    /* Buffer manager:  | ||||
|     */ | ||||
|    intel->bm = bm_intel_Attach( intel ); | ||||
| #if 0 | ||||
|    bmInitPool(intel->bm, | ||||
|               intel->intelScreen->tex.offset, /* low offset */ | ||||
|               intel->intelScreen->tex.map, /* low virtual */ | ||||
|               intel->intelScreen->tex.size, | ||||
| 	      DRM_MM_TT); | ||||
| #endif | ||||
|  | ||||
|    /* XXX FBO: these have to go away! | ||||
|     * FBO regions should be setup when creating the drawable. */ | ||||
|  | ||||
|    /* These are still static, but create regions for them.   | ||||
|     */ | ||||
|    intel->front_region =  | ||||
|       intel_region_create_static(intel, | ||||
| 				 DRM_MM_TT, | ||||
| 				 intelScreen->front.offset, | ||||
| 				 intelScreen->front.map, | ||||
| 				 intelScreen->cpp, | ||||
| 				 intelScreen->front.pitch, | ||||
| 				 intelScreen->height); | ||||
|  | ||||
|  | ||||
|    intel->back_region =  | ||||
|       intel_region_create_static(intel, | ||||
| 				 DRM_MM_TT, | ||||
| 				 intelScreen->back.offset, | ||||
| 				 intelScreen->back.map, | ||||
| 				 intelScreen->cpp, | ||||
| 				 intelScreen->back.pitch, | ||||
| 				 intelScreen->height); | ||||
|  | ||||
|    /* Still assuming front.cpp == depth.cpp | ||||
|     */ | ||||
|    intel->depth_region =  | ||||
|       intel_region_create_static(intel, | ||||
| 				 DRM_MM_TT, | ||||
| 				 intelScreen->depth.offset, | ||||
| 				 intelScreen->depth.map, | ||||
| 				 intelScreen->cpp, | ||||
| 				 intelScreen->depth.pitch, | ||||
| 				 intelScreen->height); | ||||
|     | ||||
|    intel->batch = intel_batchbuffer_alloc( intel ); | ||||
|    intel->last_swap_fence_retired = GL_TRUE; | ||||
|    intel->last_swap_fence = bmInitFence(intel->bm); | ||||
|    intel_bufferobj_init( intel ); | ||||
|    intel_fbo_init( intel ); | ||||
|  | ||||
|    if (intel->ctx.Mesa_DXTn) { | ||||
|      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" ); | ||||
| @@ -381,30 +443,15 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|      _mesa_enable_extension( ctx, "GL_EXT_texture_compression_s3tc" ); | ||||
|    } | ||||
|  | ||||
| /*    driInitTextureObjects( ctx, & intel->swapped, */ | ||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_1D | */ | ||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_2D |  */ | ||||
| /* 			  DRI_TEXMGR_DO_TEXTURE_RECT ); */ | ||||
|  | ||||
|  | ||||
|    intel->prim.flush = intelInitBatchBuffer; | ||||
|    intel->prim.primitive = ~0; | ||||
|  | ||||
|  | ||||
| #if DO_DEBUG | ||||
|    INTEL_DEBUG  = driParseDebugString( getenv( "INTEL_DEBUG" ), | ||||
| 				       debug_control ); | ||||
|    INTEL_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ), | ||||
| 				       debug_control ); | ||||
| #endif | ||||
|  | ||||
| #ifndef VERBOSE | ||||
|    if (getenv("INTEL_VERBOSE")) | ||||
|       VERBOSE=1; | ||||
| #endif | ||||
|  | ||||
|    if (getenv("INTEL_NO_RAST") ||  | ||||
|        getenv("INTEL_NO_RAST")) { | ||||
|    if (getenv("INTEL_NO_RAST")) { | ||||
|       fprintf(stderr, "disabling 3D rasterization\n"); | ||||
|       FALLBACK(intel, INTEL_FALLBACK_USER, 1);  | ||||
|    } | ||||
| @@ -414,7 +461,7 @@ GLboolean intelInitContext( intelContextPtr intel, | ||||
|  | ||||
| void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | ||||
| { | ||||
|    intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate; | ||||
|    struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; | ||||
|  | ||||
|    assert(intel); /* should never be null */ | ||||
|    if (intel) { | ||||
| @@ -431,121 +478,19 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) | ||||
|       _swrast_DestroyContext (&intel->ctx); | ||||
|       intel->Fallback = 0;	/* don't call _swrast_Flush later */ | ||||
|  | ||||
|       intelDestroyBatchBuffer(&intel->ctx); | ||||
|       intel_batchbuffer_free(intel->batch); | ||||
|        | ||||
|  | ||||
|       if ( release_texture_heaps ) { | ||||
|          /* This share group is about to go away, free our private | ||||
|           * texture object data. | ||||
|           */ | ||||
|          int i; | ||||
|  | ||||
|          for ( i = 0 ; i < intel->nr_heaps ; i++ ) { | ||||
| 	    driDestroyTextureHeap( intel->texture_heaps[ i ] ); | ||||
| 	    intel->texture_heaps[ i ] = NULL; | ||||
|          } | ||||
|  | ||||
| 	 assert( is_empty_list( & intel->swapped ) ); | ||||
| 	 if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	    fprintf(stderr, "do something to free texture heaps\n"); | ||||
|       } | ||||
|  | ||||
|       /* free the Mesa context */ | ||||
|       _mesa_destroy_context(&intel->ctx); | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelSetFrontClipRects( intelContextPtr intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    intel->numClipRects = dPriv->numClipRects; | ||||
|    intel->pClipRects = dPriv->pClipRects; | ||||
|    intel->drawX = dPriv->x; | ||||
|    intel->drawY = dPriv->y; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelSetBackClipRects( intelContextPtr intel ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|    if (!dPriv) return; | ||||
|  | ||||
|    if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { | ||||
|       intel->numClipRects = dPriv->numClipRects; | ||||
|       intel->pClipRects = dPriv->pClipRects; | ||||
|       intel->drawX = dPriv->x; | ||||
|       intel->drawY = dPriv->y; | ||||
|    } else { | ||||
|       intel->numClipRects = dPriv->numBackClipRects; | ||||
|       intel->pClipRects = dPriv->pBackClipRects; | ||||
|       intel->drawX = dPriv->backX; | ||||
|       intel->drawY = dPriv->backY; | ||||
|        | ||||
|       if (dPriv->numBackClipRects == 1 && | ||||
| 	  dPriv->x == dPriv->backX && | ||||
| 	  dPriv->y == dPriv->backY) { | ||||
|        | ||||
| 	 /* Repeat the calculation of the back cliprect dimensions here | ||||
| 	  * as early versions of dri.a in the Xserver are incorrect.  Try | ||||
| 	  * very hard not to restrict future versions of dri.a which | ||||
| 	  * might eg. allocate truly private back buffers. | ||||
| 	  */ | ||||
| 	 int x1, y1; | ||||
| 	 int x2, y2; | ||||
| 	  | ||||
| 	 x1 = dPriv->x; | ||||
| 	 y1 = dPriv->y;       | ||||
| 	 x2 = dPriv->x + dPriv->w; | ||||
| 	 y2 = dPriv->y + dPriv->h; | ||||
| 	  | ||||
| 	 if (x1 < 0) x1 = 0; | ||||
| 	 if (y1 < 0) y1 = 0; | ||||
| 	 if (x2 > intel->intelScreen->width) x2 = intel->intelScreen->width; | ||||
| 	 if (y2 > intel->intelScreen->height) y2 = intel->intelScreen->height; | ||||
|  | ||||
| 	 if (x1 == dPriv->pBackClipRects[0].x1 && | ||||
| 	     y1 == dPriv->pBackClipRects[0].y1) { | ||||
|  | ||||
| 	    dPriv->pBackClipRects[0].x2 = x2; | ||||
| 	    dPriv->pBackClipRects[0].y2 = y2; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelWindowMoved( intelContextPtr intel ) | ||||
| { | ||||
|    if (!intel->ctx.DrawBuffer) { | ||||
|       intelSetFrontClipRects( intel ); | ||||
|    } | ||||
|    else { | ||||
|       switch (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0]) { | ||||
|       case BUFFER_BIT_FRONT_LEFT: | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
| 	 break; | ||||
|       case BUFFER_BIT_BACK_LEFT: | ||||
| 	 intelSetBackClipRects( intel ); | ||||
| 	 break; | ||||
|       default: | ||||
| 	 /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ | ||||
| 	 intelSetFrontClipRects( intel ); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Set state we know depends on drawable parameters: | ||||
|     */ | ||||
|    { | ||||
|       GLcontext *ctx = &intel->ctx; | ||||
|  | ||||
|       ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			   ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|        | ||||
|       ctx->Driver.DepthRange( ctx,  | ||||
| 			      ctx->Viewport.Near, | ||||
| 			      ctx->Viewport.Far ); | ||||
|       _mesa_free_context_data(&intel->ctx); | ||||
|    } | ||||
| } | ||||
|  | ||||
| @@ -560,7 +505,9 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, | ||||
| { | ||||
|  | ||||
|    if (driContextPriv) { | ||||
|       intelContextPtr intel = (intelContextPtr) driContextPriv->driverPrivate; | ||||
|       struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; | ||||
|       GLframebuffer *drawFb = (GLframebuffer *) driDrawPriv->driverPrivate; | ||||
|       GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate; | ||||
|  | ||||
|       if ( intel->driDrawable != driDrawPriv ) { | ||||
| 	 /* Shouldn't the readbuffer be stored also? */ | ||||
| @@ -568,28 +515,53 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv, | ||||
| 	 intelWindowMoved( intel ); | ||||
|       } | ||||
|  | ||||
|       _mesa_make_current(&intel->ctx, | ||||
| 			 (GLframebuffer *) driDrawPriv->driverPrivate, | ||||
| 			 (GLframebuffer *) driReadPriv->driverPrivate); | ||||
|       /* XXX FBO temporary fix-ups! */ | ||||
|       /* if the renderbuffers don't have regions, init them from the context */ | ||||
|       { | ||||
|          struct intel_renderbuffer *irbFront | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_FRONT_LEFT); | ||||
|          struct intel_renderbuffer *irbBack | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_BACK_LEFT); | ||||
|          struct intel_renderbuffer *irbDepth | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_DEPTH); | ||||
|          struct intel_renderbuffer *irbStencil | ||||
|             = intel_get_renderbuffer(drawFb, BUFFER_STENCIL); | ||||
|  | ||||
|       intel->ctx.Driver.DrawBuffer( &intel->ctx, intel->ctx.Color.DrawBuffer[0] ); | ||||
|    } else { | ||||
|          if (irbFront && !irbFront->region) { | ||||
|             intel_region_reference(&irbFront->region, intel->front_region); | ||||
|          } | ||||
|          if (irbBack && !irbBack->region) { | ||||
|             intel_region_reference(&irbBack->region, intel->back_region); | ||||
|          } | ||||
|          if (irbDepth && !irbDepth->region) { | ||||
|             intel_region_reference(&irbDepth->region, intel->depth_region); | ||||
|          } | ||||
|          if (irbStencil && !irbStencil->region) { | ||||
|             intel_region_reference(&irbStencil->region, intel->depth_region); | ||||
|          } | ||||
|       } | ||||
|  | ||||
|       _mesa_make_current(&intel->ctx, drawFb, readFb); | ||||
|  | ||||
|       intel_draw_buffer(&intel->ctx, drawFb); | ||||
|    } | ||||
|    else { | ||||
|       _mesa_make_current(NULL, NULL, NULL); | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| void intelGetLock( intelContextPtr intel, GLuint flags ) | ||||
| void intelGetLock( struct intel_context *intel, GLuint flags ) | ||||
| { | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    __DRIscreenPrivate *sPriv = intel->driScreen; | ||||
|    drmI830Sarea * sarea = intel->sarea; | ||||
|    int me = intel->hHWContext; | ||||
|    unsigned   i; | ||||
|  | ||||
|    drmGetLock(intel->driFd, intel->hHWContext, flags); | ||||
|  | ||||
|  | ||||
|    /* If the window moved, may need to set a new cliprect now. | ||||
|     * | ||||
|     * NOTE: This releases and regains the hw lock, so all state | ||||
| @@ -598,143 +570,19 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) | ||||
|    if (dPriv) | ||||
|       DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); | ||||
|  | ||||
|    /* If we lost context, need to dump all registers to hardware. | ||||
|     * Note that we don't care about 2d contexts, even if they perform | ||||
|     * accelerated commands, so the DRI locking in the X server is even | ||||
|     * more broken than usual. | ||||
|    /* Lost context? | ||||
|     */ | ||||
|  | ||||
|    if (sarea->ctxOwner != me) { | ||||
|       intel->perf_boxes |= I830_BOX_LOST_CONTEXT; | ||||
|       sarea->ctxOwner = me; | ||||
|    } | ||||
|  | ||||
|    /* Shared texture managment - if another client has played with | ||||
|     * texture space, figure out which if any of our textures have been | ||||
|     * ejected, and update our global LRU. | ||||
|    /* Drawable changed? | ||||
|     */ | ||||
|  | ||||
|    for ( i = 0 ; i < intel->nr_heaps ; i++ ) { | ||||
|       DRI_AGE_TEXTURES( intel->texture_heaps[ i ] ); | ||||
|    } | ||||
|  | ||||
|    if (dPriv && intel->lastStamp != dPriv->lastStamp) { | ||||
|       intelWindowMoved( intel ); | ||||
|       intel->lastStamp = dPriv->lastStamp; | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intelSwapBuffers( __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
|    if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | ||||
|       intelContextPtr intel; | ||||
|       GLcontext *ctx; | ||||
|       intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|       ctx = &intel->ctx; | ||||
|       if (ctx->Visual.doubleBufferMode) { | ||||
| 	 _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */ | ||||
| 	 if ( 0 /*intel->doPageFlip*/ ) { /* doPageFlip is never set !!! */ | ||||
| 	    intelPageFlip( dPriv ); | ||||
| 	 } else { | ||||
| 	    intelCopyBuffer( dPriv ); | ||||
| 	 } | ||||
|       } | ||||
|    } else { | ||||
|       /* XXX this shouldn't be an error but we can't handle it for now */ | ||||
|       fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitState( GLcontext *ctx ) | ||||
| { | ||||
|    /* Mesa should do this for us: | ||||
|     */ | ||||
|    ctx->Driver.AlphaFunc( ctx,  | ||||
| 			  ctx->Color.AlphaFunc, | ||||
| 			  ctx->Color.AlphaRef); | ||||
|  | ||||
|    ctx->Driver.BlendColor( ctx, | ||||
| 			   ctx->Color.BlendColor ); | ||||
|  | ||||
|    ctx->Driver.BlendEquationSeparate( ctx,  | ||||
| 				      ctx->Color.BlendEquationRGB, | ||||
| 				      ctx->Color.BlendEquationA); | ||||
|  | ||||
|    ctx->Driver.BlendFuncSeparate( ctx, | ||||
| 				  ctx->Color.BlendSrcRGB, | ||||
| 				  ctx->Color.BlendDstRGB, | ||||
| 				  ctx->Color.BlendSrcA, | ||||
| 				  ctx->Color.BlendDstA); | ||||
|  | ||||
|    ctx->Driver.ColorMask( ctx,  | ||||
| 			  ctx->Color.ColorMask[RCOMP], | ||||
| 			  ctx->Color.ColorMask[GCOMP], | ||||
| 			  ctx->Color.ColorMask[BCOMP], | ||||
| 			  ctx->Color.ColorMask[ACOMP]); | ||||
|  | ||||
|    ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode ); | ||||
|    ctx->Driver.DepthFunc( ctx, ctx->Depth.Func ); | ||||
|    ctx->Driver.DepthMask( ctx, ctx->Depth.Mask ); | ||||
|  | ||||
|    ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test ); | ||||
|    ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE ); | ||||
|  | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); | ||||
|  | ||||
|    ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace ); | ||||
|  | ||||
|    { | ||||
|       GLfloat f = (GLfloat)ctx->Light.Model.ColorControl; | ||||
|       ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f ); | ||||
|    } | ||||
|  | ||||
|    ctx->Driver.LineWidth( ctx, ctx->Line.Width ); | ||||
|    ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp ); | ||||
|    ctx->Driver.PointSize( ctx, ctx->Point.Size ); | ||||
|    ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple ); | ||||
|    ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|    ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT, | ||||
|                                     ctx->Stencil.Function[0], | ||||
|                                     ctx->Stencil.Ref[0], | ||||
|                                     ctx->Stencil.ValueMask[0] ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_BACK, | ||||
|                                     ctx->Stencil.Function[1], | ||||
|                                     ctx->Stencil.Ref[1], | ||||
|                                     ctx->Stencil.ValueMask[1] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] ); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_FRONT, | ||||
|                                   ctx->Stencil.FailFunc[0], | ||||
|                                   ctx->Stencil.ZFailFunc[0], | ||||
|                                   ctx->Stencil.ZPassFunc[0]); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_BACK, | ||||
|                                   ctx->Stencil.FailFunc[1], | ||||
|                                   ctx->Stencil.ZFailFunc[1], | ||||
|                                   ctx->Stencil.ZPassFunc[1]); | ||||
|  | ||||
|  | ||||
|    ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); | ||||
| } | ||||
|   | ||||
| @@ -47,82 +47,122 @@ | ||||
| #define DV_PF_565  (2<<8) | ||||
| #define DV_PF_8888 (3<<8) | ||||
|  | ||||
| #define INTEL_CONTEXT(ctx)	((intelContextPtr)(ctx)) | ||||
| struct intel_region; | ||||
| struct intel_context; | ||||
|  | ||||
| typedef struct intel_context intelContext; | ||||
| typedef struct intel_context *intelContextPtr; | ||||
| typedef struct intel_texture_object *intelTextureObjectPtr; | ||||
|  | ||||
| typedef void (*intel_tri_func)(intelContextPtr, intelVertex *, intelVertex *, | ||||
| typedef void (*intel_tri_func)(struct intel_context *, intelVertex *, intelVertex *, | ||||
| 							  intelVertex *); | ||||
| typedef void (*intel_line_func)(intelContextPtr, intelVertex *, intelVertex *); | ||||
| typedef void (*intel_point_func)(intelContextPtr, intelVertex *); | ||||
| typedef void (*intel_line_func)(struct intel_context *, intelVertex *, intelVertex *); | ||||
| typedef void (*intel_point_func)(struct intel_context *, intelVertex *); | ||||
|  | ||||
| #define INTEL_FALLBACK_DRAW_BUFFER	 0x1 | ||||
| #define INTEL_FALLBACK_READ_BUFFER	 0x2 | ||||
| #define INTEL_FALLBACK_USER		 0x4 | ||||
| #define INTEL_FALLBACK_NO_BATCHBUFFER	 0x8 | ||||
| #define INTEL_FALLBACK_NO_TEXMEM	 0x10 | ||||
| #define INTEL_FALLBACK_DEPTH_BUFFER      0x4 | ||||
| #define INTEL_FALLBACK_STENCIL_BUFFER    0x8 | ||||
| #define INTEL_FALLBACK_USER		 0x10 | ||||
| #define INTEL_FALLBACK_RENDERMODE	 0x20 | ||||
|  | ||||
| extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ); | ||||
| extern void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode ); | ||||
| #define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode ) | ||||
|  | ||||
|  | ||||
| #define INTEL_TEX_MAXLEVELS 10 | ||||
|  | ||||
|  | ||||
| struct intel_texture_object | ||||
| { | ||||
|    driTextureObject    base;	/* the parent class */ | ||||
|    struct gl_texture_object base; /* The "parent" object */ | ||||
|  | ||||
|    GLuint texelBytes; | ||||
|    GLuint age; | ||||
|    GLuint Pitch; | ||||
|    GLuint Height; | ||||
|    GLuint TextureOffset; | ||||
|    GLubyte *BufAddr;    | ||||
|    /* The mipmap tree must include at least these levels once | ||||
|     * validated: | ||||
|     */ | ||||
|    GLuint firstLevel; | ||||
|    GLuint lastLevel; | ||||
|  | ||||
|    GLuint min_level; | ||||
|    GLuint max_level; | ||||
|    GLuint depth_pitch; | ||||
|    /* Offset for firstLevel image: | ||||
|     */ | ||||
|    GLuint textureOffset; | ||||
|  | ||||
|    struct { | ||||
|       const struct gl_texture_image *image; | ||||
|       GLuint offset;       /* into BufAddr */ | ||||
|       GLuint height; | ||||
|       GLuint internalFormat; | ||||
|    } image[6][INTEL_TEX_MAXLEVELS]; | ||||
|  | ||||
|    GLuint dirty; | ||||
|    GLuint firstLevel,lastLevel; | ||||
|    /* On validation any active images held in main memory or in other | ||||
|     * regions will be copied to this region and the old storage freed. | ||||
|     */ | ||||
|    struct intel_mipmap_tree *mt; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| struct intel_texture_image  | ||||
| { | ||||
|    struct gl_texture_image base; | ||||
|  | ||||
|    /* These aren't stored in gl_texture_image  | ||||
|     */ | ||||
|    GLuint level; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* If intelImage->mt != NULL, image data is stored here. | ||||
|     * Else if intelImage->base.Data != NULL, image is stored there. | ||||
|     * Else there is no image data. | ||||
|     */ | ||||
|    struct intel_mipmap_tree *mt; | ||||
| }; | ||||
|  | ||||
|  | ||||
| #define INTEL_MAX_FIXUP 64 | ||||
|  | ||||
| struct intel_context | ||||
| { | ||||
|    GLcontext ctx;		/* the parent class */ | ||||
|  | ||||
|    struct { | ||||
|       void (*destroy)( intelContextPtr intel );  | ||||
|       void (*emit_state)( intelContextPtr intel ); | ||||
|       void (*emit_invarient_state)( intelContextPtr intel ); | ||||
|       void (*lost_hardware)( intelContextPtr intel ); | ||||
|       void (*update_texture_state)( intelContextPtr intel ); | ||||
|       void (*destroy)( struct intel_context *intel );  | ||||
|       void (*emit_state)( struct intel_context *intel ); | ||||
|       void (*lost_hardware)( struct intel_context *intel ); | ||||
|       void (*update_texture_state)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*render_start)( intelContextPtr intel ); | ||||
|       void (*set_draw_offset)( intelContextPtr intel, int offset ); | ||||
|       void (*emit_flush)( intelContextPtr intel ); | ||||
|       void (*render_start)( struct intel_context *intel ); | ||||
|       void (*set_draw_region)( struct intel_context *intel,  | ||||
| 			       struct intel_region *draw_region, | ||||
| 			       struct intel_region *depth_region ); | ||||
|  | ||||
|       void (*reduced_primitive_state)( intelContextPtr intel, GLenum rprim ); | ||||
|       GLuint (*flush_cmd)( void ); | ||||
|  | ||||
|       GLboolean (*check_vertex_size)( intelContextPtr intel, GLuint expected ); | ||||
|       void (*reduced_primitive_state)( struct intel_context *intel, GLenum rprim ); | ||||
|  | ||||
|       void (*clear_with_tris)( intelContextPtr intel, GLbitfield mask, | ||||
| 			       GLboolean all,  | ||||
| 			       GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|       GLboolean (*check_vertex_size)( struct intel_context *intel, GLuint expected ); | ||||
|  | ||||
|       intelTextureObjectPtr (*alloc_tex_obj)( struct gl_texture_object *tObj ); | ||||
|  | ||||
|       /* Metaops:  | ||||
|        */ | ||||
|       void (*install_meta_state)( struct intel_context *intel ); | ||||
|       void (*leave_meta_state)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*meta_draw_region)( struct intel_context *intel, | ||||
| 				struct intel_region *draw_region, | ||||
| 				struct intel_region *depth_region ); | ||||
|  | ||||
|       void (*meta_color_mask)( struct intel_context *intel, | ||||
| 			       GLboolean ); | ||||
|        | ||||
|       void (*meta_stencil_replace)( struct intel_context *intel, | ||||
| 				    GLuint mask, | ||||
| 				    GLuint clear ); | ||||
|  | ||||
|       void (*meta_depth_replace)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*meta_texture_blend_replace)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*meta_no_stencil_write)( struct intel_context *intel ); | ||||
|       void (*meta_no_depth_write)( struct intel_context *intel ); | ||||
|       void (*meta_no_texture)( struct intel_context *intel ); | ||||
|  | ||||
|       void (*meta_import_pixel_state)( struct intel_context *intel ); | ||||
|  | ||||
|       GLboolean (*meta_tex_rect_source)( struct intel_context *intel, | ||||
| 					 GLuint buffer, | ||||
| 					 GLuint offset, | ||||
| 					 GLuint pitch, | ||||
| 					 GLuint height, | ||||
| 					 GLenum format, | ||||
| 					 GLenum type); | ||||
|  | ||||
|    } vtbl; | ||||
|  | ||||
| @@ -130,63 +170,44 @@ struct intel_context | ||||
|    GLuint Fallback; | ||||
|    GLuint NewGLState; | ||||
|     | ||||
|    struct { | ||||
|       GLuint start_offset; | ||||
|       GLint size; | ||||
|       GLint space; | ||||
|       GLubyte *ptr; | ||||
|    } batch; | ||||
|        | ||||
|    struct { | ||||
|       void *ptr; | ||||
|       GLint size; | ||||
|       GLuint offset; | ||||
|       GLuint active_buf; | ||||
|       GLuint irq_emitted; | ||||
|    } alloc; | ||||
|    GLuint last_fence; | ||||
|    GLuint last_swap_fence; | ||||
|    GLboolean last_swap_fence_retired; | ||||
|  | ||||
|    struct intel_batchbuffer *batch; | ||||
|  | ||||
|    struct { | ||||
|       GLuint id; | ||||
|       GLuint primitive; | ||||
|       GLubyte *start_ptr;       | ||||
|       void (*flush)( GLcontext * ); | ||||
|       void (*flush)( struct intel_context * ); | ||||
|    } prim; | ||||
|  | ||||
|    GLboolean locked; | ||||
|    char *prevLockFile; | ||||
|    int prevLockLine; | ||||
|  | ||||
|    GLubyte clear_red; | ||||
|    GLubyte clear_green; | ||||
|    GLubyte clear_blue; | ||||
|    GLubyte clear_alpha; | ||||
|    GLuint ClearColor; | ||||
|    GLuint ClearDepth; | ||||
|    GLuint ClearColor565; | ||||
|    GLuint ClearColor8888; | ||||
|  | ||||
|    /* Offsets of fields within the current vertex: | ||||
|     */ | ||||
|    GLuint coloroffset; | ||||
|    GLuint specoffset; | ||||
|  | ||||
|    /* Support for duplicating XYZW as WPOS parameter (crutch for I915). | ||||
|     */ | ||||
|    GLuint wpos_offset; | ||||
|    GLuint wpos_size; | ||||
|  | ||||
|    struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; | ||||
|    GLuint vertex_attr_count; | ||||
|  | ||||
|    GLfloat depth_scale; | ||||
|    GLfloat polygon_offset_scale; /* dependent on depth_scale, bpp */ | ||||
|    GLuint depth_clear_mask; | ||||
|    GLuint stencil_clear_mask; | ||||
|  | ||||
|    GLboolean hw_stencil; | ||||
|    GLboolean hw_stipple; | ||||
|     | ||||
|    /* Texture object bookkeeping | ||||
|    /* AGP memory buffer manager: | ||||
|     */ | ||||
|    GLuint                nr_heaps; | ||||
|    driTexHeap          * texture_heaps[1]; | ||||
|    driTextureObject      swapped; | ||||
|    GLuint                lastStamp; | ||||
|    struct bufmgr *bm; | ||||
|  | ||||
|    struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS]; | ||||
|  | ||||
|    /* State for intelvb.c and inteltris.c. | ||||
|     */ | ||||
| @@ -195,7 +216,13 @@ struct intel_context | ||||
|    GLenum render_primitive; | ||||
|    GLenum reduced_primitive; | ||||
|    GLuint vertex_size; | ||||
|    char *verts;			/* points to tnl->clipspace.vertex_buf */ | ||||
|    GLubyte *verts;			/* points to tnl->clipspace.vertex_buf */ | ||||
|  | ||||
|  | ||||
|    struct intel_region *front_region;   /* XXX FBO: obsolete */ | ||||
|    struct intel_region *back_region;    /* XXX FBO: obsolete */ | ||||
|    struct intel_region *draw_region;    /* XXX FBO: rename to color_region */ | ||||
|    struct intel_region *depth_region;   /**< currently bound depth/Z region */ | ||||
|  | ||||
|  | ||||
|    /* Fallback rasterization functions  | ||||
| @@ -204,21 +231,22 @@ struct intel_context | ||||
|    intel_line_func draw_line; | ||||
|    intel_tri_func draw_tri; | ||||
|  | ||||
|    /* These refer to the current draw (front vs. back) buffer: | ||||
|    /* These refer to the current drawing buffer: | ||||
|     */ | ||||
|    GLuint drawOffset;		/* agp offset of drawbuffer */ | ||||
|    int drawX;			/* origin of drawable in draw buffer */ | ||||
|    int drawY; | ||||
|    GLuint numClipRects;		/* cliprects for that buffer */ | ||||
|    int drawX, drawY;            /**< origin of drawing area within region */ | ||||
|    GLuint numClipRects;		/**< cliprects for drawing */ | ||||
|    drm_clip_rect_t *pClipRects; | ||||
|    drm_clip_rect_t fboRect;     /**< cliprect for FBO rendering */ | ||||
|  | ||||
|    int dirtyAge; | ||||
|    int perf_boxes; | ||||
|    int do_irqs; | ||||
|  | ||||
|    /* XXX these seem to be unused */ | ||||
| #if 0 | ||||
|    GLboolean scissor; | ||||
|    drm_clip_rect_t draw_rect; | ||||
|    drm_clip_rect_t scissor_rect; | ||||
| #endif | ||||
|  | ||||
|    drm_context_t hHWContext; | ||||
|    drmLock *driHwLock; | ||||
| @@ -228,6 +256,8 @@ struct intel_context | ||||
|    __DRIscreenPrivate *driScreen; | ||||
|    intelScreenPrivate *intelScreen;  | ||||
|    drmI830Sarea *sarea;  | ||||
|     | ||||
|    GLuint lastStamp; | ||||
|  | ||||
|    /** | ||||
|     * Configuration cache | ||||
| @@ -236,22 +266,20 @@ struct intel_context | ||||
| }; | ||||
|  | ||||
|  | ||||
| #define DEBUG_LOCKING	1 | ||||
| #define DEBUG_LOCKING 1 | ||||
|  | ||||
| #if DEBUG_LOCKING | ||||
| extern char *prevLockFile; | ||||
| extern int prevLockLine; | ||||
|  | ||||
| #define DEBUG_LOCK()							\ | ||||
|    do {									\ | ||||
|       prevLockFile = (__FILE__);					\ | ||||
|       prevLockLine = (__LINE__);					\ | ||||
|       intel->prevLockFile = (__FILE__);					\ | ||||
|       intel->prevLockLine = (__LINE__);					\ | ||||
|    } while (0) | ||||
|  | ||||
| #define DEBUG_RESET()							\ | ||||
|    do {									\ | ||||
|       prevLockFile = 0;							\ | ||||
|       prevLockLine = 0;							\ | ||||
|       intel->prevLockFile = 0;						\ | ||||
|       intel->prevLockLine = 0;						\ | ||||
|    } while (0) | ||||
|  | ||||
| /* Slightly less broken way of detecting recursive locking in a | ||||
| @@ -270,7 +298,8 @@ extern int prevLockLine; | ||||
| 	   (DRM_LOCK_HELD | intel->hHWContext) ) {			\ | ||||
| 	 fprintf( stderr,						\ | ||||
| 		  "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n",	\ | ||||
| 		  prevLockFile, prevLockLine, __FILE__, __LINE__ );	\ | ||||
| 		  intel->prevLockFile, intel->prevLockLine,		\ | ||||
| 		  __FILE__, __LINE__ );					\ | ||||
| 	 abort();							\ | ||||
|       }									\ | ||||
|    } while (0) | ||||
| @@ -283,7 +312,7 @@ extern int prevLockLine; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| extern _glthread_Mutex lockMutex; | ||||
|  | ||||
|  | ||||
| /* Lock the hardware and validate our state.   | ||||
| @@ -291,13 +320,14 @@ extern int prevLockLine; | ||||
| #define LOCK_HARDWARE( intel )				\ | ||||
| do {							\ | ||||
|     char __ret=0;					\ | ||||
|     _glthread_LOCK_MUTEX(lockMutex);                    \ | ||||
|     DEBUG_CHECK_LOCK();					\ | ||||
|     assert(!(intel)->locked);				\ | ||||
|     DRM_CAS((intel)->driHwLock, (intel)->hHWContext,	\ | ||||
|         (DRM_LOCK_HELD|(intel)->hHWContext), __ret);	\ | ||||
|     if (__ret)						\ | ||||
|         intelGetLock( (intel), 0 );			\ | ||||
|       DEBUG_LOCK();					\ | ||||
|      DEBUG_LOCK();					\ | ||||
|     (intel)->locked = 1;				\ | ||||
| }while (0) | ||||
|   | ||||
| @@ -313,6 +343,7 @@ do {									\ | ||||
|    }									\ | ||||
|    DRM_UNLOCK((intel)->driFd, (intel)->driHwLock, (intel)->hHWContext);	\ | ||||
|    DEBUG_RESET();							\ | ||||
|    _glthread_UNLOCK_MUTEX(lockMutex);                                   \ | ||||
| } while (0) | ||||
|  | ||||
|  | ||||
| @@ -321,8 +352,7 @@ do {									\ | ||||
|  | ||||
| #define INTEL_FIREVERTICES(intel)		\ | ||||
| do {						\ | ||||
|    if ((intel)->prim.flush)			\ | ||||
|       (intel)->prim.flush(&(intel)->ctx);		\ | ||||
|    assert(!(intel)->prim.flush);		\ | ||||
| } while (0) | ||||
|  | ||||
| /* ================================================================ | ||||
| @@ -343,20 +373,14 @@ do {						\ | ||||
|   ((a<<24) | (r<<16) | (g<<8) | b) | ||||
|  | ||||
|  | ||||
| #define INTEL_PACKCOLOR(format, r,  g,  b, a)		\ | ||||
| (format == DV_PF_555 ? INTEL_PACKCOLOR1555(r,g,b,a) :	\ | ||||
|  (format == DV_PF_565 ? INTEL_PACKCOLOR565(r,g,b) :	\ | ||||
|   (format == DV_PF_8888 ? INTEL_PACKCOLOR8888(r,g,b,a) :	\ | ||||
|    0))) | ||||
|  | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * From linux kernel i386 header files, copes with odd sizes better | ||||
|  * than COPY_DWORDS would: | ||||
|  * XXX Put this in src/mesa/main/imports.h ??? | ||||
|  */ | ||||
| #if defined(i386) || defined(__i386__) | ||||
| static __inline__ void * __memcpy(void * to, const void * from, size_t n) | ||||
| static INLINE void * __memcpy(void * to, const void * from, size_t n) | ||||
| { | ||||
|    int d0, d1, d2; | ||||
|    __asm__ __volatile__( | ||||
| @@ -417,21 +441,19 @@ extern int INTEL_DEBUG; | ||||
|  * intel_context.c: | ||||
|  */ | ||||
|  | ||||
| extern void intelInitDriverFunctions( struct dd_function_table *functions ); | ||||
|  | ||||
| extern GLboolean intelInitContext( intelContextPtr intel,  | ||||
| extern GLboolean intelInitContext( struct intel_context *intel,  | ||||
| 				   const __GLcontextModes *mesaVis, | ||||
| 				   __DRIcontextPrivate *driContextPriv, | ||||
| 				   void *sharedContextPrivate, | ||||
| 				   struct dd_function_table *functions ); | ||||
|  | ||||
| extern void intelGetLock(intelContextPtr intel, GLuint flags); | ||||
| extern void intelSetBackClipRects(intelContextPtr intel); | ||||
| extern void intelSetFrontClipRects(intelContextPtr intel); | ||||
| extern void intelWindowMoved( intelContextPtr intel ); | ||||
| extern void intelGetLock(struct intel_context *intel, GLuint flags); | ||||
|  | ||||
| extern void intelInitState( GLcontext *ctx ); | ||||
| extern const GLubyte *intelGetString( GLcontext *ctx, GLenum name ); | ||||
| extern void intelFinish( GLcontext *ctx ); | ||||
| extern void intelFlush( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelInitDriverFunctions( struct dd_function_table *functions ); | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
| @@ -491,6 +513,8 @@ extern void intelInitStateFuncs( struct dd_function_table *functions ); | ||||
| #define BLENDFACT_INV_CONST_ALPHA	0x0f | ||||
| #define BLENDFACT_MASK          	0x0f | ||||
|  | ||||
| #define MI_BATCH_BUFFER_END 	(0xA<<23) | ||||
|  | ||||
|  | ||||
| extern int intel_translate_compare_func( GLenum func ); | ||||
| extern int intel_translate_stencil_op( GLenum op ); | ||||
| @@ -498,19 +522,26 @@ extern int intel_translate_blend_factor( GLenum factor ); | ||||
| extern int intel_translate_logic_op( GLenum opcode ); | ||||
|  | ||||
|  | ||||
| /* ================================================================ | ||||
|  * intel_ioctl.c: | ||||
| /*====================================================================== | ||||
|  * Inline conversion functions.   | ||||
|  * These are better-typed than the macros used previously: | ||||
|  */ | ||||
| extern void intel_dump_batchbuffer( long offset, | ||||
| 				    int *ptr, | ||||
| 				    int count ); | ||||
| static INLINE struct intel_context *intel_context( GLcontext *ctx ) | ||||
| { | ||||
|    return (struct intel_context *)ctx; | ||||
| } | ||||
|  | ||||
| static INLINE struct intel_texture_object *intel_texture_object( struct gl_texture_object *obj ) | ||||
| { | ||||
|    return (struct intel_texture_object *)obj; | ||||
| } | ||||
|  | ||||
| /* ================================================================ | ||||
|  * intel_pixel.c: | ||||
|  */	 | ||||
| extern void intelInitPixelFuncs( struct dd_function_table *functions ); | ||||
| static INLINE struct intel_texture_image *intel_texture_image( struct gl_texture_image *img ) | ||||
| { | ||||
|    return (struct intel_texture_image *)img; | ||||
| } | ||||
|  | ||||
| extern struct intel_renderbuffer *intel_renderbuffer( struct gl_renderbuffer *rb ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										281
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "imports.h" | ||||
| #include "context.h" | ||||
| #include "depthstencil.h" | ||||
| #include "fbobject.h" | ||||
| #include "framebuffer.h" | ||||
| #include "hash.h" | ||||
| #include "mtypes.h" | ||||
| #include "renderbuffer.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_depthstencil.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * The GL_EXT_framebuffer_object allows the user to create their own | ||||
|  * framebuffer objects consisting of color renderbuffers (0 or more), | ||||
|  * depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1). | ||||
|  * | ||||
|  * The spec considers depth and stencil renderbuffers to be totally independent | ||||
|  * buffers.  In reality, most graphics hardware today uses a combined | ||||
|  * depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil). | ||||
|  * | ||||
|  * This causes difficulty because the user may create some number of depth | ||||
|  * renderbuffers and some number of stencil renderbuffers and bind them | ||||
|  * together in framebuffers in any combination. | ||||
|  * | ||||
|  * This code manages all that. | ||||
|  * | ||||
|  * 1. Depth renderbuffers are always allocated in hardware as 32bpp | ||||
|  *    GL_DEPTH24_STENCIL8 buffers. | ||||
|  * | ||||
|  * 2. Stencil renderbuffers are initially allocated in software as 8bpp | ||||
|  *    GL_STENCIL_INDEX8 buffers. | ||||
|  * | ||||
|  * 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth | ||||
|  *    fields (respectively) to indicate if the buffer's currently paired | ||||
|  *    with another stencil or depth buffer (respectively). | ||||
|  * | ||||
|  * 4. When a depth and stencil buffer are initially both attached to the | ||||
|  *    current framebuffer, we merge the stencil buffer values into the | ||||
|  *    depth buffer (really a depth+stencil buffer).  The then hardware uses | ||||
|  *    the combined buffer. | ||||
|  * | ||||
|  * 5. Whenever a depth or stencil buffer is reallocated (with | ||||
|  *    glRenderbufferStorage) we undo the pairing and copy the stencil values | ||||
|  *    from the combined depth/stencil buffer back to the stencil-only buffer. | ||||
|  * | ||||
|  * 6. We also undo the pairing when we find a change in buffer bindings. | ||||
|  * | ||||
|  * 7. If a framebuffer is only using a depth renderbuffer (no stencil), we | ||||
|  *    just use the combined depth/stencil buffer and ignore the stencil values. | ||||
|  * | ||||
|  * 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have | ||||
|  *    to promote the 8bpp software stencil buffer to a 32bpp hardware | ||||
|  *    depth+stencil buffer. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| map_regions(GLcontext *ctx,  | ||||
|             struct intel_renderbuffer *depthRb, | ||||
|             struct intel_renderbuffer *stencilRb) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    if (depthRb && depthRb->region) { | ||||
|       intel_region_map(intel, depthRb->region); | ||||
|       depthRb->pfMap = depthRb->region->map; | ||||
|       depthRb->pfPitch = depthRb->region->pitch; | ||||
|    } | ||||
|    if (stencilRb && stencilRb->region) { | ||||
|       intel_region_map(intel, stencilRb->region); | ||||
|       stencilRb->pfMap = stencilRb->region->map; | ||||
|       stencilRb->pfPitch = stencilRb->region->pitch; | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void | ||||
| unmap_regions(GLcontext *ctx,  | ||||
|               struct intel_renderbuffer *depthRb, | ||||
|               struct intel_renderbuffer *stencilRb) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    if (depthRb && depthRb->region) { | ||||
|       intel_region_unmap(intel, depthRb->region); | ||||
|       depthRb->pfMap = NULL; | ||||
|       depthRb->pfPitch = 0; | ||||
|    } | ||||
|    if (stencilRb && stencilRb->region) { | ||||
|       intel_region_unmap(intel, stencilRb->region); | ||||
|       stencilRb->pfMap = NULL; | ||||
|       stencilRb->pfPitch = 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Undo the pairing/interleaving between depth and stencil buffers. | ||||
|  * irb should be a depth/stencil or stencil renderbuffer. | ||||
|  */ | ||||
| void | ||||
| intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb) | ||||
| { | ||||
|    if (irb->PairedStencil) { | ||||
|       /* irb is a depth/stencil buffer */ | ||||
|       struct gl_renderbuffer *stencilRb; | ||||
|       struct intel_renderbuffer *stencilIrb; | ||||
|  | ||||
|       ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|  | ||||
|       stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil); | ||||
|       stencilIrb = intel_renderbuffer(stencilRb); | ||||
|       if (stencilIrb) { | ||||
|          /* need to extract stencil values from the depth buffer */ | ||||
|          ASSERT(stencilIrb->PairedDepth == irb->Base.Name); | ||||
|          map_regions(ctx, irb, stencilIrb); | ||||
|          _mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base); | ||||
|          unmap_regions(ctx, irb, stencilIrb); | ||||
|          stencilIrb->PairedDepth = 0; | ||||
|       } | ||||
|       irb->PairedStencil = 0; | ||||
|    } | ||||
|    else if (irb->PairedDepth) { | ||||
|       /* irb is a stencil buffer */ | ||||
|       struct gl_renderbuffer *depthRb; | ||||
|       struct intel_renderbuffer *depthIrb; | ||||
|  | ||||
|       ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || | ||||
|              irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|  | ||||
|       depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth); | ||||
|       depthIrb = intel_renderbuffer(depthRb); | ||||
|       if (depthIrb) { | ||||
|          /* need to extract stencil values from the depth buffer */ | ||||
|          ASSERT(depthIrb->PairedStencil == irb->Base.Name); | ||||
|          map_regions(ctx, depthIrb, irb); | ||||
|          _mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base); | ||||
|          unmap_regions(ctx, depthIrb, irb); | ||||
|          depthIrb->PairedStencil = 0; | ||||
|       } | ||||
|       irb->PairedDepth = 0; | ||||
|    } | ||||
|    else { | ||||
|       _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing"); | ||||
|    } | ||||
|  | ||||
|    ASSERT(irb->PairedStencil == 0); | ||||
|    ASSERT(irb->PairedDepth == 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Examine the depth and stencil renderbuffers which are attached to the | ||||
|  * framebuffer.  If both depth and stencil are attached, make sure that the | ||||
|  * renderbuffers are 'paired' (combined).  If only depth or only stencil is | ||||
|  * attached, undo any previous pairing. | ||||
|  * | ||||
|  * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments | ||||
|  * change, for example). | ||||
|  */ | ||||
| void | ||||
| intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb) | ||||
| { | ||||
|    struct intel_renderbuffer *depthRb, *stencilRb; | ||||
|  | ||||
|    depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH); | ||||
|    stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL); | ||||
|  | ||||
|    if (depthRb && stencilRb) { | ||||
|       if (depthRb == stencilRb) { | ||||
|          /* Using a user-created combined depth/stencil buffer. | ||||
|           * Nothing to do. | ||||
|           */ | ||||
|          ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT); | ||||
|          ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|       } | ||||
|       else { | ||||
|          /* Separate depth/stencil buffers, need to interleave now */ | ||||
|          ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT); | ||||
|          ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX); | ||||
|          /* may need to interleave depth/stencil now */ | ||||
|          if (depthRb->PairedStencil == stencilRb->Base.Name) { | ||||
|             /* OK, the depth and stencil buffers are already interleaved */ | ||||
|             ASSERT(stencilRb->PairedDepth == depthRb->Base.Name); | ||||
|          } | ||||
|          else { | ||||
|             /* need to setup new pairing/interleaving */ | ||||
|             if (depthRb->PairedStencil) { | ||||
|                intel_unpair_depth_stencil(ctx, depthRb); | ||||
|             } | ||||
|             if (stencilRb->PairedDepth) { | ||||
|                intel_unpair_depth_stencil(ctx, stencilRb); | ||||
|             } | ||||
|  | ||||
|             ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|             ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || | ||||
|                    stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|  | ||||
|             /* establish new pairing: interleave stencil into depth buffer */ | ||||
|             map_regions(ctx, depthRb, stencilRb); | ||||
|             _mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base); | ||||
|             unmap_regions(ctx, depthRb, stencilRb); | ||||
|             depthRb->PairedStencil = stencilRb->Base.Name; | ||||
|             stencilRb->PairedDepth = depthRb->Base.Name; | ||||
|          } | ||||
|  | ||||
|       } | ||||
|    } | ||||
|    else if (depthRb) { | ||||
|       /* Depth buffer but no stencil buffer. | ||||
|        * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits. | ||||
|        */ | ||||
|       /* can't assert this until storage is allocated: | ||||
|       ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|       */ | ||||
|       /* intel_undo any previous pairing */ | ||||
|       if (depthRb->PairedStencil) { | ||||
|          intel_unpair_depth_stencil(ctx, depthRb); | ||||
|       } | ||||
|    } | ||||
|    else if (stencilRb) { | ||||
|       /* Stencil buffer but no depth buffer. | ||||
|        * Since h/w doesn't typically support just 8bpp stencil w/out Z, | ||||
|        * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits. | ||||
|        */ | ||||
|       /* undo any previous pairing */ | ||||
|       if (stencilRb->PairedDepth) { | ||||
|          intel_unpair_depth_stencil(ctx, stencilRb); | ||||
|       } | ||||
|       if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) { | ||||
|          /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */ | ||||
|          _mesa_promote_stencil(ctx, &stencilRb->Base); | ||||
|          ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */ | ||||
|    _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); | ||||
|    if (depthRb && depthRb->PairedStencil) | ||||
|       _mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH); | ||||
|    else | ||||
|       _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); | ||||
|  | ||||
|  | ||||
|    /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer | ||||
|     * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer | ||||
|     * if present. | ||||
|     */ | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/mesa/drivers/dri/i915/intel_depthstencil.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
|  | ||||
| #ifndef INTEL_DEPTH_STENCIL_H | ||||
| #define INTEL_DEPTH_STENCIL_H | ||||
|  | ||||
|  | ||||
| extern void | ||||
| intel_unpair_depth_stencil(GLcontext *ctx, struct intel_renderbuffer *irb); | ||||
|  | ||||
| extern void | ||||
| intel_validate_paired_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb); | ||||
|  | ||||
|  | ||||
| #endif /* INTEL_DEPTH_STENCIL_H */ | ||||
							
								
								
									
										638
									
								
								src/mesa/drivers/dri/i915/intel_fbo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										638
									
								
								src/mesa/drivers/dri/i915/intel_fbo.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,638 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
|  | ||||
| #include "imports.h" | ||||
| #include "mtypes.h" | ||||
| #include "fbobject.h" | ||||
| #include "framebuffer.h" | ||||
| #include "renderbuffer.h" | ||||
| #include "context.h" | ||||
| #include "texformat.h" | ||||
| #include "texrender.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_bufmgr.h" | ||||
| #include "intel_depthstencil.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_span.h" | ||||
|  | ||||
| #define INTEL_RB_CLASS 0x12345678 | ||||
|  | ||||
|  | ||||
| /* XXX FBO: move this to intel_context.h (inlined) */ | ||||
| /** | ||||
|  * Return a gl_renderbuffer ptr casted to intel_renderbuffer. | ||||
|  * NULL will be returned if the rb isn't really an intel_renderbuffer. | ||||
|  * This is determiend by checking the ClassID. | ||||
|  */ | ||||
| struct intel_renderbuffer *intel_renderbuffer( struct gl_renderbuffer *rb ) | ||||
| { | ||||
|    struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb; | ||||
|    if (irb && irb->Base.ClassID == INTEL_RB_CLASS) { | ||||
|       /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/ | ||||
|       return irb; | ||||
|    } | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct intel_renderbuffer * | ||||
| intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) | ||||
| { | ||||
|    return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); | ||||
| } | ||||
|  | ||||
|  | ||||
| struct intel_region * | ||||
| intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) | ||||
| { | ||||
|    struct intel_renderbuffer *irb | ||||
|       = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); | ||||
|    if (irb) | ||||
|       return irb->region; | ||||
|    else | ||||
|       return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Create a new framebuffer object. | ||||
|  */ | ||||
| static struct gl_framebuffer * | ||||
| intel_new_framebuffer(GLcontext *ctx, GLuint name) | ||||
| { | ||||
|    /* there's no intel_framebuffer at this time, just use Mesa's class */ | ||||
|    return _mesa_new_framebuffer(ctx, name); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_delete_renderbuffer(struct gl_renderbuffer *rb) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb); | ||||
|  | ||||
|    ASSERT(irb); | ||||
|  | ||||
|    if (irb->PairedStencil || irb->PairedDepth) { | ||||
|       intel_unpair_depth_stencil(ctx, irb); | ||||
|    } | ||||
|  | ||||
|    if (intel && irb->region) { | ||||
|       intel_region_release(intel, &irb->region); | ||||
|    } | ||||
|  | ||||
|    _mesa_free(irb); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Return a pointer to a specific pixel in a renderbuffer. | ||||
|  */ | ||||
| static void * | ||||
| intel_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb, | ||||
|                   GLint x, GLint y) | ||||
| { | ||||
|    /* By returning NULL we force all software rendering to go through | ||||
|     * the span routines. | ||||
|     */ | ||||
|    return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glRenderbufferStorageEXT() to set the format and allocate | ||||
|  * storage for a user-created renderbuffer. | ||||
|  */ | ||||
| static GLboolean | ||||
| intel_alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, | ||||
|                                  GLenum internalFormat, | ||||
|                                  GLuint width, GLuint height) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb); | ||||
|    GLboolean softwareBuffer = GL_FALSE; | ||||
|    int cpp; | ||||
|  | ||||
|    ASSERT(rb->Name != 0); | ||||
|  | ||||
|    switch (internalFormat) { | ||||
|    case GL_R3_G3_B2: | ||||
|    case GL_RGB4: | ||||
|    case GL_RGB5: | ||||
|       rb->_ActualFormat = GL_RGB5; | ||||
|       rb->DataType = GL_UNSIGNED_BYTE; | ||||
|       rb->RedBits = 5; | ||||
|       rb->GreenBits = 6; | ||||
|       rb->BlueBits = 5; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_RGB: | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|    case GL_RGBA: | ||||
|    case GL_RGBA2: | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGB5_A1: | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       rb->_ActualFormat = GL_RGBA8; | ||||
|       rb->DataType = GL_UNSIGNED_BYTE; | ||||
|       rb->RedBits = 8; | ||||
|       rb->GreenBits = 8; | ||||
|       rb->BlueBits = 8; | ||||
|       rb->AlphaBits = 8; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_STENCIL_INDEX: | ||||
|    case GL_STENCIL_INDEX1_EXT: | ||||
|    case GL_STENCIL_INDEX4_EXT: | ||||
|    case GL_STENCIL_INDEX8_EXT: | ||||
|    case GL_STENCIL_INDEX16_EXT: | ||||
|       /* alloc a depth+stencil buffer */ | ||||
|       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       rb->DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       rb->StencilBits = 8; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|       rb->_ActualFormat = GL_DEPTH_COMPONENT16; | ||||
|       rb->DataType = GL_UNSIGNED_SHORT; | ||||
|       rb->DepthBits = 16; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       rb->DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       rb->DepthBits = 24; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_DEPTH_STENCIL_EXT: | ||||
|    case GL_DEPTH24_STENCIL8_EXT: | ||||
|       rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       rb->DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       rb->DepthBits = 24; | ||||
|       rb->StencilBits = 8; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    default: | ||||
|       _mesa_problem(ctx, "Unexpected format in intel_alloc_renderbuffer_storage"); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    /* free old region */ | ||||
|    if (irb->region) { | ||||
|       /*LOCK_HARDWARE(intel);*/ | ||||
|       intel_region_release(intel, &irb->region); | ||||
|       /*UNLOCK_HARDWARE(intel);*/ | ||||
|    } | ||||
|  | ||||
|    /* allocate new memory region/renderbuffer */ | ||||
|    if (softwareBuffer) { | ||||
|       return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat, | ||||
|                                              width, height); | ||||
|    } | ||||
|    else { | ||||
|       /* Choose a pitch to match hardware requirements: | ||||
|        */ | ||||
|       GLuint pitch = ((cpp * width + 63) & ~63) / cpp; | ||||
|  | ||||
|       /* alloc hardware renderbuffer */ | ||||
|       _mesa_debug(ctx, "Allocating %d x %d Intel RBO (pitch %d)\n", width, height, pitch); | ||||
|  | ||||
|       irb->region = intel_region_alloc(intel, cpp, pitch, height); | ||||
|       if (!irb->region) | ||||
|          return GL_FALSE; /* out of memory? */ | ||||
|  | ||||
|       ASSERT(irb->region->buffer); | ||||
|  | ||||
|       rb->Width = width; | ||||
|       rb->Height = height; | ||||
|  | ||||
|       /* This sets the Get/PutRow/Value functions */ | ||||
|       intel_set_span_functions(&irb->Base); | ||||
|  | ||||
|       return GL_TRUE; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called for each hardware renderbuffer when a _window_ is resized. | ||||
|  * Just update fields. | ||||
|  * Not used for user-created renderbuffers! | ||||
|  */ | ||||
| static GLboolean | ||||
| intel_alloc_window_storage(GLcontext *ctx, struct gl_renderbuffer *rb, | ||||
|                            GLenum internalFormat, | ||||
|                            GLuint width, GLuint height) | ||||
| { | ||||
|    ASSERT(rb->Name == 0); | ||||
|    rb->Width = width; | ||||
|    rb->Height = height; | ||||
|    rb->_ActualFormat = internalFormat; | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intel_nop_alloc_storage(GLcontext *ctx, struct gl_renderbuffer *rb, | ||||
|                         GLenum internalFormat, | ||||
|                         GLuint width, GLuint height) | ||||
| { | ||||
|    _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Create a new intel_renderbuffer which corresponds to an on-screen window, | ||||
|  * not a user-created renderbuffer. | ||||
|  * \param width  the screen width | ||||
|  * \param height  the screen height | ||||
|  */ | ||||
| struct intel_renderbuffer * | ||||
| intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height, | ||||
|                           int offset, int pitch, int cpp, void *map) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|     | ||||
|    struct intel_renderbuffer *irb; | ||||
|    const GLuint name = 0; | ||||
|  | ||||
|    irb = CALLOC_STRUCT(intel_renderbuffer); | ||||
|    if (!irb) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    _mesa_init_renderbuffer(&irb->Base, name); | ||||
|    irb->Base.ClassID = INTEL_RB_CLASS; | ||||
|  | ||||
|    switch (intFormat) { | ||||
|    case GL_RGB5: | ||||
|       irb->Base._ActualFormat = GL_RGB5; | ||||
|       irb->Base._BaseFormat = GL_RGBA; | ||||
|       irb->Base.RedBits = 5; | ||||
|       irb->Base.GreenBits = 6; | ||||
|       irb->Base.BlueBits = 5; | ||||
|       irb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_RGBA8: | ||||
|       irb->Base._ActualFormat = GL_RGBA8; | ||||
|       irb->Base._BaseFormat = GL_RGBA; | ||||
|       irb->Base.RedBits = 8; | ||||
|       irb->Base.GreenBits = 8; | ||||
|       irb->Base.BlueBits = 8; | ||||
|       irb->Base.AlphaBits = 8; | ||||
|       irb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_STENCIL_INDEX8_EXT: | ||||
|       irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT; | ||||
|       irb->Base._BaseFormat = GL_STENCIL_INDEX; | ||||
|       irb->Base.StencilBits = 8; | ||||
|       irb->Base.DataType = GL_UNSIGNED_BYTE; | ||||
|       cpp = 1; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|       irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_COMPONENT; | ||||
|       irb->Base.DepthBits = 16; | ||||
|       irb->Base.DataType = GL_UNSIGNED_SHORT; | ||||
|       cpp = 2; | ||||
|       break; | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|       irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_COMPONENT; | ||||
|       irb->Base.DepthBits = 24; | ||||
|       irb->Base.DataType = GL_UNSIGNED_INT; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    case GL_DEPTH24_STENCIL8_EXT: | ||||
|       irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; | ||||
|       irb->Base.DepthBits = 24; | ||||
|       irb->Base.StencilBits = 8; | ||||
|       irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; | ||||
|       cpp = 4; | ||||
|       break; | ||||
|    default: | ||||
|       _mesa_problem(NULL, "Unexpected intFormat in intel_create_renderbuffer"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    irb->Base.InternalFormat = intFormat; | ||||
|  | ||||
|    /* intel-specific methods */ | ||||
|    irb->Base.Delete = intel_delete_renderbuffer; | ||||
|    irb->Base.AllocStorage = intel_alloc_window_storage; | ||||
|    irb->Base.GetPointer = intel_get_pointer; | ||||
|    /* This sets the Get/PutRow/Value functions */ | ||||
|    intel_set_span_functions(&irb->Base); | ||||
|  | ||||
|    irb->pfMap = map; | ||||
|    irb->pfPitch = pitch; | ||||
|  | ||||
| #if 00 | ||||
|    irb->region = intel_region_create_static(intel, | ||||
|                                             DRM_MM_TT, | ||||
|                                             offset, | ||||
|                                             map, | ||||
|                                             cpp, | ||||
|                                             width, height); | ||||
| #endif | ||||
|  | ||||
|    return irb; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Create a new renderbuffer object. | ||||
|  * Typically called via glBindRenderbufferEXT(). | ||||
|  */ | ||||
| static struct gl_renderbuffer * | ||||
| intel_new_renderbuffer(GLcontext *ctx, GLuint name) | ||||
| { | ||||
|    /*struct intel_context *intel = intel_context(ctx);*/ | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    irb = CALLOC_STRUCT(intel_renderbuffer); | ||||
|    if (!irb) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    _mesa_init_renderbuffer(&irb->Base, name); | ||||
|    irb->Base.ClassID = INTEL_RB_CLASS; | ||||
|  | ||||
|    /* intel-specific methods */ | ||||
|    irb->Base.Delete = intel_delete_renderbuffer; | ||||
|    irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; | ||||
|    irb->Base.GetPointer = intel_get_pointer; | ||||
|    /* span routines set in alloc_storage function */ | ||||
|  | ||||
|    return &irb->Base; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glBindFramebufferEXT(). | ||||
|  */ | ||||
| static void | ||||
| intel_bind_framebuffer(GLcontext *ctx, GLenum target, | ||||
|                        struct gl_framebuffer *fb) | ||||
| { | ||||
|    /* | ||||
|    _mesa_debug(ctx, "%s %d\n", __FUNCTION__, fb->Name); | ||||
|    */ | ||||
|    /* XXX FBO: putting this flush here fixes a rendering offset bug. | ||||
|     * Not sure why this is needed when _mesa_BindFrameBuffer does | ||||
|     * a FLUSH_VERTICES(). | ||||
|     */ | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { | ||||
|       intel_draw_buffer(ctx, fb); | ||||
|       /* Integer depth range depends on depth buffer bits */ | ||||
|       ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); | ||||
|    } | ||||
|    else { | ||||
|       /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called via glFramebufferRenderbufferEXT(). | ||||
|  */ | ||||
| static void | ||||
| intel_framebuffer_renderbuffer(GLcontext *ctx,  | ||||
|                                struct gl_framebuffer *fb, | ||||
|                                GLenum attachment, | ||||
|                                struct gl_renderbuffer *rb) | ||||
| { | ||||
|    /* | ||||
|    _mesa_debug(ctx, "Intel FramebufferRenderbuffer %u %u\n", | ||||
|                fb->Name, rb ? rb->Name : 0); | ||||
|    */ | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); | ||||
|    intel_draw_buffer(ctx, fb); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * When glFramebufferTexture[123]D is called this function sets up the | ||||
|  * gl_renderbuffer wrapp around the texture image. | ||||
|  * This will have the region info needed for hardware rendering. | ||||
|  */ | ||||
| static struct intel_renderbuffer * | ||||
| intel_wrap_texture(GLcontext *ctx, struct gl_texture_image *texImage) | ||||
| { | ||||
|    const GLuint name = ~0; /* not significant, but distinct for debugging */ | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    /* make an intel_renderbuffer to wrap the texture image */ | ||||
|    irb = CALLOC_STRUCT(intel_renderbuffer); | ||||
|    if (!irb) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    _mesa_init_renderbuffer(&irb->Base, name); | ||||
|    irb->Base.ClassID = INTEL_RB_CLASS; | ||||
|  | ||||
|    if (texImage->TexFormat == &_mesa_texformat_argb8888) { | ||||
|       irb->Base._ActualFormat = GL_RGBA8; | ||||
|       irb->Base._BaseFormat = GL_RGBA; | ||||
|       _mesa_debug(ctx, "Render to RGBA8 texture OK\n"); | ||||
|    } | ||||
|    else if (texImage->TexFormat == &_mesa_texformat_rgb565) { | ||||
|       irb->Base._ActualFormat = GL_RGB5; | ||||
|       irb->Base._BaseFormat = GL_RGB; | ||||
|       _mesa_debug(ctx, "Render to RGB5 texture OK\n"); | ||||
|    } | ||||
|    else if (texImage->TexFormat == &_mesa_texformat_depth_component16) { | ||||
|       irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; | ||||
|       irb->Base._BaseFormat = GL_DEPTH_COMPONENT; | ||||
|       _mesa_debug(ctx, "Render to DEPTH16 texture OK\n"); | ||||
|    } | ||||
|    else { | ||||
|       _mesa_debug(ctx, "Render to texture BAD FORMAT %d\n", texImage->TexFormat->MesaFormat); | ||||
|       _mesa_free(irb); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    irb->Base.InternalFormat = irb->Base._ActualFormat; | ||||
|    irb->Base.Width = texImage->Width; | ||||
|    irb->Base.Height = texImage->Height; | ||||
|    irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */ | ||||
|    irb->Base.RedBits = texImage->TexFormat->RedBits; | ||||
|    irb->Base.GreenBits = texImage->TexFormat->GreenBits; | ||||
|    irb->Base.BlueBits = texImage->TexFormat->BlueBits; | ||||
|    irb->Base.AlphaBits = texImage->TexFormat->AlphaBits; | ||||
|    irb->Base.DepthBits = texImage->TexFormat->DepthBits; | ||||
|  | ||||
|    irb->Base.Delete = intel_delete_renderbuffer; | ||||
|    irb->Base.AllocStorage = intel_nop_alloc_storage; | ||||
|    intel_set_span_functions(&irb->Base); | ||||
|  | ||||
|    irb->RenderToTexture = GL_TRUE; | ||||
|  | ||||
|    return irb; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called by glFramebufferTexture[123]DEXT() (and other places) to | ||||
|  * prepare for rendering into texture memory.  This might be called | ||||
|  * many times to choose different texture levels, cube faces, etc | ||||
|  * before intel_finish_render_texture() is ever called. | ||||
|  */ | ||||
| static void | ||||
| intel_render_texture(GLcontext *ctx, | ||||
|                      struct gl_framebuffer *fb, | ||||
|                      struct gl_renderbuffer_attachment *att) | ||||
| { | ||||
|    struct gl_texture_image *newImage | ||||
|       = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; | ||||
|    struct intel_renderbuffer *irb | ||||
|       = intel_renderbuffer(att->Renderbuffer); | ||||
|    struct intel_texture_image *intel_image; | ||||
|    GLuint imageOffset; | ||||
|  | ||||
|    (void) fb; | ||||
|  | ||||
|    ASSERT(newImage); | ||||
|  | ||||
|    if (!irb) { | ||||
|       irb = intel_wrap_texture(ctx, newImage); | ||||
|       if (irb) { | ||||
|          /* bind the wrapper to the attachment point */ | ||||
|          att->Renderbuffer = &irb->Base; | ||||
|       } | ||||
|       else { | ||||
|          /* fallback to software rendering */ | ||||
|          _mesa_render_texture(ctx, fb, att); | ||||
|          return; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* | ||||
|    _mesa_debug(ctx, "Begin render texture tex=%u w=%d h=%d refcount=%d\n", | ||||
|                att->Texture->Name, newImage->Width, newImage->Height, | ||||
|                irb->Base.RefCount); | ||||
|    */ | ||||
|  | ||||
|    /* point the renderbufer's region to the texture image region */ | ||||
|    intel_image = intel_texture_image(newImage); | ||||
|    if (irb->region != intel_image->mt->region) | ||||
|       intel_region_reference(&irb->region, intel_image->mt->region); | ||||
|  | ||||
|    /* compute offset of the particular 2D image within the texture region */ | ||||
|    imageOffset = intel_miptree_image_offset(intel_image->mt, | ||||
|                                             att->CubeMapFace, | ||||
|                                             att->TextureLevel); | ||||
|    if (att->Texture->Target == GL_TEXTURE_3D) { | ||||
|       GLuint imgStride = intel_miptree_depth_image_stride(intel_image->mt, | ||||
|                                                           att->CubeMapFace, | ||||
|                                                           att->TextureLevel); | ||||
|       imageOffset += imgStride * att->Zoffset; | ||||
|    } | ||||
|    /* store that offset in the region */ | ||||
|    intel_image->mt->region->draw_offset = imageOffset; | ||||
|  | ||||
|    /* update drawing region, etc */ | ||||
|    intel_draw_buffer(ctx, fb); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Called by Mesa when rendering to a texture is done. | ||||
|  */ | ||||
| static void | ||||
| intel_finish_render_texture(GLcontext *ctx, | ||||
|                            struct gl_renderbuffer_attachment *att) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_renderbuffer *irb | ||||
|       = intel_renderbuffer(att->Renderbuffer); | ||||
|  | ||||
|    /* | ||||
|    _mesa_debug(ctx, "End render texture (tid %u) tex %u\n", | ||||
|                _glthread_GetID(), att->Texture->Name); | ||||
|    */ | ||||
|  | ||||
|    if (irb) { | ||||
|       /* just release the region */ | ||||
|       intel_region_release(intel, &irb->region); | ||||
|    } | ||||
|    else if (att->Renderbuffer) { | ||||
|       /* software fallback */ | ||||
|       _mesa_finish_render_texture(ctx, att); | ||||
|       /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */ | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Do one-time context initializations related to GL_EXT_framebuffer_object. | ||||
|  * Hook in device driver functions. | ||||
|  */ | ||||
| void | ||||
| intel_fbo_init( struct intel_context *intel ) | ||||
| { | ||||
|    intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; | ||||
|    intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; | ||||
|    intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; | ||||
|    intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; | ||||
|    intel->ctx.Driver.RenderTexture = intel_render_texture; | ||||
|    intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; | ||||
| } | ||||
							
								
								
									
										75
									
								
								src/mesa/drivers/dri/i915/intel_fbo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/mesa/drivers/dri/i915/intel_fbo.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_FBO_H | ||||
| #define INTEL_FBO_H | ||||
|  | ||||
|  | ||||
| struct intel_context; | ||||
| struct intel_region; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Intel renderbuffer, derived from gl_renderbuffer. | ||||
|  * Note: The PairedDepth and PairedStencil fields use renderbuffer IDs, | ||||
|  * not pointers because in some circumstances a deleted renderbuffer could | ||||
|  * result in a dangling pointer here. | ||||
|  */ | ||||
| struct intel_renderbuffer { | ||||
|    struct gl_renderbuffer Base; | ||||
|    struct intel_region *region; | ||||
|    void *pfMap;    /* possibly paged flipped map pointer */ | ||||
|    GLuint pfPitch; /* possibly paged flipped pitch */ | ||||
|    GLboolean RenderToTexture; /* RTT? */ | ||||
|  | ||||
|    GLuint PairedDepth;   /**< only used if this is a depth renderbuffer */ | ||||
|    GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| extern struct intel_renderbuffer * | ||||
| intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height, | ||||
|                           int offset, int pitch, int cpp, void *map); | ||||
|  | ||||
|  | ||||
| extern void | ||||
| intel_fbo_init( struct intel_context *intel ); | ||||
|  | ||||
|  | ||||
| /* XXX make inline or macro */ | ||||
| extern struct intel_renderbuffer * | ||||
| intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex); | ||||
|  | ||||
|  | ||||
| /* XXX make inline or macro */ | ||||
| extern struct intel_region * | ||||
| intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif /* INTEL_FBO_H */ | ||||
| @@ -38,11 +38,13 @@ | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_regions.h" | ||||
| #include "drm.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static int intelEmitIrqLocked( intelContextPtr intel ) | ||||
| int intelEmitIrqLocked( struct intel_context *intel ) | ||||
| { | ||||
|    drmI830IrqEmit ie; | ||||
|    int ret, seq = 0; | ||||
| @@ -51,21 +53,21 @@ static int intelEmitIrqLocked( intelContextPtr intel ) | ||||
| 	  (DRM_LOCK_HELD|intel->hHWContext)); | ||||
|  | ||||
|    ie.irq_seq = &seq; | ||||
| 	  | ||||
|  | ||||
|    ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT,  | ||||
| 			      &ie, sizeof(ie) ); | ||||
|    if ( ret ) { | ||||
|       fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret ); | ||||
|       exit(1); | ||||
|    } | ||||
|     | ||||
|    }    | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s -->  %d\n", __FUNCTION__, seq ); | ||||
|  | ||||
|    return seq; | ||||
| } | ||||
|  | ||||
| static void intelWaitIrq( intelContextPtr intel, int seq ) | ||||
| void intelWaitIrq( struct intel_context *intel, int seq ) | ||||
| { | ||||
|    drmI830IrqWait iw; | ||||
|    int ret; | ||||
| @@ -81,527 +83,69 @@ static void intelWaitIrq( intelContextPtr intel, int seq ) | ||||
|  | ||||
|    if ( ret ) { | ||||
|       fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret ); | ||||
|       if (0) | ||||
| 	 intel_dump_batchbuffer( intel->alloc.offset, | ||||
| 				 intel->alloc.ptr, | ||||
| 				 intel->alloc.size ); | ||||
|       exit(1); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static void age_intel( intelContextPtr intel, int age ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) | ||||
|       if (intel->CurrentTexObj[i])  | ||||
| 	 intel->CurrentTexObj[i]->age = age; | ||||
| } | ||||
|  | ||||
| void intel_dump_batchbuffer( long offset, | ||||
| 			     int *ptr, | ||||
| 			     int count ) | ||||
| { | ||||
|    int i; | ||||
|    fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count); | ||||
|    for (i = 0; i < count/4; i += 4)  | ||||
|       fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n",  | ||||
| 	      (unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); | ||||
|    fprintf(stderr, "END BATCH\n\n\n"); | ||||
| } | ||||
|  | ||||
| void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ) | ||||
| { | ||||
|    GLuint last_irq = intel->alloc.irq_emitted; | ||||
|    GLuint half = intel->alloc.size / 2; | ||||
|    GLuint buf = (intel->alloc.active_buf ^= 1); | ||||
|  | ||||
|    intel->alloc.irq_emitted = intelEmitIrqLocked( intel ); | ||||
|  | ||||
|    if (last_irq) { | ||||
|       if (allow_unlock) UNLOCK_HARDWARE( intel );  | ||||
|       intelWaitIrq( intel, last_irq ); | ||||
|       if (allow_unlock) LOCK_HARDWARE( intel );  | ||||
|    } | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf); | ||||
|  | ||||
|    intel->batch.start_offset = intel->alloc.offset + buf * half; | ||||
|    intel->batch.ptr = (GLubyte *)intel->alloc.ptr + buf * half; | ||||
|    intel->batch.size = half - 8; | ||||
|    intel->batch.space = half - 8; | ||||
|    assert(intel->batch.space >= 0); | ||||
| } | ||||
|  | ||||
| #define MI_BATCH_BUFFER_END 	(0xA<<23) | ||||
|  | ||||
|  | ||||
| void intelFlushBatchLocked( intelContextPtr intel,  | ||||
| 			    GLboolean ignore_cliprects, | ||||
| 			    GLboolean refill, | ||||
| 			    GLboolean allow_unlock) | ||||
| void intel_batch_ioctl( struct intel_context *intel,  | ||||
| 			GLuint start_offset, | ||||
| 			GLuint used, | ||||
| 			GLboolean ignore_cliprects, | ||||
| 			GLboolean allow_unlock) | ||||
| { | ||||
|    drmI830BatchBuffer batch; | ||||
|  | ||||
|    assert(intel->locked); | ||||
|    assert(used); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s used %d of %d offset %x..%x refill %d\n", | ||||
|       fprintf(stderr, "%s used %d offset %x..%x ignore_cliprects %d\n", | ||||
| 	      __FUNCTION__,  | ||||
| 	      (intel->batch.size - intel->batch.space),  | ||||
| 	      intel->batch.size, | ||||
| 	      intel->batch.start_offset, | ||||
| 	      intel->batch.start_offset +  | ||||
| 	      (intel->batch.size - intel->batch.space),  | ||||
| 	      refill); | ||||
| 	      used,  | ||||
| 	      start_offset, | ||||
| 	      start_offset + used, | ||||
| 	      ignore_cliprects); | ||||
|  | ||||
|    /* Throw away non-effective packets.  Won't work once we have | ||||
|     * hardware contexts which would preserve statechanges beyond a | ||||
|     * single buffer. | ||||
|     */ | ||||
|    if (intel->numClipRects == 0 && !ignore_cliprects) { | ||||
|        | ||||
|       /* Without this yeild, an application with no cliprects can hog | ||||
|        * the hardware.  Without unlocking, the effect is much worse - | ||||
|        * effectively a lock-out of other contexts. | ||||
|        */ | ||||
|       if (allow_unlock) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 UNLOCK_HARDWARE(intel); | ||||
| 	 sched_yield(); | ||||
| 	 LOCK_HARDWARE( intel ); | ||||
| 	 LOCK_HARDWARE(intel); | ||||
|       } | ||||
|  | ||||
|       /* Note that any state thought to have been emitted actually | ||||
|        * hasn't: | ||||
|        */ | ||||
|       intel->batch.ptr -= (intel->batch.size - intel->batch.space); | ||||
|       intel->batch.space = intel->batch.size; | ||||
|       intel->vtbl.lost_hardware( intel );  | ||||
|    } | ||||
|  | ||||
|    if (intel->batch.space != intel->batch.size) { | ||||
|       batch.start = intel->batch.start_offset; | ||||
|       batch.used = intel->batch.size - intel->batch.space; | ||||
|       batch.cliprects = intel->pClipRects; | ||||
|       batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; | ||||
|       batch.DR1 = 0; | ||||
|       batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |  | ||||
| 		   (((GLuint)intel->drawY) << 16)); | ||||
|        | ||||
|       if (intel->alloc.offset) { | ||||
| 	 if ((batch.used & 0x4) == 0) { | ||||
| 	    ((int *)intel->batch.ptr)[0] = 0; | ||||
| 	    ((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END; | ||||
| 	    batch.used += 0x8; | ||||
| 	    intel->batch.ptr += 0x8; | ||||
| 	 } | ||||
| 	 else { | ||||
| 	    ((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END; | ||||
| 	    batch.used += 0x4; | ||||
| 	    intel->batch.ptr += 0x4; | ||||
| 	 }       | ||||
|       } | ||||
|  | ||||
|       if (0) | ||||
|  	 intel_dump_batchbuffer( batch.start, | ||||
| 				 (int *)(intel->batch.ptr - batch.used), | ||||
| 				 batch.used ); | ||||
|  | ||||
|       if (0) | ||||
| 	 fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", | ||||
| 		 __FUNCTION__,  | ||||
| 		 batch.start,  | ||||
| 		 batch.start + batch.used, | ||||
| 		 batch.DR4, batch.num_cliprects); | ||||
|  | ||||
|       intel->batch.start_offset += batch.used; | ||||
|       intel->batch.size -= batch.used; | ||||
|  | ||||
|       if (intel->batch.size < 8) { | ||||
| 	 refill = GL_TRUE; | ||||
| 	 intel->batch.space = intel->batch.size = 0; | ||||
|       } | ||||
|       else { | ||||
| 	 intel->batch.size -= 8; | ||||
| 	 intel->batch.space = intel->batch.size; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       assert(intel->batch.space >= 0); | ||||
|       assert(batch.start >= intel->alloc.offset); | ||||
|       assert(batch.start < intel->alloc.offset + intel->alloc.size); | ||||
|       assert(batch.start + batch.used > intel->alloc.offset); | ||||
|       assert(batch.start + batch.used <=  | ||||
| 	     intel->alloc.offset + intel->alloc.size); | ||||
|  | ||||
|  | ||||
|       if (intel->alloc.offset) { | ||||
| 	 if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,  | ||||
| 			      sizeof(batch))) { | ||||
| 	    fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n",  -errno); | ||||
| 	    UNLOCK_HARDWARE(intel); | ||||
| 	    exit(1); | ||||
| 	 } | ||||
|       } else { | ||||
| 	 drmI830CmdBuffer cmd; | ||||
| 	 cmd.buf = (char *)intel->alloc.ptr + batch.start; | ||||
| 	 cmd.sz = batch.used; | ||||
| 	 cmd.DR1 = batch.DR1; | ||||
| 	 cmd.DR4 = batch.DR4; | ||||
| 	 cmd.num_cliprects = batch.num_cliprects; | ||||
| 	 cmd.cliprects = batch.cliprects; | ||||
| 	  | ||||
| 	 if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd,  | ||||
| 			      sizeof(cmd))) { | ||||
| 	    fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n",  -errno); | ||||
| 	    UNLOCK_HARDWARE(intel); | ||||
| 	    exit(1); | ||||
| 	 } | ||||
|       }	  | ||||
|  | ||||
|        | ||||
|       age_intel(intel, intel->sarea->last_enqueue); | ||||
|  | ||||
|       /* FIXME: use hardware contexts to avoid 'losing' hardware after | ||||
|        * each buffer flush. | ||||
|        */ | ||||
|       intel->vtbl.lost_hardware( intel ); | ||||
|    } | ||||
|  | ||||
|    if (refill) | ||||
|       intelRefillBatchLocked( intel, allow_unlock ); | ||||
| } | ||||
|  | ||||
| void intelFlushBatch( intelContextPtr intel, GLboolean refill ) | ||||
| { | ||||
|    if (intel->locked) { | ||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE ); | ||||
|    }  | ||||
|    else { | ||||
|       LOCK_HARDWARE(intel); | ||||
|       intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE ); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelWaitForIdle( intelContextPtr intel ) | ||||
| {    | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intel->vtbl.emit_flush( intel ); | ||||
|    intelFlushBatch( intel, GL_TRUE ); | ||||
|  | ||||
|    /* Use an irq to wait for dma idle -- Need to track lost contexts | ||||
|     * to shortcircuit consecutive calls to this function: | ||||
|     */ | ||||
|    intelWaitIrq( intel, intel->alloc.irq_emitted ); | ||||
|    intel->alloc.irq_emitted = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelFlush( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|  | ||||
|    if (intel->Fallback) | ||||
|       _swrast_flush( ctx ); | ||||
|  | ||||
|    INTEL_FIREVERTICES( intel ); | ||||
|  | ||||
|    if (intel->batch.size != intel->batch.space) | ||||
|       intelFlushBatch( intel, GL_FALSE ); | ||||
| } | ||||
|  | ||||
| void intelFinish( GLcontext *ctx  )  | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    intelFlush( ctx ); | ||||
|    intelWaitForIdle( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 		GLint cx, GLint cy, GLint cw, GLint ch) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); | ||||
|    GLbitfield tri_mask = 0; | ||||
|    GLbitfield blit_mask = 0; | ||||
|    GLbitfield swrast_mask = 0; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Take care of cliprects, which are handled differently for | ||||
|     * clears, etc. | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|  | ||||
|    if (mask & BUFFER_BIT_FRONT_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_FRONT_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_BACK_LEFT) { | ||||
|       if (colorMask == ~0) { | ||||
| 	 blit_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       }  | ||||
|       else { | ||||
| 	 tri_mask |= BUFFER_BIT_BACK_LEFT; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_DEPTH) { | ||||
|       blit_mask |= BUFFER_BIT_DEPTH; | ||||
|    } | ||||
|  | ||||
|    if (mask & BUFFER_BIT_STENCIL) { | ||||
|       if (!intel->hw_stencil) { | ||||
| 	 swrast_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|       else if (ctx->Stencil.WriteMask[0] != 0xff) { | ||||
| 	 tri_mask |= BUFFER_BIT_STENCIL; | ||||
|       }  | ||||
|       else { | ||||
| 	 blit_mask |= BUFFER_BIT_STENCIL; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    swrast_mask |= (mask & BUFFER_BIT_ACCUM); | ||||
|  | ||||
|    if (blit_mask)  | ||||
|       intelClearWithBlit( ctx, blit_mask, all, cx, cy, cw, ch ); | ||||
|  | ||||
|    if (tri_mask)  | ||||
|       intel->vtbl.clear_with_tris( intel, tri_mask, all, cx, cy, cw, ch); | ||||
|  | ||||
|    if (swrast_mask) | ||||
|       _swrast_Clear( ctx, swrast_mask, all, cx, cy, cw, ch ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) | ||||
| { | ||||
|    int region_offset = 0; | ||||
|    drmI830MemAlloc alloc; | ||||
|    int ret; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size); | ||||
|  | ||||
|    alloc.region = I830_MEM_REGION_AGP; | ||||
|    alloc.alignment = 0; | ||||
|    alloc.size = size; | ||||
|    alloc.region_offset = ®ion_offset; | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* Make sure the global heap is initialized | ||||
|     */ | ||||
|    if (intel->texture_heaps[0]) | ||||
|       driAgeTextures( intel->texture_heaps[0] ); | ||||
|  | ||||
|  | ||||
|    ret = drmCommandWriteRead( intel->driFd, | ||||
| 			      DRM_I830_ALLOC, | ||||
| 			      &alloc, sizeof(alloc)); | ||||
|     | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       return NULL; | ||||
|    } | ||||
|     | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size); | ||||
|  | ||||
|    /* Need to propogate this information (agp memory in use) to our | ||||
|     * local texture lru.  The kernel has already updated the global | ||||
|     * lru.  An alternative would have been to allocate memory the | ||||
|     * usual way and then notify the kernel to pin the allocation. | ||||
|     */ | ||||
|    if (intel->texture_heaps[0]) | ||||
|       driAgeTextures( intel->texture_heaps[0] ); | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel);    | ||||
|  | ||||
|    return (void *)((char *)intel->intelScreen->tex.map + region_offset); | ||||
| } | ||||
|  | ||||
| void intelFreeAGP( intelContextPtr intel, void *pointer ) | ||||
| { | ||||
|    int region_offset; | ||||
|    drmI830MemFree memfree; | ||||
|    int ret; | ||||
|  | ||||
|    region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map; | ||||
|  | ||||
|    if (region_offset < 0 ||  | ||||
|        region_offset > intel->intelScreen->tex.size) { | ||||
|       fprintf(stderr, "offset %d outside range 0..%d\n", region_offset, | ||||
| 	      intel->intelScreen->tex.size); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    memfree.region = I830_MEM_REGION_AGP; | ||||
|    memfree.region_offset = region_offset; | ||||
|     | ||||
|    ret = drmCommandWrite( intel->driFd, | ||||
| 			  DRM_I830_FREE, | ||||
| 			  &memfree, sizeof(memfree)); | ||||
|     | ||||
|    if (ret)  | ||||
|       fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret); | ||||
| } | ||||
|  | ||||
| /* This version of AllocateMemoryMESA allocates only agp memory, and | ||||
|  * only does so after the point at which the driver has been | ||||
|  * initialized. | ||||
|  * | ||||
|  * Theoretically a valid context isn't required.  However, in this | ||||
|  * implementation, it is, as I'm using the hardware lock to protect | ||||
|  * the kernel data structures, and the current context to get the | ||||
|  * device fd. | ||||
|  */ | ||||
| void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn, | ||||
| 			      GLsizei size, GLfloat readfreq, | ||||
| 			      GLfloat writefreq, GLfloat priority) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq,  | ||||
| 	      writefreq, priority); | ||||
|  | ||||
|    if (getenv("INTEL_NO_ALLOC")) | ||||
|       return NULL; | ||||
|     | ||||
|    if (!ctx || INTEL_CONTEXT(ctx) == 0)  | ||||
|       return NULL; | ||||
|     | ||||
|    return intelAllocateAGP( INTEL_CONTEXT(ctx), size ); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Called via glXFreeMemoryMESA() */ | ||||
| void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL)  | ||||
|       fprintf(stderr, "%s %p\n", __FUNCTION__, pointer); | ||||
|  | ||||
|    if (!ctx || INTEL_CONTEXT(ctx) == 0) { | ||||
|       fprintf(stderr, "%s: no context\n", __FUNCTION__); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    intelFreeAGP( INTEL_CONTEXT(ctx), pointer ); | ||||
| } | ||||
|  | ||||
| /* Called via glXGetMemoryOffsetMESA()  | ||||
|  * | ||||
|  * Returns offset of pointer from the start of agp aperture. | ||||
|  */ | ||||
| GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn,  | ||||
| 				const GLvoid *pointer) | ||||
| { | ||||
|    GET_CURRENT_CONTEXT(ctx); | ||||
|    intelContextPtr intel; | ||||
|  | ||||
|    if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) { | ||||
|       fprintf(stderr, "%s: no context\n", __FUNCTION__); | ||||
|       return ~0; | ||||
|    } | ||||
|  | ||||
|    if (!intelIsAgpMemory( intel, pointer, 0 )) | ||||
|       return ~0; | ||||
|  | ||||
|    return intelAgpOffsetFromVirtual( intel, pointer ); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, | ||||
| 			   GLint size ) | ||||
| { | ||||
|    int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; | ||||
|    int valid = (size >= 0 && | ||||
| 		offset >= 0 && | ||||
| 		offset + size < intel->intelScreen->tex.size); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid ); | ||||
|     | ||||
|    return valid; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer ) | ||||
| { | ||||
|    int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; | ||||
|  | ||||
|    if (offset < 0 || offset > intel->intelScreen->tex.size) | ||||
|       return ~0; | ||||
|    else | ||||
|       return intel->intelScreen->tex.offset + offset; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Flip the front & back buffes | ||||
|  */ | ||||
| void intelPageFlip( const __DRIdrawablePrivate *dPriv ) | ||||
| { | ||||
| #if 0 | ||||
|    intelContextPtr intel; | ||||
|    int tmp, ret; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_IOCTL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(dPriv); | ||||
|    assert(dPriv->driContextPriv); | ||||
|    assert(dPriv->driContextPriv->driverPrivate); | ||||
|  | ||||
|    intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (dPriv->pClipRects) { | ||||
|       *(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0]; | ||||
|       intel->sarea->nbox = 1; | ||||
|    } | ||||
|  | ||||
|    ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);  | ||||
|    if (ret) { | ||||
|       fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|    batch.start = start_offset; | ||||
|    batch.used = used; | ||||
|    batch.cliprects = intel->pClipRects; | ||||
|    batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; | ||||
|    batch.DR1 = 0; | ||||
|    batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) |  | ||||
| 		(((GLuint)intel->drawY) << 16)); | ||||
|        | ||||
|    if (INTEL_DEBUG & DEBUG_DMA) | ||||
|       fprintf(stderr, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n", | ||||
| 	      __FUNCTION__,  | ||||
| 	      batch.start,  | ||||
| 	      batch.start + batch.used * 4, | ||||
| 	      batch.DR4, batch.num_cliprects); | ||||
| #if 1 | ||||
|    if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch,  | ||||
| 			sizeof(batch))) { | ||||
|       fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n",  -errno); | ||||
|       UNLOCK_HARDWARE(intel); | ||||
|       exit(1); | ||||
|    } | ||||
|  | ||||
|    tmp = intel->sarea->last_enqueue; | ||||
|    intelRefillBatchLocked( intel ); | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|  | ||||
|    intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer ); | ||||
| #endif | ||||
|        | ||||
|    /* FIXME: use hardware contexts to avoid 'losing' hardware after | ||||
|     * each buffer flush. | ||||
|     */ | ||||
|    intel->vtbl.lost_hardware( intel ); | ||||
| } | ||||
|   | ||||
| @@ -30,37 +30,14 @@ | ||||
|  | ||||
| #include "intel_context.h" | ||||
|  | ||||
| extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock ); | ||||
| void intelWaitIrq( struct intel_context *intel, int seq ); | ||||
| int intelEmitIrqLocked( struct intel_context *intel ); | ||||
|  | ||||
| extern void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, | ||||
| 		       GLint cx, GLint cy, GLint cw, GLint ch); | ||||
|  | ||||
| extern void intelPageFlip( const __DRIdrawablePrivate *dpriv ); | ||||
| extern void intelWaitForIdle( intelContextPtr intel ); | ||||
| extern void intelFlushBatch( intelContextPtr intel, GLboolean refill ); | ||||
| extern void intelFlushBatchLocked( intelContextPtr intel, | ||||
| 				   GLboolean ignore_cliprects, | ||||
| 				   GLboolean refill, | ||||
| 				   GLboolean allow_unlock); | ||||
| extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ); | ||||
| extern void intelFinish( GLcontext *ctx ); | ||||
| extern void intelFlush( GLcontext *ctx ); | ||||
|  | ||||
| extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size ); | ||||
| extern void intelFreeAGP( intelContextPtr intel, void *pointer ); | ||||
|  | ||||
| extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn,  | ||||
| 				      GLsizei size, GLfloat readfreq, | ||||
| 				      GLfloat writefreq, GLfloat priority ); | ||||
|  | ||||
| extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn,  | ||||
| 				 GLvoid *pointer ); | ||||
|  | ||||
| extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer ); | ||||
| extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, | ||||
| 				  GLint size ); | ||||
|  | ||||
| extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p ); | ||||
| void intel_batch_ioctl( struct intel_context *intel,  | ||||
| 			GLuint start_offset, | ||||
| 			GLuint used, | ||||
| 			GLboolean ignore_cliprects, | ||||
| 			GLboolean allow_unlock); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										300
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_bufmgr.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| static GLenum target_to_target( GLenum target ) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: | ||||
|       return GL_TEXTURE_CUBE_MAP_ARB; | ||||
|    default: | ||||
|       return target; | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel, | ||||
| 						GLenum target, | ||||
| 						GLenum internal_format, | ||||
| 						GLuint first_level, | ||||
| 						GLuint last_level, | ||||
| 						GLuint width0, | ||||
| 						GLuint height0, | ||||
| 						GLuint depth0, | ||||
| 						GLuint cpp, | ||||
| 						GLboolean compressed) | ||||
| { | ||||
|    GLboolean ok; | ||||
|    struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); | ||||
|  | ||||
|    DBG("%s target %s format %s level %d..%d\n", __FUNCTION__, | ||||
| 		_mesa_lookup_enum_by_nr(target), | ||||
| 		_mesa_lookup_enum_by_nr(internal_format), | ||||
| 		first_level, | ||||
| 		last_level); | ||||
|  | ||||
|    mt->target = target_to_target(target); | ||||
|    mt->internal_format = internal_format; | ||||
|    mt->first_level = first_level; | ||||
|    mt->last_level = last_level; | ||||
|    mt->width0 = width0; | ||||
|    mt->height0 = height0; | ||||
|    mt->depth0 = depth0; | ||||
|    mt->cpp = cpp; | ||||
|    mt->compressed = compressed; | ||||
|    mt->refcount = 1; | ||||
|  | ||||
|    switch (intel->intelScreen->deviceID) { | ||||
|    case PCI_CHIP_I945_G: | ||||
| /*    case PCI_CHIP_I945_GM: */ | ||||
|       ok = i945_miptree_layout( mt ); | ||||
|       break; | ||||
|    default: | ||||
|       /* All the i830 chips and the i915 use this layout: | ||||
|        */ | ||||
|       ok = i915_miptree_layout( mt ); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    if (ok) | ||||
|       mt->region = intel_region_alloc( intel,  | ||||
| 				       mt->cpp, | ||||
| 				       mt->pitch,  | ||||
| 				       mt->total_height ); | ||||
|  | ||||
|    if (!mt->region) { | ||||
|       free(mt); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return mt; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intel_miptree_reference( struct intel_mipmap_tree **dst,  | ||||
| 			      struct intel_mipmap_tree *src ) | ||||
| { | ||||
|    src->refcount++; | ||||
|    *dst = src; | ||||
| } | ||||
|  | ||||
| void intel_miptree_release( struct intel_context *intel, | ||||
| 			    struct intel_mipmap_tree **mt ) | ||||
| { | ||||
|    if (!*mt) | ||||
|       return; | ||||
|  | ||||
|    DBG("%s %d\n", __FUNCTION__, (*mt)->refcount-1); | ||||
|    if (--(*mt)->refcount == 0) { | ||||
|       intel_region_release(intel, &((*mt)->region)); | ||||
|       free(*mt); | ||||
|    } | ||||
|    *mt = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Can the image be pulled into a unified mipmap tree.  This mirrors | ||||
|  * the completeness test in a lot of ways. | ||||
|  * | ||||
|  * Not sure whether I want to pass gl_texture_image here. | ||||
|  */ | ||||
| GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,  | ||||
| 				     struct gl_texture_image *image, | ||||
| 				     GLuint face, | ||||
| 				     GLuint level ) | ||||
| { | ||||
|    DBG("%s %d %d/%d %d/%d\n", __FUNCTION__, | ||||
| 		image->Border, | ||||
| 		image->InternalFormat, mt->internal_format, | ||||
| 		image->IsCompressed, mt->compressed); | ||||
|  | ||||
|    /* Images with borders are never pulled into mipmap trees.  | ||||
|     */ | ||||
|    if (image->Border) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (image->InternalFormat != mt->internal_format || | ||||
|        image->IsCompressed != mt->compressed) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    DBG("%s: %d/%d %d/%d %d/%d\n", __FUNCTION__, | ||||
| 		image->Width, mt->offset[face][level].width, | ||||
| 		image->Height, mt->offset[face][level].height, | ||||
| 		image->Depth, mt->offset[face][level].depth); | ||||
|  | ||||
|    /* Test image dimensions against the base level image adjusted for | ||||
|     * minification.  This will also catch images not present in the | ||||
|     * tree, changed targets, etc. | ||||
|     */ | ||||
|    if (image->Width != mt->offset[face][level].width || | ||||
|        image->Height != mt->offset[face][level].height || | ||||
|        image->Depth != mt->offset[face][level].depth) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|    DBG("%s: success\n", __FUNCTION__); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt, | ||||
| 				  GLuint face, | ||||
| 				  GLuint level) | ||||
| { | ||||
|    return mt->offset[face][level].offset; | ||||
| } | ||||
|  | ||||
| GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt, | ||||
| 					GLuint face, | ||||
| 					GLuint level) | ||||
| { | ||||
|    return mt->offset[face][level].depth_image_stride; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, | ||||
| 				    GLuint face, | ||||
| 				    GLuint level, | ||||
| 				    GLuint x, GLuint y, | ||||
| 				    GLuint w, GLuint h, GLuint d) | ||||
| { | ||||
|    mt->offset[face][level].offset = (x + y * mt->pitch) * mt->cpp; | ||||
|    mt->offset[face][level].width = w; | ||||
|    mt->offset[face][level].height = h; | ||||
|    mt->offset[face][level].depth = d; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Map a teximage in a mipmap tree. | ||||
|  * \param row_stride  returns row stride in bytes | ||||
|  * \param image_stride  returns image stride in bytes (for 3D textures). | ||||
|  * \return address of mapping | ||||
|  */ | ||||
| GLubyte *intel_miptree_image_map(struct intel_context *intel,  | ||||
| 				 struct intel_mipmap_tree *mt, | ||||
| 				 GLuint face, | ||||
| 				 GLuint level, | ||||
| 				 GLuint *row_stride, | ||||
| 				 GLuint *image_stride) | ||||
| { | ||||
|    DBG("%s \n", __FUNCTION__); | ||||
|     | ||||
|    if (row_stride) | ||||
|       *row_stride = mt->pitch * mt->cpp; | ||||
|     | ||||
|    if (image_stride)  | ||||
|       *image_stride = mt->offset[face][level].depth_image_stride; | ||||
|  | ||||
|    return (intel_region_map(intel, mt->region) + | ||||
| 	   intel_miptree_image_offset(mt, face, level)); | ||||
| } | ||||
|  | ||||
| void intel_miptree_image_unmap(struct intel_context *intel,  | ||||
| 			       struct intel_mipmap_tree *mt) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    intel_region_unmap(intel, mt->region); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload data for a particular image. | ||||
|  */ | ||||
| void intel_miptree_image_data(struct intel_context *intel,  | ||||
| 			      struct intel_mipmap_tree *dst, | ||||
| 			      GLuint face, | ||||
| 			      GLuint level, | ||||
| 			      void *src,  | ||||
| 			      GLuint src_row_pitch, | ||||
| 			      GLuint src_image_pitch) | ||||
| { | ||||
|    GLuint depth = dst->offset[face][level].depth; | ||||
|    GLuint dst_offset = intel_miptree_image_offset(dst, face, level); | ||||
|    GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level); | ||||
|    GLuint i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    for (i = 0; i < depth; i++) { | ||||
|       intel_region_data(intel, | ||||
| 			dst->region, dst_offset, | ||||
| 			0, | ||||
| 			0, | ||||
| 			src, | ||||
| 			src_row_pitch, | ||||
| 			0, 0,	/* source x,y */ | ||||
| 			dst->offset[face][level].width, | ||||
| 			dst->offset[face][level].height); | ||||
|       dst_offset += dst_image_stride; | ||||
|       src += src_image_pitch; | ||||
|    } | ||||
| } | ||||
| 			   | ||||
| /* Copy mipmap image between trees | ||||
|  */ | ||||
| void intel_miptree_image_copy( struct intel_context *intel, | ||||
| 			       struct intel_mipmap_tree *dst, | ||||
| 			       GLuint face, GLuint level, | ||||
| 			       struct intel_mipmap_tree *src ) | ||||
| { | ||||
|    GLuint width = src->offset[face][level].width; | ||||
|    GLuint height = src->offset[face][level].height; | ||||
|    GLuint depth = src->offset[face][level].depth; | ||||
|    GLuint dst_offset = intel_miptree_image_offset(dst, face, level); | ||||
|    GLuint src_offset = intel_miptree_image_offset(src, face, level); | ||||
|    GLuint dst_image_stride = intel_miptree_depth_image_stride(dst, face, level); | ||||
|    GLuint src_image_stride = intel_miptree_depth_image_stride(src, face, level); | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0; i < depth; i++) { | ||||
|       intel_region_copy(intel, | ||||
| 			dst->region, dst_offset, | ||||
| 			0, | ||||
| 			0, | ||||
| 			src->region, src_offset, | ||||
| 			0, | ||||
| 			0, | ||||
| 			width, | ||||
| 			height); | ||||
|  | ||||
|       dst_offset += dst_image_stride; | ||||
|       src_offset += src_image_stride; | ||||
|    } | ||||
| 		      | ||||
| } | ||||
							
								
								
									
										183
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/mesa/drivers/dri/i915/intel_mipmap_tree.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_MIPMAP_TREE_H | ||||
| #define INTEL_MIPMAP_TREE_H | ||||
|  | ||||
| #include "intel_regions.h" | ||||
|  | ||||
| /* A layer on top of the intel_regions code which adds: | ||||
|  * | ||||
|  * - Code to size and layout a region to hold a set of mipmaps. | ||||
|  * - Query to determine if a new image fits in an existing tree. | ||||
|  * - More refcounting  | ||||
|  *     - maybe able to remove refcounting from intel_region? | ||||
|  * - ? | ||||
|  * | ||||
|  * The fixed mipmap layout of intel hardware where one offset | ||||
|  * specifies the position of all images in a mipmap hierachy | ||||
|  * complicates the implementation of GL texture image commands, | ||||
|  * compared to hardware where each image is specified with an | ||||
|  * independent offset. | ||||
|  * | ||||
|  * In an ideal world, each texture object would be associated with a | ||||
|  * single bufmgr buffer or 2d intel_region, and all the images within | ||||
|  * the texture object would slot into the tree as they arrive.  The | ||||
|  * reality can be a little messier, as images can arrive from the user | ||||
|  * with sizes that don't fit in the existing tree, or in an order | ||||
|  * where the tree layout cannot be guessed immediately.   | ||||
|  *  | ||||
|  * This structure encodes an idealized mipmap tree.  The GL image | ||||
|  * commands build these where possible, otherwise store the images in | ||||
|  * temporary system buffers. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Describes the location of each texture image within a texture region. | ||||
|  */ | ||||
| struct intel_mipmap_offset { | ||||
|    GLuint offset;  | ||||
|    GLuint width; | ||||
|    GLuint height; | ||||
|    GLuint depth; | ||||
|    GLuint depth_image_stride; | ||||
| }; | ||||
|  | ||||
| struct intel_mipmap_tree { | ||||
|    /* Effectively the key: | ||||
|     */ | ||||
|    GLenum target; | ||||
|    GLenum internal_format; | ||||
|  | ||||
|    GLuint first_level; | ||||
|    GLuint last_level; | ||||
|  | ||||
|    GLuint width0, height0, depth0; /**< Level zero image dimensions */ | ||||
|    GLuint cpp; | ||||
|    GLboolean compressed; | ||||
|  | ||||
|    /* Derived from the above: | ||||
|     */    | ||||
|    GLuint pitch; | ||||
|    GLuint depth_pitch;		/* per-image on i945? */ | ||||
|    GLuint total_height; | ||||
|    struct intel_mipmap_offset offset[MAX_FACES][MAX_TEXTURE_LEVELS]; | ||||
|  | ||||
|    /* The data is held here: | ||||
|     */ | ||||
|    struct intel_region *region; | ||||
|  | ||||
|    /* These are also refcounted: | ||||
|     */ | ||||
|    GLuint refcount; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| struct intel_mipmap_tree *intel_miptree_create( struct intel_context *intel, | ||||
| 						GLenum target, | ||||
| 						GLenum internal_format, | ||||
| 						GLuint first_level, | ||||
| 						GLuint last_level, | ||||
| 						GLuint width0, | ||||
| 						GLuint height0, | ||||
| 						GLuint depth0, | ||||
| 						GLuint cpp, | ||||
| 						GLboolean compressed); | ||||
|  | ||||
| void intel_miptree_reference( struct intel_mipmap_tree **dst, | ||||
| 			      struct intel_mipmap_tree *src ); | ||||
|  | ||||
| void intel_miptree_release( struct intel_context *intel, | ||||
| 			    struct intel_mipmap_tree **mt ); | ||||
|  | ||||
| /* Check if an image fits an existing mipmap tree layout | ||||
|  */ | ||||
| GLboolean intel_miptree_match_image( struct intel_mipmap_tree *mt,  | ||||
| 				     struct gl_texture_image *image, | ||||
| 				     GLuint face, | ||||
| 				     GLuint level ); | ||||
|  | ||||
| /* Return a pointer to an image within a tree.  Return image stride as | ||||
|  * well. | ||||
|  */ | ||||
| GLubyte *intel_miptree_image_map( struct intel_context *intel, | ||||
| 				  struct intel_mipmap_tree *mt, | ||||
| 				  GLuint face, | ||||
| 				  GLuint level, | ||||
| 				  GLuint *row_stride, | ||||
| 				  GLuint *image_stride); | ||||
|  | ||||
| void intel_miptree_image_unmap( struct intel_context *intel, | ||||
| 				struct intel_mipmap_tree *mt ); | ||||
|  | ||||
|  | ||||
| /* Return the linear offset of an image relative to the start of the | ||||
|  * tree: | ||||
|  */ | ||||
| GLuint intel_miptree_image_offset( struct intel_mipmap_tree *mt, | ||||
| 				   GLuint face, | ||||
| 				   GLuint level ); | ||||
|  | ||||
| void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, | ||||
| 				    GLuint face, | ||||
| 				    GLuint level, | ||||
| 				    GLuint x, GLuint y, | ||||
| 				    GLuint w, GLuint h, GLuint d); | ||||
|  | ||||
| GLuint intel_miptree_depth_image_stride(struct intel_mipmap_tree *mt, | ||||
| 					GLuint face, | ||||
| 					GLuint level); | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload an image into a tree | ||||
|  */ | ||||
| void intel_miptree_image_data(struct intel_context *intel,  | ||||
| 			      struct intel_mipmap_tree *dst, | ||||
| 			      GLuint face, | ||||
| 			      GLuint level, | ||||
| 			      void *src,  | ||||
| 			      GLuint src_row_pitch, | ||||
| 			      GLuint src_image_pitch); | ||||
|  | ||||
| /* Copy an image between two trees | ||||
|  */ | ||||
| void intel_miptree_image_copy( struct intel_context *intel, | ||||
| 			       struct intel_mipmap_tree *dst, | ||||
| 			       GLuint face, GLuint level, | ||||
| 			       struct intel_mipmap_tree *src ); | ||||
|  | ||||
| /* i915_mipmap_tree.c: | ||||
|  */ | ||||
| GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt ); | ||||
| GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt ); | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -1,6 +1,6 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
| @@ -12,7 +12,7 @@ | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * next paragraph) shall be included in all copies or substantial portionsalloc | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
| @@ -25,465 +25,98 @@ | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "state.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_regions.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| check_color( const GLcontext *ctx, GLenum type, GLenum format, | ||||
| 	     const struct gl_pixelstore_attrib *packing, | ||||
| 	     const void *pixels, GLint sz, GLint pitch ) | ||||
| /** | ||||
|  * Check if any fragment operations are in effect which might effect | ||||
|  * glDraw/CopyPixels. | ||||
|  */ | ||||
| GLboolean intel_check_blit_fragment_ops( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLuint cpp = intel->intelScreen->cpp; | ||||
|    if (ctx->NewState) | ||||
|       _mesa_update_state(ctx); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|    /* XXX Note: Scissor could be done with the blitter: | ||||
|     */ | ||||
|    return !(ctx->_ImageTransferState || | ||||
| 	    ctx->Color.AlphaEnabled ||  | ||||
| 	    ctx->Depth.Test || | ||||
| 	    ctx->Fog.Enabled || | ||||
| 	    ctx->Scissor.Enabled || | ||||
| 	    ctx->Stencil.Enabled || | ||||
| 	    !ctx->Color.ColorMask[0] || | ||||
| 	    !ctx->Color.ColorMask[1] || | ||||
| 	    !ctx->Color.ColorMask[2] || | ||||
| 	    !ctx->Color.ColorMask[3] || | ||||
| 	    ctx->Color.ColorLogicOpEnabled || | ||||
| 	    ctx->Texture._EnabledUnits || | ||||
| 	    ctx->FragmentProgram._Enabled); | ||||
| } | ||||
|  | ||||
|    if (	(pitch & 63) || | ||||
| 	ctx->_ImageTransferState || | ||||
| 	packing->SwapBytes || | ||||
| 	packing->LsbFirst) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: failed 1\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|  | ||||
| GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx ) | ||||
| { | ||||
|    if (ctx->NewState) | ||||
|       _mesa_update_state(ctx); | ||||
|  | ||||
|    /* Some of _ImageTransferState (scale, bias) could be done with | ||||
|     * fragment programs on i915. | ||||
|     */ | ||||
|    return !(ctx->_ImageTransferState || | ||||
| 	    ctx->Fog.Enabled ||	/* not done yet */ | ||||
| 	    ctx->Texture._EnabledUnits || | ||||
| 	    ctx->FragmentProgram._Enabled); | ||||
| } | ||||
|  | ||||
| /* The intel_region struct doesn't really do enough to capture the | ||||
|  * format of the pixels in the region.  For now this code assumes that | ||||
|  * the region is a display surface and hence is either ARGB8888 or | ||||
|  * RGB565. | ||||
|  * XXX FBO: If we'd pass in the intel_renderbuffer instead of region, we'd | ||||
|  * know the buffer's pixel format. | ||||
|  * | ||||
|  * \param format  as given to glDraw/ReadPixels | ||||
|  * \param type  as given to glDraw/ReadPixels | ||||
|  */ | ||||
| GLboolean intel_check_blit_format( struct intel_region *region, | ||||
| 				   GLenum format, GLenum type ) | ||||
| { | ||||
|    if (region->cpp == 4 && | ||||
|        (type == GL_UNSIGNED_INT_8_8_8_8_REV || | ||||
| 	type == GL_UNSIGNED_BYTE) &&         | ||||
|        format == GL_BGRA ) { | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|  | ||||
|    if ( type == GL_UNSIGNED_INT_8_8_8_8_REV &&  | ||||
| 	cpp == 4 &&  | ||||
| 	format == GL_BGRA ) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: passed 2\n", __FUNCTION__); | ||||
|     | ||||
|    if (region->cpp == 2 &&  | ||||
|        type == GL_UNSIGNED_SHORT_5_6_5_REV &&  | ||||
|        format == GL_BGR ) { | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s: failed\n", __FUNCTION__); | ||||
|       fprintf(stderr, "%s: bad format for blit (cpp %d, type %s format %s)\n",  | ||||
| 	      __FUNCTION__, region->cpp,  | ||||
| 	      _mesa_lookup_enum_by_nr(type), | ||||
| 	      _mesa_lookup_enum_by_nr(format)); | ||||
|  | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
| static GLboolean | ||||
| check_color_per_fragment_ops( const GLcontext *ctx ) | ||||
| { | ||||
|    int result; | ||||
|    result = (!(     ctx->Color.AlphaEnabled ||  | ||||
| 		    ctx->Depth.Test || | ||||
| 		    ctx->Fog.Enabled || | ||||
| 		    ctx->Scissor.Enabled || | ||||
| 		    ctx->Stencil.Enabled || | ||||
| 		    !ctx->Color.ColorMask[0] || | ||||
| 		    !ctx->Color.ColorMask[1] || | ||||
| 		    !ctx->Color.ColorMask[2] || | ||||
| 		    !ctx->Color.ColorMask[3] || | ||||
| 		    ctx->Color.ColorLogicOpEnabled || | ||||
| 		    ctx->Texture._EnabledUnits | ||||
|            ) && | ||||
| 	   ctx->Current.RasterPosValid); | ||||
|     | ||||
|    return result; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| clip_pixelrect( const GLcontext *ctx, | ||||
| 		const GLframebuffer *buffer, | ||||
| 		GLint *x, GLint *y, | ||||
| 		GLsizei *width, GLsizei *height, | ||||
| 		GLint *size ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|  | ||||
|    /* left clipping */ | ||||
|    if (*x < buffer->_Xmin) { | ||||
|       *width -= (buffer->_Xmin - *x); | ||||
|       *x = buffer->_Xmin; | ||||
|    } | ||||
|  | ||||
|    /* right clipping */ | ||||
|    if (*x + *width > buffer->_Xmax) | ||||
|       *width -= (*x + *width - buffer->_Xmax - 1); | ||||
|  | ||||
|    if (*width <= 0) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    /* bottom clipping */ | ||||
|    if (*y < buffer->_Ymin) { | ||||
|       *height -= (buffer->_Ymin - *y); | ||||
|       *y = buffer->_Ymin; | ||||
|    } | ||||
|  | ||||
|    /* top clipping */ | ||||
|    if (*y + *height > buffer->_Ymax) | ||||
|       *height -= (*y + *height - buffer->_Ymax - 1); | ||||
|  | ||||
|    if (*height <= 0) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    *size = ((*y + *height - 1) * intel->intelScreen->front.pitch + | ||||
| 	    (*x + *width - 1) * intel->intelScreen->cpp); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static GLboolean | ||||
| intelTryReadPixels( GLcontext *ctx, | ||||
| 		  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		  GLenum format, GLenum type, | ||||
| 		  const struct gl_pixelstore_attrib *pack, | ||||
| 		  GLvoid *pixels ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLint size = 0; | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    /* Only accelerate reading to agp buffers. | ||||
|     */ | ||||
|    if ( !intelIsAgpMemory(intel, pixels,  | ||||
| 			pitch * height * intel->intelScreen->cpp ) ) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from | ||||
|     * blitter: | ||||
|     */ | ||||
|    if (!pack->Invert) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (!check_color(ctx, type, format, pack, pixels, size, pitch)) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    switch ( intel->intelScreen->cpp ) { | ||||
|    case 4: | ||||
|       break; | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* Although the blits go on the command buffer, need to do this and | ||||
|     * fire with lock held to guarentee cliprects and drawOffset are | ||||
|     * correct. | ||||
|     * | ||||
|     * This is an unusual situation however, as the code which flushes | ||||
|     * a full command buffer expects to be called unlocked.  As a | ||||
|     * workaround, immediately flush the buffer on aquiring the lock. | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       int src_offset = intel->drawOffset; | ||||
|       int src_pitch = intel->intelScreen->front.pitch; | ||||
|       int dst_offset = intelAgpOffsetFromVirtual( intel, pixels); | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       int i; | ||||
|  | ||||
|       if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, | ||||
| 			  &size)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s totally clipped -- nothing to do\n", | ||||
| 		    __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", | ||||
| 		 src_pitch, pitch); | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++) | ||||
|       { | ||||
| 	 GLint bx = box[i].x1; | ||||
| 	 GLint by = box[i].y1; | ||||
| 	 GLint bw = box[i].x2 - bx; | ||||
| 	 GLint bh = box[i].y2 - by; | ||||
| 	  | ||||
| 	 if (bx < x) bw -= x - bx, bx = x; | ||||
| 	 if (by < y) bh -= y - by, by = y; | ||||
| 	 if (bx + bw > x + width) bw = x + width - bx; | ||||
| 	 if (by + bh > y + height) bh = y + height - by; | ||||
| 	 if (bw <= 0) continue; | ||||
| 	 if (bh <= 0) continue; | ||||
|  | ||||
| 	 intelEmitCopyBlitLocked( intel, | ||||
| 			    intel->intelScreen->cpp, | ||||
| 			    src_pitch, src_offset, | ||||
| 			    pitch, dst_offset, | ||||
| 			    bx, by, | ||||
| 			    bx - x, by - y, | ||||
| 			    bw, bh ); | ||||
|       } | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( &intel->ctx ); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| intelReadPixels( GLcontext *ctx, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLenum format, GLenum type, | ||||
| 		 const struct gl_pixelstore_attrib *pack, | ||||
| 		 GLvoid *pixels ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!intelTryReadPixels( ctx, x, y, width, height, format, type, pack,  | ||||
| 			   pixels)) | ||||
|       _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack,  | ||||
| 			  pixels); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void do_draw_pix( GLcontext *ctx, | ||||
| 			 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			 GLint pitch, | ||||
| 			 const void *pixels, | ||||
| 			 GLuint dest ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|    int nbox = dPriv->numClipRects; | ||||
|    int i; | ||||
|    int size; | ||||
|    int src_offset = intelAgpOffsetFromVirtual( intel, pixels); | ||||
|    int src_pitch = pitch; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|    if (ctx->DrawBuffer) | ||||
|    { | ||||
|       y -= height;			/* cope with pixel zoom */ | ||||
|     | ||||
|       if (!clip_pixelrect(ctx, ctx->DrawBuffer, | ||||
| 			  &x, &y, &width, &height, | ||||
| 			  &size)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 return; | ||||
|       } | ||||
|  | ||||
|       y = dPriv->h - y - height; 	/* convert from gl to hardware coords */ | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++ ) | ||||
|       { | ||||
| 	 GLint bx = box[i].x1; | ||||
| 	 GLint by = box[i].y1; | ||||
| 	 GLint bw = box[i].x2 - bx; | ||||
| 	 GLint bh = box[i].y2 - by; | ||||
|  | ||||
| 	 if (bx < x) bw -= x - bx, bx = x; | ||||
| 	 if (by < y) bh -= y - by, by = y; | ||||
| 	 if (bx + bw > x + width) bw = x + width - bx; | ||||
| 	 if (by + bh > y + height) bh = y + height - by; | ||||
| 	 if (bw <= 0) continue; | ||||
| 	 if (bh <= 0) continue; | ||||
|  | ||||
| 	 intelEmitCopyBlitLocked( intel, | ||||
| 			    intel->intelScreen->cpp, | ||||
| 			    src_pitch, src_offset, | ||||
| 			    intel->intelScreen->front.pitch, | ||||
| 			      intel->drawOffset, | ||||
| 			    bx - x, by - y, | ||||
| 			    bx, by, | ||||
| 			    bw, bh ); | ||||
|       } | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    intelFinish( &intel->ctx ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intelTryDrawPixels( GLcontext *ctx, | ||||
| 		  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		  GLenum format, GLenum type, | ||||
| 		  const struct gl_pixelstore_attrib *unpack, | ||||
| 		  const GLvoid *pixels ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    GLint pitch = unpack->RowLength ? unpack->RowLength : width; | ||||
|    GLuint dest; | ||||
|    GLuint cpp = intel->intelScreen->cpp; | ||||
|    GLint size = width * pitch * cpp; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    switch (format) { | ||||
|    case GL_RGB: | ||||
|    case GL_RGBA: | ||||
|    case GL_BGRA: | ||||
|       dest = intel->drawOffset; | ||||
|  | ||||
|       /* Planemask doesn't have full support in blits. | ||||
|        */ | ||||
|       if (!ctx->Color.ColorMask[RCOMP] || | ||||
| 	  !ctx->Color.ColorMask[GCOMP] || | ||||
| 	  !ctx->Color.ColorMask[BCOMP] || | ||||
| 	  !ctx->Color.ColorMask[ACOMP]) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s: planemask\n", __FUNCTION__); | ||||
| 	 return GL_FALSE;	 | ||||
|       } | ||||
|  | ||||
|       /* Can't do conversions on agp reads/draws.  | ||||
|        */ | ||||
|       if ( !intelIsAgpMemory( intel, pixels, size ) ) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s: not agp memory\n", __FUNCTION__); | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|       if (!check_color_per_fragment_ops(ctx)) { | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|  | ||||
|       if (ctx->Pixel.ZoomX != 1.0F || | ||||
| 	  ctx->Pixel.ZoomY != -1.0F) | ||||
| 	 return GL_FALSE; | ||||
|       break; | ||||
|  | ||||
|    default: | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if ( intelIsAgpMemory(intel, pixels, size) ) | ||||
|    { | ||||
|       do_draw_pix( ctx, x, y, width, height, pitch, pixels, | ||||
| 		   dest ); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|    else if (0) | ||||
|    { | ||||
|       /* Pixels is in regular memory -- get dma buffers and perform | ||||
|        * upload through them.  No point doing this for regular uploads | ||||
|        * but once we remove some of the restrictions above (colormask, | ||||
|        * pixelformat conversion, zoom?, etc), this could be a win. | ||||
|        */ | ||||
|    } | ||||
|    else | ||||
|       return GL_FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| intelDrawPixels( GLcontext *ctx, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLenum format, GLenum type, | ||||
| 		 const struct gl_pixelstore_attrib *unpack, | ||||
| 		 const GLvoid *pixels ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!intelTryDrawPixels( ctx, x, y, width, height, format, type, | ||||
| 			  unpack, pixels )) | ||||
|       _swrast_DrawPixels( ctx, x, y, width, height, format, type, | ||||
| 			  unpack, pixels ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Implement glCopyPixels for the front color buffer (or back buffer Pixmap) | ||||
|  * for the color buffer.  Don't support zooming, pixel transfer, etc. | ||||
|  * We do support copying from one window to another, ala glXMakeCurrentRead. | ||||
|  */ | ||||
| static void | ||||
| intelCopyPixels( GLcontext *ctx, | ||||
| 		 GLint srcx, GLint srcy, GLsizei width, GLsizei height, | ||||
| 		 GLint destx, GLint desty, GLenum type ) | ||||
| { | ||||
| #if 0 | ||||
|    const XMesaContext xmesa = XMESA_CONTEXT(ctx); | ||||
|    const SWcontext *swrast = SWRAST_CONTEXT( ctx ); | ||||
|    XMesaDisplay *dpy = xmesa->xm_visual->display; | ||||
|    const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer; | ||||
|    const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer; | ||||
|    const XMesaGC gc = xmesa->xm_draw_buffer->gc; | ||||
|  | ||||
|    ASSERT(dpy); | ||||
|    ASSERT(gc); | ||||
|  | ||||
|    if (drawBuffer &&  /* buffer != 0 means it's a Window or Pixmap */ | ||||
|        readBuffer && | ||||
|        type == GL_COLOR && | ||||
|        (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */ | ||||
|        ctx->_ImageTransferState == 0 &&  /* no color tables, scale/bias, etc */ | ||||
|        ctx->Pixel.ZoomX == 1.0 &&        /* no zooming */ | ||||
|        ctx->Pixel.ZoomY == 1.0) { | ||||
|       /* Note: we don't do any special clipping work here.  We could, | ||||
|        * but X will do it for us. | ||||
|        */ | ||||
|       srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1; | ||||
|       desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1; | ||||
|       XCopyArea(dpy, readBuffer, drawBuffer, gc, | ||||
|                 srcx, srcy, width, height, destx, desty); | ||||
|    } | ||||
| #else | ||||
|    _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type ); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelInitPixelFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    /* Pixel path fallbacks. | ||||
|     */ | ||||
|    functions->Accum = _swrast_Accum; | ||||
|    functions->Bitmap = _swrast_Bitmap; | ||||
|    functions->CopyPixels = intelCopyPixels; | ||||
|  | ||||
|    if (!getenv("INTEL_NO_BLITS")) { | ||||
|       functions->ReadPixels = intelReadPixels;   | ||||
|       functions->DrawPixels = intelDrawPixels;  | ||||
|    } | ||||
|    else { | ||||
|       functions->ReadPixels = _swrast_ReadPixels; | ||||
|       functions->DrawPixels = _swrast_DrawPixels; | ||||
|    } | ||||
|    functions->ReadPixels = intelReadPixels;   | ||||
|    functions->DrawPixels = intelDrawPixels;  | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										64
									
								
								src/mesa/drivers/dri/i915/intel_pixel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/mesa/drivers/dri/i915/intel_pixel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_PIXEL_H | ||||
| #define INTEL_PIXEL_H | ||||
|  | ||||
| #include "mtypes.h" | ||||
|  | ||||
| void intelInitPixelFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| GLboolean intel_check_blit_fragment_ops( GLcontext *ctx ); | ||||
|  | ||||
| GLboolean intel_check_meta_tex_fragment_ops( GLcontext *ctx ); | ||||
|  | ||||
| GLboolean intel_check_blit_format( struct intel_region *region, | ||||
| 				   GLenum format, GLenum type ); | ||||
|  | ||||
|  | ||||
| void intelReadPixels( GLcontext *ctx, | ||||
| 		      GLint x, GLint y,  | ||||
| 		      GLsizei width, GLsizei height, | ||||
| 		      GLenum format, GLenum type, | ||||
| 		      const struct gl_pixelstore_attrib *pack, | ||||
| 		      GLvoid *pixels ); | ||||
|  | ||||
| void intelDrawPixels( GLcontext *ctx, | ||||
| 		      GLint x, GLint y,  | ||||
| 		      GLsizei width, GLsizei height, | ||||
| 		      GLenum format,  | ||||
| 		      GLenum type, | ||||
| 		      const struct gl_pixelstore_attrib *unpack, | ||||
| 		      const GLvoid *pixels ); | ||||
|  | ||||
| void intelCopyPixels( GLcontext *ctx, | ||||
| 		      GLint srcx, GLint srcy,  | ||||
| 		      GLsizei width, GLsizei height, | ||||
| 		      GLint destx, GLint desty,  | ||||
| 		      GLenum type ); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										349
									
								
								src/mesa/drivers/dri/i915/intel_pixel_copy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								src/mesa/drivers/dri/i915/intel_pixel_copy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,349 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
|  | ||||
| static struct intel_region *copypix_src_region( struct intel_context *intel, | ||||
| 						GLenum type ) | ||||
| { | ||||
|    switch (type) { | ||||
|    case GL_COLOR: | ||||
|       return intel_readbuf_region( intel ); | ||||
|    case GL_DEPTH: | ||||
|       /* Don't think this is really possible execpt at 16bpp, when we have no stencil. | ||||
|        */ | ||||
|       if (intel->depth_region && | ||||
| 	  intel->depth_region->cpp == 2) | ||||
| 	 return intel->depth_region; | ||||
|    case GL_STENCIL: | ||||
|       /* Don't think this is really possible.  | ||||
|        */ | ||||
|       break; | ||||
|    case GL_DEPTH_STENCIL_EXT: | ||||
|       /* Does it matter whether it is stencil/depth or depth/stencil? | ||||
|        */ | ||||
|       return intel->depth_region; | ||||
|    default: | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    return NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Doesn't work for overlapping regions.  Could do a double copy or | ||||
|  * just fallback. | ||||
|  */ | ||||
| static GLboolean do_texture_copypixels( GLcontext *ctx, | ||||
| 					GLint srcx, GLint srcy,  | ||||
| 					GLsizei width, GLsizei height, | ||||
| 					GLint dstx, GLint dsty,  | ||||
| 					GLenum type ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    struct intel_region *dst = intel_drawbuf_region( intel ); | ||||
|    struct intel_region *src = copypix_src_region(intel, type); | ||||
|    GLenum src_format; | ||||
|    GLenum src_type; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!src || !dst || type != GL_COLOR) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    /* Can't handle overlapping regions.  Don't have sufficient control | ||||
|     * over rasterization to pull it off in-place.  Punt on these for | ||||
|     * now. | ||||
|     *  | ||||
|     * XXX: do a copy to a temporary.  | ||||
|     */ | ||||
|    { | ||||
|       drm_clip_rect_t src; | ||||
|       drm_clip_rect_t dst; | ||||
|       drm_clip_rect_t tmp; | ||||
|        | ||||
|       src.x1 = srcx; | ||||
|       src.y1 = srcy; | ||||
|       src.x2 = srcx + width; | ||||
|       src.y2 = srcy + height; | ||||
|  | ||||
|       dst.x1 = dstx; | ||||
|       dst.y1 = dsty; | ||||
|       dst.x1 = dstx + width * ctx->Pixel.ZoomX; | ||||
|       dst.y2 = dsty + height * ctx->Pixel.ZoomY; | ||||
|  | ||||
|  | ||||
|       if (intel_intersect_cliprects(&tmp, &src, &dst)) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    _mesa_printf("%s: regions overlap\n", __FUNCTION__); | ||||
| 	 return GL_FALSE; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|  | ||||
|    intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|    /* Is this true?  Also will need to turn depth testing on according | ||||
|     * to state: | ||||
|     */ | ||||
|    intel->vtbl.meta_no_stencil_write(intel); | ||||
|    intel->vtbl.meta_no_depth_write(intel); | ||||
|  | ||||
|    /* Set the 3d engine to draw into the destination region: | ||||
|     */ | ||||
|    intel->vtbl.meta_draw_region(intel, dst, intel->depth_region); | ||||
|  | ||||
|    intel->vtbl.meta_import_pixel_state(intel); | ||||
|  | ||||
|    if (src->cpp == 2) { | ||||
|       src_format = GL_RGB; | ||||
|       src_type = GL_UNSIGNED_SHORT_5_6_5; | ||||
|    }  | ||||
|    else { | ||||
|       src_format = GL_BGRA; | ||||
|       src_type = GL_UNSIGNED_BYTE; | ||||
|    } | ||||
|  | ||||
|    /* Set the frontbuffer up as a large rectangular texture. | ||||
|     */ | ||||
|    if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, 0, | ||||
| 					  src->pitch, | ||||
| 					  src->height, | ||||
| 					  src_format, | ||||
| 					  src_type )) { | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|        | ||||
|    intel->vtbl.meta_texture_blend_replace( intel );  | ||||
|  | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|     | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|  | ||||
|  | ||||
|       srcy = dPriv->h - srcy - height; 	/* convert from gl to hardware coords */ | ||||
|  | ||||
|       srcx += dPriv->x; | ||||
|       srcy += dPriv->y; | ||||
|  | ||||
|       /* Clip against the source region.  This is the only source | ||||
|        * clipping we do.  XXX: Just set the texcord wrap mode to clamp | ||||
|        * or similar. | ||||
|        * | ||||
|        */ | ||||
|       if (0) { | ||||
| 	 GLint orig_x = srcx; | ||||
| 	 GLint orig_y = srcy; | ||||
|  | ||||
| 	 if (!_mesa_clip_to_region(0, 0, src->pitch, src->height, | ||||
|                                    &srcx, &srcy, &width, &height))  | ||||
| 	    goto out; | ||||
|  | ||||
| 	 dstx += srcx - orig_x;  | ||||
| 	 dsty += (srcy - orig_y) * ctx->Pixel.ZoomY;  | ||||
|       } | ||||
|  | ||||
|       /* Just use the regular cliprect mechanism...  Does this need to | ||||
|        * even hold the lock??? | ||||
|        */ | ||||
|       intel_meta_draw_quad(intel,  | ||||
|  | ||||
| 			   dstx,  | ||||
| 			   dstx + width * ctx->Pixel.ZoomX,  | ||||
| 			   dPriv->h - (dsty + height * ctx->Pixel.ZoomY),  | ||||
| 			   dPriv->h - (dsty),  | ||||
|   | ||||
| 			   0,	/* XXX: what z value? */ | ||||
| 			   0x00ff00ff,  | ||||
| 			   srcx, srcx+width,  | ||||
| 			   srcy, srcy+height); | ||||
|  | ||||
|    out: | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * CopyPixels with the blitter.  Don't support zooming, pixel transfer, etc. | ||||
|  */ | ||||
| static GLboolean do_blit_copypixels( GLcontext *ctx, | ||||
| 				     GLint srcx, GLint srcy,  | ||||
| 				     GLsizei width, GLsizei height, | ||||
| 				     GLint dstx, GLint dsty,  | ||||
| 				     GLenum type ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    struct intel_region *dst = intel_drawbuf_region( intel ); | ||||
|    struct intel_region *src = copypix_src_region( intel, type ); | ||||
|  | ||||
|    /* Copypixels can be more than a straight copy.  Ensure all the | ||||
|     * extra operations are disabled: | ||||
|     */ | ||||
|    if (!intel_check_blit_fragment_ops(ctx) || | ||||
|        ctx->Pixel.ZoomX != 1.0F ||  | ||||
|        ctx->Pixel.ZoomY != 1.0F) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (!src || !dst)  | ||||
|       return GL_FALSE; | ||||
|  | ||||
|  | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    intel->vtbl.render_start(intel); | ||||
|    intel->vtbl.emit_state(intel); | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t dest_rect; | ||||
|       GLint nbox = dPriv->numClipRects; | ||||
|       GLint delta_x = 0;       | ||||
|       GLint delta_y = 0;       | ||||
|       GLuint i; | ||||
|  | ||||
|  | ||||
|       dsty = dPriv->h - dsty - height; 	/* convert from gl to hardware coords */ | ||||
|       srcy = dPriv->h - srcy - height; 	/* convert from gl to hardware coords */ | ||||
|       dstx += dPriv->x; | ||||
|       dsty += dPriv->y; | ||||
|       srcx += dPriv->x; | ||||
|       srcy += dPriv->y; | ||||
|  | ||||
|       /* Clip against the source region.  This is the only source | ||||
|        * clipping we do.  Dst is clipped with cliprects below. | ||||
|        * | ||||
|        * TODO: Scissor? | ||||
|        */ | ||||
|       { | ||||
| 	 delta_x = srcx - dstx; | ||||
| 	 delta_y = srcy - dsty; | ||||
|  | ||||
| 	 if (!_mesa_clip_to_region(0, 0, src->pitch, src->height, | ||||
|                                    &srcx, &srcy, &width, &height))  | ||||
| 	    goto out; | ||||
|  | ||||
| 	 dstx = srcx - delta_x; | ||||
| 	 dsty = srcy - delta_y; | ||||
|       } | ||||
|  | ||||
|       dest_rect.x1 = dstx; | ||||
|       dest_rect.y1 = dsty; | ||||
|       dest_rect.x2 = dstx + width; | ||||
|       dest_rect.y2 = dsty + height; | ||||
|  | ||||
|       /* Could do slightly more clipping: Eg, take the intersection of | ||||
|        * the existing set of cliprects and those cliprects translated | ||||
|        * by delta_x, delta_y: | ||||
|        *  | ||||
|        * This code will not overwrite other windows, but will | ||||
|        * introduce garbage when copying from obscured window regions. | ||||
|        */ | ||||
|       for (i = 0 ; i < nbox ; i++ ) | ||||
|       { | ||||
| 	 drm_clip_rect_t rect; | ||||
|  | ||||
| 	 if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i])) | ||||
| 	    continue; | ||||
|  | ||||
| 	  | ||||
| 	 intelEmitCopyBlit( intel, | ||||
| 			    dst->cpp, | ||||
| 			    src->pitch, src->buffer, 0, | ||||
| 			    dst->pitch, dst->buffer, 0, | ||||
| 			    rect.x1 + delta_x,  | ||||
| 			    rect.y1 + delta_y, /* srcx, srcy */ | ||||
| 			    rect.x1,  | ||||
| 			    rect.y1, /* dstx, dsty */ | ||||
| 			    rect.x2 - rect.x1,  | ||||
| 			    rect.y2 - rect.y1 ); | ||||
|       } | ||||
|  | ||||
|    out: | ||||
|       intel_batchbuffer_flush( intel->batch ); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelCopyPixels( GLcontext *ctx, | ||||
| 		      GLint srcx, GLint srcy,  | ||||
| 		      GLsizei width, GLsizei height, | ||||
| 		      GLint destx, GLint desty,  | ||||
| 		      GLenum type ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (do_blit_copypixels( ctx, srcx, srcy, width, height, destx, desty, type)) | ||||
|       return; | ||||
|  | ||||
|    if (do_texture_copypixels( ctx, srcx, srcy, width, height, destx, desty, type)) | ||||
|       return; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("fallback to _swrast_CopyPixels\n"); | ||||
|  | ||||
|    _swrast_CopyPixels( ctx, srcx, srcy, width, height, destx, desty, type); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										365
									
								
								src/mesa/drivers/dri/i915/intel_pixel_draw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										365
									
								
								src/mesa/drivers/dri/i915/intel_pixel_draw.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,365 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portionsalloc | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "bufferobj.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_buffer_objects.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean do_texture_drawpixels( GLcontext *ctx, | ||||
| 					GLint x, GLint y,  | ||||
| 					GLsizei width, GLsizei height, | ||||
| 					GLenum format, GLenum type, | ||||
| 					const struct gl_pixelstore_attrib *unpack, | ||||
| 					const GLvoid *pixels ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    struct intel_region *dst = intel_drawbuf_region( intel ); | ||||
|    struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj); | ||||
|    GLuint rowLength = unpack->RowLength ? unpack->RowLength : width; | ||||
|    GLuint src_offset; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    intel->vtbl.render_start(intel); | ||||
|    intel->vtbl.emit_state(intel); | ||||
|  | ||||
|    if (!dst) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (src) { | ||||
|       if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, | ||||
|                                      format, type, pixels)) { | ||||
|          _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); | ||||
|          return GL_TRUE; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* PBO only for now: | ||||
|        */ | ||||
| /*       _mesa_printf("%s - not PBO\n", __FUNCTION__); */ | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    /* There are a couple of things we can't do yet, one of which is | ||||
|     * set the correct state for pixel operations when GL texturing is | ||||
|     * enabled.  That's a pretty rare state and probably not worth the | ||||
|     * effort.  A completely device-independent version of this may do | ||||
|     * more. | ||||
|     * | ||||
|     * Similarly, we make no attempt to merge metaops processing with | ||||
|     * an enabled fragment program, though it would certainly be | ||||
|     * possible. | ||||
|     */ | ||||
|    if (!intel_check_meta_tex_fragment_ops(ctx)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - bad GL fragment state for metaops texture\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.install_meta_state(intel); | ||||
|  | ||||
|  | ||||
|    /* Is this true?  Also will need to turn depth testing on according | ||||
|     * to state: | ||||
|     */ | ||||
|    intel->vtbl.meta_no_stencil_write(intel); | ||||
|    intel->vtbl.meta_no_depth_write(intel); | ||||
|  | ||||
|    /* Set the 3d engine to draw into the destination region: | ||||
|     */ | ||||
|    intel->vtbl.meta_draw_region(intel, dst, intel->depth_region); | ||||
|  | ||||
|    intel->vtbl.meta_import_pixel_state(intel); | ||||
|  | ||||
|    src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height, | ||||
| 					     format, type, 0, 0, 0); | ||||
|  | ||||
|  | ||||
|    /* Setup the pbo up as a rectangular texture, if possible. | ||||
|     * | ||||
|     * TODO: This is almost always possible if the i915 fragment | ||||
|     * program is adjusted to correctly swizzle the sampled colors. | ||||
|     * The major exception is any 24bit texture, like RGB888, for which | ||||
|     * there is no hardware support.   | ||||
|     */ | ||||
|    if (!intel->vtbl.meta_tex_rect_source( intel, src->buffer, src_offset, | ||||
| 					  rowLength, height, | ||||
| 					  format, type )) { | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|        | ||||
|    intel->vtbl.meta_texture_blend_replace( intel );  | ||||
|  | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       GLint srcx, srcy; | ||||
|       GLint dstx, dsty; | ||||
|  | ||||
|       dstx = x; | ||||
|       dsty = dPriv->h - (y + height); | ||||
|  | ||||
|       srcx = 0;			/* skiprows/pixels already done */ | ||||
|       srcy = 0; | ||||
|  | ||||
|       if (0) { | ||||
| 	 const GLint orig_x = dstx; | ||||
| 	 const GLint orig_y = dsty; | ||||
|  | ||||
| 	 if (!_mesa_clip_to_region(0, 0, dst->pitch, dst->height, | ||||
|                                    &dstx, &dsty, &width, &height))  | ||||
| 	    goto out; | ||||
|  | ||||
| 	 srcx += dstx - orig_x;  | ||||
| 	 srcy += dsty - orig_y;  | ||||
|       } | ||||
|  | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("draw %d,%d %dx%d\n", dstx,dsty,width,height); | ||||
|  | ||||
|       /* Must use the regular cliprect mechanism in order to get the | ||||
|        * drawing origin set correctly.  Otherwise scissor state is in | ||||
|        * incorrect coordinate space.  Does this even need to hold the | ||||
|        * lock??? | ||||
|        */ | ||||
|       intel_meta_draw_quad(intel,  | ||||
| 			   dstx, dstx + width * ctx->Pixel.ZoomX,  | ||||
| 			   dPriv->h - (y + height * ctx->Pixel.ZoomY),  | ||||
| 			   dPriv->h - (y),  | ||||
| 			   - ctx->Current.RasterPos[2] * .5, | ||||
| 			   0x00ff00ff,  | ||||
| 			   srcx, srcx+width,  | ||||
| 			   srcy+height, srcy); | ||||
|    out: | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|       intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Pros:   | ||||
|  *   - no waiting for idle before updating framebuffer. | ||||
|  *    | ||||
|  * Cons: | ||||
|  *   - if upload is by memcpy, this may actually be slower than fallback path. | ||||
|  *   - uploads the whole image even if destination is clipped | ||||
|  *    | ||||
|  * Need to benchmark. | ||||
|  * | ||||
|  * Given the questions about performance, implement for pbo's only. | ||||
|  * This path is definitely a win if the pbo is already in agp.  If it | ||||
|  * turns out otherwise, we can add the code necessary to upload client | ||||
|  * data to agp space before performing the blit.  (Though it may turn | ||||
|  * out to be better/simpler just to use the texture engine). | ||||
|  */ | ||||
| static GLboolean do_blit_drawpixels( GLcontext *ctx, | ||||
| 				      GLint x, GLint y,  | ||||
| 				      GLsizei width, GLsizei height, | ||||
| 				      GLenum format, GLenum type, | ||||
| 				      const struct gl_pixelstore_attrib *unpack, | ||||
| 				      const GLvoid *pixels ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *dest = intel_drawbuf_region(intel); | ||||
|    struct intel_buffer_object *src = intel_buffer_object(unpack->BufferObj); | ||||
|    GLuint src_offset; | ||||
|    GLuint rowLength; | ||||
|    GLuint fence = bmInitFence(intel->bm); | ||||
|     | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s\n", __FUNCTION__); | ||||
|     | ||||
|     | ||||
|    if (!dest) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - no dest\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (src) { | ||||
|       /* This validation should be done by core mesa: | ||||
|        */ | ||||
|       if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, | ||||
|                                      format, type, pixels)) { | ||||
|          _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); | ||||
|          return GL_TRUE; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* PBO only for now: | ||||
|        */ | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - not PBO\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|     | ||||
|    if (!intel_check_blit_format(dest, format, type)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - bad format for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (!intel_check_meta_tex_fragment_ops(ctx)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - bad GL fragment state for meta tex\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (ctx->Pixel.ZoomX != 1.0F) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - bad PixelZoomX for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (unpack->RowLength > 0) | ||||
|       rowLength = unpack->RowLength; | ||||
|    else | ||||
|       rowLength = width; | ||||
|  | ||||
|    if (ctx->Pixel.ZoomY == -1.0F) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE;		/* later */ | ||||
|       y -= height; | ||||
|    } | ||||
|    else if (ctx->Pixel.ZoomY == 1.0F) { | ||||
|       rowLength = -rowLength; | ||||
|    } | ||||
|    else { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - bad PixelZoomY for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    src_offset = (GLuint) _mesa_image_address(2, unpack, pixels, width, height, | ||||
| 					     format, type, 0, 0, 0); | ||||
|  | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|    { | ||||
|       __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t rect; | ||||
|       drm_clip_rect_t dest_rect; | ||||
|       int i; | ||||
|        | ||||
|       dest_rect.x1 = dPriv->x + x; | ||||
|       dest_rect.y1 = dPriv->y + dPriv->h - (y + height); | ||||
|       dest_rect.x2 = dest_rect.x1 + width; | ||||
|       dest_rect.y2 = dest_rect.y1 + height; | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++ ) | ||||
|       { | ||||
| 	 if (!intel_intersect_cliprects(&rect, &dest_rect, &box[i])) | ||||
| 	    continue; | ||||
|  | ||||
| 	 intelEmitCopyBlit( intel, | ||||
| 			    dest->cpp, | ||||
| 			    rowLength,  | ||||
| 			    intel_bufferobj_buffer(src), src_offset, | ||||
| 			    dest->pitch,  | ||||
| 			    dest->buffer, 0, | ||||
| 			    rect.x1 - dest_rect.x1,  | ||||
| 			    rect.y2 - dest_rect.y2, | ||||
| 			    rect.x1,  | ||||
| 			    rect.y1, | ||||
| 			    rect.x2 - rect.x1, | ||||
| 			    rect.y2 - rect.y1 ); | ||||
|       } | ||||
|       fence = intel_batchbuffer_flush( intel->batch ); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|       bmFinishFence(intel->bm, fence);    | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s - DONE\n", __FUNCTION__); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelDrawPixels( GLcontext *ctx, | ||||
| 		      GLint x, GLint y,  | ||||
| 		      GLsizei width, GLsizei height, | ||||
| 		      GLenum format,  | ||||
| 		      GLenum type, | ||||
| 		      const struct gl_pixelstore_attrib *unpack, | ||||
| 		      const GLvoid *pixels ) | ||||
| { | ||||
|    if (do_blit_drawpixels( ctx, x, y, width, height, format, type, | ||||
| 			    unpack, pixels )) | ||||
|       return; | ||||
|  | ||||
|    if (do_texture_drawpixels( ctx, x, y, width, height, format, type, | ||||
| 			       unpack, pixels )) | ||||
|       return; | ||||
|  | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); | ||||
|  | ||||
|    _swrast_DrawPixels( ctx, x, y, width, height, format, type, | ||||
| 		       unpack, pixels ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										321
									
								
								src/mesa/drivers/dri/i915/intel_pixel_read.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								src/mesa/drivers/dri/i915/intel_pixel_read.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,321 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "enums.h" | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
| #include "image.h" | ||||
| #include "bufferobj.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_buffer_objects.h" | ||||
|  | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
| /* For many applications, the new ability to pull the source buffers | ||||
|  * back out of the GTT and then do the packing/conversion operations | ||||
|  * in software will be as much of an improvement as trying to get the | ||||
|  * blitter and/or texture engine to do the work.  | ||||
|  * | ||||
|  * This step is gated on private backbuffers. | ||||
|  *  | ||||
|  * Obviously the frontbuffer can't be pulled back, so that is either | ||||
|  * an argument for blit/texture readpixels, or for blitting to a | ||||
|  * temporary and then pulling that back. | ||||
|  * | ||||
|  * When the destination is a pbo, however, it's not clear if it is | ||||
|  * ever going to be pulled to main memory (though the access param | ||||
|  * will be a good hint).  So it sounds like we do want to be able to | ||||
|  * choose between blit/texture implementation on the gpu and pullback | ||||
|  * and cpu-based copying. | ||||
|  * | ||||
|  * Unless you can magically turn client memory into a PBO for the | ||||
|  * duration of this call, there will be a cpu-based copying step in | ||||
|  * any case. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| do_texture_readpixels( GLcontext *ctx, | ||||
| 			GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const struct gl_pixelstore_attrib *pack, | ||||
| 			struct intel_region *dest_region ) | ||||
| { | ||||
| #if 0 | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    GLint pitch = pack->RowLength ? pack->RowLength : width; | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|    int textureFormat; | ||||
|    GLenum glTextureFormat; | ||||
|    int destFormat, depthFormat, destPitch; | ||||
|    drm_clip_rect_t tmp; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|  | ||||
|    if (	ctx->_ImageTransferState || | ||||
| 	pack->SwapBytes || | ||||
| 	pack->LsbFirst || | ||||
| 	!pack->Invert) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: check_color failed\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.meta_texrect_source(intel, intel_readbuf_region(intel)); | ||||
|  | ||||
|    if (!intel->vtbl.meta_render_dest(intel, | ||||
| 				     dest_region, | ||||
| 				     type, format)) | ||||
|    { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 fprintf(stderr, "%s: couldn't set dest %s/%s\n", | ||||
| 		 __FUNCTION__, | ||||
| 		 _mesa_lookup_enum_by_nr(type), | ||||
| 		 _mesa_lookup_enum_by_nr(format)); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) { | ||||
|       intel->vtbl.install_meta_state(intel); | ||||
|       intel->vtbl.meta_no_depth_write(intel); | ||||
|       intel->vtbl.meta_no_stencil_write(intel); | ||||
|  | ||||
|       if (!driClipRectToFramebuffer(ctx->ReadBuffer, &x, &y, &width, &height)) { | ||||
| 	 UNLOCK_HARDWARE( intel ); | ||||
| 	 SET_STATE(i830, state); | ||||
| 	 if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	    fprintf(stderr, "%s: cliprect failed\n", __FUNCTION__); | ||||
| 	 return GL_TRUE; | ||||
|       } | ||||
|  | ||||
|       y = dPriv->h - y - height; | ||||
|       x += dPriv->x; | ||||
|       y += dPriv->y; | ||||
|  | ||||
|  | ||||
|       /* Set the frontbuffer up as a large rectangular texture. | ||||
|        */ | ||||
|       intel->vtbl.meta_tex_rect_source( intel, | ||||
| 					src_region, | ||||
| 					textureFormat );  | ||||
|     | ||||
|     | ||||
|       intel->vtbl.meta_texture_blend_replace( i830, glTextureFormat );  | ||||
|  | ||||
|  | ||||
|       /* Set the 3d engine to draw into the destination region: | ||||
|        */ | ||||
|  | ||||
|       intel->vtbl.meta_draw_region(intel, dest_region);  | ||||
|       intel->vtbl.meta_draw_format(intel, destFormat, depthFormat ); /* ?? */ | ||||
|  | ||||
|  | ||||
|       /* Draw a single quad, no cliprects: | ||||
|        */ | ||||
|       intel->vtbl.meta_disable_cliprects(intel); | ||||
|  | ||||
|       intel->vtbl.draw_quad(intel,  | ||||
| 			    0, width, 0, height,  | ||||
| 			    0x00ff00ff,  | ||||
| 			    x, x+width,  | ||||
| 			    y, y+height ); | ||||
|  | ||||
|       intel->vtbl.leave_meta_state(intel); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|    intel_region_wait_fence( ctx, dest_region ); /* required by GL */ | ||||
|    return GL_TRUE; | ||||
| #endif | ||||
|  | ||||
|    return GL_FALSE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean do_blit_readpixels( GLcontext *ctx, | ||||
| 				     GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 				     GLenum format, GLenum type, | ||||
| 				     const struct gl_pixelstore_attrib *pack, | ||||
| 				     GLvoid *pixels ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_region *src = intel_readbuf_region(intel); | ||||
|    struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); | ||||
|    GLuint dst_offset; | ||||
|    GLuint rowLength; | ||||
|    GLuint fence = bmInitFence(intel->bm); | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (!src) | ||||
|       return GL_FALSE; | ||||
|  | ||||
|    if (dst) { | ||||
|       /* XXX This validation should be done by core mesa: | ||||
|        */ | ||||
|       if (!_mesa_validate_pbo_access(2, pack, width, height, 1, | ||||
|                                      format, type, pixels)) { | ||||
|          _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawPixels"); | ||||
|          return GL_TRUE; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* PBO only for now: | ||||
|        */ | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - not PBO\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|     | ||||
|    if (ctx->_ImageTransferState || | ||||
|        !intel_check_blit_format(src, format, type)) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s - bad format for blit\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (pack->Alignment != 1 || pack->SwapBytes || pack->LsbFirst) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s: bad packing params\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|    if (pack->RowLength > 0) | ||||
|       rowLength = pack->RowLength; | ||||
|    else | ||||
|       rowLength = width; | ||||
|  | ||||
|    if (pack->Invert) { | ||||
|       if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
| 	 _mesa_printf("%s: MESA_PACK_INVERT not done yet\n", __FUNCTION__); | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|    else { | ||||
|       rowLength = -rowLength; | ||||
|    } | ||||
|  | ||||
|    /* XXX 64-bit cast? */ | ||||
|    dst_offset = (GLuint) _mesa_image_address(2, pack, pixels, width, height, | ||||
| 					     format, type, 0, 0, 0); | ||||
|  | ||||
|  | ||||
|    /* Although the blits go on the command buffer, need to do this and | ||||
|     * fire with lock held to guarentee cliprects are correct. | ||||
|     */ | ||||
|    intelFlush( &intel->ctx ); | ||||
|    LOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|    { | ||||
|        __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|       int nbox = dPriv->numClipRects; | ||||
|       drm_clip_rect_t *box = dPriv->pClipRects; | ||||
|       drm_clip_rect_t rect; | ||||
|       drm_clip_rect_t src_rect; | ||||
|       int i; | ||||
|        | ||||
|       src_rect.x1 = dPriv->x + x; | ||||
|       src_rect.y1 = dPriv->y + dPriv->h - (y + height); | ||||
|       src_rect.x2 = src_rect.x1 + width; | ||||
|       src_rect.y2 = src_rect.y1 + height; | ||||
|  | ||||
|  | ||||
|  | ||||
|       for (i = 0 ; i < nbox ; i++) | ||||
|       { | ||||
| 	 if (!intel_intersect_cliprects(&rect, &src_rect, &box[i])) | ||||
| 	    continue; | ||||
|  | ||||
| 	 intelEmitCopyBlit( intel, | ||||
| 			    src->cpp, | ||||
| 			    src->pitch, src->buffer, 0, | ||||
| 			    rowLength,  | ||||
| 			    intel_bufferobj_buffer(dst), dst_offset, | ||||
| 			    rect.x1,  | ||||
| 			    rect.y1, | ||||
| 			    rect.x1 - src_rect.x1,  | ||||
| 			    rect.y2 - src_rect.y2, | ||||
| 			    rect.x2 - rect.x1, | ||||
| 			    rect.y2 - rect.y1 ); | ||||
|       } | ||||
|  | ||||
|       fence = intel_batchbuffer_flush(intel->batch); | ||||
|    } | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
|  | ||||
|    if (intel->driDrawable->numClipRects) | ||||
|       bmFinishFence(intel->bm, fence);    | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s - DONE\n", __FUNCTION__); | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
| void | ||||
| intelReadPixels( GLcontext *ctx, | ||||
| 		 GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 		 GLenum format, GLenum type, | ||||
| 		 const struct gl_pixelstore_attrib *pack, | ||||
| 		 GLvoid *pixels ) | ||||
| { | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       fprintf(stderr, "%s\n", __FUNCTION__); | ||||
|  | ||||
|    intelFlush( ctx ); | ||||
|  | ||||
|    if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels)) | ||||
|       return; | ||||
|  | ||||
|    if (do_texture_readpixels(ctx, x, y, width, height, format, type, pack, pixels)) | ||||
|       return; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_PIXEL) | ||||
|       _mesa_printf("%s: fallback to swrast\n", __FUNCTION__); | ||||
|  | ||||
|    _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels); | ||||
| } | ||||
|  | ||||
							
								
								
									
										264
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								src/mesa/drivers/dri/i915/intel_regions.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,264 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| /* Provide additional functionality on top of bufmgr buffers: | ||||
|  *   - 2d semantics and blit operations | ||||
|  *   - refcounting of buffers for multiple images in a buffer. | ||||
|  *   - refcounting of buffer mappings. | ||||
|  *   - some logic for moving the buffers to the best memory pools for | ||||
|  *     given operations. | ||||
|  * | ||||
|  * Most of this is to make it easier to implement the fixed-layout | ||||
|  * mipmap tree required by intel hardware in the face of GL's | ||||
|  * programming interface where each image can be specifed in random | ||||
|  * order and it isn't clear what layout the tree should have until the | ||||
|  * last moment. | ||||
|  */ | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
| /* XXX: Thread safety? | ||||
|  */ | ||||
| GLubyte *intel_region_map(struct intel_context *intel, struct intel_region *region) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    if (!region->map_refcount++) { | ||||
|       region->map = bmMapBuffer(intel->bm, region->buffer, 0); | ||||
|    } | ||||
|  | ||||
|    return region->map; | ||||
| } | ||||
|  | ||||
| void intel_region_unmap(struct intel_context *intel,  | ||||
| 			struct intel_region *region) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|    if (!--region->map_refcount) { | ||||
|       bmUnmapBuffer(intel->bm, region->buffer); | ||||
|       region->map = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
| struct intel_region *intel_region_alloc( struct intel_context *intel,  | ||||
| 					 GLuint cpp, | ||||
| 					 GLuint pitch,  | ||||
| 					 GLuint height ) | ||||
| { | ||||
|    struct intel_region *region = calloc(sizeof(*region), 1); | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    region->cpp = cpp; | ||||
|    region->pitch = pitch; | ||||
|    region->height = height; 	/* needed? */ | ||||
|    region->refcount = 1; | ||||
|  | ||||
|    bmGenBuffers(intel->bm, 1, ®ion->buffer, 0); | ||||
|    bmBufferData(intel->bm, region->buffer, pitch * cpp * height, NULL, 0); | ||||
|  | ||||
|    return region; | ||||
| } | ||||
|  | ||||
| void intel_region_reference( struct intel_region **dst, | ||||
| 			     struct intel_region *src) | ||||
| { | ||||
|    assert(*dst == NULL); | ||||
|    if (src) { | ||||
|       src->refcount++; | ||||
|       *dst = src; | ||||
|    } | ||||
| } | ||||
|  | ||||
| void intel_region_release( struct intel_context *intel, | ||||
| 			   struct intel_region **region ) | ||||
| { | ||||
|    if (!*region) | ||||
|       return; | ||||
|  | ||||
|    DBG("%s %d\n", __FUNCTION__, (*region)->refcount-1); | ||||
|  | ||||
|    ASSERT((*region)->refcount > 0); | ||||
|    (*region)->refcount--; | ||||
|  | ||||
|    if ((*region)->refcount == 0) { | ||||
|       assert((*region)->map_refcount == 0); | ||||
|       bmDeleteBuffers(intel->bm, 1, &(*region)->buffer); | ||||
|       free(*region); | ||||
|    } | ||||
|    *region = NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct intel_region *intel_region_create_static( struct intel_context *intel, | ||||
| 						 GLuint mem_type, | ||||
| 						 GLuint offset, | ||||
| 						 void *virtual, | ||||
| 						 GLuint cpp, | ||||
| 						 GLuint pitch,  | ||||
| 						 GLuint height ) | ||||
| { | ||||
|    struct intel_region *region = calloc(sizeof(*region), 1); | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    region->cpp = cpp; | ||||
|    region->pitch = pitch; | ||||
|    region->height = height; 	/* needed? */ | ||||
|    region->refcount = 1; | ||||
|  | ||||
|    /* | ||||
|     * We use a "shared" buffer type to indicate buffers created and | ||||
|     * shared by others. | ||||
|     */ | ||||
|  | ||||
|    bmGenBuffers(intel->bm, 1, ®ion->buffer, DRM_MM_TT | DRM_MM_SHARED); | ||||
|    bmSetShared(intel->bm, region->buffer, DRM_MM_TT, offset, virtual); | ||||
|  | ||||
|    return region; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * XXX Move this into core Mesa? | ||||
|  */ | ||||
| static void _mesa_copy_rect( GLubyte *dst, | ||||
| 			     GLuint cpp, | ||||
| 			     GLuint dst_pitch, | ||||
| 			     GLuint dst_x,  | ||||
| 			     GLuint dst_y, | ||||
| 			     GLuint width, | ||||
| 			     GLuint height, | ||||
| 			     GLubyte *src, | ||||
| 			     GLuint src_pitch, | ||||
| 			     GLuint src_x, | ||||
| 			     GLuint src_y ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    dst_pitch *= cpp; | ||||
|    src_pitch *= cpp; | ||||
|    dst += dst_x * cpp; | ||||
|    src += src_x * cpp; | ||||
|    dst += dst_y * dst_pitch; | ||||
|    src += src_y * dst_pitch; | ||||
|    width *= cpp; | ||||
|  | ||||
|    if (width == dst_pitch &&  | ||||
|        width == src_pitch) | ||||
|       memcpy(dst, src, height * width); | ||||
|    else { | ||||
|       for (i = 0; i < height; i++) { | ||||
| 	 memcpy(dst, src, width); | ||||
| 	 dst += dst_pitch; | ||||
| 	 src += src_pitch; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Upload data to a rectangular sub-region.  Lots of choices how to do this: | ||||
|  * | ||||
|  * - memcpy by span to current destination | ||||
|  * - upload data as new buffer and blit | ||||
|  * | ||||
|  * Currently always memcpy. | ||||
|  */ | ||||
| void intel_region_data(struct intel_context *intel,  | ||||
| 		       struct intel_region *dst, | ||||
| 		       GLuint dst_offset, | ||||
| 		       GLuint dstx, GLuint dsty, | ||||
| 		       void *src, GLuint src_pitch, | ||||
| 		       GLuint srcx, GLuint srcy, | ||||
| 		       GLuint width, GLuint height) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|     | ||||
|    _mesa_copy_rect(intel_region_map(intel, dst) + dst_offset, | ||||
| 		   dst->cpp, | ||||
| 		   dst->pitch, | ||||
| 		   dstx, dsty, | ||||
| 		   width, height, | ||||
| 		   src, | ||||
| 		   src_pitch, | ||||
| 		   srcx, srcy);       | ||||
|  | ||||
|    intel_region_unmap(intel, dst); | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|     | ||||
| } | ||||
| 			   | ||||
| /* Copy rectangular sub-regions. Need better logic about when to | ||||
|  * push buffers into AGP - will currently do so whenever possible. | ||||
|  */ | ||||
| void intel_region_copy( struct intel_context *intel, | ||||
| 			struct intel_region *dst, | ||||
| 			GLuint dst_offset, | ||||
| 			GLuint dstx, GLuint dsty, | ||||
| 			struct intel_region *src, | ||||
| 			GLuint src_offset, | ||||
| 			GLuint srcx, GLuint srcy, | ||||
| 			GLuint width, GLuint height ) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    assert(src->cpp == dst->cpp); | ||||
|  | ||||
|    intelEmitCopyBlit(intel, | ||||
| 		     dst->cpp, | ||||
| 		     src->pitch, src->buffer, src_offset, | ||||
| 		     dst->pitch, dst->buffer, dst_offset,  | ||||
| 		     srcx, srcy, | ||||
| 		     dstx, dsty, | ||||
| 		     width, height); | ||||
| } | ||||
|  | ||||
| /* Fill a rectangular sub-region.  Need better logic about when to | ||||
|  * push buffers into AGP - will currently do so whenever possible. | ||||
|  */ | ||||
| void intel_region_fill( struct intel_context *intel, | ||||
| 			struct intel_region *dst, | ||||
| 			GLuint dst_offset, | ||||
| 			GLuint dstx, GLuint dsty, | ||||
| 			GLuint width, GLuint height, | ||||
| 			GLuint color ) | ||||
| { | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|     | ||||
|    intelEmitFillBlit(intel, | ||||
| 		     dst->cpp, | ||||
| 		     dst->pitch, dst->buffer, dst_offset,  | ||||
| 		     dstx, dsty, | ||||
| 		     width, height, | ||||
| 		     color ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										119
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								src/mesa/drivers/dri/i915/intel_regions.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #ifndef INTEL_REGIONS_H | ||||
| #define INTEL_REGIONS_H | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "intel_bufmgr.h"		/* for DBG! */ | ||||
| struct intel_context; | ||||
|  | ||||
| /** | ||||
|  * A layer on top of the bufmgr buffers that adds a few useful things: | ||||
|  * | ||||
|  * - Refcounting for local buffer references. | ||||
|  * - Refcounting for buffer maps | ||||
|  * - Buffer dimensions - pitch and height. | ||||
|  * - Blitter commands for copying 2D regions between buffers. (really???) | ||||
|  */ | ||||
| struct intel_region { | ||||
|    GLuint buffer;   /**< buffer manager's buffer ID */ | ||||
|    GLuint refcount; /**< Reference count for region */ | ||||
|    GLuint cpp;      /**< bytes per pixel */ | ||||
|    GLuint pitch;    /**< in pixels */ | ||||
|    GLuint height;   /**< in pixels */ | ||||
|    GLubyte *map;    /**< only non-NULL when region is actually mapped */ | ||||
|    GLuint map_refcount;  /**< Reference count for mapping */ | ||||
|  | ||||
|    GLuint draw_offset; /**< Offset of drawing address within the region */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| /* Allocate a refcounted region.  Pointers to regions should only be | ||||
|  * copied by calling intel_reference_region(). | ||||
|  */ | ||||
| struct intel_region *intel_region_alloc( struct intel_context *intel, | ||||
| 					 GLuint cpp, | ||||
| 					 GLuint pitch,  | ||||
| 					 GLuint height ); | ||||
|  | ||||
| void intel_region_reference( struct intel_region **dst,  | ||||
| 			     struct intel_region *src ); | ||||
|  | ||||
| void intel_region_release(struct intel_context *intel, | ||||
| 			  struct intel_region **ib ); | ||||
|  | ||||
|  | ||||
| struct intel_region *intel_region_create_static( struct intel_context *intel, | ||||
| 						 GLuint mem_type, | ||||
| 						 GLuint offset, | ||||
| 						 void *virtual, | ||||
| 						 GLuint cpp, | ||||
| 						 GLuint pitch, | ||||
| 						 GLuint height ); | ||||
|  | ||||
| /* Map/unmap regions.  This is refcounted also:  | ||||
|  */ | ||||
| GLubyte *intel_region_map(struct intel_context *intel,  | ||||
| 		       struct intel_region *ib); | ||||
|  | ||||
| void intel_region_unmap(struct intel_context *intel, | ||||
| 			struct intel_region *ib); | ||||
|  | ||||
|  | ||||
| /* Upload data to a rectangular sub-region | ||||
|  */ | ||||
| void intel_region_data(struct intel_context *intel,  | ||||
| 		       struct intel_region *dest, | ||||
| 		       GLuint dest_offset, | ||||
| 		       GLuint destx, GLuint desty, | ||||
| 		       void *src, GLuint src_stride, | ||||
| 		       GLuint srcx, GLuint srcy, | ||||
| 		       GLuint width, GLuint height); | ||||
| 			   | ||||
| /* Copy rectangular sub-regions | ||||
|  */ | ||||
| void intel_region_copy( struct intel_context *intel, | ||||
| 			struct intel_region *dest, | ||||
| 			GLuint dest_offset, | ||||
| 			GLuint destx, GLuint desty, | ||||
| 			struct intel_region *src, | ||||
| 			GLuint src_offset, | ||||
| 			GLuint srcx, GLuint srcy, | ||||
| 			GLuint width, GLuint height ); | ||||
|  | ||||
| /* Fill a rectangular sub-region | ||||
|  */ | ||||
| void intel_region_fill( struct intel_context *intel, | ||||
| 			struct intel_region *dest, | ||||
| 			GLuint dest_offset, | ||||
| 			GLuint destx, GLuint desty, | ||||
| 			GLuint width, GLuint height, | ||||
| 			GLuint color ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -106,24 +106,29 @@ static const int scale_prim[GL_POLYGON+1] = { | ||||
| }; | ||||
|  | ||||
|  | ||||
| static void intelDmaPrimitive( intelContextPtr intel, GLenum prim ) | ||||
| static void intelDmaPrimitive( struct intel_context *intel, GLenum prim ) | ||||
| { | ||||
|    if (0) fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|    INTEL_FIREVERTICES(intel); | ||||
|    intel->vtbl.reduced_primitive_state( intel, reduced_prim[prim] ); | ||||
|    intelStartInlinePrimitive( intel, hw_prim[prim] ); | ||||
|    intelStartInlinePrimitive( intel, hw_prim[prim], INTEL_BATCH_CLIPRECTS ); | ||||
| } | ||||
|  | ||||
|  | ||||
| #define LOCAL_VARS intelContextPtr intel = INTEL_CONTEXT(ctx) | ||||
| #define LOCAL_VARS struct intel_context *intel = intel_context(ctx) | ||||
| #define INIT( prim ) 				\ | ||||
| do {						\ | ||||
|    intelDmaPrimitive( intel, prim );		\ | ||||
| } while (0) | ||||
| #define FLUSH()  INTEL_FIREVERTICES( intel ) | ||||
|  | ||||
| #define FLUSH()  				\ | ||||
| do {						\ | ||||
|    if (intel->prim.flush) 			\ | ||||
|       intel->prim.flush(intel);			\ | ||||
| } while (0) | ||||
|  | ||||
| #define GET_SUBSEQUENT_VB_MAX_VERTS() \ | ||||
|   (((intel->alloc.size / 2) - 1500) / (intel->vertex_size*4)) | ||||
|   ((BATCH_SZ - 1500) / (intel->vertex_size*4)) | ||||
| #define GET_CURRENT_VB_MAX_VERTS() GET_SUBSEQUENT_VB_MAX_VERTS() | ||||
|  | ||||
| #define ALLOC_VERTS( nr ) \ | ||||
| @@ -142,7 +147,7 @@ do {						\ | ||||
|  | ||||
| /* Heuristic to choose between the two render paths:   | ||||
|  */ | ||||
| static GLboolean choose_render( intelContextPtr intel, | ||||
| static GLboolean choose_render( struct intel_context *intel, | ||||
| 				struct vertex_buffer *VB ) | ||||
| { | ||||
|    int vertsz = intel->vertex_size; | ||||
| @@ -194,7 +199,7 @@ static GLboolean choose_render( intelContextPtr intel, | ||||
| static GLboolean intel_run_render( GLcontext *ctx,  | ||||
| 				 struct tnl_pipeline_stage *stage ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &tnl->vb; | ||||
|    GLuint i; | ||||
| @@ -225,6 +230,9 @@ static GLboolean intel_run_render( GLcontext *ctx, | ||||
|    } | ||||
|        | ||||
|    tnl->Driver.Render.Finish( ctx ); | ||||
|     | ||||
|    if (intel->prim.flush) | ||||
|       intel->prim.flush(intel); | ||||
|  | ||||
|    return GL_FALSE;     /* finished the pipe */ | ||||
| } | ||||
|   | ||||
| @@ -37,15 +37,16 @@ | ||||
|  | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_span.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
|  | ||||
| #include "intel_fbo.h" | ||||
|  | ||||
| #include "i830_dri.h" | ||||
|  | ||||
|  | ||||
| PUBLIC const char __driConfigOptions[] = | ||||
| DRI_CONF_BEGIN | ||||
|     DRI_CONF_SECTION_PERFORMANCE | ||||
| @@ -104,14 +105,14 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|    intelScreen->cpp = gDRIPriv->cpp; | ||||
| 			  | ||||
|    switch (gDRIPriv->bitsPerPixel) { | ||||
|    case 15: intelScreen->fbFormat = DV_PF_555; break; | ||||
|    case 16: intelScreen->fbFormat = DV_PF_565; break; | ||||
|    case 32: intelScreen->fbFormat = DV_PF_8888; break; | ||||
|    default: exit(1); break; | ||||
|    } | ||||
|  | ||||
|    intelScreen->front.pitch = gDRIPriv->fbStride; | ||||
|    intelScreen->front.offset = gDRIPriv->fbOffset; | ||||
|    intelScreen->front.map = sPriv->pFB; | ||||
|    intelScreen->front.map = (char *)sPriv->pFB; | ||||
|  | ||||
|    intelScreen->back.offset = gDRIPriv->backOffset; | ||||
|    intelScreen->back.pitch = gDRIPriv->backPitch; | ||||
| @@ -146,6 +147,12 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
| #if 0 | ||||
|  | ||||
|    /* | ||||
|     * FIXME: Remove this code and its references. | ||||
|     */ | ||||
|  | ||||
|    intelScreen->tex.offset = gDRIPriv->textureOffset; | ||||
|    intelScreen->logTextureGranularity = gDRIPriv->logTextureGranularity; | ||||
|    intelScreen->tex.handle = gDRIPriv->textures; | ||||
| @@ -163,10 +170,17 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|       sPriv->private = NULL; | ||||
|       return GL_FALSE; | ||||
|    } | ||||
| 			  | ||||
| 	 | ||||
| #else | ||||
|    intelScreen->tex.offset = 0; | ||||
|    intelScreen->logTextureGranularity = 0; | ||||
|    intelScreen->tex.handle = 0; | ||||
|    intelScreen->tex.size = 0; | ||||
| #endif | ||||
| 		  | ||||
|    intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; | ||||
|     | ||||
|    if (0) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); | ||||
|    if (1) intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); | ||||
|  | ||||
|    intelScreen->drmMinor = sPriv->drmMinor; | ||||
|  | ||||
| @@ -202,13 +216,8 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) | ||||
|  | ||||
|    if (glx_enable_extension != NULL) { | ||||
|       (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" ); | ||||
|       (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" ); | ||||
|    } | ||||
|     | ||||
|    sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA; | ||||
|    sPriv->psc->freeMemory     = (void *) intelFreeMemoryMESA; | ||||
|    sPriv->psc->memoryOffset   = (void *) intelGetMemoryOffsetMESA; | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
| 		 | ||||
| @@ -227,6 +236,9 @@ static void intelDestroyScreen(__DRIscreenPrivate *sPriv) | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * This is called when we need to set up GL rendering to a new X window. | ||||
|  */ | ||||
| static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv, | ||||
| 				    __DRIdrawablePrivate *driDrawPriv, | ||||
| 				    const __GLcontextModes *mesaVis, | ||||
| @@ -239,70 +251,71 @@ static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv, | ||||
|    } else { | ||||
|       GLboolean swStencil = (mesaVis->stencilBits > 0 &&  | ||||
| 			     mesaVis->depthBits != 24); | ||||
|       GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8); | ||||
|  | ||||
|       struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); | ||||
|  | ||||
|       /* setup the hardware-based renderbuffers */ | ||||
|       { | ||||
|          driRenderbuffer *frontRb | ||||
|             = driNewRenderbuffer(GL_RGBA, | ||||
|                                  driScrnPriv->pFB, | ||||
|                                  screen->cpp, | ||||
|                                  screen->front.offset, screen->front.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(frontRb, mesaVis); | ||||
|          struct intel_renderbuffer *frontRb | ||||
|             = intel_create_renderbuffer(rgbFormat, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->front.offset, | ||||
|                                         screen->front.pitch, | ||||
|                                         screen->cpp, | ||||
|                                         driScrnPriv->pFB); | ||||
|          intel_set_span_functions(&frontRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); | ||||
|       } | ||||
|  | ||||
|       if (mesaVis->doubleBufferMode) { | ||||
|          driRenderbuffer *backRb | ||||
|             = driNewRenderbuffer(GL_RGBA, | ||||
|                                  screen->back.map, | ||||
|                                  screen->cpp, | ||||
|                                  screen->back.offset, screen->back.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(backRb, mesaVis); | ||||
|          struct intel_renderbuffer *backRb | ||||
|             = intel_create_renderbuffer(rgbFormat, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->back.offset, | ||||
|                                         screen->back.pitch, | ||||
|                                         screen->cpp, | ||||
|                                         screen->back.map); | ||||
|          intel_set_span_functions(&backRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); | ||||
|       } | ||||
|  | ||||
|       if (mesaVis->depthBits == 16) { | ||||
|          driRenderbuffer *depthRb | ||||
|             = driNewRenderbuffer(GL_DEPTH_COMPONENT16, | ||||
|                                  screen->depth.map, | ||||
|                                  screen->cpp, | ||||
|                                  screen->depth.offset, screen->depth.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(depthRb, mesaVis); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); | ||||
|       if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { | ||||
|          /* combined depth/stencil buffer */ | ||||
|          struct intel_renderbuffer *depthStencilRb | ||||
|             = intel_create_renderbuffer( | ||||
|                                         GL_DEPTH24_STENCIL8_EXT, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->depth.offset, | ||||
|                                         screen->depth.pitch, | ||||
|                                         screen->cpp, /* 4! */ | ||||
|                                         screen->depth.map); | ||||
|          intel_set_span_functions(&depthStencilRb->Base); | ||||
|          /* note: bind RB to two attachment points */ | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); | ||||
|       } | ||||
|       else if (mesaVis->depthBits == 24) { | ||||
|          driRenderbuffer *depthRb | ||||
|             = driNewRenderbuffer(GL_DEPTH_COMPONENT24, | ||||
|                                  screen->depth.map, | ||||
|                                  screen->cpp, | ||||
|                                  screen->depth.offset, screen->depth.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(depthRb, mesaVis); | ||||
|       else if (mesaVis->depthBits == 16) { | ||||
|          /* just 16-bit depth buffer, no hw stencil */ | ||||
|          struct intel_renderbuffer *depthRb | ||||
|             = intel_create_renderbuffer(GL_DEPTH_COMPONENT16, | ||||
|                                         screen->width, screen->height, | ||||
|                                         screen->depth.offset, | ||||
|                                         screen->depth.pitch, | ||||
|                                         screen->cpp, /* 2! */ | ||||
|                                         screen->depth.map); | ||||
|          intel_set_span_functions(&depthRb->Base); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); | ||||
|       } | ||||
|  | ||||
|       if (mesaVis->stencilBits > 0 && !swStencil) { | ||||
|          driRenderbuffer *stencilRb | ||||
|             = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, | ||||
|                                  screen->depth.map, | ||||
|                                  screen->cpp, | ||||
|                                  screen->depth.offset, screen->depth.pitch, | ||||
|                                  driDrawPriv); | ||||
|          intelSetSpanFunctions(stencilRb, mesaVis); | ||||
|          _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); | ||||
|       } | ||||
|  | ||||
|       /* now add any/all software-based renderbuffers we may need */ | ||||
|       _mesa_add_soft_renderbuffers(fb, | ||||
|                                    GL_FALSE, /* color */ | ||||
|                                    GL_FALSE, /* depth */ | ||||
|                                    GL_FALSE, /* never sw color */ | ||||
|                                    GL_FALSE, /* never sw depth */ | ||||
|                                    swStencil, | ||||
|                                    mesaVis->accumRedBits > 0, | ||||
|                                    GL_FALSE, /* alpha */ | ||||
|                                    GL_FALSE /* aux */); | ||||
|                                    GL_FALSE, /* never sw alpha */ | ||||
|                                    GL_FALSE  /* never sw aux */); | ||||
|       driDrawPriv->driverPrivate = (void *) fb; | ||||
|  | ||||
|       return (driDrawPriv->driverPrivate != NULL); | ||||
| @@ -338,6 +351,8 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, | ||||
|    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; | ||||
|  | ||||
|    switch (intelScreen->deviceID) { | ||||
|       /* Don't deal with i830 until texture work complete: | ||||
|        */ | ||||
|    case PCI_CHIP_845_G: | ||||
|    case PCI_CHIP_I830_M: | ||||
|    case PCI_CHIP_I855_GM: | ||||
|   | ||||
| @@ -32,6 +32,9 @@ | ||||
| #include "dri_util.h" | ||||
| #include "xmlconfig.h" | ||||
|  | ||||
| /* XXX: change name or eliminate to avoid conflict with "struct | ||||
|  * intel_region"!!! | ||||
|  */ | ||||
| typedef struct { | ||||
|    drm_handle_t handle; | ||||
|    drmSize size;        /* region size in bytes */ | ||||
| @@ -54,7 +57,7 @@ typedef struct | ||||
|  | ||||
|    int cpp;         /* for front and back buffers */ | ||||
|    int bitsPerPixel;  /* unused */ | ||||
|    int fbFormat; | ||||
|    int fbFormat;  /* XXX FBO: this is obsolete - remove after i830 updates */ | ||||
|  | ||||
|    int logTextureGranularity; | ||||
|     | ||||
| @@ -84,7 +87,4 @@ intelMakeCurrent(__DRIcontextPrivate *driContextPriv, | ||||
|                 __DRIdrawablePrivate *driDrawPriv, | ||||
|                 __DRIdrawablePrivate *driReadPriv); | ||||
|  | ||||
| extern void | ||||
| intelSwapBuffers( __DRIdrawablePrivate *dPriv); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -30,194 +30,340 @@ | ||||
| #include "mtypes.h" | ||||
| #include "colormac.h" | ||||
|  | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_screen.h" | ||||
|  | ||||
| #include "intel_span.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_ioctl.h" | ||||
| #include "intel_tex.h" | ||||
|  | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| /* | ||||
|   break intelWriteRGBASpan_ARGB8888 | ||||
| */ | ||||
|  | ||||
| #undef DBG | ||||
| #define DBG 0 | ||||
|  | ||||
| #define LOCAL_VARS						\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch * drb->cpp;			\ | ||||
|    GLuint height = dPriv->h;					\ | ||||
|    char *buf = (char *) drb->Base.Data +			\ | ||||
| 			dPriv->x * drb->cpp +			\ | ||||
| 			dPriv->y * pitch;			\ | ||||
|    GLushort p;							\ | ||||
|    (void) buf; (void) p | ||||
| #define LOCAL_VARS							\ | ||||
|    struct intel_context *intel = intel_context(ctx);			\ | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb);		\ | ||||
|    const GLint yScale = irb->RenderToTexture ? 1 : -1;			\ | ||||
|    const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;	\ | ||||
|    GLubyte *buf = (GLubyte *) irb->pfMap				\ | ||||
|       + (intel->drawY * irb->pfPitch + intel->drawX) * irb->region->cpp;\ | ||||
|    GLuint p;								\ | ||||
|    assert(irb->pfMap);\ | ||||
|    (void) p; | ||||
|  | ||||
| #define LOCAL_DEPTH_VARS					\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch * drb->cpp;			\ | ||||
|    GLuint height = dPriv->h;					\ | ||||
|    char *buf = (char *) drb->Base.Data +			\ | ||||
| 			dPriv->x * drb->cpp +			\ | ||||
| 			dPriv->y * pitch | ||||
| /* XXX FBO: this is identical to the macro in spantmp2.h except we get | ||||
|  * the cliprect info from the context, not the driDrawable. | ||||
|  * Move this into spantmp2.h someday. | ||||
|  */ | ||||
| #define HW_CLIPLOOP()							\ | ||||
|    do {									\ | ||||
|       int _nc = intel->numClipRects;					\ | ||||
|       while ( _nc-- ) {							\ | ||||
| 	 int minx = intel->pClipRects[_nc].x1 - intel->drawX;		\ | ||||
| 	 int miny = intel->pClipRects[_nc].y1 - intel->drawY;		\ | ||||
| 	 int maxx = intel->pClipRects[_nc].x2 - intel->drawX;		\ | ||||
| 	 int maxy = intel->pClipRects[_nc].y2 - intel->drawY; | ||||
|  | ||||
| #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS  | ||||
|  | ||||
| #define INIT_MONO_PIXEL(p,color)\ | ||||
| 	 p = INTEL_PACKCOLOR565(color[0],color[1],color[2]) | ||||
|  | ||||
| #define Y_FLIP(_y) (height - _y - 1) | ||||
|  | ||||
| #define Y_FLIP(_y) ((_y) * yScale + yBias) | ||||
|  | ||||
| #define HW_LOCK() | ||||
|  | ||||
| #define HW_UNLOCK() | ||||
|  | ||||
| /* 16 bit, 565 rgb color spanline and pixel functions | ||||
| /* 16 bit, RGB565 color spanline and pixel functions | ||||
|  */ | ||||
| #define WRITE_RGBA( _x, _y, r, g, b, a )				\ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch)  = ( (((int)r & 0xf8) << 8) |	\ | ||||
| 		                             (((int)g & 0xfc) << 3) |	\ | ||||
| 		                             (((int)b & 0xf8) >> 3)) | ||||
| #define WRITE_PIXEL( _x, _y, p )  \ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch) = p | ||||
| #define SPANTMP_PIXEL_FMT GL_RGB | ||||
| #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5 | ||||
|  | ||||
| #define READ_RGBA( rgba, _x, _y )				\ | ||||
| do {								\ | ||||
|    GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch);		\ | ||||
|    rgba[0] = (((p >> 11) & 0x1f) * 255) / 31;			\ | ||||
|    rgba[1] = (((p >>  5) & 0x3f) * 255) / 63;			\ | ||||
|    rgba[2] = (((p >>  0) & 0x1f) * 255) / 31;			\ | ||||
|    rgba[3] = 255;						\ | ||||
| } while(0) | ||||
| #define TAG(x)    intel##x##_RGB565 | ||||
| #define TAG2(x,y) intel##x##_RGB565##y | ||||
| #define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 2) | ||||
| #include "spantmp2.h" | ||||
|  | ||||
| #define TAG(x) intel##x##_565 | ||||
| #include "spantmp.h" | ||||
|  | ||||
| /* 15 bit, 555 rgb color spanline and pixel functions | ||||
| /* 32 bit, ARGB8888 color spanline and pixel functions | ||||
|  */ | ||||
| #define WRITE_RGBA( _x, _y, r, g, b, a )			\ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch)  = (((r & 0xf8) << 7) |	\ | ||||
| 		                            ((g & 0xf8) << 3) |	\ | ||||
|                          		    ((b & 0xf8) >> 3)) | ||||
| #define SPANTMP_PIXEL_FMT GL_BGRA | ||||
| #define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV | ||||
|  | ||||
| #define WRITE_PIXEL( _x, _y, p )  \ | ||||
|    *(GLushort *)(buf + _x*2 + _y*pitch)  = p | ||||
| #define TAG(x)    intel##x##_ARGB8888 | ||||
| #define TAG2(x,y) intel##x##_ARGB8888##y | ||||
| #define GET_PTR(X,Y) (buf + ((Y) * irb->pfPitch + (X)) * 4) | ||||
| #include "spantmp2.h" | ||||
|  | ||||
| #define READ_RGBA( rgba, _x, _y )				\ | ||||
| do {								\ | ||||
|    GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch);		\ | ||||
|    rgba[0] = (p >> 7) & 0xf8;					\ | ||||
|    rgba[1] = (p >> 3) & 0xf8;					\ | ||||
|    rgba[2] = (p << 3) & 0xf8;					\ | ||||
|    rgba[3] = 255;						\ | ||||
| } while(0) | ||||
|  | ||||
| #define TAG(x) intel##x##_555 | ||||
| #include "spantmp.h" | ||||
| #define LOCAL_DEPTH_VARS						\ | ||||
|    struct intel_context *intel = intel_context(ctx);			\ | ||||
|    struct intel_renderbuffer *irb = intel_renderbuffer(rb);		\ | ||||
|    const GLuint pitch = irb->pfPitch/***XXX region->pitch*/; /* in pixels */ \ | ||||
|    const GLint yScale = irb->RenderToTexture ? 1 : -1;			\ | ||||
|    const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;	\ | ||||
|    char *buf = (char *) irb->pfMap/*XXX use region->map*/ +             \ | ||||
|       (intel->drawY * pitch + intel->drawX) * irb->region->cpp; | ||||
|  | ||||
| /* 16 bit depthbuffer functions. | ||||
|  */ | ||||
|  | ||||
| #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS  | ||||
|  | ||||
| /** | ||||
|  ** 16-bit depthbuffer functions. | ||||
|  **/ | ||||
| #define WRITE_DEPTH( _x, _y, d ) \ | ||||
|    *(GLushort *)(buf + (_x)*2 + (_y)*pitch)  = d; | ||||
|    ((GLushort *)buf)[(_x) + (_y) * pitch] = d; | ||||
|  | ||||
| #define READ_DEPTH( d, _x, _y )	\ | ||||
|    d = *(GLushort *)(buf + (_x)*2 + (_y)*pitch);	  | ||||
|    d = ((GLushort *)buf)[(_x) + (_y) * pitch]; | ||||
|  | ||||
|  | ||||
| #define TAG(x) intel##x##_z16 | ||||
| #include "depthtmp.h" | ||||
|  | ||||
|  | ||||
| #undef LOCAL_VARS | ||||
| #define LOCAL_VARS						\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|    __DRIdrawablePrivate *dPriv = intel->driDrawable;		\ | ||||
|    driRenderbuffer *drb = (driRenderbuffer *) rb;		\ | ||||
|    GLuint pitch = drb->pitch * drb->cpp;			\ | ||||
|    GLuint height = dPriv->h;					\ | ||||
|    char *buf = (char *)drb->Base.Data +				\ | ||||
| 			dPriv->x * drb->cpp +			\ | ||||
| 			dPriv->y * pitch;			\ | ||||
|    GLuint p;							\ | ||||
|    (void) buf; (void) p | ||||
|  | ||||
| #undef INIT_MONO_PIXEL | ||||
| #define INIT_MONO_PIXEL(p,color)\ | ||||
| 	 p = INTEL_PACKCOLOR8888(color[0],color[1],color[2],color[3]) | ||||
|  | ||||
| /* 32 bit, 8888 argb color spanline and pixel functions | ||||
|  */ | ||||
| #define WRITE_RGBA(_x, _y, r, g, b, a)			\ | ||||
|     *(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) |	\ | ||||
| 					  (g << 8)  |	\ | ||||
| 					  (b << 0)  |	\ | ||||
| 					  (a << 24) ) | ||||
|  | ||||
| #define WRITE_PIXEL(_x, _y, p)			\ | ||||
|     *(GLuint *)(buf + _x*4 + _y*pitch) = p | ||||
|  | ||||
|  | ||||
| #define READ_RGBA(rgba, _x, _y)					\ | ||||
|     do {							\ | ||||
| 	GLuint p = *(GLuint *)(buf + _x*4 + _y*pitch);		\ | ||||
| 	rgba[0] = (p >> 16) & 0xff;				\ | ||||
| 	rgba[1] = (p >> 8)  & 0xff;				\ | ||||
| 	rgba[2] = (p >> 0)  & 0xff;				\ | ||||
| 	rgba[3] = (p >> 24) & 0xff;				\ | ||||
|     } while (0) | ||||
|  | ||||
| #define TAG(x) intel##x##_8888 | ||||
| #include "spantmp.h" | ||||
|  | ||||
|  | ||||
| /* 24/8 bit interleaved depth/stencil functions | ||||
|  */ | ||||
| #define WRITE_DEPTH( _x, _y, d ) {			\ | ||||
|    GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch);	\ | ||||
|    tmp &= 0xff000000;					\ | ||||
|    tmp |= (d) & 0xffffff;				\ | ||||
|    *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp;		\ | ||||
| /** | ||||
|  ** 24/8-bit interleaved depth/stencil functions | ||||
|  ** Note: we're actually reading back combined depth+stencil values. | ||||
|  ** The wrappers in main/depthstencil.c are used to extract the depth | ||||
|  ** and stencil values. | ||||
|  **/ | ||||
| /* Change ZZZS -> SZZZ */ | ||||
| #define WRITE_DEPTH( _x, _y, d ) {				\ | ||||
|    GLuint tmp = ((d) >> 8) | ((d) << 24);			\ | ||||
|    ((GLuint *)buf)[(_x) + (_y) * pitch] = tmp;			\ | ||||
| } | ||||
|  | ||||
| #define READ_DEPTH( d, _x, _y )		\ | ||||
|    d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) & 0xffffff; | ||||
|  | ||||
| /* Change SZZZ -> ZZZS */ | ||||
| #define READ_DEPTH( d, _x, _y ) {				\ | ||||
|    GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch];		\ | ||||
|    d = (tmp << 8) | (tmp >> 24);				\ | ||||
| } | ||||
|  | ||||
| #define TAG(x) intel##x##_z24_s8 | ||||
| #include "depthtmp.h" | ||||
|  | ||||
| #define WRITE_STENCIL( _x, _y, d ) {			\ | ||||
|    GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch);	\ | ||||
|    tmp &= 0xffffff;					\ | ||||
|    tmp |= ((d)<<24);					\ | ||||
|    *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp;		\ | ||||
|  | ||||
| /** | ||||
|  ** 8-bit stencil function (XXX FBO: This is obsolete) | ||||
|  **/ | ||||
| #define WRITE_STENCIL( _x, _y, d ) {				\ | ||||
|    GLuint tmp = ((GLuint *)buf)[(_x) + (_y) * pitch];		\ | ||||
|    tmp &= 0xffffff;						\ | ||||
|    tmp |= ((d) << 24);						\ | ||||
|    ((GLuint *) buf)[(_x) + (_y) * pitch] = tmp;			\ | ||||
| } | ||||
|  | ||||
| #define READ_STENCIL( d, _x, _y )			\ | ||||
|    d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch) >> 24; | ||||
| #define READ_STENCIL( d, _x, _y )				\ | ||||
|    d = ((GLuint *)buf)[(_x) + (_y) * pitch] >> 24; | ||||
|  | ||||
| #define TAG(x) intel##x##_z24_s8 | ||||
| #include "stenciltmp.h" | ||||
|  | ||||
|  | ||||
| /* Move locking out to get reasonable span performance. | ||||
|  | ||||
| /** | ||||
|  * Map or unmap all the renderbuffers which we may need during | ||||
|  * software rendering. | ||||
|  * XXX in the future, we could probably convey extra information to | ||||
|  * reduce the number of mappings needed.  I.e. if doing a glReadPixels | ||||
|  * from the depth buffer, we really only need one mapping. | ||||
|  * | ||||
|  * XXX Rewrite this function someday. | ||||
|  * We can probably just loop over all the renderbuffer attachments, | ||||
|  * map/unmap all of them, and not worry about the _ColorDrawBuffers | ||||
|  * _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields. | ||||
|  */ | ||||
| static void | ||||
| intel_map_unmap_buffers(struct intel_context *intel, GLboolean map) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLuint i, j; | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    /* color draw buffers */ | ||||
|    for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { | ||||
|       for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers[i]; j++) { | ||||
|          struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i][j]; | ||||
|          irb = intel_renderbuffer(rb); | ||||
|          if (irb) { | ||||
|             /* this is a user-created intel_renderbuffer */ | ||||
|             if (irb->region) { | ||||
|                if (map) | ||||
|                   intel_region_map(intel, irb->region); | ||||
|                else | ||||
|                   intel_region_unmap(intel, irb->region); | ||||
|             } | ||||
|             irb->pfMap = irb->region->map; | ||||
|             irb->pfPitch = irb->region->pitch; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* check for render to textures */ | ||||
|    for (i = 0; i < BUFFER_COUNT; i++) { | ||||
|       struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment + i; | ||||
|       struct gl_texture_object *tex = att->Texture; | ||||
|       if (tex) { | ||||
|          /* render to texture */ | ||||
|          ASSERT(att->Renderbuffer); | ||||
|          if (map) { | ||||
|             struct gl_texture_image *texImg; | ||||
|             texImg = tex->Image[att->CubeMapFace][att->TextureLevel]; | ||||
|             intel_tex_map_images(intel, intel_texture_object(tex)); | ||||
|          } | ||||
|          else { | ||||
|             intel_tex_unmap_images(intel, intel_texture_object(tex)); | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* color read buffers */ | ||||
|    irb = intel_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); | ||||
|    if (irb && irb->region) { | ||||
|       if (map) | ||||
|          intel_region_map(intel, irb->region); | ||||
|       else | ||||
|          intel_region_unmap(intel, irb->region); | ||||
|       irb->pfMap = irb->region->map; | ||||
|       irb->pfPitch = irb->region->pitch; | ||||
|    } | ||||
|  | ||||
|    /* Account for front/back color page flipping. | ||||
|     * The span routines use the pfMap and pfPitch fields which will | ||||
|     * swap the front/back region map/pitch if we're page flipped. | ||||
|     * Do this after mapping, above, so the map field is valid. | ||||
|     */ | ||||
| #if 0 | ||||
|    if (map && ctx->DrawBuffer->Name == 0) { | ||||
|       struct intel_renderbuffer *irbFront | ||||
|          = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_FRONT_LEFT); | ||||
|       struct intel_renderbuffer *irbBack | ||||
|          = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_BACK_LEFT); | ||||
|       if (irbBack) { | ||||
|          /* double buffered */ | ||||
|          if (intel->sarea->pf_current_page == 0) { | ||||
|             irbFront->pfMap = irbFront->region->map; | ||||
|             irbFront->pfPitch = irbFront->region->pitch; | ||||
|             irbBack->pfMap = irbBack->region->map; | ||||
|             irbBack->pfPitch = irbBack->region->pitch; | ||||
|          } | ||||
|          else { | ||||
|             irbFront->pfMap = irbBack->region->map; | ||||
|             irbFront->pfPitch = irbBack->region->pitch; | ||||
|             irbBack->pfMap = irbFront->region->map; | ||||
|             irbBack->pfPitch = irbFront->region->pitch; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    /* depth buffer (Note wrapper!) */ | ||||
|    if (ctx->DrawBuffer->_DepthBuffer) { | ||||
|       irb = intel_renderbuffer(ctx->DrawBuffer->_DepthBuffer->Wrapped); | ||||
|       if (irb && irb->region && irb->Base.Name != 0) { | ||||
|          if (map) { | ||||
|             intel_region_map(intel, irb->region); | ||||
|             irb->pfMap = irb->region->map; | ||||
|             irb->pfPitch = irb->region->pitch; | ||||
|          } | ||||
|          else { | ||||
|             intel_region_unmap(intel, irb->region); | ||||
|             irb->pfMap = NULL; | ||||
|             irb->pfPitch = 0; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* stencil buffer (Note wrapper!) */ | ||||
|    if (ctx->DrawBuffer->_StencilBuffer) { | ||||
|       irb = intel_renderbuffer(ctx->DrawBuffer->_StencilBuffer->Wrapped); | ||||
|       if (irb && irb->region && irb->Base.Name != 0) { | ||||
|          if (map) { | ||||
|             intel_region_map(intel, irb->region); | ||||
|             irb->pfMap = irb->region->map; | ||||
|             irb->pfPitch = irb->region->pitch; | ||||
|          } | ||||
|          else { | ||||
|             intel_region_unmap(intel, irb->region); | ||||
|             irb->pfMap = NULL; | ||||
|             irb->pfPitch = 0; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Prepare for softare rendering.  Map current read/draw framebuffers' | ||||
|  * renderbuffes and all currently bound texture objects. | ||||
|  * | ||||
|  * Old note: Moved locking out to get reasonable span performance. | ||||
|  */ | ||||
| void intelSpanRenderStart( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint i; | ||||
|  | ||||
|    intelFlush(&intel->ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    intelWaitForIdle(intel); | ||||
|  | ||||
| #if 0 | ||||
|    /* Just map the framebuffer and all textures.  Bufmgr code will | ||||
|     * take care of waiting on the necessary fences: | ||||
|     */ | ||||
|    intel_region_map(intel, intel->front_region); | ||||
|    intel_region_map(intel, intel->back_region); | ||||
|    intel_region_map(intel, intel->depth_region); | ||||
| #endif | ||||
|  | ||||
|    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { | ||||
|       if (ctx->Texture.Unit[i]._ReallyEnabled) { | ||||
| 	 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current; | ||||
| 	 intel_tex_map_images(intel, intel_texture_object(texObj)); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intel_map_unmap_buffers(intel, GL_TRUE); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Called when done softare rendering.  Unmap the buffers we mapped in | ||||
|  * the above function. | ||||
|  */ | ||||
| void intelSpanRenderFinish( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    GLuint i; | ||||
|  | ||||
|    _swrast_flush( ctx ); | ||||
|  | ||||
|    /* Now unmap the framebuffer: | ||||
|     */ | ||||
| #if 0 | ||||
|    intel_region_unmap(intel, intel->front_region); | ||||
|    intel_region_unmap(intel, intel->back_region); | ||||
|    intel_region_unmap(intel, intel->depth_region); | ||||
| #endif | ||||
|  | ||||
|    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { | ||||
|       if (ctx->Texture.Unit[i]._ReallyEnabled) { | ||||
| 	 struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current; | ||||
| 	 intel_tex_unmap_images(intel, intel_texture_object(texObj)); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    intel_map_unmap_buffers(intel, GL_FALSE); | ||||
|  | ||||
|    UNLOCK_HARDWARE( intel ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitSpanFuncs( GLcontext *ctx ) | ||||
| { | ||||
|    struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); | ||||
| @@ -227,32 +373,31 @@ void intelInitSpanFuncs( GLcontext *ctx ) | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Plug in the Get/Put routines for the given driRenderbuffer. | ||||
|  * Plug in appropriate span read/write functions for the given renderbuffer. | ||||
|  * These are used for the software fallbacks. | ||||
|  */ | ||||
| void | ||||
| intelSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) | ||||
| intel_set_span_functions(struct gl_renderbuffer *rb) | ||||
| { | ||||
|    if (drb->Base.InternalFormat == GL_RGBA) { | ||||
|       if (vis->redBits == 5 && vis->greenBits == 5 && vis->blueBits == 5) { | ||||
|          intelInitPointers_555(&drb->Base); | ||||
|       } | ||||
|       else if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { | ||||
|          intelInitPointers_565(&drb->Base); | ||||
|       } | ||||
|       else { | ||||
|          assert(vis->redBits == 8); | ||||
|          assert(vis->greenBits == 8); | ||||
|          assert(vis->blueBits == 8); | ||||
|          intelInitPointers_8888(&drb->Base); | ||||
|       } | ||||
|    if (rb->_ActualFormat == GL_RGB5) { | ||||
|       /* 565 RGB */ | ||||
|       intelInitPointers_RGB565(rb); | ||||
|    } | ||||
|    else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) { | ||||
|       intelInitDepthPointers_z16(&drb->Base); | ||||
|    else if (rb->_ActualFormat == GL_RGBA8) { | ||||
|       /* 8888 RGBA */ | ||||
|       intelInitPointers_ARGB8888(rb); | ||||
|    } | ||||
|    else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) { | ||||
|       intelInitDepthPointers_z24_s8(&drb->Base); | ||||
|    else if (rb->_ActualFormat == GL_DEPTH_COMPONENT16) { | ||||
|       intelInitDepthPointers_z16(rb); | ||||
|    } | ||||
|    else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) { | ||||
|       intelInitStencilPointers_z24_s8(&drb->Base); | ||||
|    else if (rb->_ActualFormat == GL_DEPTH_COMPONENT24 || /* XXX FBO remove */ | ||||
|             rb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) { | ||||
|       intelInitDepthPointers_z24_s8(rb); | ||||
|    } | ||||
|    else if (rb->_ActualFormat == GL_STENCIL_INDEX8_EXT) { /* XXX FBO remove */ | ||||
|       intelInitStencilPointers_z24_s8(rb); | ||||
|    } | ||||
|    else { | ||||
|       _mesa_problem(NULL, "Unexpected _ActualFormat in intelSetSpanFunctions"); | ||||
|    } | ||||
| } | ||||
|   | ||||
| @@ -28,14 +28,12 @@ | ||||
| #ifndef _INTEL_SPAN_H | ||||
| #define _INTEL_SPAN_H | ||||
|  | ||||
| #include "drirenderbuffer.h" | ||||
|  | ||||
| extern void intelInitSpanFuncs( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelSpanRenderFinish( GLcontext *ctx ); | ||||
| extern void intelSpanRenderStart( GLcontext *ctx ); | ||||
|  | ||||
| extern void | ||||
| intelSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis); | ||||
| intel_set_span_functions(struct gl_renderbuffer *rb); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -30,10 +30,13 @@ | ||||
| #include "context.h" | ||||
| #include "macros.h" | ||||
| #include "enums.h" | ||||
| #include "colormac.h" | ||||
| #include "dd.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_regions.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| int intel_translate_compare_func( GLenum func ) | ||||
| @@ -164,86 +167,67 @@ int intel_translate_logic_op( GLenum opcode ) | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelDrawBuffer(GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    int front = 0; | ||||
|   | ||||
|    if (!ctx->DrawBuffer) | ||||
|       return; | ||||
|  | ||||
|    switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) { | ||||
|    case BUFFER_BIT_FRONT_LEFT: | ||||
|       front = 1; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    case BUFFER_BIT_BACK_LEFT: | ||||
|       front = 0; | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE ); | ||||
|       break; | ||||
|    default: | ||||
|       FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE ); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if ( intel->sarea->pf_current_page == 1 )  | ||||
|       front ^= 1; | ||||
|     | ||||
|    intelSetFrontClipRects( intel ); | ||||
|  | ||||
|    if (front) { | ||||
|       intel->drawOffset = screen->front.offset; | ||||
|    } else { | ||||
|       intel->drawOffset = screen->back.offset; | ||||
|    } | ||||
|  | ||||
|    intel->vtbl.set_draw_offset( intel, intel->drawOffset ); | ||||
| } | ||||
|  | ||||
| static void intelReadBuffer( GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelClearColor(GLcontext *ctx, const GLfloat color[4]) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    intelScreenPrivate *screen = intel->intelScreen; | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLubyte clear[4]; | ||||
|  | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_red, color[0]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_green, color[1]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_blue, color[2]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(intel->clear_alpha, color[3]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[0], color[0]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[1], color[1]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[2], color[2]); | ||||
|    CLAMPED_FLOAT_TO_UBYTE(clear[3], color[3]); | ||||
|  | ||||
|    intel->ClearColor = INTEL_PACKCOLOR(screen->fbFormat, | ||||
| 				       intel->clear_red,  | ||||
| 				       intel->clear_green,  | ||||
| 				       intel->clear_blue,  | ||||
| 				       intel->clear_alpha); | ||||
|    /* compute both 32 and 16-bit clear values */ | ||||
|    intel->ClearColor8888 = INTEL_PACKCOLOR8888(clear[0], clear[1], | ||||
|                                                clear[2], clear[3]); | ||||
|    intel->ClearColor565 = INTEL_PACKCOLOR565(clear[0], clear[1], clear[2]); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Update the viewport transformation matrix.  Depends on: | ||||
|  *  - viewport pos/size | ||||
|  *  - depthrange | ||||
|  *  - window pos/size or FBO size | ||||
|  */ | ||||
| static void intelCalcViewport( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    const GLfloat *v = ctx->Viewport._WindowMap.m; | ||||
|    const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; | ||||
|    GLfloat *m = intel->ViewportMatrix.m; | ||||
|    GLint h = 0; | ||||
|    GLfloat yScale, yBias; | ||||
|  | ||||
|    if (intel->driDrawable)  | ||||
|       h = intel->driDrawable->h + SUBPIXEL_Y; | ||||
|    if (ctx->DrawBuffer->Name) { | ||||
|       /* User created FBO */ | ||||
|       struct intel_renderbuffer *irb | ||||
|          = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]); | ||||
|       if (irb && !irb->RenderToTexture) { | ||||
|          /* y=0=top */ | ||||
|          yScale = -1.0; | ||||
|          yBias = irb->Base.Height; | ||||
|       } | ||||
|       else { | ||||
|          /* y=0=bottom */ | ||||
|          yScale = 1.0; | ||||
|          yBias = 0.0; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       /* window buffer, y=0=top */ | ||||
|       yScale = -1.0; | ||||
|       yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F; | ||||
|    } | ||||
|  | ||||
|    /* See also intel_translate_vertex.  SUBPIXEL adjustments can be done | ||||
|     * via state vars, too. | ||||
|     */ | ||||
|    m[MAT_SX] =   v[MAT_SX]; | ||||
|    m[MAT_TX] =   v[MAT_TX] + SUBPIXEL_X; | ||||
|    m[MAT_SY] = - v[MAT_SY]; | ||||
|    m[MAT_TY] = - v[MAT_TY] + h; | ||||
|    m[MAT_SZ] =   v[MAT_SZ] * intel->depth_scale; | ||||
|    m[MAT_TZ] =   v[MAT_TZ] * intel->depth_scale; | ||||
|    m[MAT_SX] = v[MAT_SX]; | ||||
|    m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X; | ||||
|  | ||||
|    m[MAT_SY] = v[MAT_SY] * yScale; | ||||
|    m[MAT_TY] = v[MAT_TY] * yScale + yBias + SUBPIXEL_Y; | ||||
|  | ||||
|    m[MAT_SZ] = v[MAT_SZ] * depthScale; | ||||
|    m[MAT_TZ] = v[MAT_TZ] * depthScale; | ||||
| } | ||||
|  | ||||
| static void intelViewport( GLcontext *ctx, | ||||
| @@ -263,18 +247,112 @@ static void intelDepthRange( GLcontext *ctx, | ||||
|  */ | ||||
| static void intelRenderMode( GLcontext *ctx, GLenum mode ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    FALLBACK( intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER) ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitStateFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->DrawBuffer = intelDrawBuffer; | ||||
|    functions->ReadBuffer = intelReadBuffer; | ||||
|    functions->RenderMode = intelRenderMode; | ||||
|    functions->Viewport = intelViewport; | ||||
|    functions->DepthRange = intelDepthRange; | ||||
|    functions->ClearColor = intelClearColor; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelInitState( GLcontext *ctx ) | ||||
| { | ||||
|    /* Mesa should do this for us: | ||||
|     */ | ||||
|    ctx->Driver.AlphaFunc( ctx,  | ||||
| 			  ctx->Color.AlphaFunc, | ||||
| 			  ctx->Color.AlphaRef); | ||||
|  | ||||
|    ctx->Driver.BlendColor( ctx, | ||||
| 			   ctx->Color.BlendColor ); | ||||
|  | ||||
|    ctx->Driver.BlendEquationSeparate( ctx,  | ||||
| 				      ctx->Color.BlendEquationRGB, | ||||
| 				      ctx->Color.BlendEquationA); | ||||
|  | ||||
|    ctx->Driver.BlendFuncSeparate( ctx, | ||||
| 				  ctx->Color.BlendSrcRGB, | ||||
| 				  ctx->Color.BlendDstRGB, | ||||
| 				  ctx->Color.BlendSrcA, | ||||
| 				  ctx->Color.BlendDstA); | ||||
|  | ||||
|    ctx->Driver.ColorMask( ctx,  | ||||
| 			  ctx->Color.ColorMask[RCOMP], | ||||
| 			  ctx->Color.ColorMask[GCOMP], | ||||
| 			  ctx->Color.ColorMask[BCOMP], | ||||
| 			  ctx->Color.ColorMask[ACOMP]); | ||||
|  | ||||
|    ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode ); | ||||
|    ctx->Driver.DepthFunc( ctx, ctx->Depth.Func ); | ||||
|    ctx->Driver.DepthMask( ctx, ctx->Depth.Mask ); | ||||
|  | ||||
|    ctx->Driver.Enable( ctx, GL_ALPHA_TEST, ctx->Color.AlphaEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_BLEND, ctx->Color.BlendEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_LOGIC_OP, ctx->Color.ColorLogicOpEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_COLOR_SUM, ctx->Fog.ColorSumEnabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_CULL_FACE, ctx->Polygon.CullFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_DEPTH_TEST, ctx->Depth.Test ); | ||||
|    ctx->Driver.Enable( ctx, GL_DITHER, ctx->Color.DitherFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_FOG, ctx->Fog.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LIGHTING, ctx->Light.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_POLYGON_STIPPLE, ctx->Polygon.StippleFlag ); | ||||
|    ctx->Driver.Enable( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_1D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_2D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_RECTANGLE_NV, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_3D, GL_FALSE ); | ||||
|    ctx->Driver.Enable( ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE ); | ||||
|  | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); | ||||
|    ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); | ||||
|  | ||||
|    ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace ); | ||||
|  | ||||
|    { | ||||
|       GLfloat f = (GLfloat)ctx->Light.Model.ColorControl; | ||||
|       ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_COLOR_CONTROL, &f ); | ||||
|    } | ||||
|  | ||||
|    ctx->Driver.LineWidth( ctx, ctx->Line.Width ); | ||||
|    ctx->Driver.LogicOpcode( ctx, ctx->Color.LogicOp ); | ||||
|    ctx->Driver.PointSize( ctx, ctx->Point.Size ); | ||||
|    ctx->Driver.PolygonStipple( ctx, (const GLubyte *)ctx->PolygonStipple ); | ||||
|    ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y, | ||||
| 			ctx->Scissor.Width, ctx->Scissor.Height ); | ||||
|    ctx->Driver.ShadeModel( ctx, ctx->Light.ShadeModel ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_FRONT, | ||||
|                                     ctx->Stencil.Function[0], | ||||
|                                     ctx->Stencil.Ref[0], | ||||
|                                     ctx->Stencil.ValueMask[0] ); | ||||
|    ctx->Driver.StencilFuncSeparate( ctx, GL_BACK, | ||||
|                                     ctx->Stencil.Function[1], | ||||
|                                     ctx->Stencil.Ref[1], | ||||
|                                     ctx->Stencil.ValueMask[1] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_FRONT, ctx->Stencil.WriteMask[0] ); | ||||
|    ctx->Driver.StencilMaskSeparate( ctx, GL_BACK, ctx->Stencil.WriteMask[1] ); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_FRONT, | ||||
|                                   ctx->Stencil.FailFunc[0], | ||||
|                                   ctx->Stencil.ZFailFunc[0], | ||||
|                                   ctx->Stencil.ZPassFunc[0]); | ||||
|    ctx->Driver.StencilOpSeparate( ctx, GL_BACK, | ||||
|                                   ctx->Stencil.FailFunc[1], | ||||
|                                   ctx->Stencil.ZFailFunc[1], | ||||
|                                   ctx->Stencil.ZPassFunc[1]); | ||||
|  | ||||
|  | ||||
|    /* XXX this isn't really needed */ | ||||
|    ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] ); | ||||
| } | ||||
|   | ||||
| @@ -1,830 +1,163 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "mtypes.h" | ||||
| #include "imports.h" | ||||
| #include "macros.h" | ||||
| #include "simple_list.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "texstore.h" | ||||
| #include "texformat.h" | ||||
| #include "teximage.h" | ||||
| #include "texmem.h" | ||||
| #include "texobj.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "mm.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLboolean | ||||
| intelValidateClientStorage( intelContextPtr intel, GLenum target, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint srcWidth, GLint srcHeight,  | ||||
| 			    GLenum format, GLenum type,  const void *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage) | ||||
|  | ||||
| static GLboolean intelIsTextureResident(GLcontext *ctx, | ||||
|                                       struct gl_texture_object *texObj) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    int texelBytes; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "intformat %s format %s type %s\n", | ||||
| 	      _mesa_lookup_enum_by_nr( internalFormat ), | ||||
| 	      _mesa_lookup_enum_by_nr( format ), | ||||
| 	      _mesa_lookup_enum_by_nr( type )); | ||||
|  | ||||
|    if (!ctx->Unpack.ClientStorage) | ||||
|       return 0; | ||||
|  | ||||
|    if (ctx->_ImageTransferState || | ||||
|        texImage->IsCompressed || | ||||
|        texObj->GenerateMipmap) | ||||
|       return 0; | ||||
|  | ||||
|  | ||||
|    /* This list is incomplete | ||||
|     */ | ||||
|    switch ( internalFormat ) { | ||||
|    case GL_RGBA: | ||||
|       if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_argb8888; | ||||
| 	 texelBytes = 4; | ||||
|       } | ||||
|       else | ||||
| 	 return 0; | ||||
|       break; | ||||
|  | ||||
|    case GL_RGB: | ||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_rgb565; | ||||
| 	 texelBytes = 2; | ||||
|       } | ||||
|       else | ||||
| 	 return 0; | ||||
|       break; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if ( format == GL_YCBCR_MESA &&  | ||||
| 	   type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_ycbcr_rev; | ||||
| 	 texelBytes = 2; | ||||
|       } | ||||
|       else if ( format == GL_YCBCR_MESA &&  | ||||
| 		(type == GL_UNSIGNED_SHORT_8_8_APPLE ||  | ||||
| 		 type == GL_UNSIGNED_BYTE)) { | ||||
| 	 texImage->TexFormat = &_mesa_texformat_ycbcr; | ||||
| 	 texelBytes = 2; | ||||
|       } | ||||
|       else | ||||
| 	 return 0; | ||||
|       break; | ||||
|        | ||||
| 	  | ||||
|    default: | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    /* Could deal with these packing issues, but currently don't: | ||||
|     */ | ||||
|    if (packing->SkipPixels ||  | ||||
|        packing->SkipRows ||  | ||||
|        packing->SwapBytes || | ||||
|        packing->LsbFirst) { | ||||
|       return 0; | ||||
|    } | ||||
|  | ||||
|    {       | ||||
|       GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, | ||||
| 						  format, type); | ||||
|  | ||||
|        | ||||
|       if (0) | ||||
| 	 fprintf(stderr, "%s: srcRowStride %d/%x\n",  | ||||
| 		 __FUNCTION__, srcRowStride, srcRowStride); | ||||
|  | ||||
|       /* Could check this later in upload, pitch restrictions could be | ||||
|        * relaxed, but would need to store the image pitch somewhere, | ||||
|        * as packing details might change before image is uploaded: | ||||
|        */ | ||||
|       if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) || | ||||
| 	  (srcRowStride & 63)) | ||||
| 	 return 0; | ||||
|  | ||||
|  | ||||
|       /* Have validated that _mesa_transfer_teximage would be a straight | ||||
|        * memcpy at this point.  NOTE: future calls to TexSubImage will | ||||
|        * overwrite the client data.  This is explicitly mentioned in the | ||||
|        * extension spec. | ||||
|        */ | ||||
|       texImage->Data = (void *)pixels; | ||||
|       texImage->IsClientData = GL_TRUE; | ||||
|       texImage->RowStride = srcRowStride / texelBytes; | ||||
|       return 1; | ||||
|    } | ||||
| } | ||||
|  | ||||
|   | ||||
|  | ||||
| static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint width, GLint border, | ||||
| 			    GLenum format, GLenum type, const GLvoid *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|  | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    _mesa_store_teximage1d( ctx, target, level, internalFormat, | ||||
| 			   width, border, format, type, | ||||
| 			   pixels, packing, texObj, texImage ); | ||||
|  | ||||
|    t->dirty_images[0] |= (1 << level); | ||||
| } | ||||
|  | ||||
| static void intelTexSubImage1D( GLcontext *ctx,  | ||||
| 			       GLenum target, | ||||
| 			       GLint level,	 | ||||
| 			       GLint xoffset, | ||||
| 				GLsizei width, | ||||
| 			       GLenum format, GLenum type, | ||||
| 			       const GLvoid *pixels, | ||||
| 			       const struct gl_pixelstore_attrib *packing, | ||||
| 			       struct gl_texture_object *texObj, | ||||
| 			       struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|  | ||||
|    _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,  | ||||
| 			     format, type, pixels, packing, texObj, | ||||
| 			     texImage); | ||||
| #if 0 | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(texObj); | ||||
|     | ||||
|    return  | ||||
|       intelObj->mt &&  | ||||
|       intelObj->mt->region &&  | ||||
|       intel_is_region_resident(intel, intelObj->mt->region); | ||||
| #endif | ||||
|    return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Handles 2D, CUBE, RECT: | ||||
|  | ||||
| static struct gl_texture_image *intelNewTextureImage( GLcontext *ctx ) | ||||
| { | ||||
|    (void) ctx; | ||||
|    return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image); | ||||
| } | ||||
|  | ||||
|  | ||||
| static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx,  | ||||
| 							GLuint name,  | ||||
| 							GLenum target ) | ||||
| { | ||||
|    struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); | ||||
|  | ||||
|    _mesa_initialize_texture_object(&obj->base, name, target); | ||||
|  | ||||
|    return &obj->base; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelFreeTextureImageData( GLcontext *ctx,  | ||||
| 				     struct gl_texture_image *texImage ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|    } | ||||
|     | ||||
|    if (texImage->Data) { | ||||
|       free(texImage->Data); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifndef __x86_64__ | ||||
| static unsigned | ||||
| fastrdtsc(void) | ||||
| { | ||||
|     unsigned eax; | ||||
|     __asm__ volatile ("\t" | ||||
| 	"pushl  %%ebx\n\t" | ||||
| 	"cpuid\n\t" ".byte 0x0f, 0x31\n\t" "popl %%ebx\n":"=a" (eax) | ||||
| 	:"0"(0) | ||||
| 	:"ecx", "edx", "cc"); | ||||
|  | ||||
|     return eax; | ||||
| } | ||||
| #else | ||||
| static unsigned | ||||
| fastrdtsc(void) | ||||
| { | ||||
|     unsigned eax; | ||||
|     __asm__ volatile ("\t" | ||||
| 	"cpuid\n\t" ".byte 0x0f, 0x31\n\t" :"=a" (eax) | ||||
| 	:"0"(0) | ||||
| 		      :"ecx", "edx", "ebx", "cc"); | ||||
|  | ||||
|     return eax; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static unsigned | ||||
| time_diff(unsigned t, unsigned t2) | ||||
| { | ||||
|     return ((t < t2) ? t2 - t : 0xFFFFFFFFU - (t - t2 - 1)); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* The system memcpy (at least on ubuntu 5.10) has problems copying | ||||
|  * to agp (writecombined) memory from a source which isn't 64-byte | ||||
|  * aligned - there is a 4x performance falloff. | ||||
|  * | ||||
|  * The x86 __memcpy is immune to this but is slightly slower | ||||
|  * (10%-ish) than the system memcpy. | ||||
|  * | ||||
|  * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but | ||||
|  * isn't much faster than x86_memcpy for agp copies. | ||||
|  *  | ||||
|  * TODO: switch dynamically. | ||||
|  */ | ||||
| static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			    GLint internalFormat, | ||||
| 			    GLint width, GLint height, GLint border, | ||||
| 			    GLenum format, GLenum type, const GLvoid *pixels, | ||||
| 			    const struct gl_pixelstore_attrib *packing, | ||||
| 			    struct gl_texture_object *texObj, | ||||
| 			    struct gl_texture_image *texImage ) | ||||
| static void *do_memcpy( void *dest, const void *src, size_t n ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    if ( (((unsigned)src) & 63) || | ||||
| 	(((unsigned)dest) & 63)) { | ||||
|       return  __memcpy(dest, src, n);	 | ||||
|    } | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target,  | ||||
| 				   internalFormat,  | ||||
| 				   width, height,  | ||||
| 				   format, type, pixels,  | ||||
| 				   packing, texObj, texImage)) { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "%s: Using client storage\n", __FUNCTION__);  | ||||
|    } | ||||
|    else { | ||||
|       _mesa_store_teximage2d( ctx, target, level, internalFormat, | ||||
| 			      width, height, border, format, type, | ||||
| 			      pixels, packing, texObj, texImage ); | ||||
|  | ||||
|       t->dirty_images[face] |= (1 << level); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelTexSubImage2D( GLcontext *ctx,  | ||||
| 			       GLenum target, | ||||
| 			       GLint level,	 | ||||
| 			       GLint xoffset, GLint yoffset, | ||||
| 			       GLsizei width, GLsizei height, | ||||
| 			       GLenum format, GLenum type, | ||||
| 			       const GLvoid *pixels, | ||||
| 			       const struct gl_pixelstore_attrib *packing, | ||||
| 			       struct gl_texture_object *texObj, | ||||
| 			       struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    } | ||||
|  | ||||
|    if (texImage->IsClientData && | ||||
|        (char *)pixels == (char *)texImage->Data +  | ||||
|        ((xoffset + yoffset * texImage->RowStride) *  | ||||
| 	texImage->TexFormat->TexelBytes)) { | ||||
|  | ||||
|       /* Notification only - no upload required */ | ||||
|    } | ||||
|    else { | ||||
|       assert( t ); /* this _should_ be true */ | ||||
|       intelFlush( ctx ); | ||||
|       driSwapOutTextureObject( t ); | ||||
|  | ||||
|       _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,  | ||||
| 				height, format, type, pixels, packing, texObj, | ||||
| 				texImage); | ||||
|  | ||||
|       t->dirty_images[face] |= (1 << level); | ||||
|    } | ||||
| } | ||||
|  | ||||
| static void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                               GLint internalFormat, | ||||
|                               GLint width, GLint height, GLint border, | ||||
|                               GLsizei imageSize, const GLvoid *data, | ||||
|                               struct gl_texture_object *texObj, | ||||
|                               struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    } | ||||
|  | ||||
|    assert(t); | ||||
|    intelFlush( ctx ); | ||||
|     | ||||
|    driSwapOutTextureObject( t ); | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
|      fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__);  | ||||
|     | ||||
|    _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width, | ||||
| 				     height, border, imageSize, data, texObj, texImage); | ||||
|     | ||||
|    t->dirty_images[face] |= (1 << level); | ||||
|    else | ||||
|       return memcpy(dest, src, n); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                                  GLint xoffset, GLint yoffset, | ||||
|                                  GLsizei width, GLsizei height, | ||||
|                                  GLenum format, | ||||
|                                  GLsizei imageSize, const GLvoid *data, | ||||
|                                  struct gl_texture_object *texObj, | ||||
|                                  struct gl_texture_image *texImage ) | ||||
| static void *timed_memcpy( void *dest, const void *src, size_t n ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    GLuint face; | ||||
|    void *ret; | ||||
|    unsigned t1, t2; | ||||
|    double rate; | ||||
|  | ||||
|    if ( (((unsigned)src) & 63) || | ||||
| 	(((unsigned)dest) & 63))  | ||||
|       _mesa_printf("Warning - non-aligned texture copy!\n"); | ||||
|  | ||||
|    /* which cube face or ordinary 2D image */ | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | ||||
|       face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | ||||
|       ASSERT(face < 6); | ||||
|       break; | ||||
|    default: | ||||
|       face = 0; | ||||
|    } | ||||
|    t1 = fastrdtsc(); | ||||
|    ret =  do_memcpy(dest, src, n);	 | ||||
|    t2 = fastrdtsc(); | ||||
|  | ||||
|    assert( t ); /* this _should_ be true */ | ||||
|    intelFlush( ctx ); | ||||
|    driSwapOutTextureObject( t ); | ||||
|     | ||||
|    _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width, | ||||
| 					height, format, imageSize, data, texObj, texImage); | ||||
|     | ||||
|    t->dirty_images[face] |= (1 << level); | ||||
|    rate = time_diff(t1, t2); | ||||
|    rate /= (double) n; | ||||
|    _mesa_printf("timed_memcpy: %u %u --> %f clocks/byte\n", t1, t2, rate);  | ||||
|    return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                             GLint internalFormat, | ||||
|                             GLint width, GLint height, GLint depth, | ||||
|                             GLint border, | ||||
|                             GLenum format, GLenum type, const GLvoid *pixels, | ||||
|                             const struct gl_pixelstore_attrib *packing, | ||||
|                             struct gl_texture_object *texObj, | ||||
|                             struct gl_texture_image *texImage ) | ||||
| void intelInitTextureFuncs(struct dd_function_table * functions) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|    functions->ChooseTextureFormat = intelChooseTextureFormat; | ||||
|    functions->TexImage1D = intelTexImage1D; | ||||
|    functions->TexImage2D = intelTexImage2D; | ||||
|    functions->TexImage3D = intelTexImage3D; | ||||
|    functions->TexSubImage1D = intelTexSubImage1D; | ||||
|    functions->TexSubImage2D = intelTexSubImage2D; | ||||
|    functions->TexSubImage3D = intelTexSubImage3D; | ||||
|    functions->CopyTexImage1D = intelCopyTexImage1D; | ||||
|    functions->CopyTexImage2D = intelCopyTexImage2D; | ||||
|    functions->CopyTexSubImage1D = intelCopyTexSubImage1D; | ||||
|    functions->CopyTexSubImage2D = intelCopyTexSubImage2D; | ||||
|    functions->GetTexImage = intelGetTexImage; | ||||
|    functions->NewTextureObject = intelNewTextureObject; | ||||
|    functions->NewTextureImage = intelNewTextureImage; | ||||
|    functions->DeleteTexture = _mesa_delete_texture_object; | ||||
|    functions->FreeTexImageData = intelFreeTextureImageData; | ||||
|    functions->UpdateTexturePalette = 0; | ||||
|    functions->IsTextureResident = intelIsTextureResident; | ||||
|  | ||||
|    assert(t); | ||||
|    driSwapOutTextureObject( t ); | ||||
|    texImage->IsClientData = GL_FALSE; | ||||
|  | ||||
|    _mesa_store_teximage3d(ctx, target, level, internalFormat, | ||||
| 			  width, height, depth, border, | ||||
| 			  format, type, pixels, | ||||
| 			  &ctx->Unpack, texObj, texImage); | ||||
|     | ||||
|    t->dirty_images[0] |= (1 << level); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, | ||||
|                    GLint xoffset, GLint yoffset, GLint zoffset, | ||||
|                    GLsizei width, GLsizei height, GLsizei depth, | ||||
|                    GLenum format, GLenum type, | ||||
|                    const GLvoid *pixels, | ||||
|                    const struct gl_pixelstore_attrib *packing, | ||||
|                    struct gl_texture_object *texObj, | ||||
|                    struct gl_texture_image *texImage ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) texObj->DriverData; | ||||
|  | ||||
|    assert( t ); /* this _should_ be true */ | ||||
|    driSwapOutTextureObject( t ); | ||||
|  | ||||
|    _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset, | ||||
|                              width, height, depth, | ||||
|                              format, type, pixels, packing, texObj, texImage); | ||||
|  | ||||
|    t->dirty_images[0] |= (1 << level); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) | ||||
| { | ||||
|    driTextureObject * t = (driTextureObject *) tObj->DriverData; | ||||
|  | ||||
|    if ( t != NULL ) { | ||||
|       intelFlush( ctx ); | ||||
|       driDestroyTextureObject( t ); | ||||
|    } | ||||
|     | ||||
|    /* Free mipmap images and the texture object itself */ | ||||
|    _mesa_delete_texture_object(ctx, tObj); | ||||
| } | ||||
|  | ||||
|  | ||||
| static const struct gl_texture_format * | ||||
| intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, | ||||
| 			 GLenum format, GLenum type ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 && | ||||
| 			       intel->intelScreen->tex.size > 4*1024*1024); | ||||
|  | ||||
|    switch ( internalFormat ) { | ||||
|    case 4: | ||||
|    case GL_RGBA: | ||||
|    case GL_COMPRESSED_RGBA: | ||||
|       if ( format == GL_BGRA ) { | ||||
| 	 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | ||||
| 	    return &_mesa_texformat_argb8888; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { | ||||
|             return &_mesa_texformat_argb4444; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { | ||||
| 	    return &_mesa_texformat_argb1555; | ||||
| 	 } | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case 3: | ||||
|    case GL_RGB: | ||||
|    case GL_COMPRESSED_RGB: | ||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | ||||
| 	 return &_mesa_texformat_rgb565; | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGBA2: | ||||
|       return &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGB5_A1: | ||||
|       return &_mesa_texformat_argb1555; | ||||
|  | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGB5: | ||||
|    case GL_RGB4: | ||||
|    case GL_R3_G3_B2: | ||||
|       return &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_ALPHA: | ||||
|    case GL_ALPHA4: | ||||
|    case GL_ALPHA8: | ||||
|    case GL_ALPHA12: | ||||
|    case GL_ALPHA16: | ||||
|    case GL_COMPRESSED_ALPHA: | ||||
|       return &_mesa_texformat_a8; | ||||
|  | ||||
|    case 1: | ||||
|    case GL_LUMINANCE: | ||||
|    case GL_LUMINANCE4: | ||||
|    case GL_LUMINANCE8: | ||||
|    case GL_LUMINANCE12: | ||||
|    case GL_LUMINANCE16: | ||||
|    case GL_COMPRESSED_LUMINANCE: | ||||
|       return &_mesa_texformat_l8; | ||||
|  | ||||
|    case 2: | ||||
|    case GL_LUMINANCE_ALPHA: | ||||
|    case GL_LUMINANCE4_ALPHA4: | ||||
|    case GL_LUMINANCE6_ALPHA2: | ||||
|    case GL_LUMINANCE8_ALPHA8: | ||||
|    case GL_LUMINANCE12_ALPHA4: | ||||
|    case GL_LUMINANCE12_ALPHA12: | ||||
|    case GL_LUMINANCE16_ALPHA16: | ||||
|    case GL_COMPRESSED_LUMINANCE_ALPHA: | ||||
|       return &_mesa_texformat_al88; | ||||
|  | ||||
|    case GL_INTENSITY: | ||||
|    case GL_INTENSITY4: | ||||
|    case GL_INTENSITY8: | ||||
|    case GL_INTENSITY12: | ||||
|    case GL_INTENSITY16: | ||||
|    case GL_COMPRESSED_INTENSITY: | ||||
|       return &_mesa_texformat_i8; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if (type == GL_UNSIGNED_SHORT_8_8_MESA || | ||||
| 	  type == GL_UNSIGNED_BYTE) | ||||
|          return &_mesa_texformat_ycbcr; | ||||
|       else | ||||
|          return &_mesa_texformat_ycbcr_rev; | ||||
|  | ||||
|    case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgb_fxt1; | ||||
|    case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgba_fxt1; | ||||
|  | ||||
|    case GL_RGB_S3TC: | ||||
|    case GL_RGB4_S3TC: | ||||
|    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgb_dxt1; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt1; | ||||
|  | ||||
|    case GL_RGBA_S3TC: | ||||
|    case GL_RGBA4_S3TC: | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt3; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt5; | ||||
|  | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       return &_mesa_texformat_depth_component16; | ||||
|  | ||||
|    default: | ||||
|       fprintf(stderr, "unexpected texture format %s in %s\n",  | ||||
| 	      _mesa_lookup_enum_by_nr(internalFormat), | ||||
| 	      __FUNCTION__); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return NULL; /* never get here */ | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t) | ||||
| { | ||||
|    unsigned   i; | ||||
|  | ||||
|    if ( intel == NULL )  | ||||
|       return; | ||||
|  | ||||
|    if ( t->age > intel->dirtyAge ) | ||||
|       intel->dirtyAge = t->age; | ||||
|  | ||||
|    for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) { | ||||
|       if ( t == intel->CurrentTexObj[ i ] )  | ||||
| 	 intel->CurrentTexObj[ i ] = NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* Upload an image from mesa's internal copy.  Image may be 1D, 2D or | ||||
|  * 3D.  Cubemaps are expanded elsewhere. | ||||
|  */ | ||||
| static void intelUploadTexImage( intelContextPtr intel, | ||||
| 				 intelTextureObjectPtr t, | ||||
| 				 const struct gl_texture_image *image, | ||||
| 				 const GLuint offset ) | ||||
| { | ||||
|  | ||||
|    if (!image || !image->Data)  | ||||
|       return; | ||||
|  | ||||
|    if (image->Depth == 1 && image->IsClientData) { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "Blit uploading\n"); | ||||
|  | ||||
|       /* Do it with a blit. | ||||
|        */ | ||||
|       intelEmitCopyBlitLocked( intel, | ||||
| 			       image->TexFormat->TexelBytes, | ||||
| 			       image->RowStride, /* ? */ | ||||
| 			       intelGetMemoryOffsetMESA( NULL, 0, image->Data ), | ||||
| 			       t->Pitch / image->TexFormat->TexelBytes, | ||||
| 			       intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ), | ||||
| 			       0, 0, | ||||
| 			       0, 0, | ||||
| 			       image->Width, | ||||
| 			       image->Height); | ||||
|    } | ||||
|    else if (image->IsCompressed) { | ||||
|       GLuint row_len = image->Width * 2; | ||||
|       GLubyte *dst = (GLubyte *)(t->BufAddr + offset); | ||||
|       GLubyte *src = (GLubyte *)image->Data; | ||||
|       GLuint j; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr,  | ||||
| 		 "Upload image %dx%dx%d offset %xm row_len %x " | ||||
| 		 "pitch %x depth_pitch %x\n", | ||||
| 		 image->Width, image->Height, image->Depth, offset, | ||||
| 		 row_len, t->Pitch, t->depth_pitch); | ||||
|  | ||||
|       switch (image->InternalFormat) { | ||||
| 	case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
| 	case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
| 	case GL_RGB_S3TC: | ||||
| 	case GL_RGB4_S3TC: | ||||
| 	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
| 	  for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { | ||||
| 	    __memcpy(dst, src, row_len ); | ||||
| 	    src += row_len; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	case GL_RGBA_S3TC: | ||||
| 	case GL_RGBA4_S3TC: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
| 	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
| 	  for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { | ||||
| 	    __memcpy(dst, src, (image->Width*4) ); | ||||
| 	    src += image->Width*4; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat); | ||||
| 	  break; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       GLuint row_len = image->Width * image->TexFormat->TexelBytes; | ||||
|       GLubyte *dst = (GLubyte *)(t->BufAddr + offset); | ||||
|       GLubyte *src = (GLubyte *)image->Data; | ||||
|       GLuint d, j; | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr,  | ||||
| 		 "Upload image %dx%dx%d offset %xm row_len %x " | ||||
| 		 "pitch %x depth_pitch %x\n", | ||||
| 		 image->Width, image->Height, image->Depth, offset, | ||||
| 		 row_len, t->Pitch, t->depth_pitch); | ||||
|  | ||||
|       if (row_len == t->Pitch) { | ||||
| 	 for (d = 0; d < image->Depth; d++) { | ||||
| 	    memcpy( dst, src, t->Pitch * image->Height ); | ||||
| 	    dst += t->depth_pitch; | ||||
| 	    src += row_len * image->Height; | ||||
| 	 } | ||||
|       } | ||||
|       else {  | ||||
| 	 for (d = 0 ; d < image->Depth ; d++) { | ||||
| 	    for (j = 0 ; j < image->Height ; j++) { | ||||
| 	       __memcpy(dst, src, row_len ); | ||||
| 	       src += row_len; | ||||
| 	       dst += t->Pitch; | ||||
| 	    } | ||||
|  | ||||
| 	    dst += t->depth_pitch - (t->Pitch * image->Height); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| int intelUploadTexImages( intelContextPtr intel,  | ||||
| 			  intelTextureObjectPtr t, | ||||
| 			  GLuint face) | ||||
| { | ||||
|    const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; | ||||
|    const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image; | ||||
|    int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes; | ||||
|  | ||||
|    /* Can we texture out of the existing client data? */ | ||||
|    if ( numLevels == 1 && | ||||
| 	firstImage->IsClientData && | ||||
| 	(pitch & 3) == 0) { | ||||
|  | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 fprintf(stderr, "AGP texturing from client memory\n"); | ||||
|  | ||||
|       t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data ); | ||||
|       t->BufAddr = 0; | ||||
|       t->dirty = ~0; | ||||
|       return GL_TRUE; | ||||
|    } | ||||
|    else { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE)  | ||||
| 	 fprintf(stderr, "Uploading client data to agp\n"); | ||||
|  | ||||
|       INTEL_FIREVERTICES( intel ); | ||||
|       LOCK_HARDWARE( intel ); | ||||
|  | ||||
|       if ( t->base.memBlock == NULL ) { | ||||
| 	 int heap; | ||||
|  | ||||
| 	 heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps, | ||||
| 				    (driTextureObject *) t ); | ||||
| 	 if ( heap == -1 ) { | ||||
| 	    UNLOCK_HARDWARE( intel ); | ||||
| 	    return GL_FALSE; | ||||
| 	 } | ||||
|  | ||||
| 	 /* Set the base offset of the texture image */ | ||||
| 	 t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs; | ||||
| 	 t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs; | ||||
| 	 t->dirty = ~0; | ||||
|       } | ||||
|  | ||||
|  | ||||
|       /* Let the world know we've used this memory recently. | ||||
|        */ | ||||
|       driUpdateTextureLRU( (driTextureObject *) t ); | ||||
|  | ||||
|  | ||||
|       /* Upload any images that are new */ | ||||
|       if (t->base.dirty_images[face]) { | ||||
| 	 int i; | ||||
|  | ||||
|  	 intelWaitForIdle( intel ); | ||||
| 	     | ||||
| 	 for (i = 0 ; i < numLevels ; i++) {  | ||||
| 	    int level = i + t->base.firstLevel; | ||||
|  | ||||
| 	    if (t->base.dirty_images[face] & (1<<level)) { | ||||
|  | ||||
| 	       const struct gl_texture_image *image = t->image[face][i].image; | ||||
| 	       GLuint offset = t->image[face][i].offset; | ||||
|  | ||||
|      	       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	          fprintf(stderr, "upload level %d, offset %x\n",  | ||||
| 			  level, offset); | ||||
|  | ||||
| 	       intelUploadTexImage( intel, t, image, offset ); | ||||
| 	    } | ||||
| 	 } | ||||
| 	 t->base.dirty_images[face] = 0; | ||||
| 	 intel->perf_boxes |= I830_BOX_TEXTURE_LOAD; | ||||
|       } | ||||
|        | ||||
|       UNLOCK_HARDWARE( intel ); | ||||
|       return GL_TRUE; | ||||
|    } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Allocate a new texture object. | ||||
|  * Called via ctx->Driver.NewTextureObject. | ||||
|  * Note: this function will be called during context creation to | ||||
|  * allocate the default texture objects. | ||||
|  * Note: we could use containment here to 'derive' the driver-specific | ||||
|  * texture object from the core mesa gl_texture_object.  Not done at this time. | ||||
|  */ | ||||
| static struct gl_texture_object * | ||||
| intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target ) | ||||
| { | ||||
|    struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target); | ||||
|    INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj ); | ||||
|    return obj; | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelInitTextureFuncs( struct dd_function_table *functions ) | ||||
| { | ||||
|    functions->NewTextureObject          = intelNewTextureObject; | ||||
|    functions->ChooseTextureFormat       = intelChooseTextureFormat; | ||||
|    functions->TexImage1D                = intelTexImage1D; | ||||
|    functions->TexImage2D                = intelTexImage2D; | ||||
|    functions->TexImage3D                = intelTexImage3D; | ||||
|    functions->TexSubImage1D             = intelTexSubImage1D; | ||||
|    functions->TexSubImage2D             = intelTexSubImage2D; | ||||
|    functions->TexSubImage3D             = intelTexSubImage3D; | ||||
|    functions->CopyTexImage1D            = _swrast_copy_teximage1d; | ||||
|    functions->CopyTexImage2D            = _swrast_copy_teximage2d; | ||||
|    functions->CopyTexSubImage1D         = _swrast_copy_texsubimage1d; | ||||
|    functions->CopyTexSubImage2D         = _swrast_copy_texsubimage2d; | ||||
|    functions->CopyTexSubImage3D         = _swrast_copy_texsubimage3d; | ||||
|    functions->DeleteTexture             = intelDeleteTexture; | ||||
|    functions->UpdateTexturePalette      = NULL; | ||||
|    functions->IsTextureResident         = driIsTextureResident; | ||||
|    functions->TestProxyTexImage         = _mesa_test_proxy_teximage; | ||||
|    functions->DeleteTexture             = intelDeleteTexture; | ||||
|    functions->CompressedTexImage2D      = intelCompressedTexImage2D; | ||||
|    functions->CompressedTexSubImage2D   = intelCompressedTexSubImage2D; | ||||
|    if (INTEL_DEBUG & DEBUG_BUFMGR) | ||||
|       functions->TextureMemCpy = timed_memcpy; | ||||
|    else | ||||
|       functions->TextureMemCpy = do_memcpy; | ||||
| } | ||||
|   | ||||
| @@ -35,8 +35,102 @@ | ||||
|  | ||||
| void intelInitTextureFuncs( struct dd_function_table *functions ); | ||||
|  | ||||
| void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t ); | ||||
| int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t, | ||||
| 			  GLuint face ); | ||||
| const struct gl_texture_format * | ||||
| intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, | ||||
|                           GLenum format, GLenum type ); | ||||
|  | ||||
|  | ||||
| void intelTexImage3D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint height, GLint depth, | ||||
| 		     GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *packing, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexSubImage3D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, GLint yoffset, GLint zoffset, | ||||
| 			GLsizei width, GLsizei height, GLsizei depth, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexImage2D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint height, GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *packing, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexSubImage2D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, GLint yoffset, | ||||
| 			GLsizei width, GLsizei height, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexImage1D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *packing, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelTexSubImage1D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, | ||||
| 			GLsizei width, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage); | ||||
|  | ||||
| void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			  GLenum internalFormat, | ||||
| 			  GLint x, GLint y, GLsizei width, | ||||
| 			  GLint border ); | ||||
|  | ||||
| void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			  GLenum internalFormat, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLint border ); | ||||
|  | ||||
| void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			     GLint xoffset, | ||||
| 			     GLint x, GLint y, GLsizei width ); | ||||
|  | ||||
| void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			     GLint xoffset, GLint yoffset, | ||||
| 			     GLint x, GLint y, GLsizei width, GLsizei height ); | ||||
|  | ||||
| void intelGetTexImage( GLcontext *ctx, GLenum target, GLint level, | ||||
|                        GLenum format, GLenum type, GLvoid *pixels, | ||||
|                        struct gl_texture_object *texObj, | ||||
|                        struct gl_texture_image *texImage ); | ||||
|  | ||||
| GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit ); | ||||
|  | ||||
| void intel_tex_map_images( struct intel_context *intel, | ||||
| 			   struct intel_texture_object *intelObj ); | ||||
|  | ||||
| void intel_tex_unmap_images( struct intel_context *intel, | ||||
| 			     struct intel_texture_object *intelObj ); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										296
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								src/mesa/drivers/dri/i915/intel_tex_copy.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,296 @@ | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "enums.h" | ||||
| #include "image.h" | ||||
| #include "teximage.h" | ||||
| #include "swrast/swrast.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_buffers.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_regions.h" | ||||
| #include "intel_fbo.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_blit.h" | ||||
| #include "intel_pixel.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Get the intel_region which is the source for any glCopyTex[Sub]Image call. | ||||
|  * | ||||
|  * Do the best we can using the blitter.  A future project is to use | ||||
|  * the texture engine and fragment programs for these copies. | ||||
|  */ | ||||
| static const struct intel_region * | ||||
| get_teximage_source(struct intel_context *intel, GLenum internalFormat) | ||||
| { | ||||
|    struct intel_renderbuffer *irb; | ||||
|  | ||||
|    if (0) | ||||
|       _mesa_printf("%s %s\n", __FUNCTION__,  | ||||
| 		   _mesa_lookup_enum_by_nr(internalFormat)); | ||||
|  | ||||
|    switch (internalFormat) { | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16_ARB: | ||||
|       irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); | ||||
|       if (irb && irb->region && irb->region->cpp == 2) | ||||
| 	 return irb->region; | ||||
|       return NULL; | ||||
|    case GL_DEPTH24_STENCIL8_EXT: | ||||
|    case GL_DEPTH_STENCIL_EXT: | ||||
|       irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); | ||||
|       if (irb && irb->region && irb->region->cpp == 4) | ||||
| 	 return irb->region; | ||||
|       return NULL; | ||||
|    case GL_RGBA: | ||||
|       return intel_readbuf_region( intel ); | ||||
|    case GL_RGB: | ||||
|       if (intel->intelScreen->cpp == 2) | ||||
| 	 return intel_readbuf_region( intel ); | ||||
|       return NULL; | ||||
|    default: | ||||
|       return NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static GLboolean do_copy_texsubimage( struct intel_context *intel, | ||||
| 				      struct intel_texture_image *intelImage, | ||||
| 				      GLenum internalFormat, | ||||
| 				      GLint dstx, GLint dsty, | ||||
| 				      GLint x, GLint y, | ||||
| 				      GLsizei width, GLsizei height ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    const struct intel_region *src = get_teximage_source(intel, internalFormat); | ||||
|  | ||||
|    if (!intelImage->mt || !src) | ||||
|       return GL_FALSE; | ||||
|   | ||||
|    intelFlush(ctx); | ||||
|    LOCK_HARDWARE(intel); | ||||
|    { | ||||
|       GLuint image_offset = intel_miptree_image_offset(intelImage->mt,  | ||||
| 						       intelImage->face, | ||||
| 						       intelImage->level); | ||||
|       const GLint orig_x = x; | ||||
|       const GLint orig_y = y; | ||||
|       const struct gl_framebuffer *fb = ctx->DrawBuffer; | ||||
|  | ||||
|       if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, | ||||
|                                &x, &y, &width, &height)) { | ||||
| 	 /* Update dst for clipped src.  Need to also clip the source rect. | ||||
| 	  */ | ||||
| 	 dstx += x - orig_x; | ||||
| 	 dsty += y - orig_y; | ||||
|  | ||||
|          if (ctx->ReadBuffer->Name == 0) { | ||||
|             /* reading from a window, adjust x, y */ | ||||
|             __DRIdrawablePrivate *dPriv = intel->driDrawable; | ||||
|             GLuint window_y; | ||||
|             /* window_y = position of window on screen if y=0=bottom */ | ||||
|             window_y = intel->intelScreen->height - (dPriv->y + dPriv->h); | ||||
|             y = window_y + y; | ||||
|             x += dPriv->x; | ||||
|          } | ||||
|          else { | ||||
|             /* reading from a FBO */ | ||||
|             /* invert Y */ | ||||
|             y = ctx->ReadBuffer->Height - y - 1; | ||||
|          } | ||||
|  | ||||
|  | ||||
| 	 /* A bit of fiddling to get the blitter to work with -ve | ||||
| 	  * pitches.  But we get a nice inverted blit this way, so it's | ||||
| 	  * worth it: | ||||
| 	  */ | ||||
| 	 intelEmitCopyBlit( intel, | ||||
| 			    intelImage->mt->cpp, | ||||
|  | ||||
| 			    -src->pitch,  | ||||
| 			    src->buffer, | ||||
| 			    src->height * src->pitch * src->cpp,  | ||||
|  | ||||
| 			    intelImage->mt->pitch,  | ||||
| 			    intelImage->mt->region->buffer, | ||||
| 			    image_offset, | ||||
|  | ||||
| 			    x, y + height,  | ||||
| 			    dstx, dsty, | ||||
| 			    width, height ); | ||||
|  | ||||
| 	 intel_batchbuffer_flush( intel->batch ); | ||||
|       } | ||||
|    } | ||||
|     | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap -- this can be accelerated now. | ||||
|     * XXX Add a ctx->Driver.GenerateMipmaps() function? | ||||
|     */ | ||||
|    if (level == texObj->BaseLevel &&  | ||||
|        texObj->GenerateMipmap) { | ||||
|       intel_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelCopyTexImage1D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			  GLenum internalFormat, | ||||
| 			  GLint x, GLint y, GLsizei width, | ||||
| 			  GLint border ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target); | ||||
|    struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|  | ||||
|    if (border) | ||||
|       goto fail; | ||||
|  | ||||
|    /* Setup or redefine the texture object, mipmap tree and texture | ||||
|     * image.  Don't populate yet.   | ||||
|     */ | ||||
|    ctx->Driver.TexImage1D(ctx, target, level, internalFormat, | ||||
| 			  width, border, | ||||
| 			  GL_RGBA, CHAN_TYPE, NULL, | ||||
| 			  &ctx->DefaultPacking, texObj, texImage); | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx),  | ||||
| 			    intel_texture_image(texImage), | ||||
| 			    internalFormat, | ||||
| 			    0, 0, | ||||
| 			    x, y,  | ||||
| 			    width, 1)) | ||||
|        goto fail; | ||||
|  | ||||
|    return; | ||||
|  | ||||
|  fail: | ||||
|    _swrast_copy_teximage1d( ctx, target, level, internalFormat, x, y, | ||||
| 			    width, border ); | ||||
| } | ||||
|  | ||||
| void intelCopyTexImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			  GLenum internalFormat, | ||||
| 			  GLint x, GLint y, GLsizei width, GLsizei height, | ||||
| 			  GLint border ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_object *texObj = _mesa_select_tex_object(ctx, texUnit, target); | ||||
|    struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|  | ||||
|    if (border) | ||||
|       goto fail; | ||||
|  | ||||
|    /* Setup or redefine the texture object, mipmap tree and texture | ||||
|     * image.  Don't populate yet.   | ||||
|     */ | ||||
|    ctx->Driver.TexImage2D(ctx, target, level, internalFormat, | ||||
| 			  width, height, border, | ||||
| 			  GL_RGBA, CHAN_TYPE, NULL, | ||||
| 			  &ctx->DefaultPacking, texObj, texImage); | ||||
|  | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx),  | ||||
| 			    intel_texture_image(texImage), | ||||
| 			    internalFormat, | ||||
| 			    0, 0, | ||||
| 			    x, y,  | ||||
| 			    width, height)) | ||||
|        goto fail; | ||||
|  | ||||
|    return; | ||||
|  | ||||
|  fail: | ||||
|    _swrast_copy_teximage2d( ctx, target, level, internalFormat, x, y, | ||||
| 			    width, height, border ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelCopyTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			     GLint xoffset, | ||||
| 			     GLint x, GLint y, GLsizei width ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|    GLenum internalFormat = texImage->InternalFormat; | ||||
|  | ||||
|    /* XXX need to check <border> as in above function? */ | ||||
|  | ||||
|    /* Need to check texture is compatible with source format.  | ||||
|     */ | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx),  | ||||
| 			    intel_texture_image(texImage), | ||||
| 			    internalFormat, | ||||
| 			    xoffset, 0, | ||||
| 			    x, y, width, 1)) { | ||||
|       _swrast_copy_texsubimage1d( ctx, target, level,  | ||||
| 				  xoffset, x, y, width ); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelCopyTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, | ||||
| 			     GLint xoffset, GLint yoffset, | ||||
| 			     GLint x, GLint y, GLsizei width, GLsizei height ) | ||||
| { | ||||
|    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; | ||||
|    struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texUnit, target, level); | ||||
|    GLenum internalFormat = texImage->InternalFormat; | ||||
|  | ||||
|  | ||||
|    /* Need to check texture is compatible with source format.  | ||||
|     */ | ||||
|  | ||||
|    if (!do_copy_texsubimage(intel_context(ctx),  | ||||
| 			    intel_texture_image(texImage), | ||||
| 			    internalFormat, | ||||
| 			    xoffset, yoffset, | ||||
| 			    x, y, width, height)) { | ||||
|       _swrast_copy_texsubimage2d( ctx, target, level, | ||||
| 				  xoffset, yoffset, | ||||
| 				  x, y, width, height ); | ||||
|    } | ||||
| } | ||||
							
								
								
									
										148
									
								
								src/mesa/drivers/dri/i915/intel_tex_format.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/mesa/drivers/dri/i915/intel_tex_format.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| #include "intel_context.h" | ||||
| #include "intel_tex.h" | ||||
| #include "texformat.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| /* It works out that this function is fine for all the supported | ||||
|  * hardware.  However, there is still a need to map the formats onto | ||||
|  * hardware descriptors. | ||||
|  */ | ||||
| /* Note that the i915 can actually support many more formats than | ||||
|  * these if we take the step of simply swizzling the colors | ||||
|  * immediately after sampling... | ||||
|  */ | ||||
| const struct gl_texture_format * | ||||
| intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, | ||||
|                           GLenum format, GLenum type ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    const GLboolean do32bpt = (intel->intelScreen->cpp == 4); | ||||
|  | ||||
|    switch ( internalFormat ) { | ||||
|    case 4: | ||||
|    case GL_RGBA: | ||||
|    case GL_COMPRESSED_RGBA: | ||||
|       if ( format == GL_BGRA ) { | ||||
| 	 if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | ||||
| 	    return &_mesa_texformat_argb8888; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { | ||||
|             return &_mesa_texformat_argb4444; | ||||
| 	 } | ||||
|          else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { | ||||
| 	    return &_mesa_texformat_argb1555; | ||||
| 	 } | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case 3: | ||||
|    case GL_RGB: | ||||
|    case GL_COMPRESSED_RGB: | ||||
|       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | ||||
| 	 return &_mesa_texformat_rgb565; | ||||
|       } | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_RGBA8: | ||||
|    case GL_RGB10_A2: | ||||
|    case GL_RGBA12: | ||||
|    case GL_RGBA16: | ||||
|       return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGBA4: | ||||
|    case GL_RGBA2: | ||||
|       return &_mesa_texformat_argb4444; | ||||
|  | ||||
|    case GL_RGB5_A1: | ||||
|       return &_mesa_texformat_argb1555; | ||||
|  | ||||
|    case GL_RGB8: | ||||
|    case GL_RGB10: | ||||
|    case GL_RGB12: | ||||
|    case GL_RGB16: | ||||
|       return &_mesa_texformat_argb8888; | ||||
|  | ||||
|    case GL_RGB5: | ||||
|    case GL_RGB4: | ||||
|    case GL_R3_G3_B2: | ||||
|       return &_mesa_texformat_rgb565; | ||||
|  | ||||
|    case GL_ALPHA: | ||||
|    case GL_ALPHA4: | ||||
|    case GL_ALPHA8: | ||||
|    case GL_ALPHA12: | ||||
|    case GL_ALPHA16: | ||||
|    case GL_COMPRESSED_ALPHA: | ||||
|       return &_mesa_texformat_a8; | ||||
|  | ||||
|    case 1: | ||||
|    case GL_LUMINANCE: | ||||
|    case GL_LUMINANCE4: | ||||
|    case GL_LUMINANCE8: | ||||
|    case GL_LUMINANCE12: | ||||
|    case GL_LUMINANCE16: | ||||
|    case GL_COMPRESSED_LUMINANCE: | ||||
|       return &_mesa_texformat_l8; | ||||
|  | ||||
|    case 2: | ||||
|    case GL_LUMINANCE_ALPHA: | ||||
|    case GL_LUMINANCE4_ALPHA4: | ||||
|    case GL_LUMINANCE6_ALPHA2: | ||||
|    case GL_LUMINANCE8_ALPHA8: | ||||
|    case GL_LUMINANCE12_ALPHA4: | ||||
|    case GL_LUMINANCE12_ALPHA12: | ||||
|    case GL_LUMINANCE16_ALPHA16: | ||||
|    case GL_COMPRESSED_LUMINANCE_ALPHA: | ||||
|       return &_mesa_texformat_al88; | ||||
|  | ||||
|    case GL_INTENSITY: | ||||
|    case GL_INTENSITY4: | ||||
|    case GL_INTENSITY8: | ||||
|    case GL_INTENSITY12: | ||||
|    case GL_INTENSITY16: | ||||
|    case GL_COMPRESSED_INTENSITY: | ||||
|       return &_mesa_texformat_i8; | ||||
|  | ||||
|    case GL_YCBCR_MESA: | ||||
|       if (type == GL_UNSIGNED_SHORT_8_8_MESA || | ||||
| 	  type == GL_UNSIGNED_BYTE) | ||||
|          return &_mesa_texformat_ycbcr; | ||||
|       else | ||||
|          return &_mesa_texformat_ycbcr_rev; | ||||
|  | ||||
|    case GL_COMPRESSED_RGB_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgb_fxt1; | ||||
|    case GL_COMPRESSED_RGBA_FXT1_3DFX: | ||||
|      return &_mesa_texformat_rgba_fxt1; | ||||
|  | ||||
|    case GL_RGB_S3TC: | ||||
|    case GL_RGB4_S3TC: | ||||
|    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgb_dxt1; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt1; | ||||
|  | ||||
|    case GL_RGBA_S3TC: | ||||
|    case GL_RGBA4_S3TC: | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | ||||
|      return &_mesa_texformat_rgba_dxt3; | ||||
|  | ||||
|    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | ||||
|       return &_mesa_texformat_rgba_dxt5; | ||||
|  | ||||
|    case GL_DEPTH_COMPONENT: | ||||
|    case GL_DEPTH_COMPONENT16: | ||||
|    case GL_DEPTH_COMPONENT24: | ||||
|    case GL_DEPTH_COMPONENT32: | ||||
|       return &_mesa_texformat_depth_component16; | ||||
|  | ||||
|    default: | ||||
|       fprintf(stderr, "unexpected texture format %s in %s\n",  | ||||
| 	      _mesa_lookup_enum_by_nr(internalFormat), | ||||
| 	      __FUNCTION__); | ||||
|       return NULL; | ||||
|    } | ||||
|  | ||||
|    return NULL; /* never get here */ | ||||
| } | ||||
							
								
								
									
										444
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										444
									
								
								src/mesa/drivers/dri/i915/intel_tex_image.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,444 @@ | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "glheader.h" | ||||
| #include "macros.h" | ||||
| #include "mtypes.h" | ||||
| #include "enums.h" | ||||
| #include "colortab.h" | ||||
| #include "convolve.h" | ||||
| #include "context.h" | ||||
| #include "simple_list.h" | ||||
| #include "texcompress.h" | ||||
| #include "texformat.h" | ||||
| #include "texobj.h" | ||||
| #include "texstore.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_ioctl.h" | ||||
|  | ||||
|  | ||||
| /* Functions to store texture images.  Where possible, mipmap_tree's | ||||
|  * will be created or further instantiated with image data, otherwise | ||||
|  * images will be stored in malloc'd memory.  A validation step is | ||||
|  * required to pull those images into a mipmap tree, or otherwise | ||||
|  * decide a fallback is required. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| static int logbase2(int n) | ||||
| { | ||||
|    GLint i = 1; | ||||
|    GLint log2 = 0; | ||||
|  | ||||
|    while (n > i) { | ||||
|       i *= 2; | ||||
|       log2++; | ||||
|    } | ||||
|  | ||||
|    return log2; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Otherwise, store it in memory if (Border != 0) or (any dimension == | ||||
|  * 1). | ||||
|  *     | ||||
|  * Otherwise, if max_level >= level >= min_level, create tree with | ||||
|  * space for textures from min_level down to max_level. | ||||
|  * | ||||
|  * Otherwise, create tree with space for textures from (level | ||||
|  * 0)..(1x1).  Consider pruning this tree at a validation if the | ||||
|  * saving is worth it. | ||||
|  */ | ||||
| static void guess_and_alloc_mipmap_tree( struct intel_context *intel, | ||||
| 					 struct intel_texture_object *intelObj, | ||||
| 					 struct intel_texture_image *intelImage ) | ||||
| { | ||||
|    GLuint firstLevel; | ||||
|    GLuint lastLevel; | ||||
|    GLuint width = intelImage->base.Width; | ||||
|    GLuint height = intelImage->base.Height; | ||||
|    GLuint depth = intelImage->base.Depth; | ||||
|    GLuint l2width, l2height, l2depth; | ||||
|    GLuint i; | ||||
|  | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (intelImage->base.Border) | ||||
|       return; | ||||
|  | ||||
|    if (intelImage->level > intelObj->base.BaseLevel && | ||||
|        (intelImage->base.Width == 1 || | ||||
| 	(intelObj->base.Target != GL_TEXTURE_1D &&  | ||||
| 	 intelImage->base.Height == 1) || | ||||
| 	(intelObj->base.Target == GL_TEXTURE_3D && | ||||
| 	 intelImage->base.Depth == 1))) | ||||
|       return; | ||||
|  | ||||
|    /* If this image disrespects BaseLevel, allocate from level zero. | ||||
|     * Usually BaseLevel == 0, so it's unlikely to happen. | ||||
|     */ | ||||
|    if (intelImage->level < intelObj->base.BaseLevel) | ||||
|       firstLevel = 0; | ||||
|    else | ||||
|       firstLevel = intelObj->base.BaseLevel; | ||||
|  | ||||
|  | ||||
|    /* Figure out image dimensions at start level.  | ||||
|     */ | ||||
|    for (i = intelImage->level; i > firstLevel; i--) { | ||||
|       width <<= 1; | ||||
|       if (height != 1) height <<= 1; | ||||
|       if (depth != 1) depth <<= 1; | ||||
|    } | ||||
|  | ||||
|    /* Guess a reasonable value for lastLevel.  This is probably going | ||||
|     * to be wrong fairly often and might mean that we have to look at | ||||
|     * resizable buffers, or require that buffers implement lazy | ||||
|     * pagetable arrangements. | ||||
|     */ | ||||
|    if ((intelObj->base.MinFilter == GL_NEAREST ||  | ||||
| 	intelObj->base.MinFilter == GL_LINEAR) && | ||||
|        intelImage->level == firstLevel) { | ||||
|       lastLevel = firstLevel; | ||||
|    } | ||||
|    else { | ||||
|       l2width = logbase2(width); | ||||
|       l2height = logbase2(height); | ||||
|       l2depth = logbase2(depth); | ||||
|       lastLevel = firstLevel + MAX2(MAX2(l2width,l2height),l2depth); | ||||
|    } | ||||
| 	  | ||||
|    assert(!intelObj->mt); | ||||
|    intelObj->mt = intel_miptree_create( intel, | ||||
| 					intelObj->base.Target, | ||||
| 					intelImage->base.InternalFormat, | ||||
| 					firstLevel, | ||||
| 					lastLevel, | ||||
| 					width, | ||||
| 					height, | ||||
| 					depth, | ||||
| 					intelImage->base.TexFormat->TexelBytes, | ||||
| 					intelImage->base.IsCompressed ); | ||||
|  | ||||
|    DBG("%s - success\n", __FUNCTION__); | ||||
| } | ||||
|     | ||||
|  | ||||
|  | ||||
|  | ||||
| static GLuint target_to_face( GLenum target ) | ||||
| { | ||||
|    switch (target) { | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: | ||||
|    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: | ||||
|       return ((GLuint) target -  | ||||
| 	      (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); | ||||
|    default: | ||||
|       return 0; | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intelTexImage(GLcontext *ctx,  | ||||
| 			  GLint dims, | ||||
| 			  GLenum target, GLint level, | ||||
| 			  GLint internalFormat, | ||||
| 			  GLint width, GLint height, GLint depth, | ||||
| 			  GLint border, | ||||
| 			  GLenum format, GLenum type, const void *pixels, | ||||
| 			  const struct gl_pixelstore_attrib *unpack, | ||||
| 			  struct gl_texture_object *texObj, | ||||
| 			  struct gl_texture_image *texImage) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(texObj); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|    GLint postConvWidth = width; | ||||
|    GLint postConvHeight = height; | ||||
|    GLint texelBytes, sizeInBytes; | ||||
|    GLuint dstRowStride; | ||||
|    GLuint dstImageStride; | ||||
|  | ||||
|  | ||||
|    DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, | ||||
| 		_mesa_lookup_enum_by_nr(target), | ||||
| 		level, | ||||
| 		width, height, depth, border); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    intelImage->face = target_to_face( target ); | ||||
|    intelImage->level = level; | ||||
|  | ||||
|    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { | ||||
|       _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, | ||||
|                                          &postConvHeight); | ||||
|    } | ||||
|  | ||||
|    /* choose the texture format */ | ||||
|    texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat,  | ||||
| 						  format, type); | ||||
|  | ||||
|    assert(texImage->TexFormat); | ||||
|  | ||||
|    switch (dims) { | ||||
|    case 1: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; | ||||
|       break; | ||||
|    case 2: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; | ||||
|       break; | ||||
|    case 3: | ||||
|       texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D; | ||||
|       texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df; | ||||
|       break; | ||||
|    default: | ||||
|       assert(0); | ||||
|       break; | ||||
|    } | ||||
|  | ||||
|    texelBytes = texImage->TexFormat->TexelBytes; | ||||
|  | ||||
|  | ||||
|    /* Minimum pitch of 32 bytes */ | ||||
|    if (postConvWidth * texelBytes < 32) { | ||||
|       postConvWidth = 32 / texelBytes; | ||||
|       texImage->RowStride = postConvWidth; | ||||
|    } | ||||
|  | ||||
|    assert(texImage->RowStride == postConvWidth); | ||||
|  | ||||
|    /* Release the reference to a potentially orphaned buffer.    | ||||
|     * Release any old malloced memory. | ||||
|     */ | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|       assert(!texImage->Data); | ||||
|    } | ||||
|    else if (texImage->Data) { | ||||
|       free(texImage->Data); | ||||
|    } | ||||
|  | ||||
|    /* If this is the only texture image in the tree, could call | ||||
|     * bmBufferData with NULL data to free the old block and avoid | ||||
|     * waiting on any outstanding fences. | ||||
|     */ | ||||
|    if (intelObj->mt &&  | ||||
|        intelObj->mt->first_level == level && | ||||
|        intelObj->mt->last_level == level && | ||||
|        intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB && | ||||
|        !intel_miptree_match_image(intelObj->mt, &intelImage->base, | ||||
| 				 intelImage->face, intelImage->level)) { | ||||
|  | ||||
|       DBG("release it\n"); | ||||
|       intel_miptree_release(intel, &intelObj->mt);  | ||||
|       assert(!intelObj->mt); | ||||
|    } | ||||
|     | ||||
|    if (!intelObj->mt) { | ||||
|       guess_and_alloc_mipmap_tree(intel, intelObj, intelImage); | ||||
|       if (!intelObj->mt) { | ||||
| 	 if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	    _mesa_printf("guess_and_alloc_mipmap_tree: failed\n"); | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (intelObj->mt &&  | ||||
|        intelObj->mt != intelImage->mt && | ||||
|        intel_miptree_match_image(intelObj->mt, &intelImage->base, | ||||
| 				 intelImage->face, intelImage->level)) { | ||||
|        | ||||
|       if (intelImage->mt) { | ||||
| 	 intel_miptree_release(intel, &intelImage->mt); | ||||
|       } | ||||
|  | ||||
|       intel_miptree_reference(&intelImage->mt, intelObj->mt); | ||||
|       assert(intelImage->mt); | ||||
|    } | ||||
|  | ||||
|    if (!intelImage->mt) { | ||||
|       if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
| 	 _mesa_printf("XXX: Image did not fit into tree - storing in local memory!\n"); | ||||
|    } | ||||
|  | ||||
|    /* intelCopyTexImage calls this function with pixels == NULL, with | ||||
|     * the expectation that the mipmap tree will be set up but nothing | ||||
|     * more will be done.  This is where those calls return: | ||||
|     */ | ||||
|    pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,  | ||||
| 					format, type, | ||||
| 					pixels, unpack, "glTexImage"); | ||||
|    if (!pixels)  | ||||
|       return; | ||||
|     | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|     | ||||
|    if (intelImage->mt) { | ||||
|       texImage->Data = intel_miptree_image_map(intel,  | ||||
| 					       intelImage->mt,  | ||||
| 					       intelImage->face,  | ||||
| 					       intelImage->level,  | ||||
| 					       &dstRowStride, | ||||
| 					       &dstImageStride);	  | ||||
|    } | ||||
|    else { | ||||
|       /* Allocate regular memory and store the image there temporarily.   */ | ||||
|       if (texImage->IsCompressed) { | ||||
| 	 sizeInBytes = texImage->CompressedSize; | ||||
|          dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width); | ||||
| 	 dstImageStride = 0;	/* ? */ | ||||
| 	 assert(dims != 3); | ||||
|       } | ||||
|       else { | ||||
|          dstRowStride = postConvWidth * texelBytes; | ||||
| 	 dstImageStride = dstRowStride * postConvHeight; | ||||
| 	 sizeInBytes = depth * dstImageStride; | ||||
|       } | ||||
|       texImage->Data = malloc(sizeInBytes); | ||||
|    } | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_TEXTURE) | ||||
|       _mesa_printf("Upload image %dx%dx%d row_len %x " | ||||
| 		   "pitch %x depth_pitch %x\n", | ||||
| 		   width, height, depth, | ||||
| 		   width * texelBytes, dstRowStride, dstImageStride); | ||||
|       | ||||
|    /* Copy data.  Would like to know when it's ok for us to eg. use | ||||
|     * the blitter to copy.  Or, use the hardware to do the format | ||||
|     * conversion and copy: | ||||
|     */ | ||||
|    if (!texImage->TexFormat->StoreImage(ctx, dims, | ||||
| 					texImage->_BaseFormat, | ||||
| 					texImage->TexFormat, | ||||
| 					texImage->Data, | ||||
| 					0, 0, 0,  /* dstX/Y/Zoffset */ | ||||
| 					dstRowStride, dstImageStride, | ||||
| 					width, height, depth, | ||||
| 					format, type, pixels, unpack)) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); | ||||
|    } | ||||
|  | ||||
|    _mesa_unmap_teximage_pbo(ctx, unpack); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap -- this can be accelerated now. | ||||
|     */ | ||||
|    if (level == texObj->BaseLevel &&  | ||||
|        texObj->GenerateMipmap) { | ||||
|       intel_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| void intelTexImage3D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint height, GLint depth, | ||||
| 		     GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *unpack, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage( ctx, 3, target, level,  | ||||
| 		  internalFormat, width, height, depth, border, | ||||
| 		  format, type, pixels, | ||||
| 		  unpack, texObj, texImage ); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelTexImage2D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint height, GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *unpack, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage( ctx, 2, target, level,  | ||||
| 		  internalFormat, width, height, 1, border, | ||||
| 		  format, type, pixels, | ||||
| 		  unpack, texObj, texImage ); | ||||
| } | ||||
|  | ||||
| void intelTexImage1D(GLcontext *ctx,  | ||||
| 		     GLenum target, GLint level, | ||||
| 		     GLint internalFormat, | ||||
| 		     GLint width, GLint border, | ||||
| 		     GLenum format, GLenum type, const void *pixels, | ||||
| 		     const struct gl_pixelstore_attrib *unpack, | ||||
| 		     struct gl_texture_object *texObj, | ||||
| 		     struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexImage( ctx, 1, target, level,  | ||||
| 		  internalFormat, width, 1, 1, border, | ||||
| 		  format, type, pixels, | ||||
| 		  unpack, texObj, texImage ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Need to map texture image into memory before copying image data, | ||||
|  * then unmap it. | ||||
|  */ | ||||
| void intelGetTexImage( GLcontext *ctx, GLenum target, GLint level, | ||||
|                        GLenum format, GLenum type, GLvoid *pixels, | ||||
|                        struct gl_texture_object *texObj, | ||||
|                        struct gl_texture_image *texImage ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|  | ||||
|    /* Map */ | ||||
| #ifdef ALL_IMAGES /* XXX Remove this, just for debug/test */ | ||||
|    intel_tex_map_images(intel, intel_texture_object(texObj)); | ||||
| #else | ||||
|    /* XXX what if intelImage->mt is NULL? */ | ||||
|    if (intelImage->mt) { | ||||
|       intelImage->base.Data =  | ||||
|          intel_miptree_image_map(intel,  | ||||
|                                  intelImage->mt, | ||||
|                                  intelImage->face, | ||||
|                                  intelImage->level, | ||||
|                                  &intelImage->base.RowStride, | ||||
|                                  &intelImage->base.ImageStride); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    _mesa_get_teximage(ctx, target, level, format, type, pixels, | ||||
|                       texObj, texImage); | ||||
|  | ||||
|    /* Unmap */ | ||||
| #ifdef ALL_IMAGES | ||||
|    intel_tex_unmap_images(intel, intel_texture_object(texObj)); | ||||
| #else | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       intelImage->base.Data = NULL; | ||||
|    } | ||||
| #endif | ||||
| } | ||||
|  | ||||
							
								
								
									
										178
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/mesa/drivers/dri/i915/intel_tex_subimage.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
|  | ||||
| /************************************************************************** | ||||
|  *  | ||||
|  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | ||||
|  * All Rights Reserved. | ||||
|  *  | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sub license, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice (including the | ||||
|  * next paragraph) shall be included in all copies or substantial portions | ||||
|  * of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. | ||||
|  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR | ||||
|  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
|  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
|  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  *  | ||||
|  **************************************************************************/ | ||||
|  | ||||
| #include "mtypes.h" | ||||
| #include "texobj.h" | ||||
| #include "texstore.h" | ||||
| #include "enums.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
|  | ||||
|  | ||||
| static void intelTexSubimage (GLcontext *ctx, | ||||
| 			      GLint dims, | ||||
| 			      GLenum target, GLint level, | ||||
| 			      GLint xoffset, GLint yoffset, GLint zoffset, | ||||
| 			      GLint width, GLint height, GLint depth, | ||||
| 			      GLenum format, GLenum type, const void *pixels, | ||||
| 			      const struct gl_pixelstore_attrib *packing, | ||||
| 			      struct gl_texture_object *texObj, | ||||
| 			      struct gl_texture_image *texImage) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    struct intel_texture_image *intelImage = intel_texture_image(texImage); | ||||
|    GLuint dstImageStride; | ||||
|    GLuint dstRowStride; | ||||
|  | ||||
|    DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, | ||||
| 		_mesa_lookup_enum_by_nr(target), | ||||
| 		level, | ||||
| 		xoffset, yoffset, | ||||
| 		width, height); | ||||
|  | ||||
|    intelFlush(ctx); | ||||
|  | ||||
|    pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, type, | ||||
|                                         pixels, packing, "glTexSubImage2D"); | ||||
|    if (!pixels) | ||||
|       return; | ||||
|  | ||||
|    LOCK_HARDWARE(intel); | ||||
|  | ||||
|    /* Map buffer if necessary.  Need to lock to prevent other contexts | ||||
|     * from uploading the buffer under us. | ||||
|     */ | ||||
|    if (intelImage->mt)  | ||||
|       texImage->Data = intel_miptree_image_map(intel,  | ||||
| 					       intelImage->mt,  | ||||
| 					       intelImage->face,  | ||||
| 					       intelImage->level,  | ||||
| 					       &dstRowStride, | ||||
| 					       &dstImageStride ); | ||||
|        | ||||
|    assert(dstRowStride); | ||||
|  | ||||
|    if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, | ||||
| 					texImage->TexFormat, | ||||
| 					texImage->Data, | ||||
| 					xoffset, yoffset, zoffset, | ||||
| 					dstRowStride, dstImageStride, | ||||
| 					width, height, depth, | ||||
| 					format, type, pixels, packing)) { | ||||
|       _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); | ||||
|    } | ||||
|  | ||||
| #if 0 | ||||
|    /* GL_SGIS_generate_mipmap */ | ||||
|    if (level == texObj->BaseLevel && texObj->GenerateMipmap) { | ||||
|       _mesa_generate_mipmap(ctx, target, | ||||
|                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit], | ||||
|                             texObj); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    _mesa_unmap_teximage_pbo(ctx, packing); | ||||
|  | ||||
|    if (intelImage->mt) { | ||||
|       intel_miptree_image_unmap(intel, intelImage->mt); | ||||
|       texImage->Data = NULL; | ||||
|    } | ||||
|  | ||||
|    UNLOCK_HARDWARE(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelTexSubImage3D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, GLint yoffset, GLint zoffset, | ||||
| 			GLsizei width, GLsizei height, GLsizei depth, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage) | ||||
| { | ||||
|  | ||||
|    intelTexSubimage(ctx, 3, | ||||
| 		    target, level,  | ||||
| 		    xoffset, yoffset, zoffset, | ||||
| 		    width, height, depth, | ||||
| 		    format, type, pixels, packing, texObj, | ||||
| 		    texImage); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intelTexSubImage2D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, GLint yoffset, | ||||
| 			GLsizei width, GLsizei height, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage) | ||||
| { | ||||
|  | ||||
|    intelTexSubimage(ctx, 2, | ||||
| 		    target, level,  | ||||
| 		    xoffset, yoffset, 0, | ||||
| 		    width, height, 1, | ||||
| 		    format, type, pixels, packing, texObj, | ||||
| 		    texImage); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelTexSubImage1D(GLcontext *ctx, | ||||
| 			GLenum target, | ||||
| 			GLint level, | ||||
| 			GLint xoffset, | ||||
| 			GLsizei width, | ||||
| 			GLenum format, GLenum type, | ||||
| 			const GLvoid *pixels, | ||||
| 			const struct gl_pixelstore_attrib *packing, | ||||
| 			struct gl_texture_object *texObj, | ||||
| 			struct gl_texture_image *texImage) | ||||
| { | ||||
|    intelTexSubimage(ctx, 1, | ||||
| 		    target, level,  | ||||
| 		    xoffset, 0, 0, | ||||
| 		    width, 1, 1, | ||||
| 		    format, type, pixels, packing, texObj, | ||||
| 		    texImage); | ||||
|  | ||||
| } | ||||
							
								
								
									
										247
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								src/mesa/drivers/dri/i915/intel_tex_validate.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
| #include "mtypes.h" | ||||
| #include "macros.h" | ||||
|  | ||||
| #include "intel_context.h" | ||||
| #include "intel_mipmap_tree.h" | ||||
| #include "intel_tex.h" | ||||
| #include "intel_bufmgr.h" | ||||
|  | ||||
| /** | ||||
|  * Compute which mipmap levels that really need to be sent to the hardware. | ||||
|  * This depends on the base image size, GL_TEXTURE_MIN_LOD, | ||||
|  * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. | ||||
|  */ | ||||
| static void intel_calculate_first_last_level( struct intel_texture_object *intelObj ) | ||||
| { | ||||
|    struct gl_texture_object *tObj = &intelObj->base; | ||||
|    const struct gl_texture_image * const baseImage = | ||||
|        tObj->Image[0][tObj->BaseLevel]; | ||||
|  | ||||
|    /* These must be signed values.  MinLod and MaxLod can be negative numbers, | ||||
|     * and having firstLevel and lastLevel as signed prevents the need for | ||||
|     * extra sign checks. | ||||
|     */ | ||||
|    int   firstLevel; | ||||
|    int   lastLevel; | ||||
|  | ||||
|    /* Yes, this looks overly complicated, but it's all needed. | ||||
|     */ | ||||
|    switch (tObj->Target) { | ||||
|    case GL_TEXTURE_1D: | ||||
|    case GL_TEXTURE_2D: | ||||
|    case GL_TEXTURE_3D: | ||||
|    case GL_TEXTURE_CUBE_MAP: | ||||
|       if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { | ||||
|          /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. | ||||
|           */ | ||||
|          firstLevel = lastLevel = tObj->BaseLevel; | ||||
|       } | ||||
|       else { | ||||
| 	 firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5); | ||||
| 	 firstLevel = MAX2(firstLevel, tObj->BaseLevel); | ||||
| 	 lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5); | ||||
| 	 lastLevel = MAX2(lastLevel, tObj->BaseLevel); | ||||
| 	 lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); | ||||
| 	 lastLevel = MIN2(lastLevel, tObj->MaxLevel); | ||||
| 	 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ | ||||
|       } | ||||
|       break; | ||||
|    case GL_TEXTURE_RECTANGLE_NV: | ||||
|    case GL_TEXTURE_4D_SGIS: | ||||
|       firstLevel = lastLevel = 0; | ||||
|       break; | ||||
|    default: | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    /* save these values */ | ||||
|    intelObj->firstLevel = firstLevel; | ||||
|    intelObj->lastLevel = lastLevel; | ||||
| } | ||||
|  | ||||
| static void copy_image_data_to_tree( struct intel_context *intel, | ||||
| 				     struct intel_texture_object *intelObj, | ||||
| 				     struct intel_texture_image *intelImage ) | ||||
| { | ||||
|    if (intelImage->mt) { | ||||
|       /* Copy potentially with the blitter: | ||||
|        */ | ||||
|       intel_miptree_image_copy(intel, | ||||
| 			       intelObj->mt, | ||||
| 			       intelImage->face, | ||||
| 			       intelImage->level, | ||||
| 			       intelImage->mt); | ||||
|  | ||||
|       intel_miptree_release(intel, &intelImage->mt); | ||||
|    } | ||||
|    else { | ||||
|       assert(intelImage->base.Data != NULL); | ||||
|  | ||||
|       /* More straightforward upload.   | ||||
|        */ | ||||
|       intel_miptree_image_data(intel, | ||||
| 			       intelObj->mt, | ||||
| 			       intelImage->face, | ||||
| 			       intelImage->level, | ||||
| 			       intelImage->base.Data, | ||||
| 			       intelImage->base.RowStride, | ||||
| 			       intelImage->base.RowStride * intelImage->base.Height); | ||||
|  | ||||
|       free(intelImage->base.Data); | ||||
|       intelImage->base.Data = NULL; | ||||
|    } | ||||
|  | ||||
|    intel_miptree_reference(&intelImage->mt, intelObj->mt); | ||||
| } | ||||
|  | ||||
|  | ||||
| /*   | ||||
|  */ | ||||
| GLuint intel_finalize_mipmap_tree( struct intel_context *intel, GLuint unit ) | ||||
| { | ||||
|    struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; | ||||
|    struct intel_texture_object *intelObj = intel_texture_object(tObj); | ||||
|  | ||||
|    GLuint face, i; | ||||
|    GLuint nr_faces = 0; | ||||
|    struct intel_texture_image *firstImage; | ||||
|  | ||||
|    /* We know/require this is true by now:  | ||||
|     */ | ||||
|    assert(intelObj->base.Complete); | ||||
|  | ||||
|    /* What levels must the tree include at a minimum? | ||||
|     */ | ||||
|    intel_calculate_first_last_level( intelObj ); | ||||
|    firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]); | ||||
|  | ||||
|    /* Fallback case: | ||||
|     */ | ||||
|    if (firstImage->base.Border) { | ||||
|       if (intelObj->mt) { | ||||
| 	 intel_miptree_release(intel, &intelObj->mt); | ||||
|       } | ||||
|       return GL_FALSE; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    /* If both firstImage and intelObj have a tree which can contain | ||||
|     * all active images, favour firstImage.  Note that because of the | ||||
|     * completeness requirement, we know that the image dimensions | ||||
|     * will match. | ||||
|     */ | ||||
|    if (firstImage->mt && | ||||
|        firstImage->mt != intelObj->mt && | ||||
|        firstImage->mt->first_level <= intelObj->firstLevel && | ||||
|        firstImage->mt->last_level >= intelObj->lastLevel) { | ||||
|  | ||||
|       if (intelObj->mt)  | ||||
| 	 intel_miptree_release(intel, &intelObj->mt); | ||||
|  | ||||
|       intel_miptree_reference(&intelObj->mt, firstImage->mt); | ||||
|    } | ||||
|  | ||||
|    /* Check tree can hold all active levels.  Check tree matches | ||||
|     * target, imageFormat, etc. | ||||
|     *  | ||||
|     * XXX: For some layouts (eg i945?), the test might have to be | ||||
|     * first_level == firstLevel, as the tree isn't valid except at the | ||||
|     * original start level.  Hope to get around this by | ||||
|     * programming minLod, maxLod, baseLevel into the hardware and | ||||
|     * leaving the tree alone. | ||||
|     */ | ||||
|    if (intelObj->mt && | ||||
|        ((intelObj->mt->first_level > intelObj->firstLevel) || | ||||
| 	(intelObj->mt->last_level < intelObj->lastLevel) || | ||||
| 	(intelObj->mt->internal_format != firstImage->base.InternalFormat))) { | ||||
|       intel_miptree_release(intel, &intelObj->mt); | ||||
|    } | ||||
|        | ||||
|  | ||||
|    /* May need to create a new tree: | ||||
|     */ | ||||
|    if (!intelObj->mt) { | ||||
|       intelObj->mt = intel_miptree_create(intel, | ||||
| 					  intelObj->base.Target, | ||||
| 					  firstImage->base.InternalFormat, | ||||
| 					  intelObj->firstLevel, | ||||
| 					  intelObj->lastLevel, | ||||
| 					  firstImage->base.Width, | ||||
| 					  firstImage->base.Height, | ||||
| 					  firstImage->base.Depth, | ||||
| 					  firstImage->base.TexFormat->TexelBytes, | ||||
| 					  firstImage->base.IsCompressed); | ||||
|    } | ||||
|  | ||||
|    /* Pull in any images not in the object's tree: | ||||
|     */ | ||||
|    nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { | ||||
| 	 struct intel_texture_image *intelImage =  | ||||
| 	    intel_texture_image(intelObj->base.Image[face][i]); | ||||
| 	  | ||||
| 	 /* Need to import images in main memory or held in other trees. | ||||
| 	  */ | ||||
| 	 if (intelObj->mt != intelImage->mt) { | ||||
| 	    copy_image_data_to_tree(intel, | ||||
| 				    intelObj, | ||||
| 				    intelImage); | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    return GL_TRUE; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intel_tex_map_images( struct intel_context *intel, | ||||
| 			   struct intel_texture_object *intelObj ) | ||||
| { | ||||
|    GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    GLuint face, i; | ||||
|     | ||||
|    DBG("%s\n", __FUNCTION__); | ||||
|  | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { | ||||
| 	 struct intel_texture_image *intelImage =  | ||||
| 	    intel_texture_image(intelObj->base.Image[face][i]); | ||||
|  | ||||
| 	 if (intelImage->mt) { | ||||
| 	    intelImage->base.Data =  | ||||
| 	       intel_miptree_image_map(intel,  | ||||
| 				       intelImage->mt, | ||||
| 				       intelImage->face, | ||||
| 				       intelImage->level, | ||||
| 				       &intelImage->base.RowStride, | ||||
| 				       &intelImage->base.ImageStride); | ||||
|             /* convert stride to texels, not bytes */ | ||||
|             intelImage->base.RowStride /= intelImage->mt->cpp; | ||||
|             intelImage->base.ImageStride /= intelImage->mt->cpp; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void intel_tex_unmap_images( struct intel_context *intel, | ||||
| 			     struct intel_texture_object *intelObj ) | ||||
| { | ||||
|    GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; | ||||
|    GLuint face, i; | ||||
|  | ||||
|    for (face = 0; face < nr_faces; face++) { | ||||
|       for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { | ||||
| 	 struct intel_texture_image *intelImage =  | ||||
| 	    intel_texture_image(intelObj->base.Image[face][i]); | ||||
|  | ||||
| 	 if (intelImage->mt) { | ||||
| 	    intel_miptree_image_unmap(intel, intelImage->mt); | ||||
| 	    intelImage->base.Data = NULL; | ||||
| 	 } | ||||
|       } | ||||
|    } | ||||
| } | ||||
| @@ -38,14 +38,95 @@ | ||||
| #include "tnl/t_vertex.h" | ||||
|  | ||||
| #include "intel_screen.h" | ||||
| #include "intel_context.h" | ||||
| #include "intel_tris.h" | ||||
| #include "intel_batchbuffer.h" | ||||
| #include "intel_reg.h" | ||||
| #include "intel_span.h" | ||||
| #include "intel_tex.h" | ||||
|  | ||||
| static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ); | ||||
| static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ); | ||||
|  | ||||
| /* | ||||
|  */ | ||||
| static void intel_flush_inline_primitive( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint used = intel->batch->ptr - intel->prim.start_ptr; | ||||
|  | ||||
|    assert(intel->prim.primitive != ~0); | ||||
|  | ||||
|    if (used < 8) | ||||
|       goto do_discard; | ||||
|  | ||||
|    *(int *)intel->prim.start_ptr = (_3DPRIMITIVE |  | ||||
| 				    intel->prim.primitive | | ||||
| 				    (used/4-2)); | ||||
|  | ||||
|    goto finished; | ||||
|     | ||||
|  do_discard: | ||||
|    intel->batch->ptr -= used; | ||||
|  | ||||
|  finished: | ||||
|    intel->prim.primitive = ~0; | ||||
|    intel->prim.start_ptr = 0; | ||||
|    intel->prim.flush = 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Emit a primitive referencing vertices in a vertex buffer. | ||||
|  */ | ||||
| void intelStartInlinePrimitive( struct intel_context *intel,  | ||||
| 				GLuint prim,  | ||||
| 				GLuint batch_flags ) | ||||
| { | ||||
|    BATCH_LOCALS; | ||||
|     | ||||
|    /* Emit a slot which will be filled with the inline primitive | ||||
|     * command later. | ||||
|     */ | ||||
|    BEGIN_BATCH(2, batch_flags); | ||||
|    OUT_BATCH( 0 ); | ||||
|  | ||||
|    intel->prim.start_ptr = intel->batch->ptr; | ||||
|    intel->prim.primitive = prim; | ||||
|    intel->prim.flush = intel_flush_inline_primitive; | ||||
|  | ||||
|    OUT_BATCH( 0 ); | ||||
|    ADVANCE_BATCH(); | ||||
| } | ||||
|  | ||||
|  | ||||
| void intelWrapInlinePrimitive( struct intel_context *intel ) | ||||
| { | ||||
|    GLuint prim = intel->prim.primitive; | ||||
|    GLuint batchflags = intel->batch->flags; | ||||
|  | ||||
|    intel_flush_inline_primitive(intel); | ||||
|    intel_batchbuffer_flush(intel->batch); | ||||
|  | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|    intelStartInlinePrimitive( intel, prim, batchflags ); /* ??? */ | ||||
| } | ||||
|  | ||||
| GLuint *intelExtendInlinePrimitive( struct intel_context *intel,  | ||||
| 				    GLuint dwords ) | ||||
| { | ||||
|    GLuint sz = dwords * sizeof(GLuint); | ||||
|    GLuint *ptr; | ||||
|  | ||||
|    if (intel_batchbuffer_space(intel->batch) < sz)  | ||||
|       intelWrapInlinePrimitive( intel ); | ||||
|  | ||||
|    ptr = (GLuint *)intel->batch->ptr; | ||||
|    intel->batch->ptr += sz; | ||||
|  | ||||
|    return ptr; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /*********************************************************************** | ||||
|  *                    Emit primitives as inline vertices               * | ||||
|  ***********************************************************************/ | ||||
| @@ -63,22 +144,18 @@ do {								\ | ||||
| #else | ||||
| #define COPY_DWORDS( j, vb, vertsize, v )	\ | ||||
| do {						\ | ||||
|    if (0) fprintf(stderr, "\n");	\ | ||||
|    for ( j = 0 ; j < vertsize ; j++ ) {		\ | ||||
|       if (0) fprintf(stderr, "   -- v(%d): %x/%f\n",j,	\ | ||||
| 	      ((GLuint *)v)[j],			\ | ||||
| 	      ((GLfloat *)v)[j]);		\ | ||||
|       vb[j] = ((GLuint *)v)[j];			\ | ||||
|    }						\ | ||||
|    vb += vertsize;				\ | ||||
| } while (0) | ||||
| #endif | ||||
|  | ||||
| static void __inline__ intel_draw_quad( intelContextPtr intel, | ||||
| 					intelVertexPtr v0, | ||||
| 					intelVertexPtr v1, | ||||
| 					intelVertexPtr v2, | ||||
| 					intelVertexPtr v3 ) | ||||
| static void intel_draw_quad( struct intel_context *intel, | ||||
| 			     intelVertexPtr v0, | ||||
| 			     intelVertexPtr v1, | ||||
| 			     intelVertexPtr v2, | ||||
| 			     intelVertexPtr v3 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, 6 * vertsize ); | ||||
| @@ -92,10 +169,10 @@ static void __inline__ intel_draw_quad( intelContextPtr intel, | ||||
|    COPY_DWORDS( j, vb, vertsize, v3 ); | ||||
| } | ||||
|  | ||||
| static void __inline__ intel_draw_triangle( intelContextPtr intel, | ||||
| 					    intelVertexPtr v0, | ||||
| 					    intelVertexPtr v1, | ||||
| 					    intelVertexPtr v2 ) | ||||
| static void intel_draw_triangle( struct intel_context *intel, | ||||
| 				 intelVertexPtr v0, | ||||
| 				 intelVertexPtr v1, | ||||
| 				 intelVertexPtr v2 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, 3 * vertsize ); | ||||
| @@ -107,9 +184,9 @@ static void __inline__ intel_draw_triangle( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ void intel_draw_line( intelContextPtr intel, | ||||
| 					intelVertexPtr v0, | ||||
| 					intelVertexPtr v1 ) | ||||
| static void intel_draw_line( struct intel_context *intel, | ||||
| 			     intelVertexPtr v0, | ||||
| 			     intelVertexPtr v1 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, 2 * vertsize ); | ||||
| @@ -120,8 +197,8 @@ static __inline__ void intel_draw_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static __inline__ void intel_draw_point( intelContextPtr intel, | ||||
| 					 intelVertexPtr v0 ) | ||||
| static void intel_draw_point( struct intel_context *intel, | ||||
| 			      intelVertexPtr v0 ) | ||||
| { | ||||
|    GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, vertsize ); | ||||
| @@ -140,7 +217,7 @@ static __inline__ void intel_draw_point( intelContextPtr intel, | ||||
|  *                Fixup for ARB_point_parameters                       * | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 ) | ||||
| static void intel_atten_point( struct intel_context *intel, intelVertexPtr v0 ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    GLfloat psz[4], col[4], restore_psz, restore_alpha; | ||||
| @@ -189,7 +266,7 @@ static void intel_atten_point( intelContextPtr intel, intelVertexPtr v0 ) | ||||
|  | ||||
|  | ||||
|  | ||||
| static void intel_wpos_triangle( intelContextPtr intel, | ||||
| static void intel_wpos_triangle( struct intel_context *intel, | ||||
| 				 intelVertexPtr v0, | ||||
| 				 intelVertexPtr v1, | ||||
| 				 intelVertexPtr v2 ) | ||||
| @@ -205,7 +282,7 @@ static void intel_wpos_triangle( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intel_wpos_line( intelContextPtr intel, | ||||
| static void intel_wpos_line( struct intel_context *intel, | ||||
| 			     intelVertexPtr v0, | ||||
| 			     intelVertexPtr v1 ) | ||||
| { | ||||
| @@ -219,7 +296,7 @@ static void intel_wpos_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void intel_wpos_point( intelContextPtr intel, | ||||
| static void intel_wpos_point( struct intel_context *intel, | ||||
| 			      intelVertexPtr v0 ) | ||||
| { | ||||
|    GLuint offset = intel->wpos_offset; | ||||
| @@ -349,7 +426,7 @@ do {							\ | ||||
| #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] | ||||
|  | ||||
| #define LOCAL_VARS(n)							\ | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx);				\ | ||||
|    struct intel_context *intel = intel_context(ctx);				\ | ||||
|    GLuint color[n], spec[n];						\ | ||||
|    GLuint coloroffset = intel->coloroffset;		\ | ||||
|    GLboolean specoffset = intel->specoffset;			\ | ||||
| @@ -481,7 +558,7 @@ static void init_rast_tab( void ) | ||||
|  * primitives. | ||||
|  */ | ||||
| static void | ||||
| intel_fallback_tri( intelContextPtr intel, | ||||
| intel_fallback_tri( struct intel_context *intel, | ||||
| 		   intelVertex *v0, | ||||
| 		   intelVertex *v1, | ||||
| 		   intelVertex *v2 ) | ||||
| @@ -491,6 +568,9 @@ intel_fallback_tri( intelContextPtr intel, | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "\n%s\n", __FUNCTION__); | ||||
|     | ||||
|    if (intel->prim.flush) | ||||
|       intel->prim.flush(intel); | ||||
|  | ||||
|    _swsetup_Translate( ctx, v0, &v[0] ); | ||||
|    _swsetup_Translate( ctx, v1, &v[1] ); | ||||
| @@ -502,7 +582,7 @@ intel_fallback_tri( intelContextPtr intel, | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_fallback_line( intelContextPtr intel, | ||||
| intel_fallback_line( struct intel_context *intel, | ||||
| 		    intelVertex *v0, | ||||
| 		    intelVertex *v1 ) | ||||
| { | ||||
| @@ -512,6 +592,9 @@ intel_fallback_line( intelContextPtr intel, | ||||
|    if (0) | ||||
|       fprintf(stderr, "\n%s\n", __FUNCTION__); | ||||
|  | ||||
|    if (intel->prim.flush) | ||||
|       intel->prim.flush(intel); | ||||
|  | ||||
|    _swsetup_Translate( ctx, v0, &v[0] ); | ||||
|    _swsetup_Translate( ctx, v1, &v[1] ); | ||||
|    intelSpanRenderStart( ctx ); | ||||
| @@ -520,24 +603,6 @@ intel_fallback_line( intelContextPtr intel, | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| intel_fallback_point( intelContextPtr intel, | ||||
| 		     intelVertex *v0 ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    SWvertex v[1]; | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "\n%s\n", __FUNCTION__); | ||||
|  | ||||
|    _swsetup_Translate( ctx, v0, &v[0] ); | ||||
|    intelSpanRenderStart( ctx ); | ||||
|    _swrast_Point( ctx, &v[0] ); | ||||
|    intelSpanRenderFinish( ctx ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /*               Render unclipped begin/end objects                   */ | ||||
| /**********************************************************************/ | ||||
| @@ -552,7 +617,7 @@ intel_fallback_point( intelContextPtr intel, | ||||
| #define INIT(x) intelRenderPrimitive( ctx, x ) | ||||
| #undef LOCAL_VARS | ||||
| #define LOCAL_VARS						\ | ||||
|     intelContextPtr intel = INTEL_CONTEXT(ctx);			\ | ||||
|     struct intel_context *intel = intel_context(ctx);			\ | ||||
|     GLubyte *vertptr = (GLubyte *)intel->verts;			\ | ||||
|     const GLuint vertsize = intel->vertex_size;       	\ | ||||
|     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;	\ | ||||
| @@ -578,7 +643,7 @@ intel_fallback_point( intelContextPtr intel, | ||||
| static void intelRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
| 				   GLuint n ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; | ||||
|    GLuint prim = intel->render_primitive; | ||||
| @@ -609,7 +674,7 @@ static void intelRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) | ||||
| static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
| 				       GLuint n ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT( ctx ); | ||||
|    struct intel_context *intel = intel_context( ctx ); | ||||
|    const GLuint vertsize = intel->vertex_size; | ||||
|    GLuint *vb = intelExtendInlinePrimitive( intel, (n-2) * 3 * vertsize ); | ||||
|    GLubyte *vertptr = (GLubyte *)intel->verts; | ||||
| @@ -630,17 +695,13 @@ static void intelFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, | ||||
|  | ||||
|  | ||||
|  | ||||
| #define POINT_FALLBACK (0) | ||||
| #define LINE_FALLBACK (DD_LINE_STIPPLE) | ||||
| #define TRI_FALLBACK (0) | ||||
| #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\ | ||||
|                             DD_TRI_STIPPLE|DD_POINT_ATTEN) | ||||
| #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED) | ||||
| #define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN) | ||||
| #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED) | ||||
|  | ||||
| void intelChooseRenderState(GLcontext *ctx) | ||||
| { | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|    GLuint flags = ctx->_TriangleCaps; | ||||
|    struct fragment_program *fprog = ctx->FragmentProgram._Current; | ||||
|    GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS)); | ||||
| @@ -676,15 +737,9 @@ void intelChooseRenderState(GLcontext *ctx) | ||||
|        */ | ||||
|       if (flags & ANY_FALLBACK_FLAGS) | ||||
|       { | ||||
| 	 if (flags & POINT_FALLBACK) | ||||
| 	    intel->draw_point = intel_fallback_point; | ||||
|  | ||||
| 	 if (flags & LINE_FALLBACK) | ||||
| 	 if (flags & DD_LINE_STIPPLE) | ||||
| 	    intel->draw_line = intel_fallback_line; | ||||
|  | ||||
| 	 if (flags & TRI_FALLBACK) | ||||
| 	    intel->draw_tri = intel_fallback_tri; | ||||
|  | ||||
| 	 if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)  | ||||
| 	    intel->draw_tri = intel_fallback_tri; | ||||
|  | ||||
| @@ -740,7 +795,7 @@ static const GLenum reduced_prim[GL_POLYGON+1] = { | ||||
|  | ||||
| static void intelRunPipeline( GLcontext *ctx ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (intel->NewGLState) { | ||||
|       if (intel->NewGLState & _NEW_TEXTURE) { | ||||
| @@ -760,13 +815,21 @@ static void intelRunPipeline( GLcontext *ctx ) | ||||
|  | ||||
| static void intelRenderStart( GLcontext *ctx ) | ||||
| { | ||||
|    INTEL_CONTEXT(ctx)->vtbl.render_start( INTEL_CONTEXT(ctx) ); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    intel->vtbl.render_start( intel_context(ctx) ); | ||||
|    intel->vtbl.emit_state( intel ); | ||||
| } | ||||
|  | ||||
| static void intelRenderFinish( GLcontext *ctx ) | ||||
| { | ||||
|    if (INTEL_CONTEXT(ctx)->RenderIndex & INTEL_FALLBACK_BIT) | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (intel->RenderIndex & INTEL_FALLBACK_BIT) | ||||
|       _swrast_flush( ctx ); | ||||
|  | ||||
|    if (intel->prim.flush) | ||||
|       intel->prim.flush(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -777,7 +840,7 @@ static void intelRenderFinish( GLcontext *ctx ) | ||||
|   */ | ||||
| static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
| { | ||||
|    intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %s %x\n", __FUNCTION__,  | ||||
| @@ -787,111 +850,185 @@ static void intelRasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ) | ||||
|      | ||||
|    /* Start a new primitive.  Arrange to have it flushed later on. | ||||
|     */ | ||||
|    if (hwprim != intel->prim.primitive)  | ||||
|       intelStartInlinePrimitive( intel, hwprim ); | ||||
|    if (hwprim != intel->prim.primitive) { | ||||
|       if (intel->prim.flush) | ||||
| 	 intel->prim.flush(intel); | ||||
|  | ||||
|       intelStartInlinePrimitive( intel, hwprim, INTEL_BATCH_CLIPRECTS ); | ||||
|    } | ||||
| } | ||||
|  | ||||
|  | ||||
|  /*  | ||||
|   */ | ||||
|  static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ) | ||||
|  { | ||||
|     intelContextPtr intel = INTEL_CONTEXT(ctx); | ||||
| static void intelRenderPrimitive( GLcontext *ctx, GLenum prim ) | ||||
| { | ||||
|    struct intel_context *intel = intel_context(ctx); | ||||
|  | ||||
|     if (0) | ||||
|        fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|    if (0) | ||||
|       fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); | ||||
|  | ||||
|     /* Let some clipping routines know which primitive they're dealing | ||||
|      * with. | ||||
|      */ | ||||
|     intel->render_primitive = prim; | ||||
|    /* Let some clipping routines know which primitive they're dealing | ||||
|     * with. | ||||
|     */ | ||||
|    intel->render_primitive = prim; | ||||
|  | ||||
|     /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled | ||||
|      * triangles.  The rasterized primitive will always be reset by | ||||
|      * lower level functions in that case, potentially pingponging the | ||||
|      * state: | ||||
|      */ | ||||
|     if (reduced_prim[prim] == GL_TRIANGLES &&  | ||||
| 	(ctx->_TriangleCaps & DD_TRI_UNFILLED)) | ||||
|        return; | ||||
|    /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled | ||||
|     * triangles.  The rasterized primitive will always be reset by | ||||
|     * lower level functions in that case, potentially pingponging the | ||||
|     * state: | ||||
|     */ | ||||
|    if (reduced_prim[prim] == GL_TRIANGLES &&  | ||||
|        (ctx->_TriangleCaps & DD_TRI_UNFILLED)) | ||||
|       return; | ||||
|  | ||||
|     /* Set some primitive-dependent state and Start? a new primitive. | ||||
|      */ | ||||
|     intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] ); | ||||
|  } | ||||
|    /* Set some primitive-dependent state and Start? a new primitive. | ||||
|     */ | ||||
|    intelRasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] ); | ||||
| } | ||||
|  | ||||
|  | ||||
|  /**********************************************************************/ | ||||
|  /*           Transition to/from hardware rasterization.               */ | ||||
|  /**********************************************************************/ | ||||
|  | ||||
|  static char *fallbackStrings[] = { | ||||
|     "Texture", | ||||
|     "Draw buffer", | ||||
|     "Read buffer", | ||||
|     "Color mask", | ||||
|     "Render mode", | ||||
|     "Stencil", | ||||
|     "Stipple", | ||||
|     "User disable" | ||||
|  }; | ||||
| static char *fallbackStrings[] = { | ||||
|    "Texture", | ||||
|    "Draw buffer", | ||||
|    "Read buffer", | ||||
|    "Color mask", | ||||
|    "Render mode", | ||||
|    "Stencil", | ||||
|    "Stipple", | ||||
|    "User disable" | ||||
| }; | ||||
|  | ||||
|  | ||||
|  static char *getFallbackString(GLuint bit) | ||||
|  { | ||||
|     int i = 0; | ||||
|     while (bit > 1) { | ||||
|        i++; | ||||
|        bit >>= 1; | ||||
|     } | ||||
|     return fallbackStrings[i]; | ||||
|  } | ||||
| static char *getFallbackString(GLuint bit) | ||||
| { | ||||
|    int i = 0; | ||||
|    while (bit > 1) { | ||||
|       i++; | ||||
|       bit >>= 1; | ||||
|    } | ||||
|    return fallbackStrings[i]; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ) | ||||
|  { | ||||
|     GLcontext *ctx = &intel->ctx; | ||||
|     TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|     GLuint oldfallback = intel->Fallback; | ||||
| void intelFallback( struct intel_context *intel, GLuint bit, GLboolean mode ) | ||||
| { | ||||
|    GLcontext *ctx = &intel->ctx; | ||||
|    TNLcontext *tnl = TNL_CONTEXT(ctx); | ||||
|    GLuint oldfallback = intel->Fallback; | ||||
|  | ||||
|     if (mode) { | ||||
|        intel->Fallback |= bit; | ||||
|        if (oldfallback == 0) { | ||||
| 	  intelFlush(ctx); | ||||
| 	  if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	     fprintf(stderr, "ENTER FALLBACK %x: %s\n", | ||||
| 		     bit, getFallbackString( bit )); | ||||
| 	  _swsetup_Wakeup( ctx ); | ||||
| 	  intel->RenderIndex = ~0; | ||||
|        } | ||||
|     } | ||||
|     else { | ||||
|        intel->Fallback &= ~bit; | ||||
|        if (oldfallback == bit) { | ||||
| 	  _swrast_flush( ctx ); | ||||
| 	  if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	     fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit )); | ||||
| 	  tnl->Driver.Render.Start = intelRenderStart; | ||||
| 	  tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; | ||||
| 	  tnl->Driver.Render.Finish = intelRenderFinish; | ||||
| 	  tnl->Driver.Render.BuildVertices = _tnl_build_vertices; | ||||
| 	  tnl->Driver.Render.CopyPV = _tnl_copy_pv; | ||||
| 	  tnl->Driver.Render.Interp = _tnl_interp; | ||||
|    if (mode) { | ||||
|       intel->Fallback |= bit; | ||||
|       if (oldfallback == 0) { | ||||
| 	 intelFlush(ctx); | ||||
| 	 if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	    fprintf(stderr, "ENTER FALLBACK %x: %s\n", | ||||
| 		    bit, getFallbackString( bit )); | ||||
| 	 _swsetup_Wakeup( ctx ); | ||||
| 	 intel->RenderIndex = ~0; | ||||
|       } | ||||
|    } | ||||
|    else { | ||||
|       intel->Fallback &= ~bit; | ||||
|       if (oldfallback == bit) { | ||||
| 	 _swrast_flush( ctx ); | ||||
| 	 if (INTEL_DEBUG & DEBUG_FALLBACKS)  | ||||
| 	    fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit )); | ||||
| 	 tnl->Driver.Render.Start = intelRenderStart; | ||||
| 	 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; | ||||
| 	 tnl->Driver.Render.Finish = intelRenderFinish; | ||||
| 	 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; | ||||
| 	 tnl->Driver.Render.CopyPV = _tnl_copy_pv; | ||||
| 	 tnl->Driver.Render.Interp = _tnl_interp; | ||||
|  | ||||
| 	  _tnl_invalidate_vertex_state( ctx, ~0 ); | ||||
| 	  _tnl_invalidate_vertices( ctx, ~0 ); | ||||
| 	  _tnl_install_attrs( ctx,  | ||||
| 			      intel->vertex_attrs,  | ||||
| 			      intel->vertex_attr_count, | ||||
| 			      intel->ViewportMatrix.m, 0 );  | ||||
| 	 _tnl_invalidate_vertex_state( ctx, ~0 ); | ||||
| 	 _tnl_invalidate_vertices( ctx, ~0 ); | ||||
| 	 _tnl_install_attrs( ctx,  | ||||
| 			     intel->vertex_attrs,  | ||||
| 			     intel->vertex_attr_count, | ||||
| 			     intel->ViewportMatrix.m, 0 );  | ||||
|  | ||||
| 	  intel->NewGLState |= _INTEL_NEW_RENDERSTATE; | ||||
|        } | ||||
|     } | ||||
|  } | ||||
| 	 intel->NewGLState |= _INTEL_NEW_RENDERSTATE; | ||||
|       } | ||||
|    } | ||||
| } | ||||
|  | ||||
| union fi {  | ||||
|    GLfloat f;  | ||||
|    GLint i;  | ||||
| }; | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /*             Used only with the metaops callbacks.                  */ | ||||
| /**********************************************************************/ | ||||
| void intel_meta_draw_quad(struct intel_context *intel,  | ||||
| 			  GLfloat x0, GLfloat x1, | ||||
| 			  GLfloat y0, GLfloat y1,  | ||||
| 			  GLfloat z, | ||||
| 			  GLuint color, | ||||
| 			  GLfloat s0, GLfloat s1, | ||||
| 			  GLfloat t0, GLfloat t1) | ||||
| { | ||||
|    union fi *vb; | ||||
|  | ||||
|    if (INTEL_DEBUG & DEBUG_DRI) | ||||
|       fprintf(stderr, "%s: %f,%f-%f,%f 0x%x %f,%f-%f,%f depth: %f\n", | ||||
| 	      __FUNCTION__, | ||||
| 	      x0,y0,x1,y1,color,s0,t0,s1,t1, z); | ||||
|  | ||||
|    intel->vtbl.emit_state( intel ); | ||||
|  | ||||
|    /* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS, | ||||
|     * otherwise the drawing origin (DR4) might not be set correctly. | ||||
|     */ | ||||
|    intelStartInlinePrimitive( intel, PRIM3D_TRIFAN, INTEL_BATCH_CLIPRECTS );   | ||||
|    vb = (union fi *)intelExtendInlinePrimitive( intel, 4 * 6 ); | ||||
|  | ||||
|  | ||||
|    /* initial vertex, left bottom */ | ||||
|    vb[0].f = x0; | ||||
|    vb[1].f = y0; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s0; | ||||
|    vb[5].f = t0; | ||||
|    vb += 6; | ||||
|  | ||||
|    /* right bottom */ | ||||
|    vb[0].f = x1; | ||||
|    vb[1].f = y0; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s1; | ||||
|    vb[5].f = t0; | ||||
|    vb += 6; | ||||
|  | ||||
|    /* right top */ | ||||
|    vb[0].f = x1; | ||||
|    vb[1].f = y1; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s1; | ||||
|    vb[5].f = t1; | ||||
|    vb += 6; | ||||
|  | ||||
|    /* left top */ | ||||
|    vb[0].f = x0; | ||||
|    vb[1].f = y1; | ||||
|    vb[2].f = z; | ||||
|    vb[3].i = color; | ||||
|    vb[4].f = s0; | ||||
|    vb[5].f = t1; | ||||
|  | ||||
|    if (intel->prim.flush) | ||||
|       intel->prim.flush(intel); | ||||
| } | ||||
|  | ||||
|  | ||||
| /**********************************************************************/ | ||||
|   | ||||
| @@ -30,6 +30,8 @@ | ||||
|  | ||||
| #include "mtypes.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| #define _INTEL_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |		\ | ||||
| 			       _DD_NEW_TRI_UNFILLED |		\ | ||||
| 			       _DD_NEW_TRI_LIGHT_TWOSIDE |	\ | ||||
| @@ -40,7 +42,22 @@ | ||||
|  | ||||
| extern void intelInitTriFuncs( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelPrintRenderState( const char *msg, GLuint state ); | ||||
| extern void intelChooseRenderState( GLcontext *ctx ); | ||||
|  | ||||
| extern void intelStartInlinePrimitive( struct intel_context *intel, GLuint prim, GLuint flags ); | ||||
| extern void intelWrapInlinePrimitive( struct intel_context *intel ); | ||||
|  | ||||
| GLuint *intelExtendInlinePrimitive( struct intel_context *intel,  | ||||
| 				    GLuint dwords ); | ||||
|  | ||||
|  | ||||
| void intel_meta_draw_quad(struct intel_context *intel,  | ||||
| 			  GLfloat x0, GLfloat x1, | ||||
| 			  GLfloat y0, GLfloat y1,  | ||||
| 			  GLfloat z, | ||||
| 			  GLuint color, | ||||
| 			  GLfloat s0, GLfloat s1, | ||||
| 			  GLfloat t0, GLfloat t1); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -18,11 +18,21 @@ OUTPUTS = glprocs.h glapitemp.h glapioffsets.h glapitable.h dispatch.h \ | ||||
| 	../../glx/x11/indirect_size.h \ | ||||
| 	../../glx/x11/indirect_size.c | ||||
|  | ||||
|  | ||||
| #XORG_BASE = /home/idr/devel/graphics/Xorg/xserver/xorg | ||||
| GLX_DIR   = $(XORG_BASE)/GL/glx | ||||
|  | ||||
| SERVER_OUTPUTS = $(GLX_DIR)/indirect_dispatch.c \ | ||||
| 	$(GLX_DIR)/indirect_dispatch_swap.c \ | ||||
| 	$(GLX_DIR)/indirect_dispatch.h | ||||
|  | ||||
| COMMON = gl_XML.py license.py gl_API.xml typeexpr.py | ||||
| COMMON_GLX = $(COMMON) glX_XML.py glX_proto_common.py | ||||
|  | ||||
| all: $(OUTPUTS) | ||||
|  | ||||
| server: $(SERVER_OUTPUTS) | ||||
|  | ||||
| glprocs.h: $(COMMON) gl_procs.py | ||||
| 	$(PYTHON2) $(PYTHON_FLAGS) gl_procs.py > glprocs.h | ||||
|  | ||||
| @@ -65,6 +75,21 @@ dispatch.h: $(COMMON) gl_table.py | ||||
| ../../glx/x11/indirect_size.c: $(COMMON_GLX) glX_proto_size.py | ||||
| 	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_c --only-set > ../../glx/x11/indirect_size.c | ||||
|  | ||||
| $(GLX_DIR)/indirect_dispatch.c: $(COMMON_GLX) glX_proto_recv.py | ||||
| 	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_c > $@ | ||||
|  | ||||
| $(GLX_DIR)/indirect_dispatch_swap.c: $(COMMON_GLX) glX_proto_recv.py | ||||
| 	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_c -s > $@ | ||||
|  | ||||
| $(GLX_DIR)/indirect_dispatch.h: $(COMMON_GLX) glX_proto_recv.py | ||||
| 	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_h -s > $@ | ||||
|  | ||||
| $(GLX_DIR)/indirect_size_get.h: $(COMMON_GLX) glX_proto_size.py | ||||
| 	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_h --only-get -h '_INDIRECT_SIZE_GET_H_' > $@ | ||||
|  | ||||
| $(GLX_DIR)/indirect_size_get.c: $(COMMON_GLX) glX_proto_size.py | ||||
| 	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_c > $@ | ||||
|  | ||||
| clean: | ||||
| 	rm -f *~ *.pyo | ||||
| 	rm -f $(OUTPUTS) | ||||
|   | ||||
| @@ -2512,10 +2512,13 @@ | ||||
| #define CALL_GetQueryObjectui64vEXT(disp, parameters) (*((disp)->GetQueryObjectui64vEXT)) parameters | ||||
| #define GET_GetQueryObjectui64vEXT(disp) ((disp)->GetQueryObjectui64vEXT) | ||||
| #define SET_GetQueryObjectui64vEXT(disp, fn) ((disp)->GetQueryObjectui64vEXT = fn) | ||||
| #define CALL_BlitFramebufferEXT(disp, parameters) (*((disp)->BlitFramebufferEXT)) parameters | ||||
| #define GET_BlitFramebufferEXT(disp) ((disp)->BlitFramebufferEXT) | ||||
| #define SET_BlitFramebufferEXT(disp, fn) ((disp)->BlitFramebufferEXT = fn) | ||||
|  | ||||
| #else | ||||
|  | ||||
| #define driDispatchRemapTable_size 410 | ||||
| #define driDispatchRemapTable_size 411 | ||||
| extern int driDispatchRemapTable[ driDispatchRemapTable_size ]; | ||||
|  | ||||
| #define LoadTransposeMatrixfARB_remap_index 0 | ||||
| @@ -2928,6 +2931,7 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ]; | ||||
| #define StencilMaskSeparate_remap_index 407 | ||||
| #define GetQueryObjecti64vEXT_remap_index 408 | ||||
| #define GetQueryObjectui64vEXT_remap_index 409 | ||||
| #define BlitFramebufferEXT_remap_index 410 | ||||
|  | ||||
| #define CALL_LoadTransposeMatrixfARB(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(const GLfloat *)), driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index], parameters) | ||||
| #define GET_LoadTransposeMatrixfARB(disp) GET_by_offset(disp, driDispatchRemapTable[LoadTransposeMatrixfARB_remap_index]) | ||||
| @@ -4159,6 +4163,9 @@ extern int driDispatchRemapTable[ driDispatchRemapTable_size ]; | ||||
| #define CALL_GetQueryObjectui64vEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLuint, GLenum, GLuint64EXT *)), driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], parameters) | ||||
| #define GET_GetQueryObjectui64vEXT(disp) GET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index]) | ||||
| #define SET_GetQueryObjectui64vEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index], fn) | ||||
| #define CALL_BlitFramebufferEXT(disp, parameters) CALL_by_offset(disp, (void (GLAPIENTRYP)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)), driDispatchRemapTable[BlitFramebufferEXT_remap_index], parameters) | ||||
| #define GET_BlitFramebufferEXT(disp) GET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index]) | ||||
| #define SET_BlitFramebufferEXT(disp, fn) SET_by_offset(disp, driDispatchRemapTable[BlitFramebufferEXT_remap_index], fn) | ||||
|  | ||||
| #endif /* !defined(IN_DRI_DRIVER) */ | ||||
|  | ||||
|   | ||||
| @@ -48,7 +48,7 @@ class glx_proto_type(gl_XML.gl_type): | ||||
|  | ||||
|  | ||||
| class glx_print_proto(gl_XML.gl_print_base): | ||||
| 	def size_call(self, func): | ||||
| 	def size_call(self, func, outputs_also = 0): | ||||
| 		"""Create C code to calculate 'compsize'. | ||||
|  | ||||
| 		Creates code to calculate 'compsize'.  If the function does | ||||
| @@ -58,7 +58,7 @@ class glx_print_proto(gl_XML.gl_print_base): | ||||
| 		compsize = None | ||||
|  | ||||
| 		for param in func.parameterIterator(): | ||||
| 			if not param.is_output: | ||||
| 			if outputs_also or not param.is_output: | ||||
| 				if param.is_image(): | ||||
| 					[dim, w, h, d, junk] = param.get_dimensions() | ||||
|  | ||||
|   | ||||
							
								
								
									
										561
									
								
								src/mesa/glapi/glX_proto_recv.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										561
									
								
								src/mesa/glapi/glX_proto_recv.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,561 @@ | ||||
| #!/usr/bin/env python | ||||
|  | ||||
| # (C) Copyright IBM Corporation 2005 | ||||
| # All Rights Reserved. | ||||
| # | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a | ||||
| # copy of this software and associated documentation files (the "Software"), | ||||
| # to deal in the Software without restriction, including without limitation | ||||
| # on the rights to use, copy, modify, merge, publish, distribute, sub | ||||
| # license, and/or sell copies of the Software, and to permit persons to whom | ||||
| # the Software is furnished to do so, subject to the following conditions: | ||||
| # | ||||
| # The above copyright notice and this permission notice (including the next | ||||
| # paragraph) shall be included in all copies or substantial portions of the | ||||
| # Software. | ||||
| # | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL | ||||
| # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||
| # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||||
| # IN THE SOFTWARE. | ||||
| # | ||||
| # Authors: | ||||
| #    Ian Romanick <idr@us.ibm.com> | ||||
|  | ||||
| import gl_XML, glX_XML, glX_proto_common, license | ||||
| import sys, getopt, string | ||||
|  | ||||
|  | ||||
| class PrintGlxDispatch_h(gl_XML.gl_print_base): | ||||
| 	def __init__(self): | ||||
| 		gl_XML.gl_print_base.__init__(self) | ||||
|  | ||||
| 		self.name = "glX_proto_recv.py (from Mesa)" | ||||
| 		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM") | ||||
|  | ||||
| 		self.header_tag = "_INDIRECT_DISPATCH_H_" | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def printRealHeader(self): | ||||
| 		self.printVisibility( "HIDDEN", "hidden" ) | ||||
| 		print 'struct __GLXclientStateRec;' | ||||
| 		print '' | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def printBody(self, api): | ||||
| 		for func in api.functionIterateAll(): | ||||
| 			if not func.ignore and not func.vectorequiv: | ||||
| 				if func.glx_rop != 0: | ||||
| 					print 'extern HIDDEN void __glXDisp_%s(GLbyte * pc);' % (func.name) | ||||
| 					print 'extern HIDDEN void __glXDispSwap_%s(GLbyte * pc);' % (func.name) | ||||
| 				elif func.glx_sop != 0 or func.glx_vendorpriv != 0: | ||||
| 					print 'extern HIDDEN int __glXDisp_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name) | ||||
| 					print 'extern HIDDEN int __glXDispSwap_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name) | ||||
|  | ||||
| 		return | ||||
|  | ||||
|  | ||||
| class PrintGlxDispatchFunctions(glX_proto_common.glx_print_proto): | ||||
| 	def __init__(self, do_swap): | ||||
| 		gl_XML.gl_print_base.__init__(self) | ||||
| 		self.name = "glX_proto_recv.py (from Mesa)" | ||||
| 		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM") | ||||
|  | ||||
| 		self.real_types = [ '', '', 'uint16_t', '', 'uint32_t', '', '', '', 'uint64_t' ] | ||||
| 		self.do_swap = do_swap | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def printRealHeader(self): | ||||
| 		print '#include <X11/Xmd.h>' | ||||
| 		print '#include <GL/gl.h>' | ||||
| 		print '#include <GL/glxproto.h>' | ||||
|  | ||||
|  | ||||
| 		# FIXME: Since this block will require changes as other | ||||
| 		# FIXME: platforms are added, it should probably be in a | ||||
| 		# FIXME: header file that is not generated by a script. | ||||
|  | ||||
| 		if self.do_swap: | ||||
| 			print '#ifdef __linux__' | ||||
| 			print '#include <byteswap.h>' | ||||
| 			print '#elif defined(__OpenBSD__)' | ||||
| 			print '#include <sys/endian.h>' | ||||
| 			print '#define bswap_16 __swap16' | ||||
| 			print '#define bswap_32 __swap32' | ||||
| 			print '#define bswap_64 __swap64' | ||||
| 			print '#else' | ||||
| 			print '#include <sys/endian.h>' | ||||
| 			print '#define bswap_16 bswap16' | ||||
| 			print '#define bswap_32 bswap32' | ||||
| 			print '#define bswap_64 bswap64' | ||||
| 			print '#endif' | ||||
|  | ||||
| 		print '#include <inttypes.h>' | ||||
| 		print '#include "indirect_size.h"' | ||||
| 		print '#include "indirect_size_get.h"' | ||||
| 		print '#include "indirect_dispatch.h"' | ||||
| 		print '#include "glxserver.h"' | ||||
| 		print '#include "indirect_util.h"' | ||||
| 		print '#include "singlesize.h"' | ||||
| 		print '#include "glapitable.h"' | ||||
| 		print '#include "glapi.h"' | ||||
| 		print '#include "glthread.h"' | ||||
| 		print '#include "dispatch.h"' | ||||
| 		print '' | ||||
| 		print '#define __GLX_PAD(x)  (((x) + 3) & ~3)' | ||||
| 		print '' | ||||
| 		print 'typedef struct {' | ||||
| 		print '    __GLX_PIXEL_3D_HDR;' | ||||
| 		print '} __GLXpixel3DHeader;' | ||||
| 		print '' | ||||
| 		print 'extern GLboolean __glXErrorOccured( void );' | ||||
| 		print 'extern void __glXClearErrorOccured( void );' | ||||
| 		print '' | ||||
| 		print 'static const unsigned dummy_answer[2] = {0, 0};' | ||||
| 		print '' | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def printBody(self, api): | ||||
| 		if self.do_swap: | ||||
| 			self.emit_swap_wrappers(api) | ||||
|  | ||||
|  | ||||
| 		for func in api.functionIterateByOffset(): | ||||
| 			if not func.ignore and not func.server_handcode and not func.vectorequiv and (func.glx_rop or func.glx_sop or func.glx_vendorpriv): | ||||
| 				self.printFunction(func) | ||||
|  | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def printFunction(self, f): | ||||
| 		if (f.glx_sop or f.glx_vendorpriv) and (len(f.get_images()) != 0): | ||||
| 			return | ||||
|  | ||||
| 		if not self.do_swap: | ||||
| 			base = '__glXDisp' | ||||
| 		else: | ||||
| 			base = '__glXDispSwap' | ||||
|  | ||||
| 		if f.glx_rop: | ||||
| 			print 'void %s_%s(GLbyte * pc)' % (base, f.name) | ||||
| 		else: | ||||
| 			print 'int %s_%s(__GLXclientState *cl, GLbyte *pc)' % (base, f.name) | ||||
|  | ||||
| 		print '{' | ||||
|  | ||||
| 		if f.glx_rop or f.vectorequiv: | ||||
| 			self.printRenderFunction(f) | ||||
| 		elif f.glx_sop or f.glx_vendorpriv: | ||||
| 			if len(f.get_images()) == 0:  | ||||
| 				self.printSingleFunction(f) | ||||
| 		else: | ||||
| 			print "/* Missing GLX protocol for %s. */" % (f.name) | ||||
|  | ||||
| 		print '}' | ||||
| 		print '' | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def swap_name(self, bytes): | ||||
| 		return 'bswap_%u_array' % (8 * bytes) | ||||
|  | ||||
|  | ||||
| 	def emit_swap_wrappers(self, api): | ||||
| 		self.type_map = {} | ||||
| 		already_done = [ ] | ||||
|  | ||||
| 		for t in api.typeIterate(): | ||||
| 			te = t.get_type_expression() | ||||
| 			t_size = te.get_element_size() | ||||
|  | ||||
| 			if t_size > 1 and t.glx_name: | ||||
| 				 | ||||
| 				t_name = "GL" + t.name | ||||
| 				self.type_map[ t_name ] = t.glx_name | ||||
|  | ||||
| 				if t.glx_name not in already_done: | ||||
| 					real_name = self.real_types[t_size] | ||||
|  | ||||
| 					print 'static %s' % (t_name) | ||||
| 					print 'bswap_%s( const void * src )' % (t.glx_name) | ||||
| 					print '{' | ||||
| 					print '    union { %s dst; %s ret; } x;' % (real_name, t_name) | ||||
| 					print '    x.dst = bswap_%u( *(%s *) src );' % (t_size * 8, real_name) | ||||
| 					print '    return x.ret;' | ||||
| 					print '}' | ||||
| 					print '' | ||||
| 					already_done.append( t.glx_name ) | ||||
|  | ||||
| 		for bits in [16, 32, 64]: | ||||
| 			print 'static void *' | ||||
| 			print 'bswap_%u_array( uint%u_t * src, unsigned count )' % (bits, bits) | ||||
| 			print '{' | ||||
| 			print '    unsigned  i;' | ||||
| 			print '' | ||||
| 			print '    for ( i = 0 ; i < count ; i++ ) {' | ||||
| 			print '        uint%u_t temp = bswap_%u( src[i] );' % (bits, bits) | ||||
| 			print '        src[i] = temp;' | ||||
| 			print '    }' | ||||
| 			print '' | ||||
| 			print '    return src;' | ||||
| 			print '}' | ||||
| 			print '' | ||||
| 			 | ||||
|  | ||||
| 	def fetch_param(self, param): | ||||
| 		t = param.type_string() | ||||
| 		o = param.offset | ||||
| 		element_size = param.size() / param.get_element_count() | ||||
|  | ||||
| 		if self.do_swap and (element_size != 1): | ||||
| 			if param.is_array(): | ||||
| 				real_name = self.real_types[ element_size ] | ||||
|  | ||||
| 				swap_func = self.swap_name( element_size ) | ||||
| 				return ' (%-8s)%s( (%s *) (pc + %2s), %s )' % (t, swap_func, real_name, o, param.count) | ||||
| 			else: | ||||
| 				t_name = param.get_base_type_string() | ||||
| 				return ' (%-8s)bswap_%-7s( pc + %2s )' % (t, self.type_map[ t_name ], o) | ||||
| 		else: | ||||
| 			if param.is_array(): | ||||
| 				return ' (%-8s)(pc + %2u)' % (t, o) | ||||
| 			else: | ||||
| 				return '*(%-8s *)(pc + %2u)' % (t, o) | ||||
| 				 | ||||
| 		return None | ||||
|  | ||||
|  | ||||
| 	def emit_function_call(self, f, retval_assign, indent): | ||||
| 		list = [] | ||||
|  | ||||
| 		for param in f.parameterIterator(): | ||||
|  | ||||
| 			if param.is_counter or param.is_image() or param.is_output or len(param.count_parameter_list): | ||||
| 				location = param.name | ||||
| 			else: | ||||
| 				location = self.fetch_param(param) | ||||
|  | ||||
| 			list.append( '%s        %s' % (indent, location) ) | ||||
| 			 | ||||
|  | ||||
| 		if len( list ): | ||||
| 			print '%s    %sCALL_%s( GET_DISPATCH(), (' % (indent, retval_assign, f.name) | ||||
| 			print string.join( list, ",\n" ) | ||||
| 			print '%s    ) );' % (indent) | ||||
| 		else: | ||||
| 			print '%s    %sCALL_%s( GET_DISPATCH(), () );' % (indent, retval_assign, f.name) | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def common_func_print_just_start(self, f, indent): | ||||
| 		align64 = 0 | ||||
| 		need_blank = 0 | ||||
|  | ||||
|  | ||||
| 		f.calculate_offsets() | ||||
| 		for param in f.parameterIterateGlxSend(): | ||||
| 			# If any parameter has a 64-bit base type, then we | ||||
| 			# have to do alignment magic for the while thing. | ||||
|  | ||||
| 			if param.is_64_bit(): | ||||
| 				align64 = 1 | ||||
|  | ||||
|  | ||||
| 			# FIXME img_null_flag is over-loaded.  In addition to | ||||
| 			# FIXME being used for images, it is used to signify | ||||
| 			# FIXME NULL data pointers for vertex buffer object | ||||
| 			# FIXME related functions.  Re-name it to null_data | ||||
| 			# FIXME or something similar. | ||||
|  | ||||
| 			if param.img_null_flag: | ||||
| 				print '%s    const CARD32 ptr_is_null = *(CARD32 *)(pc + %s);' % (indent, param.offset - 4) | ||||
| 				cond = '(ptr_is_null != 0) ? NULL : ' | ||||
| 			else: | ||||
| 				cond = "" | ||||
|  | ||||
|  | ||||
| 			type_string = param.type_string() | ||||
|  | ||||
| 			if param.is_image(): | ||||
| 				offset = f.offset_of( param.name ) | ||||
|  | ||||
| 				print '%s    %s const %s = (%s) %s(pc + %s);' % (indent, type_string, param.name, type_string, cond, offset) | ||||
| 				 | ||||
| 				if param.depth: | ||||
| 					print '%s    __GLXpixel3DHeader * const hdr = (__GLXpixel3DHeader *)(pc);' % (indent) | ||||
| 				else: | ||||
| 					print '%s    __GLXpixelHeader * const hdr = (__GLXpixelHeader *)(pc);' % (indent) | ||||
|  | ||||
| 				need_blank = 1 | ||||
| 			elif param.is_counter or param.name in f.count_parameter_list: | ||||
| 				location = self.fetch_param(param) | ||||
| 				print '%s    const %s %s = %s;' % (indent, type_string, param.name, location) | ||||
| 				need_blank = 1 | ||||
| 			elif len(param.count_parameter_list): | ||||
| 				if param.size() == 1 and not self.do_swap: | ||||
| 					location = self.fetch_param(param) | ||||
| 					print '%s    %s %s = %s%s;' % (indent, type_string, param.name, cond, location) | ||||
| 				else: | ||||
| 					print '%s    %s %s;' % (indent, type_string, param.name) | ||||
| 				need_blank = 1 | ||||
|  | ||||
|  | ||||
|  | ||||
| 		if need_blank: | ||||
| 			print '' | ||||
|  | ||||
| 		if align64: | ||||
| 			print '#ifdef __GLX_ALIGN64' | ||||
|  | ||||
| 			if f.has_variable_size_request(): | ||||
| 				self.emit_packet_size_calculation(f, 4) | ||||
| 				s = "cmdlen" | ||||
| 			else: | ||||
| 				s = str((f.command_fixed_length() + 3) & ~3) | ||||
|  | ||||
| 			print '    if ((unsigned long)(pc) & 7) {' | ||||
| 			print '        (void) memmove(pc-4, pc, %s);' % (s) | ||||
| 			print '        pc -= 4;' | ||||
| 			print '    }' | ||||
| 			print '#endif' | ||||
| 			print '' | ||||
|  | ||||
|  | ||||
| 		need_blank = 0 | ||||
| 		if self.do_swap: | ||||
| 			for param in f.parameterIterateGlxSend(): | ||||
| 				if param.count_parameter_list: | ||||
| 					o = param.offset | ||||
| 					count = param.get_element_count() | ||||
| 					type_size = param.size() / count | ||||
| 					 | ||||
| 					if param.counter: | ||||
| 						count_name = param.counter | ||||
| 					else: | ||||
| 						count_name = str(count) | ||||
|  | ||||
| 					# This is basically an ugly special- | ||||
| 					# case for glCallLists. | ||||
|  | ||||
| 					if type_size == 1: | ||||
| 						x = []  | ||||
| 						x.append( [1, ['BYTE', 'UNSIGNED_BYTE', '2_BYTES', '3_BYTES', '4_BYTES']] ) | ||||
| 						x.append( [2, ['SHORT', 'UNSIGNED_SHORT']] ) | ||||
| 						x.append( [4, ['INT', 'UNSIGNED_INT', 'FLOAT']] ) | ||||
|  | ||||
| 						print '    switch(%s) {' % (param.count_parameter_list[0]) | ||||
| 						for sub in x: | ||||
| 							for t_name in sub[1]: | ||||
| 								print '    case GL_%s:' % (t_name) | ||||
|  | ||||
| 							if sub[0] == 1: | ||||
| 								print '        %s = (%s) (pc + %s); break;' % (param.name, param.type_string(), o) | ||||
| 							else: | ||||
| 								swap_func = self.swap_name(sub[0]) | ||||
| 								print '        %s = (%s) %s( (%s *) (pc + %s), %s ); break;' % (param.name, param.type_string(), swap_func, self.real_types[sub[0]], o, count_name) | ||||
| 						print '    }' | ||||
| 					else: | ||||
| 						swap_func = self.swap_name(type_size) | ||||
| 						compsize = self.size_call(f, 1) | ||||
| 						print '    %s = (%s) %s( (%s *) (pc + %s), %s );' % (param.name, param.type_string(), swap_func, self.real_types[type_size], o, compsize) | ||||
|  | ||||
| 					need_blank = 1 | ||||
|  | ||||
| 		else: | ||||
| 			for param in f.parameterIterateGlxSend(): | ||||
| 				if param.count_parameter_list: | ||||
| 					print '%s    %s = (%s) (pc + %s);' % (indent, param.name, param.type_string(), param.offset) | ||||
| 					need_blank = 1 | ||||
|  | ||||
|  | ||||
| 		if need_blank: | ||||
| 			print '' | ||||
|  | ||||
|  | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def printSingleFunction(self, f): | ||||
| 		if f.glx_sop: | ||||
| 			print '    xGLXSingleReq * const req = (xGLXSingleReq *) pc;' | ||||
| 		else: | ||||
| 			print '    xGLXVendorPrivateReq * const req = (xGLXVendorPrivateReq *) pc;' | ||||
|  | ||||
| 		print '    int error;' | ||||
|  | ||||
| 		if self.do_swap: | ||||
| 		    print '    __GLXcontext * const cx = __glXForceCurrent(cl, bswap_CARD32( &req->contextTag ), &error);' | ||||
| 		else: | ||||
| 		    print '    __GLXcontext * const cx = __glXForceCurrent(cl, req->contextTag, &error);' | ||||
|  | ||||
| 		print '' | ||||
| 		if f.glx_sop: | ||||
| 			print '    pc += __GLX_SINGLE_HDR_SIZE;' | ||||
| 		else: | ||||
| 			print '    pc += __GLX_VENDPRIV_HDR_SIZE;' | ||||
|  | ||||
| 		print '    if ( cx != NULL ) {' | ||||
| 		self.common_func_print_just_start(f, "    ") | ||||
| 		 | ||||
|  | ||||
| 		if f.return_type != 'void': | ||||
| 			print '        %s retval;' % (f.return_type) | ||||
| 			retval_string = "retval" | ||||
| 			retval_assign = "retval = " | ||||
| 		else: | ||||
| 			retval_string = "0" | ||||
| 			retval_assign = "" | ||||
|  | ||||
|  | ||||
| 		type_size = 0 | ||||
| 		answer_string = "dummy_answer" | ||||
| 		answer_count = "0" | ||||
| 		is_array_string = "GL_FALSE" | ||||
|  | ||||
| 		for param in f.parameterIterateOutputs(): | ||||
| 			answer_type = param.get_base_type_string() | ||||
| 			if answer_type == "GLvoid": | ||||
| 				answer_type = "GLubyte" | ||||
|  | ||||
|  | ||||
| 			c = param.get_element_count() | ||||
| 			type_size = (param.size() / c) | ||||
| 			if type_size == 1: | ||||
| 				size_scale = "" | ||||
| 			else: | ||||
| 				size_scale = " * %u" % (type_size) | ||||
|  | ||||
|  | ||||
| 			if param.count_parameter_list: | ||||
| 				print '        const GLuint compsize = %s;' % (self.size_call(f, 1)) | ||||
| 				print '        %s answerBuffer[200];' %  (answer_type) | ||||
| 				print '        %s %s = __glXGetAnswerBuffer(cl, compsize%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, size_scale, type_size ) | ||||
| 				answer_string = param.name | ||||
| 				answer_count = "compsize" | ||||
|  | ||||
| 				print '' | ||||
| 				print '        if (%s == NULL) return BadAlloc;' % (param.name) | ||||
| 				print '        __glXClearErrorOccured();' | ||||
| 				print '' | ||||
| 			elif param.counter: | ||||
| 				print '        %s answerBuffer[200];' %  (answer_type) | ||||
| 				print '        %s %s = __glXGetAnswerBuffer(cl, %s%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, param.counter, size_scale, type_size) | ||||
| 				answer_string = param.name | ||||
| 				answer_count = param.counter | ||||
| 			elif c >= 1: | ||||
| 				print '        %s %s[%u];' % (answer_type, param.name, c) | ||||
| 				answer_string = param.name | ||||
| 				answer_count = "%u" % (c) | ||||
|  | ||||
| 			if f.reply_always_array: | ||||
| 				is_array_string = "GL_TRUE" | ||||
|  | ||||
|  | ||||
| 		self.emit_function_call(f, retval_assign, "    ") | ||||
|  | ||||
|  | ||||
| 		if f.needs_reply(): | ||||
| 			if self.do_swap: | ||||
| 				for param in f.parameterIterateOutputs(): | ||||
| 					c = param.get_element_count() | ||||
| 					type_size = (param.size() / c) | ||||
|  | ||||
| 					if type_size > 1: | ||||
| 						swap_name = self.swap_name( type_size ) | ||||
| 						print '        (void) %s( (uint%u_t *) %s, %s );' % (swap_name, 8 * type_size, param.name, answer_count) | ||||
|  | ||||
|  | ||||
| 				reply_func = '__glXSendReplySwap' | ||||
| 			else: | ||||
| 				reply_func = '__glXSendReply' | ||||
|  | ||||
| 			print '        %s(cl->client, %s, %s, %u, %s, %s);' % (reply_func, answer_string, answer_count, type_size, is_array_string, retval_string) | ||||
| 		#elif f.note_unflushed: | ||||
| 		#	print '        cx->hasUnflushedCommands = GL_TRUE;' | ||||
|  | ||||
| 		print '        error = Success;' | ||||
| 		print '    }' | ||||
| 		print '' | ||||
| 		print '    return error;' | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def printRenderFunction(self, f): | ||||
| 		# There are 4 distinct phases in a rendering dispatch function. | ||||
| 		# In the first phase we compute the sizes and offsets of each | ||||
| 		# element in the command.  In the second phase we (optionally) | ||||
| 		# re-align 64-bit data elements.  In the third phase we | ||||
| 		# (optionally) byte-swap array data.  Finally, in the fourth | ||||
| 		# phase we actually dispatch the function. | ||||
|  | ||||
| 		self.common_func_print_just_start(f, "") | ||||
|  | ||||
| 		images = f.get_images() | ||||
| 		if len(images): | ||||
| 			if self.do_swap: | ||||
| 				pre = "bswap_CARD32( & " | ||||
| 				post = " )" | ||||
| 			else: | ||||
| 				pre = "" | ||||
| 				post = "" | ||||
|  | ||||
| 			img = images[0] | ||||
|  | ||||
| 			# swapBytes and lsbFirst are single byte fields, so | ||||
| 			# the must NEVER be byte-swapped. | ||||
|  | ||||
| 			if not (img.img_type == "GL_BITMAP" and img.img_format == "GL_COLOR_INDEX"): | ||||
| 				print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES,   hdr->swapBytes) );' | ||||
|  | ||||
| 			print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_LSB_FIRST,    hdr->lsbFirst) );' | ||||
|  | ||||
| 			print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,   (GLint) %shdr->rowLength%s) );' % (pre, post) | ||||
| 			if img.depth: | ||||
| 				print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_IMAGE_HEIGHT, (GLint) %shdr->imageHeight%s) );' % (pre, post) | ||||
| 			print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS,    (GLint) %shdr->skipRows%s) );' % (pre, post) | ||||
| 			if img.depth: | ||||
| 				print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_IMAGES,  (GLint) %shdr->skipImages%s) );' % (pre, post) | ||||
| 			print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS,  (GLint) %shdr->skipPixels%s) );' % (pre, post) | ||||
| 			print '    CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ALIGNMENT,    (GLint) %shdr->alignment%s) );' % (pre, post) | ||||
| 			print '' | ||||
|  | ||||
|  | ||||
| 		self.emit_function_call(f, "", "") | ||||
| 		return | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
| 	file_name = "gl_API.xml" | ||||
|  | ||||
| 	try: | ||||
| 		(args, trail) = getopt.getopt(sys.argv[1:], "f:m:s") | ||||
| 	except Exception,e: | ||||
| 		show_usage() | ||||
|  | ||||
| 	mode = "dispatch_c" | ||||
| 	do_swap = 0 | ||||
| 	for (arg,val) in args: | ||||
| 		if arg == "-f": | ||||
| 			file_name = val | ||||
| 		elif arg == "-m": | ||||
| 			mode = val | ||||
| 		elif arg == "-s": | ||||
| 			do_swap = 1 | ||||
|  | ||||
| 	if mode == "dispatch_c": | ||||
| 		printer = PrintGlxDispatchFunctions(do_swap) | ||||
| 	elif mode == "dispatch_h": | ||||
| 		printer = PrintGlxDispatch_h() | ||||
| 	else: | ||||
| 		show_usage() | ||||
|  | ||||
| 	api = gl_XML.parse_GL_API( file_name, glX_proto_common.glx_proto_item_factory() ) | ||||
|  | ||||
| 	printer.Print( api ) | ||||
| @@ -879,7 +879,7 @@ __GLapi * __glXNewIndirectAPI( void ) | ||||
| 				if first: | ||||
| 					print '' | ||||
| 					if show_num: | ||||
| 						print '    /* % 3u. %s */' % (cat_num, cat_name) | ||||
| 						print '    /* %3u. %s */' % (cat_num, cat_name) | ||||
| 					else: | ||||
| 						print '    /* %s */' % (cat_name) | ||||
| 					print '' | ||||
|   | ||||
| @@ -10447,8 +10447,8 @@ | ||||
|     <function name="GenProgramsNV" offset="582"> | ||||
|         <param name="n" type="GLsizei" counter="true"/> | ||||
|         <param name="programs" type="GLuint *" output="true" count="n"/> | ||||
|         <glx vendorpriv="1295"/> | ||||
|     </function> | ||||
|         <glx vendorpriv="1295" always_array="true"/> | ||||
|      </function> | ||||
|  | ||||
|     <!-- This isn't 100% correct.  Currently, the only valid value of pname | ||||
|          is GL_PROGRAM_PARAMETER_NV, and the count for that pname is always | ||||
| @@ -11498,4 +11498,23 @@ | ||||
|     </function> | ||||
| </category> | ||||
|  | ||||
| <category name="GL_EXT_framebuffer_blit" number="316"> | ||||
|     <enum name="GL_READ_FRAMEBUFFER_EXT" value="0x8CA8"/> | ||||
|     <enum name="GL_DRAW_FRAMEBUFFER_EXT" value="0x8CA9"/> | ||||
|     <enum name="GL_DRAW_FRAMEBUFFER_BINDING_EXT" value="0x8CA6"/> | ||||
|     <enum name="GL_READ_FRAMEBUFFER_BINDING_EXT" value="0x8CAA"/> | ||||
|     <function name="BlitFramebufferEXT" offset="818"> | ||||
|         <param name="srcX0" type="GLint"/> | ||||
|         <param name="srcY0" type="GLint"/> | ||||
|         <param name="srcX1" type="GLint"/> | ||||
|         <param name="srcY1" type="GLint"/> | ||||
|         <param name="dstX0" type="GLint"/> | ||||
|         <param name="dstY0" type="GLint"/> | ||||
|         <param name="dstX1" type="GLint"/> | ||||
|         <param name="dstY1" type="GLint"/> | ||||
|         <param name="mask" type="GLbitfield"/> | ||||
|         <param name="filter" type="GLenum"/> | ||||
|     </function> | ||||
| </category> | ||||
|  | ||||
| </OpenGLAPI> | ||||
|   | ||||
| @@ -161,7 +161,7 @@ int _mesa_lookup_enum_by_name( const char *symbol ) | ||||
| 		print 'static const enum_elt all_enums[%u] =' % (len(name_table)) | ||||
| 		print '{' | ||||
| 		for [name, enum] in name_table: | ||||
| 			print '   { % 5u, 0x%08X }, /* %s */' % (string_offsets[name], enum, name) | ||||
| 			print '   { %5u, 0x%08X }, /* %s */' % (string_offsets[name], enum, name) | ||||
| 		print '};' | ||||
| 		print '' | ||||
|  | ||||
| @@ -174,7 +174,7 @@ int _mesa_lookup_enum_by_name( const char *symbol ) | ||||
| 			else: | ||||
| 				i = name_table.index( [name, enum] ) | ||||
|  | ||||
| 				print '      % 4u, /* %s */' % (i, name) | ||||
| 				print '      %4u, /* %s */' % (i, name) | ||||
| 		print '};' | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -113,7 +113,7 @@ class PrintGlProcs(gl_XML.gl_print_base): | ||||
| 		print 'static const glprocs_table_t static_functions[] = {' | ||||
|  | ||||
| 		for (offset, disp_name, real_name) in table: | ||||
| 			print '    NAME_FUNC_OFFSET( % 5u, gl%s, _gloffset_%s ),' % (offset, disp_name, real_name) | ||||
| 			print '    NAME_FUNC_OFFSET( %5u, gl%s, _gloffset_%s ),' % (offset, disp_name, real_name) | ||||
|  | ||||
| 		print '    NAME_FUNC_OFFSET( -1, NULL, 0 )' | ||||
| 		print '};' | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| /* | ||||
|  * Mesa 3-D graphics library | ||||
|  * Version:  6.3 | ||||
|  * Version:  6.5 | ||||
|  * | ||||
|  * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved. | ||||
|  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
| @@ -54,7 +54,6 @@ | ||||
| #include "glapi.h" | ||||
| #include "glapioffsets.h" | ||||
| #include "glapitable.h" | ||||
| #include "glthread.h" | ||||
|  | ||||
| /***** BEGIN NO-OP DISPATCH *****/ | ||||
|  | ||||
| @@ -287,14 +286,14 @@ _glapi_get_context(void) | ||||
|  | ||||
| /** | ||||
|  * Set the global or per-thread dispatch table pointer. | ||||
|  * If the dispatch parameter is NULL we'll plug in the no-op dispatch | ||||
|  * table (__glapi_noop_table). | ||||
|  */ | ||||
| PUBLIC void | ||||
| _glapi_set_dispatch(struct _glapi_table *dispatch) | ||||
| { | ||||
| #if defined(PTHREADS) || defined(GLX_USE_TLS) | ||||
|    static pthread_once_t once_control = PTHREAD_ONCE_INIT; | ||||
|  | ||||
|  | ||||
|    pthread_once( & once_control, init_glapi_relocs ); | ||||
| #endif | ||||
|  | ||||
| @@ -327,7 +326,6 @@ PUBLIC struct _glapi_table * | ||||
| _glapi_get_dispatch(void) | ||||
| { | ||||
|    struct _glapi_table * api; | ||||
|  | ||||
| #if defined(GLX_USE_TLS) | ||||
|    api = _glapi_tls_Dispatch; | ||||
| #elif defined(THREADS) | ||||
| @@ -337,13 +335,17 @@ _glapi_get_dispatch(void) | ||||
| #else | ||||
|    api = _glapi_Dispatch; | ||||
| #endif | ||||
|  | ||||
|    assert( api != NULL ); | ||||
|    return api; | ||||
| } | ||||
|  | ||||
|  | ||||
| #if !defined( USE_X86_ASM ) && !defined( XFree86Server ) | ||||
|  | ||||
| /*** | ||||
|  *** The rest of this file is pretty much concerned with GetProcAddress | ||||
|  *** functionality. | ||||
|  ***/ | ||||
|  | ||||
| #if !defined( USE_X86_ASM ) && !defined( XFree86Server ) && !defined ( XGLServer ) | ||||
| #define NEED_FUNCTION_POINTER | ||||
| #endif | ||||
|  | ||||
| @@ -359,13 +361,10 @@ static const glprocs_table_t * | ||||
| find_entry( const char * n ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0; static_functions[i].Name_offset >= 0; i++) { | ||||
|       const char * test_name; | ||||
|  | ||||
|       test_name = gl_string_table + static_functions[i].Name_offset; | ||||
|       if (strcmp(test_name, n) == 0) { | ||||
| 	 return & static_functions[i]; | ||||
|       const char *testName = gl_string_table + static_functions[i].Name_offset; | ||||
|       if (strcmp(testName, n) == 0) { | ||||
| 	 return &static_functions[i]; | ||||
|       } | ||||
|    } | ||||
|    return NULL; | ||||
| @@ -380,15 +379,14 @@ static GLint | ||||
| get_static_proc_offset(const char *funcName) | ||||
| { | ||||
|    const glprocs_table_t * const f = find_entry( funcName ); | ||||
|  | ||||
|    if ( f != NULL ) { | ||||
|    if (f) { | ||||
|       return f->Offset; | ||||
|    } | ||||
|    return -1; | ||||
| } | ||||
|  | ||||
|  | ||||
| #if !defined( XFree86Server ) | ||||
| #if !defined(XFree86Server) && !defined(XGLServer) | ||||
| #ifdef USE_X86_ASM | ||||
|  | ||||
| #if defined( GLX_USE_TLS ) | ||||
| @@ -404,42 +402,33 @@ extern const GLubyte gl_dispatch_functions_start[]; | ||||
| #  define X86_DISPATCH_FUNCTION_SIZE  16 | ||||
| # endif | ||||
|  | ||||
| #endif /* USE_X86_ASM */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Return dispatch function address the named static (built-in) function. | ||||
|  * Return dispatch function address for the named static (built-in) function. | ||||
|  * Return NULL if function not found. | ||||
|  */ | ||||
| static const _glapi_proc | ||||
| get_static_proc_address(const char *funcName) | ||||
| { | ||||
|    const glprocs_table_t * const f = find_entry( funcName ); | ||||
|  | ||||
|    if ( f != NULL ) { | ||||
|    if (f) { | ||||
| #ifdef USE_X86_ASM | ||||
|       return (_glapi_proc) (gl_dispatch_functions_start  | ||||
|                             + (X86_DISPATCH_FUNCTION_SIZE * f->Offset)); | ||||
| #else | ||||
|       return f->Address; | ||||
| #endif | ||||
|    } | ||||
|    else { | ||||
|       return NULL; | ||||
|    } | ||||
| } | ||||
|  | ||||
| #else | ||||
| #endif /* !defined(XFree86Server) && !defined(XGLServer) */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Return pointer to the named static (built-in) function. | ||||
|  * \return  NULL if function not found. | ||||
|  */ | ||||
| static const _glapi_proc | ||||
| get_static_proc_address(const char *funcName) | ||||
| { | ||||
|    const glprocs_table_t * const f = find_entry( funcName ); | ||||
|    return ( f != NULL ) ? f->Address : NULL; | ||||
| } | ||||
|  | ||||
| #endif /* USE_X86_ASM */ | ||||
| #endif /* !defined( XFree86Server ) */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Return the name of the function at the given offset in the dispatch | ||||
| @@ -449,7 +438,6 @@ static const char * | ||||
| get_static_proc_name( GLuint offset ) | ||||
| { | ||||
|    GLuint i; | ||||
|  | ||||
|    for (i = 0; static_functions[i].Name_offset >= 0; i++) { | ||||
|       if (static_functions[i].Offset == offset) { | ||||
| 	 return gl_string_table + static_functions[i].Name_offset; | ||||
| @@ -579,7 +567,7 @@ generate_entrypoint(GLuint functionOffset) | ||||
| 	   0x81c0c000,	/* jmpl		%g3, %g0			  */ | ||||
| 	   0x01000000	/*  nop						  */ | ||||
|    }; | ||||
| #endif | ||||
| #endif /* __arch64__ */ | ||||
|    unsigned int *code = (unsigned int *) malloc(sizeof(insn_template)); | ||||
|    unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch; | ||||
|    if (code) { | ||||
| @@ -601,7 +589,7 @@ generate_entrypoint(GLuint functionOffset) | ||||
|       __glapi_sparc_icache_flush(&code[0]); | ||||
|       code[2] |= (functionOffset * 4); | ||||
|       __glapi_sparc_icache_flush(&code[2]); | ||||
| #endif | ||||
| #endif /* __arch64__ */ | ||||
|    } | ||||
|    return (_glapi_proc) code; | ||||
| #else | ||||
| @@ -621,7 +609,6 @@ fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) | ||||
| #if defined(USE_X86_ASM) | ||||
|    GLubyte * const code = (GLubyte *) entrypoint; | ||||
|  | ||||
|     | ||||
| #if X86_DISPATCH_FUNCTION_SIZE == 32 | ||||
|    *((unsigned int *)(code + 11)) = 4 * offset; | ||||
|    *((unsigned int *)(code + 22)) = 4 * offset; | ||||
| @@ -763,14 +750,8 @@ _glapi_add_dispatch( const char * const * function_names, | ||||
|       /* Do some trivial validation on the name of the function. | ||||
|        */ | ||||
|  | ||||
| #ifdef MANGLE | ||||
|       if (!function_names[i] || function_names[i][0] != 'm' || function_names[i][1] != 'g' || function_names[i][2] != 'l') | ||||
| 	return GL_FALSE; | ||||
| #else | ||||
|       if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l') | ||||
| 	return GL_FALSE; | ||||
| #endif | ||||
|     | ||||
|     | ||||
|       /* Determine if the named function already exists.  If the function does | ||||
|        * exist, it must have the same parameter signature as the function | ||||
| @@ -817,13 +798,11 @@ _glapi_add_dispatch( const char * const * function_names, | ||||
|       } | ||||
|    } | ||||
|  | ||||
|  | ||||
|    if (offset == ~0) { | ||||
|       offset = next_dynamic_offset; | ||||
|       next_dynamic_offset++; | ||||
|    } | ||||
|  | ||||
|  | ||||
|    for ( i = 0 ; function_names[i] != NULL ; i++ ) { | ||||
|       if (! is_static[i] ) { | ||||
| 	 if (entry[i] == NULL) { | ||||
| @@ -835,7 +814,6 @@ _glapi_add_dispatch( const char * const * function_names, | ||||
| 	    } | ||||
| 	 } | ||||
|  | ||||
|  | ||||
| 	 entry[i]->parameter_signature = str_dup(real_sig); | ||||
| 	 fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset); | ||||
| 	 entry[i]->dispatch_offset = offset; | ||||
| @@ -859,7 +837,6 @@ _glapi_get_proc_offset(const char *funcName) | ||||
|          return ExtEntryTable[i].dispatch_offset; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    /* search static functions */ | ||||
|    return get_static_proc_offset(funcName); | ||||
| } | ||||
| @@ -892,7 +869,7 @@ _glapi_get_proc_address(const char *funcName) | ||||
|       } | ||||
|    } | ||||
|  | ||||
| #if !defined( XFree86Server ) | ||||
| #if !defined( XFree86Server ) && !defined( XGLServer ) | ||||
|    /* search static functions */ | ||||
|    { | ||||
|       const _glapi_proc func = get_static_proc_address(funcName); | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| /* | ||||
|  * Mesa 3-D graphics library | ||||
|  * Version:  6.3 | ||||
|  * Version:  6.5 | ||||
|  * | ||||
|  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved. | ||||
|  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
| @@ -47,10 +47,26 @@ | ||||
|  | ||||
| #include "GL/gl.h" | ||||
| #include "glapitable.h" | ||||
| #include "glthread.h" | ||||
|  | ||||
|  | ||||
| typedef void (*_glapi_warning_func)(void *ctx, const char *str, ...); | ||||
|  | ||||
|  | ||||
| #if defined(USE_MGL_NAMESPACE) | ||||
| #define _glapi_set_dispatch _mglapi_set_dispatch | ||||
| #define _glapi_get_dispatch _mglapi_get_dispatch | ||||
| #define _glapi_set_context _mglapi_set_context | ||||
| #define _glapi_get_context _mglapi_get_context | ||||
| #define _glapi_Context _mglapi_Context | ||||
| #define _glapi_Dispatch _mglapi_Dispatch | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /** | ||||
|  ** Define the GET_CURRENT_CONTEXT() macro. | ||||
|  ** \param C local variable which will hold the current context. | ||||
|  **/ | ||||
| #if defined (GLX_USE_TLS) | ||||
|  | ||||
| const extern void *_glapi_Context; | ||||
| @@ -66,19 +82,6 @@ extern __thread void * _glapi_tls_Context | ||||
| extern void *_glapi_Context; | ||||
| extern struct _glapi_table *_glapi_Dispatch; | ||||
|  | ||||
| /** | ||||
|  * Macro for declaration and fetching the current context. | ||||
|  * | ||||
|  * \param C local variable which will hold the current context. | ||||
|  * | ||||
|  * It should be used in the variable declaration area of a function: | ||||
|  * \code | ||||
|  * ... | ||||
|  * { | ||||
|  *   GET_CURRENT_CONTEXT(ctx); | ||||
|  *   ... | ||||
|  * \endcode | ||||
|  */ | ||||
| # ifdef THREADS | ||||
| #  define GET_CURRENT_CONTEXT(C)  GLcontext *C = (GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context()) | ||||
| # else | ||||
| @@ -87,6 +90,11 @@ extern struct _glapi_table *_glapi_Dispatch; | ||||
|  | ||||
| #endif /* defined (GLX_USE_TLS) */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  ** GL API public functions | ||||
|  **/ | ||||
|  | ||||
| extern void | ||||
| _glapi_noop_enable_warnings(GLboolean enable); | ||||
|  | ||||
|   | ||||
| @@ -850,7 +850,8 @@ | ||||
| #define _gloffset_StencilMaskSeparate 815 | ||||
| #define _gloffset_GetQueryObjecti64vEXT 816 | ||||
| #define _gloffset_GetQueryObjectui64vEXT 817 | ||||
| #define _gloffset_FIRST_DYNAMIC 818 | ||||
| #define _gloffset_BlitFramebufferEXT 818 | ||||
| #define _gloffset_FIRST_DYNAMIC 819 | ||||
|  | ||||
| #else | ||||
|  | ||||
| @@ -1264,6 +1265,7 @@ | ||||
| #define _gloffset_StencilMaskSeparate driDispatchRemapTable[StencilMaskSeparate_remap_index] | ||||
| #define _gloffset_GetQueryObjecti64vEXT driDispatchRemapTable[GetQueryObjecti64vEXT_remap_index] | ||||
| #define _gloffset_GetQueryObjectui64vEXT driDispatchRemapTable[GetQueryObjectui64vEXT_remap_index] | ||||
| #define _gloffset_BlitFramebufferEXT driDispatchRemapTable[BlitFramebufferEXT_remap_index] | ||||
|  | ||||
| #endif /* !defined(IN_DRI_DRIVER) */ | ||||
|  | ||||
|   | ||||
| @@ -855,6 +855,7 @@ struct _glapi_table | ||||
|    void (GLAPIENTRYP StencilMaskSeparate)(GLenum face, GLuint mask); /* 815 */ | ||||
|    void (GLAPIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT * params); /* 816 */ | ||||
|    void (GLAPIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT * params); /* 817 */ | ||||
|    void (GLAPIENTRYP BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); /* 818 */ | ||||
| }; | ||||
|  | ||||
| #endif /* !defined( _GLAPI_TABLE_H_ ) */ | ||||
|   | ||||
| @@ -5050,6 +5050,11 @@ KEYWORD1 void KEYWORD2 NAME(GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLu | ||||
|    DISPATCH(GetQueryObjectui64vEXT, (id, pname, params), (F, "glGetQueryObjectui64vEXT(%d, 0x%x, %p);\n", id, pname, (const void *) params)); | ||||
| } | ||||
|  | ||||
| KEYWORD1 void KEYWORD2 NAME(BlitFramebufferEXT)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) | ||||
| { | ||||
|    DISPATCH(BlitFramebufferEXT, (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), (F, "glBlitFramebufferEXT(%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x);\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter)); | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif /* defined( NAME ) */ | ||||
|  | ||||
| @@ -5882,6 +5887,7 @@ static _glapi_proc DISPATCH_TABLE_NAME[] = { | ||||
|    TABLE_ENTRY(StencilMaskSeparate), | ||||
|    TABLE_ENTRY(GetQueryObjecti64vEXT), | ||||
|    TABLE_ENTRY(GetQueryObjectui64vEXT), | ||||
|    TABLE_ENTRY(BlitFramebufferEXT), | ||||
|    /* A whole bunch of no-op functions.  These might be called | ||||
|     * when someone tries to call a dynamically-registered | ||||
|     * extension function without a current rendering context. | ||||
|   | ||||
| @@ -864,6 +864,7 @@ static const char gl_string_table[] = | ||||
|     "glStencilMaskSeparate\0" | ||||
|     "glGetQueryObjecti64vEXT\0" | ||||
|     "glGetQueryObjectui64vEXT\0" | ||||
|     "glBlitFramebufferEXT\0" | ||||
|     "glArrayElementEXT\0" | ||||
|     "glBindTextureEXT\0" | ||||
|     "glDrawArraysEXT\0" | ||||
| @@ -1863,184 +1864,185 @@ static const glprocs_table_t static_functions[] = { | ||||
|     NAME_FUNC_OFFSET( 14649, glStencilMaskSeparate, _gloffset_StencilMaskSeparate ), | ||||
|     NAME_FUNC_OFFSET( 14671, glGetQueryObjecti64vEXT, _gloffset_GetQueryObjecti64vEXT ), | ||||
|     NAME_FUNC_OFFSET( 14695, glGetQueryObjectui64vEXT, _gloffset_GetQueryObjectui64vEXT ), | ||||
|     NAME_FUNC_OFFSET( 14720, glArrayElementEXT, _gloffset_ArrayElement ), | ||||
|     NAME_FUNC_OFFSET( 14738, glBindTextureEXT, _gloffset_BindTexture ), | ||||
|     NAME_FUNC_OFFSET( 14755, glDrawArraysEXT, _gloffset_DrawArrays ), | ||||
|     NAME_FUNC_OFFSET( 14771, glCopyTexImage1DEXT, _gloffset_CopyTexImage1D ), | ||||
|     NAME_FUNC_OFFSET( 14791, glCopyTexImage2DEXT, _gloffset_CopyTexImage2D ), | ||||
|     NAME_FUNC_OFFSET( 14811, glCopyTexSubImage1DEXT, _gloffset_CopyTexSubImage1D ), | ||||
|     NAME_FUNC_OFFSET( 14834, glCopyTexSubImage2DEXT, _gloffset_CopyTexSubImage2D ), | ||||
|     NAME_FUNC_OFFSET( 14857, glDeleteTexturesEXT, _gloffset_DeleteTextures ), | ||||
|     NAME_FUNC_OFFSET( 14877, glGetPointervEXT, _gloffset_GetPointerv ), | ||||
|     NAME_FUNC_OFFSET( 14894, glPrioritizeTexturesEXT, _gloffset_PrioritizeTextures ), | ||||
|     NAME_FUNC_OFFSET( 14918, glTexSubImage1DEXT, _gloffset_TexSubImage1D ), | ||||
|     NAME_FUNC_OFFSET( 14937, glTexSubImage2DEXT, _gloffset_TexSubImage2D ), | ||||
|     NAME_FUNC_OFFSET( 14956, glBlendColorEXT, _gloffset_BlendColor ), | ||||
|     NAME_FUNC_OFFSET( 14972, glBlendEquationEXT, _gloffset_BlendEquation ), | ||||
|     NAME_FUNC_OFFSET( 14991, glDrawRangeElementsEXT, _gloffset_DrawRangeElements ), | ||||
|     NAME_FUNC_OFFSET( 15014, glColorTableSGI, _gloffset_ColorTable ), | ||||
|     NAME_FUNC_OFFSET( 15030, glColorTableEXT, _gloffset_ColorTable ), | ||||
|     NAME_FUNC_OFFSET( 15046, glColorTableParameterfvSGI, _gloffset_ColorTableParameterfv ), | ||||
|     NAME_FUNC_OFFSET( 15073, glColorTableParameterivSGI, _gloffset_ColorTableParameteriv ), | ||||
|     NAME_FUNC_OFFSET( 15100, glCopyColorTableSGI, _gloffset_CopyColorTable ), | ||||
|     NAME_FUNC_OFFSET( 15120, glColorSubTableEXT, _gloffset_ColorSubTable ), | ||||
|     NAME_FUNC_OFFSET( 15139, glCopyColorSubTableEXT, _gloffset_CopyColorSubTable ), | ||||
|     NAME_FUNC_OFFSET( 15162, glConvolutionFilter1DEXT, _gloffset_ConvolutionFilter1D ), | ||||
|     NAME_FUNC_OFFSET( 15187, glConvolutionFilter2DEXT, _gloffset_ConvolutionFilter2D ), | ||||
|     NAME_FUNC_OFFSET( 15212, glConvolutionParameterfEXT, _gloffset_ConvolutionParameterf ), | ||||
|     NAME_FUNC_OFFSET( 15239, glConvolutionParameterfvEXT, _gloffset_ConvolutionParameterfv ), | ||||
|     NAME_FUNC_OFFSET( 15267, glConvolutionParameteriEXT, _gloffset_ConvolutionParameteri ), | ||||
|     NAME_FUNC_OFFSET( 15294, glConvolutionParameterivEXT, _gloffset_ConvolutionParameteriv ), | ||||
|     NAME_FUNC_OFFSET( 15322, glCopyConvolutionFilter1DEXT, _gloffset_CopyConvolutionFilter1D ), | ||||
|     NAME_FUNC_OFFSET( 15351, glCopyConvolutionFilter2DEXT, _gloffset_CopyConvolutionFilter2D ), | ||||
|     NAME_FUNC_OFFSET( 15380, glSeparableFilter2DEXT, _gloffset_SeparableFilter2D ), | ||||
|     NAME_FUNC_OFFSET( 15403, glHistogramEXT, _gloffset_Histogram ), | ||||
|     NAME_FUNC_OFFSET( 15418, glMinmaxEXT, _gloffset_Minmax ), | ||||
|     NAME_FUNC_OFFSET( 15430, glResetHistogramEXT, _gloffset_ResetHistogram ), | ||||
|     NAME_FUNC_OFFSET( 15450, glResetMinmaxEXT, _gloffset_ResetMinmax ), | ||||
|     NAME_FUNC_OFFSET( 15467, glTexImage3DEXT, _gloffset_TexImage3D ), | ||||
|     NAME_FUNC_OFFSET( 15483, glTexSubImage3DEXT, _gloffset_TexSubImage3D ), | ||||
|     NAME_FUNC_OFFSET( 15502, glCopyTexSubImage3DEXT, _gloffset_CopyTexSubImage3D ), | ||||
|     NAME_FUNC_OFFSET( 15525, glActiveTexture, _gloffset_ActiveTextureARB ), | ||||
|     NAME_FUNC_OFFSET( 15541, glClientActiveTexture, _gloffset_ClientActiveTextureARB ), | ||||
|     NAME_FUNC_OFFSET( 15563, glMultiTexCoord1d, _gloffset_MultiTexCoord1dARB ), | ||||
|     NAME_FUNC_OFFSET( 15581, glMultiTexCoord1dv, _gloffset_MultiTexCoord1dvARB ), | ||||
|     NAME_FUNC_OFFSET( 15600, glMultiTexCoord1f, _gloffset_MultiTexCoord1fARB ), | ||||
|     NAME_FUNC_OFFSET( 15618, glMultiTexCoord1fv, _gloffset_MultiTexCoord1fvARB ), | ||||
|     NAME_FUNC_OFFSET( 15637, glMultiTexCoord1i, _gloffset_MultiTexCoord1iARB ), | ||||
|     NAME_FUNC_OFFSET( 15655, glMultiTexCoord1iv, _gloffset_MultiTexCoord1ivARB ), | ||||
|     NAME_FUNC_OFFSET( 15674, glMultiTexCoord1s, _gloffset_MultiTexCoord1sARB ), | ||||
|     NAME_FUNC_OFFSET( 15692, glMultiTexCoord1sv, _gloffset_MultiTexCoord1svARB ), | ||||
|     NAME_FUNC_OFFSET( 15711, glMultiTexCoord2d, _gloffset_MultiTexCoord2dARB ), | ||||
|     NAME_FUNC_OFFSET( 15729, glMultiTexCoord2dv, _gloffset_MultiTexCoord2dvARB ), | ||||
|     NAME_FUNC_OFFSET( 15748, glMultiTexCoord2f, _gloffset_MultiTexCoord2fARB ), | ||||
|     NAME_FUNC_OFFSET( 15766, glMultiTexCoord2fv, _gloffset_MultiTexCoord2fvARB ), | ||||
|     NAME_FUNC_OFFSET( 15785, glMultiTexCoord2i, _gloffset_MultiTexCoord2iARB ), | ||||
|     NAME_FUNC_OFFSET( 15803, glMultiTexCoord2iv, _gloffset_MultiTexCoord2ivARB ), | ||||
|     NAME_FUNC_OFFSET( 15822, glMultiTexCoord2s, _gloffset_MultiTexCoord2sARB ), | ||||
|     NAME_FUNC_OFFSET( 15840, glMultiTexCoord2sv, _gloffset_MultiTexCoord2svARB ), | ||||
|     NAME_FUNC_OFFSET( 15859, glMultiTexCoord3d, _gloffset_MultiTexCoord3dARB ), | ||||
|     NAME_FUNC_OFFSET( 15877, glMultiTexCoord3dv, _gloffset_MultiTexCoord3dvARB ), | ||||
|     NAME_FUNC_OFFSET( 15896, glMultiTexCoord3f, _gloffset_MultiTexCoord3fARB ), | ||||
|     NAME_FUNC_OFFSET( 15914, glMultiTexCoord3fv, _gloffset_MultiTexCoord3fvARB ), | ||||
|     NAME_FUNC_OFFSET( 15933, glMultiTexCoord3i, _gloffset_MultiTexCoord3iARB ), | ||||
|     NAME_FUNC_OFFSET( 15951, glMultiTexCoord3iv, _gloffset_MultiTexCoord3ivARB ), | ||||
|     NAME_FUNC_OFFSET( 15970, glMultiTexCoord3s, _gloffset_MultiTexCoord3sARB ), | ||||
|     NAME_FUNC_OFFSET( 15988, glMultiTexCoord3sv, _gloffset_MultiTexCoord3svARB ), | ||||
|     NAME_FUNC_OFFSET( 16007, glMultiTexCoord4d, _gloffset_MultiTexCoord4dARB ), | ||||
|     NAME_FUNC_OFFSET( 16025, glMultiTexCoord4dv, _gloffset_MultiTexCoord4dvARB ), | ||||
|     NAME_FUNC_OFFSET( 16044, glMultiTexCoord4f, _gloffset_MultiTexCoord4fARB ), | ||||
|     NAME_FUNC_OFFSET( 16062, glMultiTexCoord4fv, _gloffset_MultiTexCoord4fvARB ), | ||||
|     NAME_FUNC_OFFSET( 16081, glMultiTexCoord4i, _gloffset_MultiTexCoord4iARB ), | ||||
|     NAME_FUNC_OFFSET( 16099, glMultiTexCoord4iv, _gloffset_MultiTexCoord4ivARB ), | ||||
|     NAME_FUNC_OFFSET( 16118, glMultiTexCoord4s, _gloffset_MultiTexCoord4sARB ), | ||||
|     NAME_FUNC_OFFSET( 16136, glMultiTexCoord4sv, _gloffset_MultiTexCoord4svARB ), | ||||
|     NAME_FUNC_OFFSET( 16155, glLoadTransposeMatrixf, _gloffset_LoadTransposeMatrixfARB ), | ||||
|     NAME_FUNC_OFFSET( 16178, glLoadTransposeMatrixd, _gloffset_LoadTransposeMatrixdARB ), | ||||
|     NAME_FUNC_OFFSET( 16201, glMultTransposeMatrixf, _gloffset_MultTransposeMatrixfARB ), | ||||
|     NAME_FUNC_OFFSET( 16224, glMultTransposeMatrixd, _gloffset_MultTransposeMatrixdARB ), | ||||
|     NAME_FUNC_OFFSET( 16247, glSampleCoverage, _gloffset_SampleCoverageARB ), | ||||
|     NAME_FUNC_OFFSET( 16264, glDrawBuffersATI, _gloffset_DrawBuffersARB ), | ||||
|     NAME_FUNC_OFFSET( 16281, glSampleMaskEXT, _gloffset_SampleMaskSGIS ), | ||||
|     NAME_FUNC_OFFSET( 16297, glSamplePatternEXT, _gloffset_SamplePatternSGIS ), | ||||
|     NAME_FUNC_OFFSET( 16316, glPointParameterf, _gloffset_PointParameterfEXT ), | ||||
|     NAME_FUNC_OFFSET( 16334, glPointParameterfARB, _gloffset_PointParameterfEXT ), | ||||
|     NAME_FUNC_OFFSET( 16355, glPointParameterfSGIS, _gloffset_PointParameterfEXT ), | ||||
|     NAME_FUNC_OFFSET( 16377, glPointParameterfv, _gloffset_PointParameterfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 16396, glPointParameterfvARB, _gloffset_PointParameterfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 16418, glPointParameterfvSGIS, _gloffset_PointParameterfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 16441, glWindowPos2d, _gloffset_WindowPos2dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16455, glWindowPos2dARB, _gloffset_WindowPos2dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16472, glWindowPos2dv, _gloffset_WindowPos2dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16487, glWindowPos2dvARB, _gloffset_WindowPos2dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16505, glWindowPos2f, _gloffset_WindowPos2fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16519, glWindowPos2fARB, _gloffset_WindowPos2fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16536, glWindowPos2fv, _gloffset_WindowPos2fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16551, glWindowPos2fvARB, _gloffset_WindowPos2fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16569, glWindowPos2i, _gloffset_WindowPos2iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16583, glWindowPos2iARB, _gloffset_WindowPos2iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16600, glWindowPos2iv, _gloffset_WindowPos2ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16615, glWindowPos2ivARB, _gloffset_WindowPos2ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16633, glWindowPos2s, _gloffset_WindowPos2sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16647, glWindowPos2sARB, _gloffset_WindowPos2sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16664, glWindowPos2sv, _gloffset_WindowPos2svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16679, glWindowPos2svARB, _gloffset_WindowPos2svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16697, glWindowPos3d, _gloffset_WindowPos3dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16711, glWindowPos3dARB, _gloffset_WindowPos3dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16728, glWindowPos3dv, _gloffset_WindowPos3dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16743, glWindowPos3dvARB, _gloffset_WindowPos3dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16761, glWindowPos3f, _gloffset_WindowPos3fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16775, glWindowPos3fARB, _gloffset_WindowPos3fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16792, glWindowPos3fv, _gloffset_WindowPos3fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16807, glWindowPos3fvARB, _gloffset_WindowPos3fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16825, glWindowPos3i, _gloffset_WindowPos3iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16839, glWindowPos3iARB, _gloffset_WindowPos3iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16856, glWindowPos3iv, _gloffset_WindowPos3ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16871, glWindowPos3ivARB, _gloffset_WindowPos3ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16889, glWindowPos3s, _gloffset_WindowPos3sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16903, glWindowPos3sARB, _gloffset_WindowPos3sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16920, glWindowPos3sv, _gloffset_WindowPos3svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16935, glWindowPos3svARB, _gloffset_WindowPos3svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16953, glBlendFuncSeparate, _gloffset_BlendFuncSeparateEXT ), | ||||
|     NAME_FUNC_OFFSET( 16973, glBlendFuncSeparateINGR, _gloffset_BlendFuncSeparateEXT ), | ||||
|     NAME_FUNC_OFFSET( 16997, glFogCoordf, _gloffset_FogCoordfEXT ), | ||||
|     NAME_FUNC_OFFSET( 17009, glFogCoordfv, _gloffset_FogCoordfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17022, glFogCoordd, _gloffset_FogCoorddEXT ), | ||||
|     NAME_FUNC_OFFSET( 17034, glFogCoorddv, _gloffset_FogCoorddvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17047, glFogCoordPointer, _gloffset_FogCoordPointerEXT ), | ||||
|     NAME_FUNC_OFFSET( 17065, glCompressedTexImage3D, _gloffset_CompressedTexImage3DARB ), | ||||
|     NAME_FUNC_OFFSET( 17088, glCompressedTexImage2D, _gloffset_CompressedTexImage2DARB ), | ||||
|     NAME_FUNC_OFFSET( 17111, glCompressedTexImage1D, _gloffset_CompressedTexImage1DARB ), | ||||
|     NAME_FUNC_OFFSET( 17134, glCompressedTexSubImage3D, _gloffset_CompressedTexSubImage3DARB ), | ||||
|     NAME_FUNC_OFFSET( 17160, glCompressedTexSubImage2D, _gloffset_CompressedTexSubImage2DARB ), | ||||
|     NAME_FUNC_OFFSET( 17186, glCompressedTexSubImage1D, _gloffset_CompressedTexSubImage1DARB ), | ||||
|     NAME_FUNC_OFFSET( 17212, glGetCompressedTexImage, _gloffset_GetCompressedTexImageARB ), | ||||
|     NAME_FUNC_OFFSET( 17236, glSecondaryColor3b, _gloffset_SecondaryColor3bEXT ), | ||||
|     NAME_FUNC_OFFSET( 17255, glSecondaryColor3bv, _gloffset_SecondaryColor3bvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17275, glSecondaryColor3d, _gloffset_SecondaryColor3dEXT ), | ||||
|     NAME_FUNC_OFFSET( 17294, glSecondaryColor3dv, _gloffset_SecondaryColor3dvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17314, glSecondaryColor3f, _gloffset_SecondaryColor3fEXT ), | ||||
|     NAME_FUNC_OFFSET( 17333, glSecondaryColor3fv, _gloffset_SecondaryColor3fvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17353, glSecondaryColor3i, _gloffset_SecondaryColor3iEXT ), | ||||
|     NAME_FUNC_OFFSET( 17372, glSecondaryColor3iv, _gloffset_SecondaryColor3ivEXT ), | ||||
|     NAME_FUNC_OFFSET( 17392, glSecondaryColor3s, _gloffset_SecondaryColor3sEXT ), | ||||
|     NAME_FUNC_OFFSET( 17411, glSecondaryColor3sv, _gloffset_SecondaryColor3svEXT ), | ||||
|     NAME_FUNC_OFFSET( 17431, glSecondaryColor3ub, _gloffset_SecondaryColor3ubEXT ), | ||||
|     NAME_FUNC_OFFSET( 17451, glSecondaryColor3ubv, _gloffset_SecondaryColor3ubvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17472, glSecondaryColor3ui, _gloffset_SecondaryColor3uiEXT ), | ||||
|     NAME_FUNC_OFFSET( 17492, glSecondaryColor3uiv, _gloffset_SecondaryColor3uivEXT ), | ||||
|     NAME_FUNC_OFFSET( 17513, glSecondaryColor3us, _gloffset_SecondaryColor3usEXT ), | ||||
|     NAME_FUNC_OFFSET( 17533, glSecondaryColor3usv, _gloffset_SecondaryColor3usvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17554, glSecondaryColorPointer, _gloffset_SecondaryColorPointerEXT ), | ||||
|     NAME_FUNC_OFFSET( 17578, glBindProgramARB, _gloffset_BindProgramNV ), | ||||
|     NAME_FUNC_OFFSET( 17595, glDeleteProgramsARB, _gloffset_DeleteProgramsNV ), | ||||
|     NAME_FUNC_OFFSET( 17615, glGenProgramsARB, _gloffset_GenProgramsNV ), | ||||
|     NAME_FUNC_OFFSET( 17632, glGetVertexAttribPointervARB, _gloffset_GetVertexAttribPointervNV ), | ||||
|     NAME_FUNC_OFFSET( 17661, glIsProgramARB, _gloffset_IsProgramNV ), | ||||
|     NAME_FUNC_OFFSET( 17676, glPointParameteri, _gloffset_PointParameteriNV ), | ||||
|     NAME_FUNC_OFFSET( 17694, glPointParameteriv, _gloffset_PointParameterivNV ), | ||||
|     NAME_FUNC_OFFSET( 17713, glMultiDrawArrays, _gloffset_MultiDrawArraysEXT ), | ||||
|     NAME_FUNC_OFFSET( 17731, glMultiDrawElements, _gloffset_MultiDrawElementsEXT ), | ||||
|     NAME_FUNC_OFFSET( 17751, glBindBuffer, _gloffset_BindBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17764, glBufferData, _gloffset_BufferDataARB ), | ||||
|     NAME_FUNC_OFFSET( 17777, glBufferSubData, _gloffset_BufferSubDataARB ), | ||||
|     NAME_FUNC_OFFSET( 17793, glDeleteBuffers, _gloffset_DeleteBuffersARB ), | ||||
|     NAME_FUNC_OFFSET( 17809, glGenBuffers, _gloffset_GenBuffersARB ), | ||||
|     NAME_FUNC_OFFSET( 17822, glGetBufferParameteriv, _gloffset_GetBufferParameterivARB ), | ||||
|     NAME_FUNC_OFFSET( 17845, glGetBufferPointerv, _gloffset_GetBufferPointervARB ), | ||||
|     NAME_FUNC_OFFSET( 17865, glGetBufferSubData, _gloffset_GetBufferSubDataARB ), | ||||
|     NAME_FUNC_OFFSET( 17884, glIsBuffer, _gloffset_IsBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17895, glMapBuffer, _gloffset_MapBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17907, glUnmapBuffer, _gloffset_UnmapBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17921, glGenQueries, _gloffset_GenQueriesARB ), | ||||
|     NAME_FUNC_OFFSET( 17934, glDeleteQueries, _gloffset_DeleteQueriesARB ), | ||||
|     NAME_FUNC_OFFSET( 17950, glIsQuery, _gloffset_IsQueryARB ), | ||||
|     NAME_FUNC_OFFSET( 17960, glBeginQuery, _gloffset_BeginQueryARB ), | ||||
|     NAME_FUNC_OFFSET( 17973, glEndQuery, _gloffset_EndQueryARB ), | ||||
|     NAME_FUNC_OFFSET( 17984, glGetQueryiv, _gloffset_GetQueryivARB ), | ||||
|     NAME_FUNC_OFFSET( 17997, glGetQueryObjectiv, _gloffset_GetQueryObjectivARB ), | ||||
|     NAME_FUNC_OFFSET( 18016, glGetQueryObjectuiv, _gloffset_GetQueryObjectuivARB ), | ||||
|     NAME_FUNC_OFFSET( 18036, glBlendEquationSeparateATI, _gloffset_BlendEquationSeparateEXT ), | ||||
|     NAME_FUNC_OFFSET( 14720, glBlitFramebufferEXT, _gloffset_BlitFramebufferEXT ), | ||||
|     NAME_FUNC_OFFSET( 14741, glArrayElementEXT, _gloffset_ArrayElement ), | ||||
|     NAME_FUNC_OFFSET( 14759, glBindTextureEXT, _gloffset_BindTexture ), | ||||
|     NAME_FUNC_OFFSET( 14776, glDrawArraysEXT, _gloffset_DrawArrays ), | ||||
|     NAME_FUNC_OFFSET( 14792, glCopyTexImage1DEXT, _gloffset_CopyTexImage1D ), | ||||
|     NAME_FUNC_OFFSET( 14812, glCopyTexImage2DEXT, _gloffset_CopyTexImage2D ), | ||||
|     NAME_FUNC_OFFSET( 14832, glCopyTexSubImage1DEXT, _gloffset_CopyTexSubImage1D ), | ||||
|     NAME_FUNC_OFFSET( 14855, glCopyTexSubImage2DEXT, _gloffset_CopyTexSubImage2D ), | ||||
|     NAME_FUNC_OFFSET( 14878, glDeleteTexturesEXT, _gloffset_DeleteTextures ), | ||||
|     NAME_FUNC_OFFSET( 14898, glGetPointervEXT, _gloffset_GetPointerv ), | ||||
|     NAME_FUNC_OFFSET( 14915, glPrioritizeTexturesEXT, _gloffset_PrioritizeTextures ), | ||||
|     NAME_FUNC_OFFSET( 14939, glTexSubImage1DEXT, _gloffset_TexSubImage1D ), | ||||
|     NAME_FUNC_OFFSET( 14958, glTexSubImage2DEXT, _gloffset_TexSubImage2D ), | ||||
|     NAME_FUNC_OFFSET( 14977, glBlendColorEXT, _gloffset_BlendColor ), | ||||
|     NAME_FUNC_OFFSET( 14993, glBlendEquationEXT, _gloffset_BlendEquation ), | ||||
|     NAME_FUNC_OFFSET( 15012, glDrawRangeElementsEXT, _gloffset_DrawRangeElements ), | ||||
|     NAME_FUNC_OFFSET( 15035, glColorTableSGI, _gloffset_ColorTable ), | ||||
|     NAME_FUNC_OFFSET( 15051, glColorTableEXT, _gloffset_ColorTable ), | ||||
|     NAME_FUNC_OFFSET( 15067, glColorTableParameterfvSGI, _gloffset_ColorTableParameterfv ), | ||||
|     NAME_FUNC_OFFSET( 15094, glColorTableParameterivSGI, _gloffset_ColorTableParameteriv ), | ||||
|     NAME_FUNC_OFFSET( 15121, glCopyColorTableSGI, _gloffset_CopyColorTable ), | ||||
|     NAME_FUNC_OFFSET( 15141, glColorSubTableEXT, _gloffset_ColorSubTable ), | ||||
|     NAME_FUNC_OFFSET( 15160, glCopyColorSubTableEXT, _gloffset_CopyColorSubTable ), | ||||
|     NAME_FUNC_OFFSET( 15183, glConvolutionFilter1DEXT, _gloffset_ConvolutionFilter1D ), | ||||
|     NAME_FUNC_OFFSET( 15208, glConvolutionFilter2DEXT, _gloffset_ConvolutionFilter2D ), | ||||
|     NAME_FUNC_OFFSET( 15233, glConvolutionParameterfEXT, _gloffset_ConvolutionParameterf ), | ||||
|     NAME_FUNC_OFFSET( 15260, glConvolutionParameterfvEXT, _gloffset_ConvolutionParameterfv ), | ||||
|     NAME_FUNC_OFFSET( 15288, glConvolutionParameteriEXT, _gloffset_ConvolutionParameteri ), | ||||
|     NAME_FUNC_OFFSET( 15315, glConvolutionParameterivEXT, _gloffset_ConvolutionParameteriv ), | ||||
|     NAME_FUNC_OFFSET( 15343, glCopyConvolutionFilter1DEXT, _gloffset_CopyConvolutionFilter1D ), | ||||
|     NAME_FUNC_OFFSET( 15372, glCopyConvolutionFilter2DEXT, _gloffset_CopyConvolutionFilter2D ), | ||||
|     NAME_FUNC_OFFSET( 15401, glSeparableFilter2DEXT, _gloffset_SeparableFilter2D ), | ||||
|     NAME_FUNC_OFFSET( 15424, glHistogramEXT, _gloffset_Histogram ), | ||||
|     NAME_FUNC_OFFSET( 15439, glMinmaxEXT, _gloffset_Minmax ), | ||||
|     NAME_FUNC_OFFSET( 15451, glResetHistogramEXT, _gloffset_ResetHistogram ), | ||||
|     NAME_FUNC_OFFSET( 15471, glResetMinmaxEXT, _gloffset_ResetMinmax ), | ||||
|     NAME_FUNC_OFFSET( 15488, glTexImage3DEXT, _gloffset_TexImage3D ), | ||||
|     NAME_FUNC_OFFSET( 15504, glTexSubImage3DEXT, _gloffset_TexSubImage3D ), | ||||
|     NAME_FUNC_OFFSET( 15523, glCopyTexSubImage3DEXT, _gloffset_CopyTexSubImage3D ), | ||||
|     NAME_FUNC_OFFSET( 15546, glActiveTexture, _gloffset_ActiveTextureARB ), | ||||
|     NAME_FUNC_OFFSET( 15562, glClientActiveTexture, _gloffset_ClientActiveTextureARB ), | ||||
|     NAME_FUNC_OFFSET( 15584, glMultiTexCoord1d, _gloffset_MultiTexCoord1dARB ), | ||||
|     NAME_FUNC_OFFSET( 15602, glMultiTexCoord1dv, _gloffset_MultiTexCoord1dvARB ), | ||||
|     NAME_FUNC_OFFSET( 15621, glMultiTexCoord1f, _gloffset_MultiTexCoord1fARB ), | ||||
|     NAME_FUNC_OFFSET( 15639, glMultiTexCoord1fv, _gloffset_MultiTexCoord1fvARB ), | ||||
|     NAME_FUNC_OFFSET( 15658, glMultiTexCoord1i, _gloffset_MultiTexCoord1iARB ), | ||||
|     NAME_FUNC_OFFSET( 15676, glMultiTexCoord1iv, _gloffset_MultiTexCoord1ivARB ), | ||||
|     NAME_FUNC_OFFSET( 15695, glMultiTexCoord1s, _gloffset_MultiTexCoord1sARB ), | ||||
|     NAME_FUNC_OFFSET( 15713, glMultiTexCoord1sv, _gloffset_MultiTexCoord1svARB ), | ||||
|     NAME_FUNC_OFFSET( 15732, glMultiTexCoord2d, _gloffset_MultiTexCoord2dARB ), | ||||
|     NAME_FUNC_OFFSET( 15750, glMultiTexCoord2dv, _gloffset_MultiTexCoord2dvARB ), | ||||
|     NAME_FUNC_OFFSET( 15769, glMultiTexCoord2f, _gloffset_MultiTexCoord2fARB ), | ||||
|     NAME_FUNC_OFFSET( 15787, glMultiTexCoord2fv, _gloffset_MultiTexCoord2fvARB ), | ||||
|     NAME_FUNC_OFFSET( 15806, glMultiTexCoord2i, _gloffset_MultiTexCoord2iARB ), | ||||
|     NAME_FUNC_OFFSET( 15824, glMultiTexCoord2iv, _gloffset_MultiTexCoord2ivARB ), | ||||
|     NAME_FUNC_OFFSET( 15843, glMultiTexCoord2s, _gloffset_MultiTexCoord2sARB ), | ||||
|     NAME_FUNC_OFFSET( 15861, glMultiTexCoord2sv, _gloffset_MultiTexCoord2svARB ), | ||||
|     NAME_FUNC_OFFSET( 15880, glMultiTexCoord3d, _gloffset_MultiTexCoord3dARB ), | ||||
|     NAME_FUNC_OFFSET( 15898, glMultiTexCoord3dv, _gloffset_MultiTexCoord3dvARB ), | ||||
|     NAME_FUNC_OFFSET( 15917, glMultiTexCoord3f, _gloffset_MultiTexCoord3fARB ), | ||||
|     NAME_FUNC_OFFSET( 15935, glMultiTexCoord3fv, _gloffset_MultiTexCoord3fvARB ), | ||||
|     NAME_FUNC_OFFSET( 15954, glMultiTexCoord3i, _gloffset_MultiTexCoord3iARB ), | ||||
|     NAME_FUNC_OFFSET( 15972, glMultiTexCoord3iv, _gloffset_MultiTexCoord3ivARB ), | ||||
|     NAME_FUNC_OFFSET( 15991, glMultiTexCoord3s, _gloffset_MultiTexCoord3sARB ), | ||||
|     NAME_FUNC_OFFSET( 16009, glMultiTexCoord3sv, _gloffset_MultiTexCoord3svARB ), | ||||
|     NAME_FUNC_OFFSET( 16028, glMultiTexCoord4d, _gloffset_MultiTexCoord4dARB ), | ||||
|     NAME_FUNC_OFFSET( 16046, glMultiTexCoord4dv, _gloffset_MultiTexCoord4dvARB ), | ||||
|     NAME_FUNC_OFFSET( 16065, glMultiTexCoord4f, _gloffset_MultiTexCoord4fARB ), | ||||
|     NAME_FUNC_OFFSET( 16083, glMultiTexCoord4fv, _gloffset_MultiTexCoord4fvARB ), | ||||
|     NAME_FUNC_OFFSET( 16102, glMultiTexCoord4i, _gloffset_MultiTexCoord4iARB ), | ||||
|     NAME_FUNC_OFFSET( 16120, glMultiTexCoord4iv, _gloffset_MultiTexCoord4ivARB ), | ||||
|     NAME_FUNC_OFFSET( 16139, glMultiTexCoord4s, _gloffset_MultiTexCoord4sARB ), | ||||
|     NAME_FUNC_OFFSET( 16157, glMultiTexCoord4sv, _gloffset_MultiTexCoord4svARB ), | ||||
|     NAME_FUNC_OFFSET( 16176, glLoadTransposeMatrixf, _gloffset_LoadTransposeMatrixfARB ), | ||||
|     NAME_FUNC_OFFSET( 16199, glLoadTransposeMatrixd, _gloffset_LoadTransposeMatrixdARB ), | ||||
|     NAME_FUNC_OFFSET( 16222, glMultTransposeMatrixf, _gloffset_MultTransposeMatrixfARB ), | ||||
|     NAME_FUNC_OFFSET( 16245, glMultTransposeMatrixd, _gloffset_MultTransposeMatrixdARB ), | ||||
|     NAME_FUNC_OFFSET( 16268, glSampleCoverage, _gloffset_SampleCoverageARB ), | ||||
|     NAME_FUNC_OFFSET( 16285, glDrawBuffersATI, _gloffset_DrawBuffersARB ), | ||||
|     NAME_FUNC_OFFSET( 16302, glSampleMaskEXT, _gloffset_SampleMaskSGIS ), | ||||
|     NAME_FUNC_OFFSET( 16318, glSamplePatternEXT, _gloffset_SamplePatternSGIS ), | ||||
|     NAME_FUNC_OFFSET( 16337, glPointParameterf, _gloffset_PointParameterfEXT ), | ||||
|     NAME_FUNC_OFFSET( 16355, glPointParameterfARB, _gloffset_PointParameterfEXT ), | ||||
|     NAME_FUNC_OFFSET( 16376, glPointParameterfSGIS, _gloffset_PointParameterfEXT ), | ||||
|     NAME_FUNC_OFFSET( 16398, glPointParameterfv, _gloffset_PointParameterfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 16417, glPointParameterfvARB, _gloffset_PointParameterfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 16439, glPointParameterfvSGIS, _gloffset_PointParameterfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 16462, glWindowPos2d, _gloffset_WindowPos2dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16476, glWindowPos2dARB, _gloffset_WindowPos2dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16493, glWindowPos2dv, _gloffset_WindowPos2dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16508, glWindowPos2dvARB, _gloffset_WindowPos2dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16526, glWindowPos2f, _gloffset_WindowPos2fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16540, glWindowPos2fARB, _gloffset_WindowPos2fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16557, glWindowPos2fv, _gloffset_WindowPos2fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16572, glWindowPos2fvARB, _gloffset_WindowPos2fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16590, glWindowPos2i, _gloffset_WindowPos2iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16604, glWindowPos2iARB, _gloffset_WindowPos2iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16621, glWindowPos2iv, _gloffset_WindowPos2ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16636, glWindowPos2ivARB, _gloffset_WindowPos2ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16654, glWindowPos2s, _gloffset_WindowPos2sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16668, glWindowPos2sARB, _gloffset_WindowPos2sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16685, glWindowPos2sv, _gloffset_WindowPos2svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16700, glWindowPos2svARB, _gloffset_WindowPos2svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16718, glWindowPos3d, _gloffset_WindowPos3dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16732, glWindowPos3dARB, _gloffset_WindowPos3dMESA ), | ||||
|     NAME_FUNC_OFFSET( 16749, glWindowPos3dv, _gloffset_WindowPos3dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16764, glWindowPos3dvARB, _gloffset_WindowPos3dvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16782, glWindowPos3f, _gloffset_WindowPos3fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16796, glWindowPos3fARB, _gloffset_WindowPos3fMESA ), | ||||
|     NAME_FUNC_OFFSET( 16813, glWindowPos3fv, _gloffset_WindowPos3fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16828, glWindowPos3fvARB, _gloffset_WindowPos3fvMESA ), | ||||
|     NAME_FUNC_OFFSET( 16846, glWindowPos3i, _gloffset_WindowPos3iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16860, glWindowPos3iARB, _gloffset_WindowPos3iMESA ), | ||||
|     NAME_FUNC_OFFSET( 16877, glWindowPos3iv, _gloffset_WindowPos3ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16892, glWindowPos3ivARB, _gloffset_WindowPos3ivMESA ), | ||||
|     NAME_FUNC_OFFSET( 16910, glWindowPos3s, _gloffset_WindowPos3sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16924, glWindowPos3sARB, _gloffset_WindowPos3sMESA ), | ||||
|     NAME_FUNC_OFFSET( 16941, glWindowPos3sv, _gloffset_WindowPos3svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16956, glWindowPos3svARB, _gloffset_WindowPos3svMESA ), | ||||
|     NAME_FUNC_OFFSET( 16974, glBlendFuncSeparate, _gloffset_BlendFuncSeparateEXT ), | ||||
|     NAME_FUNC_OFFSET( 16994, glBlendFuncSeparateINGR, _gloffset_BlendFuncSeparateEXT ), | ||||
|     NAME_FUNC_OFFSET( 17018, glFogCoordf, _gloffset_FogCoordfEXT ), | ||||
|     NAME_FUNC_OFFSET( 17030, glFogCoordfv, _gloffset_FogCoordfvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17043, glFogCoordd, _gloffset_FogCoorddEXT ), | ||||
|     NAME_FUNC_OFFSET( 17055, glFogCoorddv, _gloffset_FogCoorddvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17068, glFogCoordPointer, _gloffset_FogCoordPointerEXT ), | ||||
|     NAME_FUNC_OFFSET( 17086, glCompressedTexImage3D, _gloffset_CompressedTexImage3DARB ), | ||||
|     NAME_FUNC_OFFSET( 17109, glCompressedTexImage2D, _gloffset_CompressedTexImage2DARB ), | ||||
|     NAME_FUNC_OFFSET( 17132, glCompressedTexImage1D, _gloffset_CompressedTexImage1DARB ), | ||||
|     NAME_FUNC_OFFSET( 17155, glCompressedTexSubImage3D, _gloffset_CompressedTexSubImage3DARB ), | ||||
|     NAME_FUNC_OFFSET( 17181, glCompressedTexSubImage2D, _gloffset_CompressedTexSubImage2DARB ), | ||||
|     NAME_FUNC_OFFSET( 17207, glCompressedTexSubImage1D, _gloffset_CompressedTexSubImage1DARB ), | ||||
|     NAME_FUNC_OFFSET( 17233, glGetCompressedTexImage, _gloffset_GetCompressedTexImageARB ), | ||||
|     NAME_FUNC_OFFSET( 17257, glSecondaryColor3b, _gloffset_SecondaryColor3bEXT ), | ||||
|     NAME_FUNC_OFFSET( 17276, glSecondaryColor3bv, _gloffset_SecondaryColor3bvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17296, glSecondaryColor3d, _gloffset_SecondaryColor3dEXT ), | ||||
|     NAME_FUNC_OFFSET( 17315, glSecondaryColor3dv, _gloffset_SecondaryColor3dvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17335, glSecondaryColor3f, _gloffset_SecondaryColor3fEXT ), | ||||
|     NAME_FUNC_OFFSET( 17354, glSecondaryColor3fv, _gloffset_SecondaryColor3fvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17374, glSecondaryColor3i, _gloffset_SecondaryColor3iEXT ), | ||||
|     NAME_FUNC_OFFSET( 17393, glSecondaryColor3iv, _gloffset_SecondaryColor3ivEXT ), | ||||
|     NAME_FUNC_OFFSET( 17413, glSecondaryColor3s, _gloffset_SecondaryColor3sEXT ), | ||||
|     NAME_FUNC_OFFSET( 17432, glSecondaryColor3sv, _gloffset_SecondaryColor3svEXT ), | ||||
|     NAME_FUNC_OFFSET( 17452, glSecondaryColor3ub, _gloffset_SecondaryColor3ubEXT ), | ||||
|     NAME_FUNC_OFFSET( 17472, glSecondaryColor3ubv, _gloffset_SecondaryColor3ubvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17493, glSecondaryColor3ui, _gloffset_SecondaryColor3uiEXT ), | ||||
|     NAME_FUNC_OFFSET( 17513, glSecondaryColor3uiv, _gloffset_SecondaryColor3uivEXT ), | ||||
|     NAME_FUNC_OFFSET( 17534, glSecondaryColor3us, _gloffset_SecondaryColor3usEXT ), | ||||
|     NAME_FUNC_OFFSET( 17554, glSecondaryColor3usv, _gloffset_SecondaryColor3usvEXT ), | ||||
|     NAME_FUNC_OFFSET( 17575, glSecondaryColorPointer, _gloffset_SecondaryColorPointerEXT ), | ||||
|     NAME_FUNC_OFFSET( 17599, glBindProgramARB, _gloffset_BindProgramNV ), | ||||
|     NAME_FUNC_OFFSET( 17616, glDeleteProgramsARB, _gloffset_DeleteProgramsNV ), | ||||
|     NAME_FUNC_OFFSET( 17636, glGenProgramsARB, _gloffset_GenProgramsNV ), | ||||
|     NAME_FUNC_OFFSET( 17653, glGetVertexAttribPointervARB, _gloffset_GetVertexAttribPointervNV ), | ||||
|     NAME_FUNC_OFFSET( 17682, glIsProgramARB, _gloffset_IsProgramNV ), | ||||
|     NAME_FUNC_OFFSET( 17697, glPointParameteri, _gloffset_PointParameteriNV ), | ||||
|     NAME_FUNC_OFFSET( 17715, glPointParameteriv, _gloffset_PointParameterivNV ), | ||||
|     NAME_FUNC_OFFSET( 17734, glMultiDrawArrays, _gloffset_MultiDrawArraysEXT ), | ||||
|     NAME_FUNC_OFFSET( 17752, glMultiDrawElements, _gloffset_MultiDrawElementsEXT ), | ||||
|     NAME_FUNC_OFFSET( 17772, glBindBuffer, _gloffset_BindBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17785, glBufferData, _gloffset_BufferDataARB ), | ||||
|     NAME_FUNC_OFFSET( 17798, glBufferSubData, _gloffset_BufferSubDataARB ), | ||||
|     NAME_FUNC_OFFSET( 17814, glDeleteBuffers, _gloffset_DeleteBuffersARB ), | ||||
|     NAME_FUNC_OFFSET( 17830, glGenBuffers, _gloffset_GenBuffersARB ), | ||||
|     NAME_FUNC_OFFSET( 17843, glGetBufferParameteriv, _gloffset_GetBufferParameterivARB ), | ||||
|     NAME_FUNC_OFFSET( 17866, glGetBufferPointerv, _gloffset_GetBufferPointervARB ), | ||||
|     NAME_FUNC_OFFSET( 17886, glGetBufferSubData, _gloffset_GetBufferSubDataARB ), | ||||
|     NAME_FUNC_OFFSET( 17905, glIsBuffer, _gloffset_IsBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17916, glMapBuffer, _gloffset_MapBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17928, glUnmapBuffer, _gloffset_UnmapBufferARB ), | ||||
|     NAME_FUNC_OFFSET( 17942, glGenQueries, _gloffset_GenQueriesARB ), | ||||
|     NAME_FUNC_OFFSET( 17955, glDeleteQueries, _gloffset_DeleteQueriesARB ), | ||||
|     NAME_FUNC_OFFSET( 17971, glIsQuery, _gloffset_IsQueryARB ), | ||||
|     NAME_FUNC_OFFSET( 17981, glBeginQuery, _gloffset_BeginQueryARB ), | ||||
|     NAME_FUNC_OFFSET( 17994, glEndQuery, _gloffset_EndQueryARB ), | ||||
|     NAME_FUNC_OFFSET( 18005, glGetQueryiv, _gloffset_GetQueryivARB ), | ||||
|     NAME_FUNC_OFFSET( 18018, glGetQueryObjectiv, _gloffset_GetQueryObjectivARB ), | ||||
|     NAME_FUNC_OFFSET( 18037, glGetQueryObjectuiv, _gloffset_GetQueryObjectuivARB ), | ||||
|     NAME_FUNC_OFFSET( 18057, glBlendEquationSeparateATI, _gloffset_BlendEquationSeparateEXT ), | ||||
|     NAME_FUNC_OFFSET( -1, NULL, 0 ) | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #!/usr/bin/env python | ||||
|  | ||||
| # $Id: mesadef.py,v 1.3 2005/09/05 14:09:25 kschultz Exp $ | ||||
| # $Id: mesadef.py,v 1.3.2.1 2006/03/25 23:48:21 brianp Exp $ | ||||
|  | ||||
| # Mesa 3-D graphics library | ||||
| # Version:  4.1 | ||||
| @@ -89,6 +89,7 @@ def PrintTail(): | ||||
| 	print '\twglDescribePixelFormat' | ||||
| 	print '\twglGetCurrentContext' | ||||
| 	print '\twglGetCurrentDC' | ||||
| 	print '\twglGetExtensionsStringARB' | ||||
| 	print '\twglGetLayerPaletteEntries' | ||||
| 	print '\twglGetPixelFormat' | ||||
| 	print '\twglGetProcAddress' | ||||
|   | ||||
| @@ -29,20 +29,21 @@ import string, copy | ||||
|  | ||||
| class type_node: | ||||
| 	def __init__(self): | ||||
| 		self.pointer = 0 | ||||
| 		self.const = 0 | ||||
| 		self.signed = 1 | ||||
| 		self.integer = 1 | ||||
| 		self.pointer = 0  # bool | ||||
| 		self.const = 0    # bool | ||||
| 		self.signed = 1   # bool | ||||
| 		self.integer = 1  # bool | ||||
|  | ||||
| 		# If elements is set to non-zero, then field is an array. | ||||
| 		self.elements = 0 | ||||
|  | ||||
| 		self.name = None | ||||
| 		self.size = 0 | ||||
| 		self.size = 0     # type's size in bytes | ||||
| 		return | ||||
|  | ||||
|  | ||||
| 	def string(self): | ||||
| 		"""Return string representation of this type_node.""" | ||||
| 		s = "" | ||||
| 		 | ||||
| 		if self.pointer: | ||||
| @@ -85,16 +86,17 @@ class type_table: | ||||
| def create_initial_types(): | ||||
| 	tt = type_table() | ||||
|  | ||||
| 	basic_types = [ ["char",   1, 1], \ | ||||
| 	                ["short",  2, 1], \ | ||||
| 	                ["int",    4, 1], \ | ||||
| 	                ["long",   4, 1], \ | ||||
| 			["float",  4, 0], \ | ||||
| 			["double", 8, 0], \ | ||||
| 			["enum",   4, 1] ] | ||||
| 	basic_types = [ | ||||
| 		("char",   1, 1), | ||||
| 		("short",  2, 1), | ||||
| 		("int",    4, 1), | ||||
| 		("long",   4, 1), | ||||
| 		("float",  4, 0), | ||||
| 		("double", 8, 0), | ||||
| 		("enum",   4, 1) | ||||
| 	] | ||||
|  | ||||
|  | ||||
| 	for [type_name, type_size, integer] in basic_types: | ||||
| 	for (type_name, type_size, integer) in basic_types: | ||||
| 		te = type_expression(None) | ||||
| 		tn = type_node() | ||||
| 		tn.name = type_name | ||||
| @@ -113,22 +115,24 @@ class type_expression: | ||||
| 	def __init__(self, type_string, extra_types = None): | ||||
| 		self.expr = [] | ||||
|  | ||||
| 		if not type_string: return | ||||
| 		if not type_string: | ||||
| 			return | ||||
|  | ||||
| 		self.original_string = type_string | ||||
|  | ||||
| 		if not type_expression.built_in_types: | ||||
| 			raise RuntimeError("create_initial_types must be called before creating type_expression objects.") | ||||
|  | ||||
| 		 | ||||
| 		elements = string.split( string.replace( type_string, "*", " * " ) ) | ||||
| 		# Replace '*' with ' * ' in type_string.  Then, split the string | ||||
| 		# into tokens, separated by spaces. | ||||
| 		tokens = string.split( string.replace( type_string, "*", " * " ) ) | ||||
|  | ||||
| 		const = 0 | ||||
| 		t = None | ||||
| 		signed = 0 | ||||
| 		unsigned = 0 | ||||
|  | ||||
| 		for i in elements: | ||||
| 		for i in tokens: | ||||
| 			if i == "const": | ||||
| 				if t and t.pointer: | ||||
| 					t.const = 1 | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user