diff options
author | Keith Whitwell <keithw@vmware.com> | 2010-03-23 06:40:39 -0700 |
---|---|---|
committer | Keith Whitwell <keithw@vmware.com> | 2010-03-23 06:40:39 -0700 |
commit | 058c5697bda4c9cf7b49d26ee27a34586544efaa (patch) | |
tree | 90f111873e4c123d40831c5706f9628a05babc9d | |
parent | dd7ba1378fc50710667724d30d6d4cf1125ad61e (diff) | |
parent | b33fd3ce3daf2921a895367d0ed3fd9c718a8575 (diff) |
Merge commit 'origin/gallium-resources' into gallium-buffer-usage-cleanup
Conflicts:
src/gallium/state_trackers/vega/api_filters.c
src/mesa/state_tracker/st_cb_drawpixels.c
435 files changed, 17087 insertions, 16478 deletions
@@ -243,7 +243,6 @@ MAIN_FILES = \ $(DIRECTORY)/src/mesa/shader/descrip.mms \ $(DIRECTORY)/src/mesa/shader/slang/*.[ch] \ $(DIRECTORY)/src/mesa/shader/slang/descrip.mms \ - $(DIRECTORY)/src/mesa/shader/slang/library/*.[ch] \ $(DIRECTORY)/src/mesa/shader/slang/library/*.gc \ $(DIRECTORY)/src/mesa/shader/slang/library/Makefile \ $(DIRECTORY)/src/mesa/swrast/*.[ch] \ @@ -379,15 +378,6 @@ SGI_GLU_FILES = \ $(DIRECTORY)/src/glu/sgi/libtess/*.[ch] \ $(DIRECTORY)/src/glu/sgi/libutil/*.[ch] -MESA_GLU_FILES = \ - $(DIRECTORY)/src/glu/mesa/README[12] \ - $(DIRECTORY)/src/glu/mesa/Makefile* \ - $(DIRECTORY)/src/glu/mesa/descrip.mms \ - $(DIRECTORY)/src/glu/mesa/mms_depend \ - $(DIRECTORY)/src/glu/mesa/*.def \ - $(DIRECTORY)/src/glu/mesa/depend \ - $(DIRECTORY)/src/glu/mesa/*.[ch] - GLW_FILES = \ $(DIRECTORY)/src/glw/*.[ch] \ $(DIRECTORY)/src/glw/Makefile* \ @@ -450,11 +440,7 @@ GLUT_FILES = \ $(DIRECTORY)/src/glut/glx/*.[ch] \ $(DIRECTORY)/src/glut/beos/*.[ch] \ $(DIRECTORY)/src/glut/beos/*.cpp \ - $(DIRECTORY)/src/glut/beos/Makefile \ - $(DIRECTORY)/src/glut/fbdev/Makefile \ - $(DIRECTORY)/src/glut/fbdev/*[ch] \ - $(DIRECTORY)/src/glut/mini/*[ch] \ - $(DIRECTORY)/src/glut/mini/glut.pc.in \ + $(DIRECTORY)/src/glut/beos/Makefile DEPEND_FILES = \ $(TOP)/src/mesa/depend \ diff --git a/configs/default b/configs/default index cfd27d3e3f..087bea2e3d 100644 --- a/configs/default +++ b/configs/default @@ -98,7 +98,7 @@ EGL_DRIVERS_DIRS = glx # Gallium directories and GALLIUM_DIRS = auxiliary drivers state_trackers GALLIUM_AUXILIARIES = $(TOP)/src/gallium/auxiliary/libgallium.a -GALLIUM_DRIVERS_DIRS = softpipe trace identity i915 i965 svga # r300 +GALLIUM_DRIVERS_DIRS = softpipe trace identity i915 i965 svga r300 nvfx nv50 GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVERS_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a) GALLIUM_WINSYS_DIRS = null xlib drm GALLIUM_TARGET_DIRS = libgl-xlib diff --git a/configs/linux-cell b/configs/linux-cell index 306b9e01f4..0908dba9e0 100644 --- a/configs/linux-cell +++ b/configs/linux-cell @@ -6,7 +6,7 @@ CONFIG_NAME = linux-cell # Omiting other gallium drivers: -GALLIUM_DRIVERS_DIRS = cell softpipe trace +GALLIUM_DRIVERS_DIRS = cell softpipe trace identity # Compiler and flags diff --git a/configs/linux-debug b/configs/linux-debug index 01763b1a30..60e0b9769f 100644 --- a/configs/linux-debug +++ b/configs/linux-debug @@ -5,5 +5,5 @@ include $(TOP)/configs/linux CONFIG_NAME = linux-debug OPT_FLAGS = -g -CFLAGS += -pedantic +#CFLAGS += -pedantic DEFINES += -DDEBUG -DDEBUG_MATH diff --git a/configs/linux-llvm b/configs/linux-llvm index 27e082ebf7..608f42d6df 100644 --- a/configs/linux-llvm +++ b/configs/linux-llvm @@ -10,7 +10,7 @@ CONFIG_NAME = linux-llvm GALLIUM_DRIVERS_DIRS += llvmpipe OPT_FLAGS = -O3 -ansi -pedantic -ARCH_FLAGS = -m32 -mmmx -msse -msse2 -mstackrealign +ARCH_FLAGS = -mmmx -msse -msse2 -mstackrealign DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE -DDRAW_LLVM -DHAVE_UDIS86 diff --git a/configure.ac b/configure.ac index 35fbcd9d85..0f51097ef6 100644 --- a/configure.ac +++ b/configure.ac @@ -1360,7 +1360,7 @@ AC_ARG_ENABLE([gallium-nouveau], [enable_gallium_nouveau=no]) if test "x$enable_gallium_nouveau" = xyes; then GALLIUM_WINSYS_DRM_DIRS="$GALLIUM_WINSYS_DRM_DIRS nouveau" - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nv30 nv40 nv50" + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50" fi dnl diff --git a/docs/GL3.txt b/docs/GL3.txt index 889edefbce..a485878af2 100644 --- a/docs/GL3.txt +++ b/docs/GL3.txt @@ -16,6 +16,7 @@ GLSL changes (GL_EXT_gpu_shader4, etc) not started Conditional rendering (GL_NV_conditional_render) DONE (swrast & softpipe) Map buffer subranges (GL_APPLE_flush_buffer_range) not started Float textures, renderbuffers some infrastructure done + (incl. GL_EXT_packed_float, GL_EXT_shared_exponent) Framebuffer objects (GL_EXT_framebuffer_object) DONE Half-float some infrastructure done Multisample blit DONE diff --git a/include/GL/gl_mangle.h b/include/GL/gl_mangle.h index b292840f91..43d2e896b0 100644 --- a/include/GL/gl_mangle.h +++ b/include/GL/gl_mangle.h @@ -393,6 +393,8 @@ #define glEdgeFlagPointerListIBM MANGLE(EdgeFlagPointerListIBM) #define glEdgeFlagPointer MANGLE(EdgeFlagPointer) #define glEdgeFlagv MANGLE(EdgeFlagv) +#define glEGLImageTargetRenderbufferStorageOES MANGLE(EGLImageTargetRenderbufferStorageOES) +#define glEGLImageTargetTexture2DOES MANGLE(EGLImageTargetTexture2DOES) #define glElementPointerAPPLE MANGLE(ElementPointerAPPLE) #define glElementPointerATI MANGLE(ElementPointerATI) #define glEnableClientStateIndexedEXT MANGLE(EnableClientStateIndexedEXT) diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 1d4e82e154..aa56eb45d7 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -41,7 +41,13 @@ #define DRI_INTERFACE_H /* For archs with no drm.h */ -#if !defined(__APPLE__) && !defined(__CYGWIN__) && !defined(__GNU__) +#if defined(__APPLE__) || defined(__CYGWIN__) || defined(__GNU__) +#ifndef __NOT_HAVE_DRM_H +#define __NOT_HAVE_DRM_H +#endif +#endif + +#ifndef __NOT_HAVE_DRM_H #include <drm.h> #else typedef unsigned int drm_context_t; diff --git a/progs/objviewer/skybox.c b/progs/objviewer/skybox.c index 4e30742e20..93331b9c16 100644 --- a/progs/objviewer/skybox.c +++ b/progs/objviewer/skybox.c @@ -88,9 +88,9 @@ LoadSkyBoxCubeTexture(const char *filePosX, return 0; if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE)) return 0; - if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, 1+GL_FALSE, GL_TRUE)) + if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, GL_TRUE, GL_TRUE)) return 0; - if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, 1+GL_FALSE, GL_TRUE)) + if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, GL_TRUE, GL_TRUE)) return 0; if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE)) return 0; diff --git a/progs/samples/copy.c b/progs/samples/copy.c index 391c637d6f..353a3a2e1a 100644 --- a/progs/samples/copy.c +++ b/progs/samples/copy.c @@ -25,6 +25,7 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <GL/glew.h> #include <GL/glut.h> @@ -35,7 +36,6 @@ GLint windW, windH; char *fileName = 0; PPMImage *image; -float point[3]; float zoom; GLint x, y; @@ -97,27 +97,27 @@ static void Mouse(int button, int state, int mouseX, int mouseY) static void Draw(void) { + GLint src[3], dst[3]; glClear(GL_COLOR_BUFFER_BIT); - point[0] = (windW / 2) - (image->sizeX / 2); - point[1] = (windH / 2) - (image->sizeY / 2); - point[2] = 0; - glRasterPos3fv(point); + src[0] = (int) ((windW / 2.0) - (image->sizeX / 2.0)); + src[1] = (int) ((windH / 2.0) - (image->sizeY / 2.0)); + src[2] = 0; + glWindowPos3ivARB(src); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelZoom(1.0, 1.0); glDrawPixels(image->sizeX, image->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image->data); - point[0] = (float)x; - point[1] = windH - (float)y; - point[2] = 0.0; - glRasterPos3fv(point); + dst[0] = x; + dst[1] = windH - y; + dst[2] = 0; + glWindowPos3ivARB(dst); glPixelZoom(zoom, zoom); - glCopyPixels((windW/2)-(image->sizeX/2), - (windH/2)-(image->sizeY/2), + glCopyPixels(src[0], src[1], image->sizeX, image->sizeY, GL_COLOR); glFlush(); @@ -170,8 +170,8 @@ int main(int argc, char **argv) image = LoadPPM(fileName); - windW = 300; - windH = 300; + windW = 2*300; + windH = 2*300; glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH); type = GLUT_RGB; @@ -182,6 +182,7 @@ int main(int argc, char **argv) exit(1); } + glewInit(); Init(); glutReshapeFunc(Reshape); diff --git a/progs/samples/loadppm.c b/progs/samples/loadppm.c index be056d6294..adae9b491e 100644 --- a/progs/samples/loadppm.c +++ b/progs/samples/loadppm.c @@ -9,7 +9,7 @@ static PPMImage *LoadPPM(const char *filename) char buff[16]; PPMImage *result; FILE *fp; - int maxval; + int maxval, w, h; fp = fopen(filename, "rb"); if (!fp) @@ -37,11 +37,13 @@ static PPMImage *LoadPPM(const char *filename) exit(1); } - if (fscanf(fp, "%lu %lu", &result->sizeX, &result->sizeY) != 2) + if (fscanf(fp, "%d %d", &w, &h) != 2) { fprintf(stderr, "Error loading image `%s'\n", filename); exit(1); } + result->sizeX = w; + result->sizeY = h; if (fscanf(fp, "%d", &maxval) != 1) { diff --git a/progs/tests/stencil_twoside.c b/progs/tests/stencil_twoside.c index 7d871e5877..1010139a20 100644 --- a/progs/tests/stencil_twoside.c +++ b/progs/tests/stencil_twoside.c @@ -26,7 +26,7 @@ * \file stencil_twoside.c * * Simple test of GL_ATI_separate_stencil (or the OGL 2.0 equivalent) functionality. - * Four squares are drawn + * Five squares (or six if stencil wrap is available) are drawn * with different stencil modes, but all should be rendered with the same * final color. */ @@ -37,7 +37,7 @@ #include <GL/glut.h> static int use20syntax = 1; -static int Width = 550; +static int Width = 650; static int Height = 200; static const GLfloat Near = 5.0, Far = 25.0; @@ -70,7 +70,7 @@ static void Display( void ) */ glDisable(GL_STENCIL_TEST); - glTranslatef(-6.0, 0, 0); + glTranslatef(-7.0, 0, 0); glBegin(GL_QUADS); glColor3f( 0.5, 0.5, 0.5 ); glVertex2f(-1, -1); @@ -85,6 +85,9 @@ static void Display( void ) /* Draw the first two squares using incr for the affected face */ + /************************************************************************* + * 2nd square + */ if (use20syntax) { stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0); stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0); @@ -98,8 +101,8 @@ static void Display( void ) glTranslatef(3.0, 0, 0); glBegin(GL_QUADS); glColor3f( 0.9, 0.9, 0.9 ); - /* this should be front facing */ for ( i = 0 ; i < (max_stencil + 5) ; i++ ) { + /* this should be front facing */ glVertex2f(-1, -1); glVertex2f( 1, -1); glVertex2f( 1, 1); @@ -107,6 +110,7 @@ static void Display( void ) } glEnd(); + /* stencil vals should be equal to max_stencil */ glStencilFunc(GL_EQUAL, max_stencil, ~0); glBegin(GL_QUADS); glColor3f( 0.5, 0.5, 0.5 ); @@ -116,6 +120,9 @@ static void Display( void ) glVertex2f(-1, 1); glEnd(); + /************************************************************************* + * 3rd square + */ if (use20syntax) { stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0); stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0); @@ -129,9 +136,8 @@ static void Display( void ) glTranslatef(3.0, 0, 0); glBegin(GL_QUADS); glColor3f( 0.9, 0.9, 0.9 ); - - /* this should be back facing */ for ( i = 0 ; i < (max_stencil + 5) ; i++ ) { + /* this should be back facing */ glVertex2f(-1, -1); glVertex2f(-1, 1); glVertex2f( 1, 1); @@ -139,6 +145,7 @@ static void Display( void ) } glEnd(); + /* stencil vals should be equal to max_stencil */ glStencilFunc(GL_EQUAL, max_stencil, ~0); glBegin(GL_QUADS); glColor3f( 0.5, 0.5, 0.5 ); @@ -148,6 +155,9 @@ static void Display( void ) glVertex2f(-1, 1); glEnd(); + /************************************************************************* + * 4th square + */ if (use20syntax) { stencil_func_separate(GL_FRONT, GL_NEVER, 0, ~0); stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0); @@ -161,15 +171,13 @@ static void Display( void ) glTranslatef(3.0, 0, 0); glBegin(GL_QUADS); glColor3f( 0.9, 0.9, 0.9 ); - - /* this should be back facing */ for ( i = 0 ; i < (max_stencil + 5) ; i++ ) { - /* this should be back facing */ + /* this should be back facing */ glVertex2f(-1, -1); glVertex2f(-1, 1); glVertex2f( 1, 1); glVertex2f( 1, -1); - /* this should be front facing */ + /* this should be front facing */ glVertex2f(-1, -1); glVertex2f( 1, -1); glVertex2f( 1, 1); @@ -177,6 +185,7 @@ static void Display( void ) } glEnd(); + /* stencil vals should be equal to max_stencil */ glStencilFunc(GL_EQUAL, max_stencil, ~0); glBegin(GL_QUADS); glColor3f( 0.5, 0.5, 0.5 ); @@ -186,6 +195,9 @@ static void Display( void ) glVertex2f(-1, 1); glEnd(); + /************************************************************************* + * 5th square + */ if (use20syntax) { stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0); stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0); @@ -193,21 +205,19 @@ static void Display( void ) else { stencil_func_separate_ati(GL_ALWAYS, GL_ALWAYS, 0, ~0); } - stencil_op_separate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR); - stencil_op_separate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR); + stencil_op_separate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR); + stencil_op_separate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR); glTranslatef(3.0, 0, 0); glBegin(GL_QUADS); glColor3f( 0.9, 0.9, 0.9 ); - - /* this should be back facing */ for ( i = 0 ; i < (max_stencil + 5) ; i++ ) { - /* this should be back facing */ + /* this should be back facing */ glVertex2f(-1, -1); glVertex2f(-1, 1); glVertex2f( 1, 1); glVertex2f( 1, -1); - /* this should be front facing */ + /* this should be front facing */ glVertex2f(-1, -1); glVertex2f( 1, -1); glVertex2f( 1, 1); @@ -224,6 +234,47 @@ static void Display( void ) glVertex2f(-1, 1); glEnd(); + /************************************************************************* + * 6th square + */ + if (glutExtensionSupported("GL_EXT_stencil_wrap")) { + if (use20syntax) { + stencil_func_separate(GL_FRONT, GL_ALWAYS, 0, ~0); + stencil_func_separate(GL_BACK, GL_ALWAYS, 0, ~0); + } + else { + stencil_func_separate_ati(GL_ALWAYS, GL_ALWAYS, 0, ~0); + } + stencil_op_separate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP); + stencil_op_separate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP); + + glTranslatef(3.0, 0, 0); + glBegin(GL_QUADS); + glColor3f( 0.9, 0.9, 0.9 ); + for ( i = 0 ; i < (max_stencil + 5) ; i++ ) { + /* this should be back facing */ + glVertex2f(-1, -1); + glVertex2f(-1, 1); + glVertex2f( 1, 1); + glVertex2f( 1, -1); + /* this should be front facing */ + glVertex2f(-1, -1); + glVertex2f( 1, -1); + glVertex2f( 1, 1); + glVertex2f(-1, 1); + } + glEnd(); + + glStencilFunc(GL_EQUAL, 260 - 255, ~0); + glBegin(GL_QUADS); + glColor3f( 0.5, 0.5, 0.5 ); + glVertex2f(-1, -1); + glVertex2f( 1, -1); + glVertex2f( 1, 1); + glVertex2f(-1, 1); + glEnd(); + } + glPopMatrix(); glutSwapBuffers(); @@ -278,7 +329,7 @@ static void Init( void ) stencil_func_separate_ati = (PFNGLSTENCILFUNCSEPARATEATIPROC) glutGetProcAddress( "glStencilFuncSeparateATI" ); stencil_op_separate = (PFNGLSTENCILOPSEPARATEPROC) glutGetProcAddress( "glStencilOpSeparate" ); - printf("\nAll 5 squares should be the same color.\n"); + printf("\nAll 5 (or 6) squares should be the same color.\n"); } diff --git a/progs/trivial/tri-stencil.c b/progs/trivial/tri-stencil.c index 9f68bca914..d66b68c415 100644 --- a/progs/trivial/tri-stencil.c +++ b/progs/trivial/tri-stencil.c @@ -77,6 +77,7 @@ static void Draw(void) glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + /* red triangle (setting stencil to 1) */ glColor3ub(200, 0, 0); glBegin(GL_POLYGON); glVertex3i(-4, -4, 0); @@ -88,6 +89,7 @@ static void Draw(void) glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_INCR, GL_KEEP, GL_DECR); + /* green quad (if over red, decr stencil to 0, else incr to 1) */ glColor3ub(0, 200, 0); glBegin(GL_POLYGON); glVertex3i(3, 3, 0); @@ -101,6 +103,7 @@ static void Draw(void) glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + /* blue quad (where stencil == 1) */ glColor3ub(0, 0, 200); glBegin(GL_POLYGON); glVertex3f(2.5, 2.5, 0); diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index b4d4825173..3cdfb45269 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -64,8 +64,6 @@ C_SOURCES = \ pipebuffer/pb_bufmgr_pool.c \ pipebuffer/pb_bufmgr_slab.c \ pipebuffer/pb_validate.c \ - piperesource/rm_context.c \ - piperesource/rm_screen.c \ rbug/rbug_connection.c \ rbug/rbug_core.c \ rbug/rbug_texture.c \ @@ -131,6 +129,7 @@ C_SOURCES = \ util/u_resource.c \ util/u_upload_mgr.c \ target-helpers/wrap_screen.c + # Disabling until pipe-video branch gets merged in #vl/vl_bitstream_parser.c \ #vl/vl_mpeg12_mc_renderer.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 65e1dc8a58..6988de733e 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -168,9 +168,8 @@ source = [ 'util/u_surface.c', 'util/u_texture.c', 'util/u_tile.c', - 'util/u_timed_winsys.c', + 'util/u_transfer.c', 'util/u_upload_mgr.c', - 'util/u_simple_screen.c', # Disabling until pipe-video branch gets merged in #'vl/vl_bitstream_parser.c', #'vl/vl_mpeg12_mc_renderer.c', diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index cb1193d2da..d6f8dd34bf 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -71,16 +71,12 @@ struct cso_context { unsigned nr_vertex_samplers_saved; void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS]; - struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; uint nr_fragment_sampler_views; struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; - uint nr_textures; uint nr_vertex_sampler_views; struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; - uint nr_textures_saved; - struct pipe_resource *textures_saved[PIPE_MAX_SAMPLERS]; uint nr_fragment_sampler_views_saved; struct pipe_sampler_view *fragment_sampler_views_saved[PIPE_MAX_SAMPLERS]; @@ -299,8 +295,6 @@ void cso_release_all( struct cso_context *ctx ) } for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - pipe_resource_reference(&ctx->textures[i], NULL); - pipe_resource_reference(&ctx->textures_saved[i], NULL); pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], NULL); } @@ -624,82 +618,6 @@ cso_restore_vertex_samplers(struct cso_context *ctx) } -enum pipe_error cso_set_sampler_textures( struct cso_context *ctx, - uint count, - struct pipe_resource **textures ) -{ - uint i; - - ctx->nr_textures = count; - - for (i = 0; i < count; i++) { - struct pipe_sampler_view templ, *view; - - u_sampler_view_default_template(&templ, - textures[i], - textures[i]->format); - view = ctx->pipe->create_sampler_view(ctx->pipe, - textures[i], - &templ); - - pipe_resource_reference(&ctx->textures[i], textures[i]); - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], view); - } - for ( ; i < PIPE_MAX_SAMPLERS; i++) { - pipe_resource_reference(&ctx->textures[i], NULL); - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - } - - ctx->pipe->set_fragment_sampler_views(ctx->pipe, - count, - ctx->fragment_sampler_views); - - return PIPE_OK; -} - -void cso_save_sampler_textures( struct cso_context *ctx ) -{ - uint i; - - ctx->nr_textures_saved = ctx->nr_textures; - for (i = 0; i < ctx->nr_textures; i++) { - assert(!ctx->textures_saved[i]); - assert(!ctx->fragment_sampler_views_saved[i]); - - pipe_resource_reference(&ctx->textures_saved[i], ctx->textures[i]); - pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], - ctx->fragment_sampler_views[i]); - } -} - -void cso_restore_sampler_textures( struct cso_context *ctx ) -{ - uint i; - - ctx->nr_textures = ctx->nr_textures_saved; - - for (i = 0; i < ctx->nr_textures; i++) { - pipe_resource_reference(&ctx->textures[i], NULL); - ctx->textures[i] = ctx->textures_saved[i]; - ctx->textures_saved[i] = NULL; - - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - ctx->fragment_sampler_views[i] = ctx->fragment_sampler_views_saved[i]; - ctx->fragment_sampler_views_saved[i] = NULL; - } - for ( ; i < PIPE_MAX_SAMPLERS; i++) { - pipe_resource_reference(&ctx->textures[i], NULL); - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - } - - ctx->pipe->set_fragment_sampler_views(ctx->pipe, - ctx->nr_textures, - ctx->fragment_sampler_views); - - ctx->nr_textures_saved = 0; -} - - enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, const struct pipe_depth_stencil_alpha_state *templ) { diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 18c2e43588..d6bcb1fe8f 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -103,14 +103,6 @@ void cso_single_vertex_sampler_done(struct cso_context *cso); - -enum pipe_error cso_set_sampler_textures( struct cso_context *cso, - uint count, - struct pipe_resource **textures ); -void cso_save_sampler_textures( struct cso_context *cso ); -void cso_restore_sampler_textures( struct cso_context *cso ); - - enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, unsigned count, const struct pipe_vertex_element *states); diff --git a/src/gallium/auxiliary/os/os_llvm.h b/src/gallium/auxiliary/gallivm/lp_bld.h index d5edfbfe92..70a4960f91 100644 --- a/src/gallium/auxiliary/os/os_llvm.h +++ b/src/gallium/auxiliary/gallivm/lp_bld.h @@ -31,8 +31,8 @@ */ -#ifndef OS_LLVM_H -#define OS_LLVM_H +#ifndef LP_BLD_H +#define LP_BLD_H #include <llvm-c/Core.h> @@ -40,8 +40,8 @@ /** Set version to 0 if missing to avoid #ifdef HAVE_LLVM everywhere */ #ifndef HAVE_LLVM -#define HAVE_LLVM 0x0 +#define HAVE_LLVM 0x0207 #endif -#endif /* OS_LLVM_H */ +#endif /* LP_BLD_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_alpha.h b/src/gallium/auxiliary/gallivm/lp_bld_alpha.h index fe3cedcc48..0f99fec65e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_alpha.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_alpha.h @@ -35,7 +35,7 @@ #define LP_BLD_ALPHA_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct pipe_alpha_state; struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index aa47338b32..8e8fcccf56 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -361,12 +361,12 @@ lp_build_mul_u8n(LLVMBuilderRef builder, LLVMValueRef c8; LLVMValueRef ab; - c8 = lp_build_int_const_scalar(i16_type, 8); + c8 = lp_build_const_int_vec(i16_type, 8); #if 0 /* a*b/255 ~= (a*(b + 1)) >> 256 */ - b = LLVMBuildAdd(builder, b, lp_build_int_const_scalar(i16_type, 1), ""); + b = LLVMBuildAdd(builder, b, lp_build_const_int_vec(i16_type, 1), ""); ab = LLVMBuildMul(builder, a, b, ""); #else @@ -374,7 +374,7 @@ lp_build_mul_u8n(LLVMBuilderRef builder, /* ab/255 ~= (ab + (ab >> 8) + 0x80) >> 8 */ ab = LLVMBuildMul(builder, a, b, ""); ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c8, ""), ""); - ab = LLVMBuildAdd(builder, ab, lp_build_int_const_scalar(i16_type, 0x80), ""); + ab = LLVMBuildAdd(builder, ab, lp_build_const_int_vec(i16_type, 0x80), ""); #endif @@ -429,7 +429,7 @@ lp_build_mul(struct lp_build_context *bld, } if(type.fixed) - shift = lp_build_int_const_scalar(type, type.width/2); + shift = lp_build_const_int_vec(type, type.width/2); else shift = NULL; @@ -491,7 +491,7 @@ lp_build_mul_imm(struct lp_build_context *bld, * for Inf and NaN. */ unsigned mantissa = lp_mantissa(bld->type); - factor = lp_build_int_const_scalar(bld->type, (unsigned long long)shift << mantissa); + factor = lp_build_const_int_vec(bld->type, (unsigned long long)shift << mantissa); a = LLVMBuildBitCast(bld->builder, a, lp_build_int_vec_type(bld->type), ""); a = LLVMBuildAdd(bld->builder, a, factor, ""); a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(bld->type), ""); @@ -499,12 +499,12 @@ lp_build_mul_imm(struct lp_build_context *bld, #endif } else { - factor = lp_build_const_scalar(bld->type, shift); + factor = lp_build_const_vec(bld->type, shift); return LLVMBuildShl(bld->builder, a, factor, ""); } } - factor = lp_build_const_scalar(bld->type, (double)b); + factor = lp_build_const_vec(bld->type, (double)b); return lp_build_mul(bld, a, factor); } @@ -567,7 +567,7 @@ lp_build_lerp(struct lp_build_context *bld, * but it will be wrong for other uses. Basically we need a more * powerful lp_type, capable of further distinguishing the values * interpretation from the value storage. */ - res = LLVMBuildAnd(bld->builder, res, lp_build_int_const_scalar(bld->type, (1 << bld->type.width/2) - 1), ""); + res = LLVMBuildAnd(bld->builder, res, lp_build_const_int_vec(bld->type, (1 << bld->type.width/2) - 1), ""); return res; } @@ -689,7 +689,7 @@ lp_build_abs(struct lp_build_context *bld, /* vector of floats */ LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); unsigned long long absMask = ~(1ULL << (type.width - 1)); - LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask)); + LLVMValueRef mask = lp_build_const_int_vec(type, ((unsigned long long) absMask)); a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); a = LLVMBuildAnd(bld->builder, a, mask, ""); a = LLVMBuildBitCast(bld->builder, a, vec_type, ""); @@ -751,7 +751,7 @@ lp_build_sgn(struct lp_build_context *bld, /* vector */ int_type = lp_build_int_vec_type(type); vec_type = lp_build_vec_type(type); - mask = lp_build_int_const_scalar(type, maskBit); + mask = lp_build_const_int_vec(type, maskBit); } /* Take the sign bit and add it to 1 constant */ @@ -763,14 +763,14 @@ lp_build_sgn(struct lp_build_context *bld, } else { - LLVMValueRef minus_one = lp_build_const_scalar(type, -1.0); + LLVMValueRef minus_one = lp_build_const_vec(type, -1.0); cond = lp_build_cmp(bld, PIPE_FUNC_GREATER, a, bld->zero); res = lp_build_select(bld, cond, bld->one, minus_one); } /* Handle zero */ cond = lp_build_cmp(bld, PIPE_FUNC_EQUAL, a, bld->zero); - res = lp_build_select(bld, cond, bld->zero, bld->one); + res = lp_build_select(bld, cond, bld->zero, res); return res; } @@ -789,8 +789,8 @@ lp_build_set_sign(struct lp_build_context *bld, const struct lp_type type = bld->type; LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef shift = lp_build_int_const_scalar(type, type.width - 1); - LLVMValueRef mask = lp_build_int_const_scalar(type, + LLVMValueRef shift = lp_build_const_int_vec(type, type.width - 1); + LLVMValueRef mask = lp_build_const_int_vec(type, ~((unsigned long long) 1 << (type.width - 1))); LLVMValueRef val, res; @@ -930,7 +930,10 @@ lp_build_floor(struct lp_build_context *bld, assert(type.floating); if (type.length == 1) { - return LLVMBuildFPTrunc(bld->builder, a, LLVMFloatType(), ""); + LLVMValueRef res; + res = lp_build_ifloor(bld, a); + res = LLVMBuildSIToFP(bld->builder, res, LLVMFloatType(), ""); + return res; } if(util_cpu_caps.has_sse4_1) @@ -993,7 +996,7 @@ lp_build_itrunc(struct lp_build_context *bld, if (type.length == 1) { LLVMTypeRef int_type = LLVMIntType(type.width); - return LLVMBuildFPTrunc(bld->builder, a, int_type, ""); + return LLVMBuildFPToSI(bld->builder, a, int_type, ""); } else { LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); @@ -1031,7 +1034,7 @@ lp_build_iround(struct lp_build_context *bld, } else { LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); + LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1)); LLVMValueRef sign; LLVMValueRef half; @@ -1040,7 +1043,7 @@ lp_build_iround(struct lp_build_context *bld, sign = LLVMBuildAnd(bld->builder, sign, mask, ""); /* sign * 0.5 */ - half = lp_build_const_scalar(type, 0.5); + half = lp_build_const_vec(type, 0.5); half = LLVMBuildBitCast(bld->builder, half, int_vec_type, ""); half = LLVMBuildOr(bld->builder, sign, half, ""); half = LLVMBuildBitCast(bld->builder, half, vec_type, ""); @@ -1083,18 +1086,18 @@ lp_build_ifloor(struct lp_build_context *bld, /* Take the sign bit and add it to 1 constant */ LLVMTypeRef vec_type = lp_build_vec_type(type); unsigned mantissa = lp_mantissa(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); + LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1)); LLVMValueRef sign; LLVMValueRef offset; /* sign = a < 0 ? ~0 : 0 */ sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); sign = LLVMBuildAnd(bld->builder, sign, mask, ""); - sign = LLVMBuildAShr(bld->builder, sign, lp_build_int_const_scalar(type, type.width - 1), ""); + sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), ""); lp_build_name(sign, "floor.sign"); /* offset = -0.99999(9)f */ - offset = lp_build_const_scalar(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa)); + offset = lp_build_const_vec(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa)); offset = LLVMConstBitCast(offset, int_vec_type); /* offset = a < 0 ? -0.99999(9)f : 0.0f */ @@ -1265,7 +1268,7 @@ lp_build_exp(struct lp_build_context *bld, LLVMValueRef x) { /* log2(e) = 1/log(2) */ - LLVMValueRef log2e = lp_build_const_scalar(bld->type, 1.4426950408889634); + LLVMValueRef log2e = lp_build_const_vec(bld->type, 1.4426950408889634); return lp_build_mul(bld, log2e, lp_build_exp2(bld, x)); } @@ -1279,7 +1282,7 @@ lp_build_log(struct lp_build_context *bld, LLVMValueRef x) { /* log(2) */ - LLVMValueRef log2 = lp_build_const_scalar(bld->type, 0.69314718055994529); + LLVMValueRef log2 = lp_build_const_vec(bld->type, 0.69314718055994529); return lp_build_mul(bld, log2, lp_build_exp2(bld, x)); } @@ -1315,7 +1318,7 @@ lp_build_polynomial(struct lp_build_context *bld, if (type.length == 1) coeff = LLVMConstReal(float_type, coeffs[i]); else - coeff = lp_build_const_scalar(type, coeffs[i]); + coeff = lp_build_const_vec(type, coeffs[i]); if(res) res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res)); @@ -1372,11 +1375,11 @@ lp_build_exp2_approx(struct lp_build_context *bld, assert(type.floating && type.width == 32); - x = lp_build_min(bld, x, lp_build_const_scalar(type, 129.0)); - x = lp_build_max(bld, x, lp_build_const_scalar(type, -126.99999)); + x = lp_build_min(bld, x, lp_build_const_vec(type, 129.0)); + x = lp_build_max(bld, x, lp_build_const_vec(type, -126.99999)); /* ipart = int(x - 0.5) */ - ipart = LLVMBuildSub(bld->builder, x, lp_build_const_scalar(type, 0.5f), ""); + ipart = LLVMBuildSub(bld->builder, x, lp_build_const_vec(type, 0.5f), ""); ipart = LLVMBuildFPToSI(bld->builder, ipart, int_vec_type, ""); /* fpart = x - ipart */ @@ -1386,8 +1389,8 @@ lp_build_exp2_approx(struct lp_build_context *bld, if(p_exp2_int_part || p_exp2) { /* expipart = (float) (1 << ipart) */ - expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_int_const_scalar(type, 127), ""); - expipart = LLVMBuildShl(bld->builder, expipart, lp_build_int_const_scalar(type, 23), ""); + expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_const_int_vec(type, 127), ""); + expipart = LLVMBuildShl(bld->builder, expipart, lp_build_const_int_vec(type, 23), ""); expipart = LLVMBuildBitCast(bld->builder, expipart, vec_type, ""); } @@ -1453,8 +1456,8 @@ lp_build_log2_approx(struct lp_build_context *bld, LLVMTypeRef vec_type = lp_build_vec_type(type); LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef expmask = lp_build_int_const_scalar(type, 0x7f800000); - LLVMValueRef mantmask = lp_build_int_const_scalar(type, 0x007fffff); + LLVMValueRef expmask = lp_build_const_int_vec(type, 0x7f800000); + LLVMValueRef mantmask = lp_build_const_int_vec(type, 0x007fffff); LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type); LLVMValueRef i = NULL; @@ -1479,8 +1482,8 @@ lp_build_log2_approx(struct lp_build_context *bld, } if(p_floor_log2 || p_log2) { - logexp = LLVMBuildLShr(bld->builder, exp, lp_build_int_const_scalar(type, 23), ""); - logexp = LLVMBuildSub(bld->builder, logexp, lp_build_int_const_scalar(type, 127), ""); + logexp = LLVMBuildLShr(bld->builder, exp, lp_build_const_int_vec(type, 23), ""); + logexp = LLVMBuildSub(bld->builder, logexp, lp_build_const_int_vec(type, 127), ""); logexp = LLVMBuildSIToFP(bld->builder, logexp, vec_type, ""); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.h b/src/gallium/auxiliary/gallivm/lp_bld_arit.h index 7a10fe1220..31efa9921c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.h @@ -37,7 +37,7 @@ #define LP_BLD_ARIT_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_blend.h b/src/gallium/auxiliary/gallivm/lp_bld_blend.h index 5a9e1c1fb2..ebbdb1a604 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_blend.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_blend.h @@ -40,7 +40,7 @@ * for a standalone example. */ -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include "pipe/p_format.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_const.c b/src/gallium/auxiliary/gallivm/lp_bld_const.c index 8a275fa72f..57843e9a60 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_const.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_const.c @@ -263,7 +263,7 @@ lp_build_one(struct lp_type type) if(type.sign) /* TODO: Unfortunately this caused "Tried to create a shift operation * on a non-integer type!" */ - vec = LLVMConstLShr(vec, lp_build_int_const_scalar(type, 1)); + vec = LLVMConstLShr(vec, lp_build_const_int_vec(type, 1)); #endif return vec; @@ -283,8 +283,8 @@ lp_build_one(struct lp_type type) * Build constant-valued vector from a scalar value. */ LLVMValueRef -lp_build_const_scalar(struct lp_type type, - double val) +lp_build_const_vec(struct lp_type type, + double val) { LLVMTypeRef elem_type = lp_build_elem_type(type); LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; @@ -309,7 +309,7 @@ lp_build_const_scalar(struct lp_type type, LLVMValueRef -lp_build_int_const_scalar(struct lp_type type, +lp_build_const_int_vec(struct lp_type type, long long val) { LLVMTypeRef elem_type = lp_build_int_elem_type(type); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_const.h b/src/gallium/auxiliary/gallivm/lp_bld_const.h index 4078636103..9ca2f0664e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_const.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_const.h @@ -37,9 +37,9 @@ #define LP_BLD_CONST_H -#include "os/os_llvm.h" +#include "pipe/p_compiler.h" +#include "gallivm/lp_bld.h" -#include <pipe/p_compiler.h> struct lp_type; @@ -85,13 +85,11 @@ lp_build_one(struct lp_type type); LLVMValueRef -lp_build_const_scalar(struct lp_type type, - double val); +lp_build_const_vec(struct lp_type type, double val); LLVMValueRef -lp_build_int_const_scalar(struct lp_type type, - long long val); +lp_build_const_int_vec(struct lp_type type, long long val); LLVMValueRef diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c index f77cf78721..3f7f2ebde9 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c @@ -114,13 +114,13 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder, scale = (double)mask/ubound; bias = (double)((unsigned long long)1 << (mantissa - n)); - res = LLVMBuildMul(builder, src, lp_build_const_scalar(src_type, scale), ""); - res = LLVMBuildAdd(builder, res, lp_build_const_scalar(src_type, bias), ""); + res = LLVMBuildMul(builder, src, lp_build_const_vec(src_type, scale), ""); + res = LLVMBuildAdd(builder, res, lp_build_const_vec(src_type, bias), ""); res = LLVMBuildBitCast(builder, res, int_vec_type, ""); if(dst_width > n) { int shift = dst_width - n; - res = LLVMBuildShl(builder, res, lp_build_int_const_scalar(src_type, shift), ""); + res = LLVMBuildShl(builder, res, lp_build_const_int_vec(src_type, shift), ""); /* TODO: Fill in the empty lower bits for additional precision? */ /* YES: this fixes progs/trivial/tri-z-eq.c. @@ -130,21 +130,21 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder, #if 0 { LLVMValueRef msb; - msb = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, dst_width - 1), ""); - msb = LLVMBuildShl(builder, msb, lp_build_int_const_scalar(src_type, shift), ""); - msb = LLVMBuildSub(builder, msb, lp_build_int_const_scalar(src_type, 1), ""); + msb = LLVMBuildLShr(builder, res, lp_build_const_int_vec(src_type, dst_width - 1), ""); + msb = LLVMBuildShl(builder, msb, lp_build_const_int_vec(src_type, shift), ""); + msb = LLVMBuildSub(builder, msb, lp_build_const_int_vec(src_type, 1), ""); res = LLVMBuildOr(builder, res, msb, ""); } #elif 0 while(shift > 0) { - res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, n), ""), ""); + res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_const_int_vec(src_type, n), ""), ""); shift -= n; n *= 2; } #endif } else - res = LLVMBuildAnd(builder, res, lp_build_int_const_scalar(src_type, mask), ""); + res = LLVMBuildAnd(builder, res, lp_build_const_int_vec(src_type, mask), ""); return res; } @@ -183,10 +183,10 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder, if(src_width > mantissa) { int shift = src_width - mantissa; - res = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(dst_type, shift), ""); + res = LLVMBuildLShr(builder, res, lp_build_const_int_vec(dst_type, shift), ""); } - bias_ = lp_build_const_scalar(dst_type, bias); + bias_ = lp_build_const_vec(dst_type, bias); res = LLVMBuildOr(builder, res, @@ -195,7 +195,7 @@ lp_build_unsigned_norm_to_float(LLVMBuilderRef builder, res = LLVMBuildBitCast(builder, res, vec_type, ""); res = LLVMBuildSub(builder, res, bias_, ""); - res = LLVMBuildMul(builder, res, lp_build_const_scalar(dst_type, scale), ""); + res = LLVMBuildMul(builder, res, lp_build_const_vec(dst_type, scale), ""); return res; } @@ -251,7 +251,7 @@ lp_build_conv(LLVMBuilderRef builder, if(dst_min == 0.0) thres = bld.zero; else - thres = lp_build_const_scalar(src_type, dst_min); + thres = lp_build_const_vec(src_type, dst_min); for(i = 0; i < num_tmps; ++i) tmp[i] = lp_build_max(&bld, tmp[i], thres); } @@ -260,7 +260,7 @@ lp_build_conv(LLVMBuilderRef builder, if(dst_max == 1.0) thres = bld.one; else - thres = lp_build_const_scalar(src_type, dst_max); + thres = lp_build_const_vec(src_type, dst_max); for(i = 0; i < num_tmps; ++i) tmp[i] = lp_build_min(&bld, tmp[i], thres); } @@ -288,7 +288,7 @@ lp_build_conv(LLVMBuilderRef builder, LLVMTypeRef tmp_vec_type; if (dst_scale != 1.0) { - LLVMValueRef scale = lp_build_const_scalar(tmp_type, dst_scale); + LLVMValueRef scale = lp_build_const_vec(tmp_type, dst_scale); for(i = 0; i < num_tmps; ++i) tmp[i] = LLVMBuildMul(builder, tmp[i], scale, ""); } @@ -315,7 +315,7 @@ lp_build_conv(LLVMBuilderRef builder, /* FIXME: compensate different offsets too */ if(src_shift > dst_shift) { - LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, src_shift - dst_shift); + LLVMValueRef shift = lp_build_const_int_vec(tmp_type, src_shift - dst_shift); for(i = 0; i < num_tmps; ++i) if(src_type.sign) tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, ""); @@ -388,7 +388,7 @@ lp_build_conv(LLVMBuilderRef builder, } if (src_scale != 1.0) { - LLVMValueRef scale = lp_build_const_scalar(tmp_type, 1.0/src_scale); + LLVMValueRef scale = lp_build_const_vec(tmp_type, 1.0/src_scale); for(i = 0; i < num_tmps; ++i) tmp[i] = LLVMBuildMul(builder, tmp[i], scale, ""); } @@ -400,7 +400,7 @@ lp_build_conv(LLVMBuilderRef builder, /* FIXME: compensate different offsets too */ if(src_shift < dst_shift) { - LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, dst_shift - src_shift); + LLVMValueRef shift = lp_build_const_int_vec(tmp_type, dst_shift - src_shift); for(i = 0; i < num_tmps; ++i) tmp[i] = LLVMBuildShl(builder, tmp[i], shift, ""); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.h b/src/gallium/auxiliary/gallivm/lp_bld_conv.h index 78e8155ff7..628831c3ad 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_conv.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.h @@ -37,7 +37,7 @@ #define LP_BLD_CONV_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.h b/src/gallium/auxiliary/gallivm/lp_bld_debug.h index 441ad94786..7b010cbdb0 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_debug.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.h @@ -30,7 +30,7 @@ #define LP_BLD_DEBUG_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include "pipe/p_compiler.h" #include "util/u_string.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_depth.c b/src/gallium/auxiliary/gallivm/lp_bld_depth.c index f08f8eb6d8..4ce1a27a06 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_depth.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_depth.c @@ -52,7 +52,14 @@ * Z31 Z32 Z41 Z42 Z33 Z34 Z43 Z44 ... * ... ... ... ... ... ... ... ... ... * - * FIXME: Code generate stencil test + * + * Stencil test: + * Two-sided stencil test is supported but probably not as efficient as + * it could be. Currently, we use if/then/else constructs to do the + * operations for front vs. back-facing polygons. We could probably do + * both the front and back arithmetic then use a Select() instruction to + * choose the result depending on polyon orientation. We'd have to + * measure performance both ways and see which is better. * * @author Jose Fonseca <jfonseca@vmware.com> */ @@ -61,11 +68,264 @@ #include "util/u_format.h" #include "lp_bld_type.h" +#include "lp_bld_arit.h" #include "lp_bld_const.h" #include "lp_bld_logic.h" #include "lp_bld_flow.h" #include "lp_bld_debug.h" #include "lp_bld_depth.h" +#include "lp_bld_swizzle.h" + + +/** Used to select fields from pipe_stencil_state */ +enum stencil_op { + S_FAIL_OP, + Z_FAIL_OP, + Z_PASS_OP +}; + + + +/** + * Do the stencil test comparison (compare FB stencil values against ref value). + * This will be used twice when generating two-sided stencil code. + * \param stencil the front/back stencil state + * \param stencilRef the stencil reference value, replicated as a vector + * \param stencilVals vector of stencil values from framebuffer + * \return vector mask of pass/fail values (~0 or 0) + */ +static LLVMValueRef +lp_build_stencil_test_single(struct lp_build_context *bld, + const struct pipe_stencil_state *stencil, + LLVMValueRef stencilRef, + LLVMValueRef stencilVals) +{ + const unsigned stencilMax = 255; /* XXX fix */ + struct lp_type type = bld->type; + LLVMValueRef res; + + assert(type.sign); + + assert(stencil->enabled); + + if (stencil->valuemask != stencilMax) { + /* compute stencilRef = stencilRef & valuemask */ + LLVMValueRef valuemask = lp_build_const_int_vec(type, stencil->valuemask); + stencilRef = LLVMBuildAnd(bld->builder, stencilRef, valuemask, ""); + /* compute stencilVals = stencilVals & valuemask */ + stencilVals = LLVMBuildAnd(bld->builder, stencilVals, valuemask, ""); + } + + res = lp_build_cmp(bld, stencil->func, stencilVals, stencilRef); + + return res; +} + + +/** + * Do the one or two-sided stencil test comparison. + * \sa lp_build_stencil_test_single + * \param face an integer indicating front (+) or back (-) facing polygon. + * If NULL, assume front-facing. + */ +static LLVMValueRef +lp_build_stencil_test(struct lp_build_context *bld, + const struct pipe_stencil_state stencil[2], + LLVMValueRef stencilRefs[2], + LLVMValueRef stencilVals, + LLVMValueRef face) +{ + LLVMValueRef res; + + assert(stencil[0].enabled); + + if (stencil[1].enabled && face) { + /* do two-sided test */ + struct lp_build_flow_context *flow_ctx; + struct lp_build_if_state if_ctx; + LLVMValueRef front_facing; + LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); + LLVMValueRef result = bld->undef; + + flow_ctx = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx); + + lp_build_flow_scope_declare(flow_ctx, &result); + + /* front_facing = face > 0.0 */ + front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, ""); + + lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing); + { + result = lp_build_stencil_test_single(bld, &stencil[0], + stencilRefs[0], stencilVals); + } + lp_build_else(&if_ctx); + { + result = lp_build_stencil_test_single(bld, &stencil[1], + stencilRefs[1], stencilVals); + } + lp_build_endif(&if_ctx); + + lp_build_flow_scope_end(flow_ctx); + lp_build_flow_destroy(flow_ctx); + + res = result; + } + else { + /* do single-side test */ + res = lp_build_stencil_test_single(bld, &stencil[0], + stencilRefs[0], stencilVals); + } + + return res; +} + + +/** + * Apply the stencil operator (add/sub/keep/etc) to the given vector + * of stencil values. + * \return new stencil values vector + */ +static LLVMValueRef +lp_build_stencil_op_single(struct lp_build_context *bld, + const struct pipe_stencil_state *stencil, + enum stencil_op op, + LLVMValueRef stencilRef, + LLVMValueRef stencilVals, + LLVMValueRef mask) + +{ + const unsigned stencilMax = 255; /* XXX fix */ + struct lp_type type = bld->type; + LLVMValueRef res; + LLVMValueRef max = lp_build_const_int_vec(type, stencilMax); + unsigned stencil_op; + + assert(type.sign); + + switch (op) { + case S_FAIL_OP: + stencil_op = stencil->fail_op; + break; + case Z_FAIL_OP: + stencil_op = stencil->zfail_op; + break; + case Z_PASS_OP: + stencil_op = stencil->zpass_op; + break; + default: + assert(0 && "Invalid stencil_op mode"); + stencil_op = PIPE_STENCIL_OP_KEEP; + } + + switch (stencil_op) { + case PIPE_STENCIL_OP_KEEP: + res = stencilVals; + /* we can return early for this case */ + return res; + case PIPE_STENCIL_OP_ZERO: + res = bld->zero; + break; + case PIPE_STENCIL_OP_REPLACE: + res = stencilRef; + break; + case PIPE_STENCIL_OP_INCR: + res = lp_build_add(bld, stencilVals, bld->one); + res = lp_build_min(bld, res, max); + break; + case PIPE_STENCIL_OP_DECR: + res = lp_build_sub(bld, stencilVals, bld->one); + res = lp_build_max(bld, res, bld->zero); + break; + case PIPE_STENCIL_OP_INCR_WRAP: + res = lp_build_add(bld, stencilVals, bld->one); + res = LLVMBuildAnd(bld->builder, res, max, ""); + break; + case PIPE_STENCIL_OP_DECR_WRAP: + res = lp_build_sub(bld, stencilVals, bld->one); + res = LLVMBuildAnd(bld->builder, res, max, ""); + break; + case PIPE_STENCIL_OP_INVERT: + res = LLVMBuildNot(bld->builder, stencilVals, ""); + res = LLVMBuildAnd(bld->builder, res, max, ""); + break; + default: + assert(0 && "bad stencil op mode"); + res = NULL; + } + + if (stencil->writemask != stencilMax) { + /* compute res = (res & mask) | (stencilVals & ~mask) */ + LLVMValueRef mask = lp_build_const_int_vec(type, stencil->writemask); + LLVMValueRef cmask = LLVMBuildNot(bld->builder, mask, "notWritemask"); + LLVMValueRef t1 = LLVMBuildAnd(bld->builder, res, mask, "t1"); + LLVMValueRef t2 = LLVMBuildAnd(bld->builder, stencilVals, cmask, "t2"); + res = LLVMBuildOr(bld->builder, t1, t2, "t1_or_t2"); + } + + /* only the update the vector elements enabled by 'mask' */ + res = lp_build_select(bld, mask, res, stencilVals); + + return res; +} + + +/** + * Do the one or two-sided stencil test op/update. + */ +static LLVMValueRef +lp_build_stencil_op(struct lp_build_context *bld, + const struct pipe_stencil_state stencil[2], + enum stencil_op op, + LLVMValueRef stencilRefs[2], + LLVMValueRef stencilVals, + LLVMValueRef mask, + LLVMValueRef face) + +{ + assert(stencil[0].enabled); + + if (stencil[1].enabled && face) { + /* do two-sided op */ + struct lp_build_flow_context *flow_ctx; + struct lp_build_if_state if_ctx; + LLVMValueRef front_facing; + LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); + LLVMValueRef result = bld->undef; + + flow_ctx = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx); + + lp_build_flow_scope_declare(flow_ctx, &result); + + /* front_facing = face > 0.0 */ + front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, ""); + + lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing); + { + result = lp_build_stencil_op_single(bld, &stencil[0], op, + stencilRefs[0], stencilVals, mask); + } + lp_build_else(&if_ctx); + { + result = lp_build_stencil_op_single(bld, &stencil[1], op, + stencilRefs[1], stencilVals, mask); + } + lp_build_endif(&if_ctx); + + lp_build_flow_scope_end(flow_ctx); + lp_build_flow_destroy(flow_ctx); + + return result; + } + else { + /* do single-sided op */ + return lp_build_stencil_op_single(bld, &stencil[0], op, + stencilRefs[0], stencilVals, mask); + } +} + /** @@ -109,105 +369,303 @@ lp_depth_type(const struct util_format_description *format_desc, /** - * Depth test. + * Compute bitmask and bit shift to apply to the incoming fragment Z values + * and the Z buffer values needed before doing the Z comparison. + * + * Note that we leave the Z bits in the position that we find them + * in the Z buffer (typically 0xffffff00 or 0x00ffffff). That lets us + * get by with fewer bit twiddling steps. */ -void -lp_build_depth_test(LLVMBuilderRef builder, - const struct pipe_depth_state *state, - struct lp_type type, - const struct util_format_description *format_desc, - struct lp_build_mask_context *mask, - LLVMValueRef src, - LLVMValueRef dst_ptr) +static boolean +get_z_shift_and_mask(const struct util_format_description *format_desc, + unsigned *shift, unsigned *mask) { - struct lp_build_context bld; + const unsigned total_bits = format_desc->block.bits; unsigned z_swizzle; - LLVMValueRef dst; - LLVMValueRef z_bitmask = NULL; - LLVMValueRef test; - - if(!state->enabled) - return; - + int chan; + unsigned padding_left, padding_right; + assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); assert(format_desc->block.width == 1); assert(format_desc->block.height == 1); z_swizzle = format_desc->swizzle[0]; - if(z_swizzle == UTIL_FORMAT_SWIZZLE_NONE) - return; - /* Sanity checking */ - assert(z_swizzle < 4); - assert(format_desc->block.bits == type.width); - if(type.floating) { - assert(z_swizzle == 0); - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_FLOAT); - assert(format_desc->channel[z_swizzle].size == format_desc->block.bits); + if (z_swizzle == UTIL_FORMAT_SWIZZLE_NONE) + return FALSE; + + padding_right = 0; + for (chan = 0; chan < z_swizzle; ++chan) + padding_right += format_desc->channel[chan].size; + + padding_left = + total_bits - (padding_right + format_desc->channel[z_swizzle].size); + + if (padding_left || padding_right) { + unsigned long long mask_left = (1ULL << (total_bits - padding_left)) - 1; + unsigned long long mask_right = (1ULL << (padding_right)) - 1; + *mask = mask_left ^ mask_right; } else { - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(format_desc->channel[z_swizzle].normalized); - assert(!type.fixed); - assert(!type.sign); - assert(type.norm); + *mask = 0xffffffff; + } + + *shift = padding_left; + + return TRUE; +} + + +/** + * Compute bitmask and bit shift to apply to the framebuffer pixel values + * to put the stencil bits in the least significant position. + * (i.e. 0x000000ff) + */ +static boolean +get_s_shift_and_mask(const struct util_format_description *format_desc, + unsigned *shift, unsigned *mask) +{ + unsigned s_swizzle; + int chan, sz; + + s_swizzle = format_desc->swizzle[1]; + + if (s_swizzle == UTIL_FORMAT_SWIZZLE_NONE) + return FALSE; + + *shift = 0; + for (chan = 0; chan < s_swizzle; chan++) + *shift += format_desc->channel[chan].size; + + sz = format_desc->channel[s_swizzle].size; + *mask = (1U << sz) - 1U; + + return TRUE; +} + + + +/** + * Generate code for performing depth and/or stencil tests. + * We operate on a vector of values (typically a 2x2 quad). + * + * \param depth the depth test state + * \param stencil the front/back stencil state + * \param type the data type of the fragment depth/stencil values + * \param format_desc description of the depth/stencil surface + * \param mask the alive/dead pixel mask for the quad (vector) + * \param stencil_refs the front/back stencil ref values (scalar) + * \param z_src the incoming depth/stencil values (a 2x2 quad) + * \param zs_dst_ptr pointer to depth/stencil values in framebuffer + * \param facing contains float value indicating front/back facing polygon + */ +void +lp_build_depth_stencil_test(LLVMBuilderRef builder, + const struct pipe_depth_state *depth, + const struct pipe_stencil_state stencil[2], + struct lp_type type, + const struct util_format_description *format_desc, + struct lp_build_mask_context *mask, + LLVMValueRef stencil_refs[2], + LLVMValueRef z_src, + LLVMValueRef zs_dst_ptr, + LLVMValueRef face) +{ + struct lp_build_context bld; + struct lp_build_context sbld; + struct lp_type s_type; + LLVMValueRef zs_dst, z_dst = NULL; + LLVMValueRef stencil_vals = NULL; + LLVMValueRef z_bitmask = NULL, stencil_shift = NULL; + LLVMValueRef z_pass = NULL, s_pass_mask = NULL; + LLVMValueRef orig_mask = mask->value; + + /* Sanity checking */ + { + const unsigned z_swizzle = format_desc->swizzle[0]; + const unsigned s_swizzle = format_desc->swizzle[1]; + + assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE || + s_swizzle != UTIL_FORMAT_SWIZZLE_NONE); + + assert(depth->enabled || stencil[0].enabled); + + assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); + assert(format_desc->block.width == 1); + assert(format_desc->block.height == 1); + + if (stencil[0].enabled) { + assert(format_desc->format == PIPE_FORMAT_Z24S8_UNORM || + format_desc->format == PIPE_FORMAT_S8Z24_UNORM); + } + + assert(z_swizzle < 4); + assert(format_desc->block.bits == type.width); + if (type.floating) { + assert(z_swizzle == 0); + assert(format_desc->channel[z_swizzle].type == + UTIL_FORMAT_TYPE_FLOAT); + assert(format_desc->channel[z_swizzle].size == + format_desc->block.bits); + } + else { + assert(format_desc->channel[z_swizzle].type == + UTIL_FORMAT_TYPE_UNSIGNED); + assert(format_desc->channel[z_swizzle].normalized); + assert(!type.fixed); + assert(!type.sign); + assert(type.norm); + } } - /* Setup build context */ + + /* Setup build context for Z vals */ lp_build_context_init(&bld, builder, type); - dst = LLVMBuildLoad(builder, dst_ptr, ""); + /* Setup build context for stencil vals */ + s_type = lp_type_int_vec(type.width); + lp_build_context_init(&sbld, builder, s_type); + + /* Load current z/stencil value from z/stencil buffer */ + zs_dst = LLVMBuildLoad(builder, zs_dst_ptr, ""); + + lp_build_name(zs_dst, "zsbufval"); - lp_build_name(dst, "zsbuf"); - /* Align the source depth bits with the destination's, and mask out any - * stencil or padding bits from both */ - if(format_desc->channel[z_swizzle].size == format_desc->block.bits) { - assert(z_swizzle == 0); - /* nothing to do */ + /* Compute and apply the Z/stencil bitmasks and shifts. + */ + { + unsigned z_shift, z_mask; + unsigned s_shift, s_mask; + + if (get_z_shift_and_mask(format_desc, &z_shift, &z_mask)) { + if (z_shift) { + LLVMValueRef shift = lp_build_const_int_vec(type, z_shift); + z_src = LLVMBuildLShr(builder, z_src, shift, ""); + } + + if (z_mask != 0xffffffff) { + LLVMValueRef mask = lp_build_const_int_vec(type, z_mask); + z_src = LLVMBuildAnd(builder, z_src, mask, ""); + z_dst = LLVMBuildAnd(builder, zs_dst, mask, ""); + z_bitmask = mask; /* used below */ + } + else { + z_dst = zs_dst; + } + + lp_build_name(z_dst, "zsbuf.z"); + } + + if (get_s_shift_and_mask(format_desc, &s_shift, &s_mask)) { + if (s_shift) { + LLVMValueRef shift = lp_build_const_int_vec(type, s_shift); + stencil_vals = LLVMBuildLShr(builder, zs_dst, shift, ""); + stencil_shift = shift; /* used below */ + } + else { + stencil_vals = zs_dst; + } + + if (s_mask != 0xffffffff) { + LLVMValueRef mask = lp_build_const_int_vec(type, s_mask); + stencil_vals = LLVMBuildAnd(builder, stencil_vals, mask, ""); + } + + lp_build_name(stencil_vals, "stencil"); + } } - else { - unsigned padding_left; - unsigned padding_right; - unsigned chan; - - assert(format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN); - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(format_desc->channel[z_swizzle].size <= format_desc->block.bits); - assert(format_desc->channel[z_swizzle].normalized); - - padding_right = 0; - for(chan = 0; chan < z_swizzle; ++chan) - padding_right += format_desc->channel[chan].size; - padding_left = format_desc->block.bits - - (padding_right + format_desc->channel[z_swizzle].size); - - if(padding_left || padding_right) { - const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1; - const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1; - z_bitmask = lp_build_int_const_scalar(type, mask_left ^ mask_right); + + + if (stencil[0].enabled) { + /* convert scalar stencil refs into vectors */ + stencil_refs[0] = lp_build_broadcast_scalar(&bld, stencil_refs[0]); + stencil_refs[1] = lp_build_broadcast_scalar(&bld, stencil_refs[1]); + + s_pass_mask = lp_build_stencil_test(&sbld, stencil, + stencil_refs, stencil_vals, face); + + /* apply stencil-fail operator */ + { + LLVMValueRef s_fail_mask = lp_build_andc(&bld, orig_mask, s_pass_mask); + stencil_vals = lp_build_stencil_op(&sbld, stencil, S_FAIL_OP, + stencil_refs, stencil_vals, + s_fail_mask, face); + } + } + + if (depth->enabled) { + /* compare src Z to dst Z, returning 'pass' mask */ + z_pass = lp_build_cmp(&bld, depth->func, z_src, z_dst); + + if (!stencil[0].enabled) { + /* We can potentially skip all remaining operations here, but only + * if stencil is disabled because we still need to update the stencil + * buffer values. Don't need to update Z buffer values. + */ + lp_build_mask_update(mask, z_pass); + } + + if (depth->writemask) { + if(z_bitmask) + z_bitmask = LLVMBuildAnd(builder, mask->value, z_bitmask, ""); + else + z_bitmask = mask->value; + + z_dst = lp_build_select(&bld, z_bitmask, z_src, z_dst); } - if(padding_left) - src = LLVMBuildLShr(builder, src, lp_build_int_const_scalar(type, padding_left), ""); - if(padding_right) - src = LLVMBuildAnd(builder, src, z_bitmask, ""); - if(padding_left || padding_right) - dst = LLVMBuildAnd(builder, dst, z_bitmask, ""); + if (stencil[0].enabled) { + /* update stencil buffer values according to z pass/fail result */ + LLVMValueRef z_fail_mask, z_pass_mask; + + /* apply Z-fail operator */ + z_fail_mask = lp_build_andc(&bld, orig_mask, z_pass); + stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_FAIL_OP, + stencil_refs, stencil_vals, + z_fail_mask, face); + + /* apply Z-pass operator */ + z_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, z_pass, ""); + stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP, + stencil_refs, stencil_vals, + z_pass_mask, face); + } + } + else { + /* No depth test: apply Z-pass operator to stencil buffer values which + * passed the stencil test. + */ + s_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, s_pass_mask, ""); + stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP, + stencil_refs, stencil_vals, + s_pass_mask, face); } - lp_build_name(dst, "zsbuf.z"); + /* The Z bits are already in the right place but we may need to shift the + * stencil bits before ORing Z with Stencil to make the final pixel value. + */ + if (stencil_vals && stencil_shift) + stencil_vals = LLVMBuildShl(bld.builder, stencil_vals, + stencil_shift, ""); - test = lp_build_cmp(&bld, state->func, src, dst); - lp_build_mask_update(mask, test); + /* Finally, merge/store the z/stencil values */ + if ((depth->enabled && depth->writemask) || + (stencil[0].enabled && stencil[0].writemask)) { - if(state->writemask) { - if(z_bitmask) - z_bitmask = LLVMBuildAnd(builder, mask->value, z_bitmask, ""); + if (z_dst && stencil_vals) + zs_dst = LLVMBuildOr(bld.builder, z_dst, stencil_vals, ""); + else if (z_dst) + zs_dst = z_dst; else - z_bitmask = mask->value; + zs_dst = stencil_vals; - dst = lp_build_select(&bld, z_bitmask, src, dst); - LLVMBuildStore(builder, dst, dst_ptr); + LLVMBuildStore(builder, zs_dst, zs_dst_ptr); } + + if (s_pass_mask) + lp_build_mask_update(mask, s_pass_mask); + + if (depth->enabled && stencil[0].enabled) + lp_build_mask_update(mask, z_pass); } diff --git a/src/gallium/auxiliary/gallivm/lp_bld_depth.h b/src/gallium/auxiliary/gallivm/lp_bld_depth.h index 8be80024ae..27dd46b625 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_depth.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_depth.h @@ -36,7 +36,7 @@ #define LP_BLD_DEPTH_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct pipe_depth_state; @@ -51,13 +51,16 @@ lp_depth_type(const struct util_format_description *format_desc, void -lp_build_depth_test(LLVMBuilderRef builder, - const struct pipe_depth_state *state, - struct lp_type type, - const struct util_format_description *format_desc, - struct lp_build_mask_context *mask, - LLVMValueRef src, - LLVMValueRef dst_ptr); +lp_build_depth_stencil_test(LLVMBuilderRef builder, + const struct pipe_depth_state *depth, + const struct pipe_stencil_state stencil[2], + struct lp_type type, + const struct util_format_description *format_desc, + struct lp_build_mask_context *mask, + LLVMValueRef stencil_refs[2], + LLVMValueRef zs_src, + LLVMValueRef zs_dst_ptr, + LLVMValueRef facing); #endif /* !LP_BLD_DEPTH_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.h b/src/gallium/auxiliary/gallivm/lp_bld_flow.h index e158836549..c2b50e1b60 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.h @@ -35,7 +35,7 @@ #define LP_BLD_FLOW_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format.h b/src/gallium/auxiliary/gallivm/lp_bld_format.h index 8972c0dc17..73ab6de3f2 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_format.h @@ -34,7 +34,7 @@ * Pixel format helpers. */ -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include "pipe/p_format.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c index abb27e4c32..45ee4b12ce 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c @@ -114,10 +114,10 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder, case UTIL_FORMAT_TYPE_UNSIGNED: if(type.floating) { if(start) - input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(type, start), ""); + input = LLVMBuildLShr(builder, input, lp_build_const_int_vec(type, start), ""); if(stop < format_desc->block.bits) { unsigned mask = ((unsigned long long)1 << width) - 1; - input = LLVMBuildAnd(builder, input, lp_build_int_const_scalar(type, mask), ""); + input = LLVMBuildAnd(builder, input, lp_build_const_int_vec(type, mask), ""); } if(format_desc->channel[chan].normalized) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_interp.c b/src/gallium/auxiliary/gallivm/lp_bld_interp.c index 2fc894017d..09efb16121 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_interp.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_interp.c @@ -289,17 +289,17 @@ pos_update(struct lp_build_interp_soa_context *bld, int quad_index) /* top-right or bottom-right quad in block */ /* build x += xstep */ x = lp_build_add(&bld->base, x, - lp_build_const_scalar(bld->base.type, xstep)); + lp_build_const_vec(bld->base.type, xstep)); } if (quad_index == 2) { /* bottom-left quad in block */ /* build y += ystep */ y = lp_build_add(&bld->base, y, - lp_build_const_scalar(bld->base.type, ystep)); + lp_build_const_vec(bld->base.type, ystep)); /* build x -= xstep */ x = lp_build_sub(&bld->base, x, - lp_build_const_scalar(bld->base.type, xstep)); + lp_build_const_vec(bld->base.type, xstep)); } lp_build_name(x, "pos.x"); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_interp.h b/src/gallium/auxiliary/gallivm/lp_bld_interp.h index 177b5e943e..a4937bbb04 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_interp.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_interp.h @@ -41,7 +41,7 @@ #define LP_BLD_INTERP_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include "tgsi/tgsi_exec.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_intr.h b/src/gallium/auxiliary/gallivm/lp_bld_intr.h index 7d5506c733..977f767322 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_intr.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_intr.h @@ -37,7 +37,7 @@ #define LP_BLD_INTR_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" /** diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.c b/src/gallium/auxiliary/gallivm/lp_bld_logic.c index f3df3dd138..a3b6970116 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_logic.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.c @@ -193,7 +193,7 @@ lp_build_compare(LLVMBuilderRef builder, if(table[func].gt && ((type.width == 8 && type.sign) || (type.width != 8 && !type.sign))) { - LLVMValueRef msb = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); + LLVMValueRef msb = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1)); a = LLVMBuildXor(builder, a, msb, ""); b = LLVMBuildXor(builder, b, msb, ""); } @@ -483,3 +483,13 @@ lp_build_alloca(struct lp_build_context *bld) return LLVMBuildAlloca(bld->builder, lp_build_elem_type(type), ""); } } + + +/** Return (a & ~b) */ +LLVMValueRef +lp_build_andc(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b) +{ + b = LLVMBuildNot(bld->builder, b, ""); + b = LLVMBuildAnd(bld->builder, a, b, ""); + return b; +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_logic.h b/src/gallium/auxiliary/gallivm/lp_bld_logic.h index b54ec13b70..00a8c75019 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_logic.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_logic.h @@ -37,7 +37,7 @@ #define LP_BLD_LOGIC_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */ @@ -79,4 +79,9 @@ lp_build_select_aos(struct lp_build_context *bld, LLVMValueRef lp_build_alloca(struct lp_build_context *bld); + +LLVMValueRef +lp_build_andc(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b); + + #endif /* !LP_BLD_LOGIC_H */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_pack.c b/src/gallium/auxiliary/gallivm/lp_bld_pack.c index 23398f41f9..2daa8a3b58 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_pack.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_pack.c @@ -164,7 +164,7 @@ lp_build_unpack2(LLVMBuilderRef builder, if(dst_type.sign && src_type.sign) { /* Replicate the sign bit in the most significant bits */ - msb = LLVMBuildAShr(builder, src, lp_build_int_const_scalar(src_type, src_type.width - 1), ""); + msb = LLVMBuildAShr(builder, src, lp_build_const_int_vec(src_type, src_type.width - 1), ""); } else /* Most significant bits always zero */ @@ -361,7 +361,7 @@ lp_build_packs2(LLVMBuilderRef builder, if(clamp) { struct lp_build_context bld; unsigned dst_bits = dst_type.sign ? dst_type.width - 1 : dst_type.width; - LLVMValueRef dst_max = lp_build_int_const_scalar(src_type, ((unsigned long long)1 << dst_bits) - 1); + LLVMValueRef dst_max = lp_build_const_int_vec(src_type, ((unsigned long long)1 << dst_bits) - 1); lp_build_context_init(&bld, builder, src_type); lo = lp_build_min(&bld, lo, dst_max); hi = lp_build_min(&bld, hi, dst_max); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_pack.h b/src/gallium/auxiliary/gallivm/lp_bld_pack.h index 346a17d580..41adeed220 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_pack.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_pack.h @@ -37,7 +37,7 @@ #define LP_BLD_PACK_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.c b/src/gallium/auxiliary/gallivm/lp_bld_sample.c index 672e06c992..0761e35f8e 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.c @@ -173,7 +173,7 @@ lp_build_sample_offset(struct lp_build_context *bld, LLVMValueRef x_stride; LLVMValueRef offset; - x_stride = lp_build_const_scalar(bld->type, format_desc->block.bits/8); + x_stride = lp_build_const_vec(bld->type, format_desc->block.bits/8); if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { LLVMValueRef x_lo, x_hi; @@ -195,9 +195,9 @@ lp_build_sample_offset(struct lp_build_context *bld, y_hi = LLVMBuildLShr(bld->builder, y, bld->one, ""); x_stride_lo = x_stride; - y_stride_lo = lp_build_const_scalar(bld->type, 2*format_desc->block.bits/8); + y_stride_lo = lp_build_const_vec(bld->type, 2*format_desc->block.bits/8); - x_stride_hi = lp_build_const_scalar(bld->type, 4*format_desc->block.bits/8); + x_stride_hi = lp_build_const_vec(bld->type, 4*format_desc->block.bits/8); y_stride_hi = LLVMBuildShl(bld->builder, y_stride, bld->one, ""); x_offset_lo = lp_build_mul(bld, x_lo, x_stride_lo); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index d35fdbb78d..fcbf084baf 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -36,7 +36,7 @@ #define LP_BLD_SAMPLE_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct pipe_resource; struct pipe_sampler_state; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 72018737a8..995c016b9d 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -292,7 +292,7 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld, int chan; for (chan = 0; chan < 4; chan++) { LLVMValueRef border_chan = - lp_build_const_scalar(bld->texel_type, + lp_build_const_vec(bld->texel_type, bld->static_state->border_color[chan]); texel[chan] = lp_build_select(&bld->texel_bld, use_border, border_chan, texel[chan]); @@ -457,8 +457,8 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, struct lp_build_context *coord_bld = &bld->coord_bld; struct lp_build_context *int_coord_bld = &bld->int_coord_bld; struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld; - LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0); - LLVMValueRef half = lp_build_const_scalar(coord_bld->type, 0.5); + LLVMValueRef two = lp_build_const_vec(coord_bld->type, 2.0); + LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5); LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length); LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one); LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one); @@ -512,7 +512,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, else { LLVMValueRef min, max; /* clamp to [0.5, length - 0.5] */ - min = lp_build_const_scalar(coord_bld->type, 0.5F); + min = lp_build_const_vec(coord_bld->type, 0.5F); max = lp_build_sub(coord_bld, length_f, min); coord = lp_build_clamp(coord_bld, coord, min, max); } @@ -533,7 +533,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, if (bld->static_state->normalized_coords) { /* min = -1.0 / (2 * length) = -0.5 / length */ min = lp_build_mul(coord_bld, - lp_build_const_scalar(coord_bld->type, -0.5F), + lp_build_const_vec(coord_bld->type, -0.5F), lp_build_rcp(coord_bld, length_f)); /* max = 1.0 - min */ max = lp_build_sub(coord_bld, coord_bld->one, min); @@ -545,7 +545,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, } else { /* clamp to [-0.5, length + 0.5] */ - min = lp_build_const_scalar(coord_bld->type, -0.5F); + min = lp_build_const_vec(coord_bld->type, -0.5F); max = lp_build_sub(coord_bld, length_f, min); coord = lp_build_clamp(coord_bld, coord, min, max); coord = lp_build_sub(coord_bld, coord, half); @@ -620,7 +620,7 @@ lp_build_sample_wrap_linear(struct lp_build_sample_context *bld, LLVMValueRef min, max; /* min = -1.0 / (2 * length) = -0.5 / length */ min = lp_build_mul(coord_bld, - lp_build_const_scalar(coord_bld->type, -0.5F), + lp_build_const_vec(coord_bld->type, -0.5F), lp_build_rcp(coord_bld, length_f)); /* max = 1.0 - min */ max = lp_build_sub(coord_bld, coord_bld->one, min); @@ -665,7 +665,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, struct lp_build_context *coord_bld = &bld->coord_bld; struct lp_build_context *int_coord_bld = &bld->int_coord_bld; struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld; - LLVMValueRef two = lp_build_const_scalar(coord_bld->type, 2.0); + LLVMValueRef two = lp_build_const_vec(coord_bld->type, 2.0); LLVMValueRef length_f = lp_build_int_to_float(coord_bld, length); LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one); LLVMValueRef length_f_minus_one = lp_build_sub(coord_bld, length_f, coord_bld->one); @@ -708,7 +708,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, } else { /* clamp to [0.5, length - 0.5] */ - min = lp_build_const_scalar(coord_bld->type, 0.5F); + min = lp_build_const_vec(coord_bld->type, 0.5F); max = lp_build_sub(coord_bld, length_f, min); } /* coord = clamp(coord, min, max) */ @@ -724,7 +724,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, if (bld->static_state->normalized_coords) { /* min = -1.0 / (2 * length) = -0.5 / length */ min = lp_build_mul(coord_bld, - lp_build_const_scalar(coord_bld->type, -0.5F), + lp_build_const_vec(coord_bld->type, -0.5F), lp_build_rcp(coord_bld, length_f)); /* max = length - min */ max = lp_build_sub(coord_bld, length_f, min); @@ -733,7 +733,7 @@ lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, } else { /* clamp to [-0.5, length + 0.5] */ - min = lp_build_const_scalar(coord_bld->type, -0.5F); + min = lp_build_const_vec(coord_bld->type, -0.5F); max = lp_build_sub(coord_bld, length_f, min); } /* coord = clamp(coord, min, max) */ @@ -843,87 +843,98 @@ lp_build_lod_selector(struct lp_build_sample_context *bld, LLVMValueRef depth) { - const int dims = texture_dims(bld->static_state->target); - struct lp_build_context *float_bld = &bld->float_bld; - LLVMValueRef lod_bias = LLVMConstReal(LLVMFloatType(), bld->static_state->lod_bias); - LLVMValueRef min_lod = LLVMConstReal(LLVMFloatType(), bld->static_state->min_lod); - LLVMValueRef max_lod = LLVMConstReal(LLVMFloatType(), bld->static_state->max_lod); - - LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0); - LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0); - LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0); - - LLVMValueRef s0, s1, s2; - LLVMValueRef t0, t1, t2; - LLVMValueRef r0, r1, r2; - LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy; - LLVMValueRef rho, lod; - - /* - * dsdx = abs(s[1] - s[0]); - * dsdy = abs(s[2] - s[0]); - * dtdx = abs(t[1] - t[0]); - * dtdy = abs(t[2] - t[0]); - * drdx = abs(r[1] - r[0]); - * drdy = abs(r[2] - r[0]); - * XXX we're assuming a four-element quad in 2x2 layout here. - */ - s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0"); - s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1"); - s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2"); - dsdx = LLVMBuildSub(bld->builder, s1, s0, ""); - dsdx = lp_build_abs(float_bld, dsdx); - dsdy = LLVMBuildSub(bld->builder, s2, s0, ""); - dsdy = lp_build_abs(float_bld, dsdy); - if (dims > 1) { - t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0"); - t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1"); - t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2"); - dtdx = LLVMBuildSub(bld->builder, t1, t0, ""); - dtdx = lp_build_abs(float_bld, dtdx); - dtdy = LLVMBuildSub(bld->builder, t2, t0, ""); - dtdy = lp_build_abs(float_bld, dtdy); - if (dims > 2) { - r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0"); - r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1"); - r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2"); - drdx = LLVMBuildSub(bld->builder, r1, r0, ""); - drdx = lp_build_abs(float_bld, drdx); - drdy = LLVMBuildSub(bld->builder, r2, r0, ""); - drdy = lp_build_abs(float_bld, drdy); - } + if (bld->static_state->min_lod == bld->static_state->max_lod) { + /* User is forcing sampling from a particular mipmap level. + * This is hit during mipmap generation. + */ + return LLVMConstReal(LLVMFloatType(), bld->static_state->min_lod); } + else { + const int dims = texture_dims(bld->static_state->target); + struct lp_build_context *float_bld = &bld->float_bld; + LLVMValueRef lod_bias = LLVMConstReal(LLVMFloatType(), + bld->static_state->lod_bias); + LLVMValueRef min_lod = LLVMConstReal(LLVMFloatType(), + bld->static_state->min_lod); + LLVMValueRef max_lod = LLVMConstReal(LLVMFloatType(), + bld->static_state->max_lod); + + LLVMValueRef index0 = LLVMConstInt(LLVMInt32Type(), 0, 0); + LLVMValueRef index1 = LLVMConstInt(LLVMInt32Type(), 1, 0); + LLVMValueRef index2 = LLVMConstInt(LLVMInt32Type(), 2, 0); + + LLVMValueRef s0, s1, s2; + LLVMValueRef t0, t1, t2; + LLVMValueRef r0, r1, r2; + LLVMValueRef dsdx, dsdy, dtdx, dtdy, drdx, drdy; + LLVMValueRef rho, lod; + + /* + * dsdx = abs(s[1] - s[0]); + * dsdy = abs(s[2] - s[0]); + * dtdx = abs(t[1] - t[0]); + * dtdy = abs(t[2] - t[0]); + * drdx = abs(r[1] - r[0]); + * drdy = abs(r[2] - r[0]); + * XXX we're assuming a four-element quad in 2x2 layout here. + */ + s0 = LLVMBuildExtractElement(bld->builder, s, index0, "s0"); + s1 = LLVMBuildExtractElement(bld->builder, s, index1, "s1"); + s2 = LLVMBuildExtractElement(bld->builder, s, index2, "s2"); + dsdx = LLVMBuildSub(bld->builder, s1, s0, ""); + dsdx = lp_build_abs(float_bld, dsdx); + dsdy = LLVMBuildSub(bld->builder, s2, s0, ""); + dsdy = lp_build_abs(float_bld, dsdy); + if (dims > 1) { + t0 = LLVMBuildExtractElement(bld->builder, t, index0, "t0"); + t1 = LLVMBuildExtractElement(bld->builder, t, index1, "t1"); + t2 = LLVMBuildExtractElement(bld->builder, t, index2, "t2"); + dtdx = LLVMBuildSub(bld->builder, t1, t0, ""); + dtdx = lp_build_abs(float_bld, dtdx); + dtdy = LLVMBuildSub(bld->builder, t2, t0, ""); + dtdy = lp_build_abs(float_bld, dtdy); + if (dims > 2) { + r0 = LLVMBuildExtractElement(bld->builder, r, index0, "r0"); + r1 = LLVMBuildExtractElement(bld->builder, r, index1, "r1"); + r2 = LLVMBuildExtractElement(bld->builder, r, index2, "r2"); + drdx = LLVMBuildSub(bld->builder, r1, r0, ""); + drdx = lp_build_abs(float_bld, drdx); + drdy = LLVMBuildSub(bld->builder, r2, r0, ""); + drdy = lp_build_abs(float_bld, drdy); + } + } - /* Compute rho = max of all partial derivatives scaled by texture size. - * XXX this could be vectorized somewhat - */ - rho = LLVMBuildMul(bld->builder, - lp_build_max(float_bld, dsdx, dsdy), - lp_build_int_to_float(float_bld, width), ""); - if (dims > 1) { - LLVMValueRef max; - max = LLVMBuildMul(bld->builder, - lp_build_max(float_bld, dtdx, dtdy), - lp_build_int_to_float(float_bld, height), ""); - rho = lp_build_max(float_bld, rho, max); - if (dims > 2) { + /* Compute rho = max of all partial derivatives scaled by texture size. + * XXX this could be vectorized somewhat + */ + rho = LLVMBuildMul(bld->builder, + lp_build_max(float_bld, dsdx, dsdy), + lp_build_int_to_float(float_bld, width), ""); + if (dims > 1) { + LLVMValueRef max; max = LLVMBuildMul(bld->builder, - lp_build_max(float_bld, drdx, drdy), - lp_build_int_to_float(float_bld, depth), ""); + lp_build_max(float_bld, dtdx, dtdy), + lp_build_int_to_float(float_bld, height), ""); rho = lp_build_max(float_bld, rho, max); + if (dims > 2) { + max = LLVMBuildMul(bld->builder, + lp_build_max(float_bld, drdx, drdy), + lp_build_int_to_float(float_bld, depth), ""); + rho = lp_build_max(float_bld, rho, max); + } } - } - /* compute lod = log2(rho) */ - lod = lp_build_log2(float_bld, rho); + /* compute lod = log2(rho) */ + lod = lp_build_log2(float_bld, rho); - /* add lod bias */ - lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "LOD bias"); + /* add lod bias */ + lod = LLVMBuildAdd(bld->builder, lod, lod_bias, "LOD bias"); - /* clamp lod */ - lod = lp_build_clamp(float_bld, lod, min_lod, max_lod); + /* clamp lod */ + lod = lp_build_clamp(float_bld, lod, min_lod, max_lod); - return lod; + return lod; + } } @@ -986,7 +997,7 @@ lp_build_linear_mip_levels(struct lp_build_sample_context *bld, last_level); /* compute level 1 and clamp to legal range of levels */ *level1_out = lp_build_add(int_bld, *level0_out, int_bld->one); - *level1_out = lp_build_min(int_bld, *level1_out, int_bld->zero); + *level1_out = lp_build_min(int_bld, *level1_out, last_level); *weight_out = lp_build_fract(float_bld, lod); } @@ -1215,7 +1226,7 @@ static LLVMValueRef lp_build_cube_ima(struct lp_build_context *coord_bld, LLVMValueRef coord) { /* ima = -0.5 / abs(coord); */ - LLVMValueRef negHalf = lp_build_const_scalar(coord_bld->type, -0.5); + LLVMValueRef negHalf = lp_build_const_vec(coord_bld->type, -0.5); LLVMValueRef absCoord = lp_build_abs(coord_bld, coord); LLVMValueRef ima = lp_build_mul(coord_bld, negHalf, lp_build_rcp(coord_bld, absCoord)); @@ -1235,7 +1246,7 @@ lp_build_cube_coord(struct lp_build_context *coord_bld, LLVMValueRef coord, LLVMValueRef ima) { /* return negate(coord) * ima * sign + 0.5; */ - LLVMValueRef half = lp_build_const_scalar(coord_bld->type, 0.5); + LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5); LLVMValueRef res; assert(negate_coord == +1 || negate_coord == -1); @@ -1414,6 +1425,85 @@ lp_build_cube_lookup(struct lp_build_sample_context *bld, /** + * Sample the texture/mipmap using given image filter and mip filter. + * data0_ptr and data1_ptr point to the two mipmap levels to sample + * from. width0/1_vec, height0/1_vec, depth0/1_vec indicate their sizes. + * If we're using nearest miplevel sampling the '1' values will be null/unused. + */ +static void +lp_build_sample_mipmap(struct lp_build_sample_context *bld, + unsigned img_filter, + unsigned mip_filter, + LLVMValueRef s, + LLVMValueRef t, + LLVMValueRef r, + LLVMValueRef lod_fpart, + LLVMValueRef width0_vec, + LLVMValueRef width1_vec, + LLVMValueRef height0_vec, + LLVMValueRef height1_vec, + LLVMValueRef depth0_vec, + LLVMValueRef depth1_vec, + LLVMValueRef row_stride0_vec, + LLVMValueRef row_stride1_vec, + LLVMValueRef img_stride0_vec, + LLVMValueRef img_stride1_vec, + LLVMValueRef data_ptr0, + LLVMValueRef data_ptr1, + LLVMValueRef *colors_out) +{ + LLVMValueRef colors0[4], colors1[4]; + int chan; + + if (img_filter == PIPE_TEX_FILTER_NEAREST) { + lp_build_sample_image_nearest(bld, + width0_vec, height0_vec, depth0_vec, + row_stride0_vec, img_stride0_vec, + data_ptr0, s, t, r, colors0); + + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + /* sample the second mipmap level, and interp */ + lp_build_sample_image_nearest(bld, + width1_vec, height1_vec, depth1_vec, + row_stride1_vec, img_stride1_vec, + data_ptr1, s, t, r, colors1); + } + } + else { + assert(img_filter == PIPE_TEX_FILTER_LINEAR); + + lp_build_sample_image_linear(bld, + width0_vec, height0_vec, depth0_vec, + row_stride0_vec, img_stride0_vec, + data_ptr0, s, t, r, colors0); + + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + /* sample the second mipmap level, and interp */ + lp_build_sample_image_linear(bld, + width1_vec, height1_vec, depth1_vec, + row_stride1_vec, img_stride1_vec, + data_ptr1, s, t, r, colors1); + } + } + + if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { + /* interpolate samples from the two mipmap levels */ + for (chan = 0; chan < 4; chan++) { + colors_out[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart, + colors0[chan], colors1[chan]); + } + } + else { + /* use first/only level's colors */ + for (chan = 0; chan < 4; chan++) { + colors_out[chan] = colors0[chan]; + } + } +} + + + +/** * General texture sampling codegen. * This function handles texture sampling for all texture targets (1D, * 2D, 3D, cube) and all filtering modes. @@ -1435,6 +1525,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld, LLVMValueRef data_array, LLVMValueRef *colors_out) { + struct lp_build_context *float_bld = &bld->float_bld; const unsigned mip_filter = bld->static_state->min_mip_filter; const unsigned min_filter = bld->static_state->min_img_filter; const unsigned mag_filter = bld->static_state->mag_img_filter; @@ -1446,7 +1537,6 @@ lp_build_sample_general(struct lp_build_sample_context *bld, LLVMValueRef row_stride0_vec = NULL, row_stride1_vec = NULL; LLVMValueRef img_stride0_vec = NULL, img_stride1_vec = NULL; LLVMValueRef data_ptr0, data_ptr1; - int chan; /* printf("%s mip %d min %d mag %d\n", __FUNCTION__, @@ -1454,16 +1544,24 @@ lp_build_sample_general(struct lp_build_sample_context *bld, */ /* - * Compute the level of detail (mipmap level index(es)). + * Compute the level of detail (float). + */ + if (min_filter != mag_filter || + mip_filter != PIPE_TEX_MIPFILTER_NONE) { + /* Need to compute lod either to choose mipmap levels or to + * distinguish between minification/magnification with one mipmap level. + */ + lod = lp_build_lod_selector(bld, s, t, r, width, height, depth); + } + + /* + * Compute integer mipmap level(s) to fetch texels from. */ if (mip_filter == PIPE_TEX_MIPFILTER_NONE) { /* always use mip level 0 */ ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0); } else { - /* compute float LOD */ - lod = lp_build_lod_selector(bld, s, t, r, width, height, depth); - if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { lp_build_nearest_mip_level(bld, unit, lod, &ilevel0); } @@ -1499,7 +1597,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld, } } if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { - /* compute width, height, depth for second mipmap level at ilevel1 */ + /* compute width, height, depth for second mipmap level at 'ilevel1' */ width1_vec = lp_build_minify(bld, width_vec, ilevel1_vec); if (dims >= 2) { height1_vec = lp_build_minify(bld, height_vec, ilevel1_vec); @@ -1516,7 +1614,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld, } /* - * Choose cube face, recompute texcoords. + * Choose cube face, recompute per-face texcoords. */ if (bld->static_state->target == PIPE_TEXTURE_CUBE) { LLVMValueRef face, face_s, face_t; @@ -1538,62 +1636,67 @@ lp_build_sample_general(struct lp_build_sample_context *bld, /* * Get/interpolate texture colors. */ - /* XXX temporarily force this path: */ - if (1 /*min_filter == mag_filter*/) { - /* same filter for minification or magnification */ - LLVMValueRef colors0[4], colors1[4]; - - if (min_filter == PIPE_TEX_FILTER_NEAREST) { - lp_build_sample_image_nearest(bld, - width0_vec, height0_vec, depth0_vec, - row_stride0_vec, img_stride0_vec, - data_ptr0, s, t, r, colors0); - - if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { - /* sample the second mipmap level, and interp */ - lp_build_sample_image_nearest(bld, - width1_vec, height1_vec, depth1_vec, - row_stride1_vec, img_stride1_vec, - data_ptr1, s, t, r, colors1); - } - } - else { - assert(min_filter == PIPE_TEX_FILTER_LINEAR); + if (min_filter == mag_filter) { + /* no need to distinquish between minification and magnification */ + lp_build_sample_mipmap(bld, min_filter, mip_filter, s, t, r, lod_fpart, + width0_vec, width1_vec, + height0_vec, height1_vec, + depth0_vec, depth1_vec, + row_stride0_vec, row_stride1_vec, + img_stride0_vec, img_stride1_vec, + data_ptr0, data_ptr1, + colors_out); + } + else { + /* Emit conditional to choose min image filter or mag image filter + * depending on the lod being >0 or <= 0, respectively. + */ + struct lp_build_flow_context *flow_ctx; + struct lp_build_if_state if_ctx; + LLVMValueRef minify; - lp_build_sample_image_linear(bld, - width0_vec, height0_vec, depth0_vec, - row_stride0_vec, img_stride0_vec, - data_ptr0, s, t, r, colors0); + flow_ctx = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx); + lp_build_flow_scope_declare(flow_ctx, &colors_out[0]); + lp_build_flow_scope_declare(flow_ctx, &colors_out[1]); + lp_build_flow_scope_declare(flow_ctx, &colors_out[2]); + lp_build_flow_scope_declare(flow_ctx, &colors_out[3]); - if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { - /* sample the second mipmap level, and interp */ - lp_build_sample_image_linear(bld, - width1_vec, height1_vec, depth1_vec, - row_stride1_vec, img_stride1_vec, - data_ptr1, s, t, r, colors1); - } - } + /* minify = lod > 0.0 */ + minify = LLVMBuildFCmp(bld->builder, LLVMRealUGE, + lod, float_bld->zero, ""); - if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { - /* interpolate samples from the two mipmap levels */ - for (chan = 0; chan < 4; chan++) { - colors_out[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart, - colors0[chan], colors1[chan]); - } + lp_build_if(&if_ctx, flow_ctx, bld->builder, minify); + { + /* Use the minification filter */ + lp_build_sample_mipmap(bld, min_filter, mip_filter, + s, t, r, lod_fpart, + width0_vec, width1_vec, + height0_vec, height1_vec, + depth0_vec, depth1_vec, + row_stride0_vec, row_stride1_vec, + img_stride0_vec, img_stride1_vec, + data_ptr0, data_ptr1, + colors_out); } - else { - /* use first/only level's colors */ - for (chan = 0; chan < 4; chan++) { - colors_out[chan] = colors0[chan]; - } + lp_build_else(&if_ctx); + { + /* Use the magnification filter */ + lp_build_sample_mipmap(bld, mag_filter, mip_filter, + s, t, r, lod_fpart, + width0_vec, width1_vec, + height0_vec, height1_vec, + depth0_vec, depth1_vec, + row_stride0_vec, row_stride1_vec, + img_stride0_vec, img_stride1_vec, + data_ptr0, data_ptr1, + colors_out); } - } - else { - /* emit conditional to choose min image filter or mag image filter - * depending on the lod being >0 or <= 0, respectively. - */ - abort(); + lp_build_endif(&if_ctx); + + lp_build_flow_scope_end(flow_ctx); + lp_build_flow_destroy(flow_ctx); } } @@ -1605,7 +1708,7 @@ lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder, LLVMValueRef packed, LLVMValueRef *rgba) { - LLVMValueRef mask = lp_build_int_const_scalar(dst_type, 0xff); + LLVMValueRef mask = lp_build_const_int_vec(dst_type, 0xff); unsigned chan; /* Decode the input vector components */ @@ -1617,7 +1720,7 @@ lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder, input = packed; if(start) - input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(dst_type, start), ""); + input = LLVMBuildLShr(builder, input, lp_build_const_int_vec(dst_type, start), ""); if(stop < 32) input = LLVMBuildAnd(builder, input, mask, ""); @@ -1679,17 +1782,17 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld, t = LLVMBuildFPToSI(builder, t, i32_vec_type, ""); /* subtract 0.5 (add -128) */ - i32_c128 = lp_build_int_const_scalar(i32.type, -128); + i32_c128 = lp_build_const_int_vec(i32.type, -128); s = LLVMBuildAdd(builder, s, i32_c128, ""); t = LLVMBuildAdd(builder, t, i32_c128, ""); /* compute floor (shift right 8) */ - i32_c8 = lp_build_int_const_scalar(i32.type, 8); + i32_c8 = lp_build_const_int_vec(i32.type, 8); s_ipart = LLVMBuildAShr(builder, s, i32_c8, ""); t_ipart = LLVMBuildAShr(builder, t, i32_c8, ""); /* compute fractional part (AND with 0xff) */ - i32_c255 = lp_build_int_const_scalar(i32.type, 255); + i32_c255 = lp_build_const_int_vec(i32.type, 255); s_fpart = LLVMBuildAnd(builder, s, i32_c255, ""); t_fpart = LLVMBuildAnd(builder, t, i32_c255, ""); @@ -1856,7 +1959,7 @@ lp_build_sample_compare(struct lp_build_sample_context *bld, } assert(res); - res = lp_build_mul(texel_bld, res, lp_build_const_scalar(texel_bld->type, 0.25)); + res = lp_build_mul(texel_bld, res, lp_build_const_vec(texel_bld->type, 0.25)); /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ for(chan = 0; chan < 3; ++chan) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_struct.h b/src/gallium/auxiliary/gallivm/lp_bld_struct.h index 34478c10f5..147336edb4 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_struct.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_struct.h @@ -37,7 +37,7 @@ #define LP_BLD_STRUCT_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include <llvm-c/Target.h> #include "util/u_debug.h" diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c index 64e81f7b1f..278c838eac 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c @@ -144,9 +144,9 @@ lp_build_broadcast_aos(struct lp_build_context *bld, #endif if(shift > 0) - tmp = LLVMBuildLShr(bld->builder, a, lp_build_int_const_scalar(type4, shift*type.width), ""); + tmp = LLVMBuildLShr(bld->builder, a, lp_build_const_int_vec(type4, shift*type.width), ""); if(shift < 0) - tmp = LLVMBuildShl(bld->builder, a, lp_build_int_const_scalar(type4, -shift*type.width), ""); + tmp = LLVMBuildShl(bld->builder, a, lp_build_const_int_vec(type4, -shift*type.width), ""); assert(tmp); if(tmp) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h index 57b5cc079f..138ca620e6 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.h @@ -37,7 +37,7 @@ #define LP_BLD_SWIZZLE_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct lp_type; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h index 0f2f8a65b1..63b938bfa9 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h @@ -35,7 +35,7 @@ #ifndef LP_BLD_TGSI_H #define LP_BLD_TGSI_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct tgsi_token; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c index 5ec59d636c..f160be878f 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c @@ -475,7 +475,7 @@ emit_store( break; case TGSI_SAT_MINUS_PLUS_ONE: - value = lp_build_max(&bld->base, value, lp_build_const_scalar(bld->base.type, -1.0)); + value = lp_build_max(&bld->base, value, lp_build_const_vec(bld->base.type, -1.0)); value = lp_build_min(&bld->base, value, bld->base.one); break; @@ -996,7 +996,7 @@ emit_instruction( src0 = emit_fetch( bld, inst, 0, chan_index ); src1 = emit_fetch( bld, inst, 1, chan_index ); src2 = emit_fetch( bld, inst, 2, chan_index ); - tmp1 = lp_build_const_scalar(bld->base.type, 0.5); + tmp1 = lp_build_const_vec(bld->base.type, 0.5); tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src2, tmp1); dst0[chan_index] = lp_build_select( &bld->base, tmp0, src0, src1 ); } @@ -1713,7 +1713,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder, assert(num_immediates < LP_MAX_IMMEDIATES); for( i = 0; i < size; ++i ) bld.immediates[num_immediates][i] = - lp_build_const_scalar(type, parse.FullToken.FullImmediate.u[i].Float); + lp_build_const_vec(type, parse.FullToken.FullImmediate.u[i].Float); for( i = size; i < 4; ++i ) bld.immediates[num_immediates][i] = bld.base.undef; num_immediates++; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_type.h b/src/gallium/auxiliary/gallivm/lp_bld_type.h index 5b351476ac..cd59d2faa6 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_type.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_type.h @@ -37,9 +37,9 @@ #define LP_BLD_TYPE_H -#include "os/os_llvm.h" +#include "pipe/p_compiler.h" +#include "gallivm/lp_bld.h" -#include <pipe/p_compiler.h> /** diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index 86f9266c95..894f995e68 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -227,6 +227,8 @@ pb_cache_is_buffer_compat(struct pb_cache_buffer *buf, pb_size size, const struct pb_desc *desc) { + void *map; + if(buf->base.base.size < size) return FALSE; @@ -239,6 +241,13 @@ pb_cache_is_buffer_compat(struct pb_cache_buffer *buf, if(!pb_check_usage(desc->usage, buf->base.base.usage)) return FALSE; + + map = pb_map(buf->buffer, PIPE_TRANSFER_DONTBLOCK); + if (!map) { + return FALSE; + } + + pb_unmap(buf->buffer); return TRUE; } diff --git a/src/gallium/auxiliary/piperesource/rm.h b/src/gallium/auxiliary/piperesource/rm.h deleted file mode 100644 index 71d936db73..0000000000 --- a/src/gallium/auxiliary/piperesource/rm.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef RM_PRIVATE_H -#define RM_PRIVATE_H - -#include "rm_public.h" - -struct rm_screen { - struct pipe_screen *screen; - struct rm_screen_callbacks cb; - unsigned default_buffer_alignment; -}; - -struct rm_context { - struct pipe_context *pipe; - struct rm_screen *rm_screen; /* ? */ - struct rm_context_callbacks cb; -}; - -#endif diff --git a/src/gallium/auxiliary/piperesource/rm_context.c b/src/gallium/auxiliary/piperesource/rm_context.c deleted file mode 100644 index 6ecbcb65cb..0000000000 --- a/src/gallium/auxiliary/piperesource/rm_context.c +++ /dev/null @@ -1,239 +0,0 @@ -#include "rm.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" - -struct rm_transfer { - struct pipe_transfer base; - struct pipe_tex_transfer *tex_transfer; - struct pipe_buffer *buffer; - unsigned buffer_usage; -}; - -static INLINE struct rm_transfer *rm_transfer( struct pipe_transfer *t ) -{ - return (struct rm_transfer *)t; -} - -struct pipe_transfer *rm_get_transfer(struct rm_context *rm_ctx, - struct pipe_resource *resource, - struct pipe_subresource sr, - enum pipe_transfer_usage usage, - const struct pipe_box *box) -{ - struct rm_transfer *transfer; - struct rm_resource *rmr = rm_resource(resource); - - transfer = CALLOC_STRUCT(rm_transfer); - if (transfer == NULL) - return NULL; - - transfer->base.resource = resource; - - if (rmr->texture && box->depth == 1) { - transfer->tex_transfer = rm_ctx->cb.get_tex_transfer(rm_ctx->pipe, - rmr->texture, - sr.face, - sr.level, - box->z, - usage, - box->x, - box->y, - box->width, - box->height); - } - else if (rmr->texture && box->depth > 1) { - /* TBD. Nobody is using this yet, hopefully can migrate drivers - * to new interfaces before I have to implement some sort of a - * workaround here. - */ - assert(0); - } - else { - transfer->buffer = rm_resource(resource)->buffer; - transfer->buffer_usage = buffer_usage(usage); - } - - assert(transfer->buffer || transfer->tex_transfer); - return &transfer->base; -} - -void rm_transfer_destroy(struct rm_context *rm_ctx, - struct pipe_transfer *transfer) -{ - struct rm_transfer *rmt = rm_transfer(transfer); - - if (rmt->tex_transfer) - rm_ctx->cb.transfer_destroy( rm_ctx->pipe, rmt->tex_transfer ); - - FREE(rmt); -} - -void *rm_transfer_map( struct rm_context *rm_ctx, - struct pipe_transfer *transfer ) -{ - struct rm_transfer *rmt = rm_transfer(transfer); - - if (rmt->tex_transfer) { - return rm_ctx->cb.transfer_map( rm_ctx->pipe, - rmt->tex_transfer ); - } - else { - return rm_ctx->rm_screen->cb.buffer_map( rm_ctx->rm_screen->screen, - rmt->buffer, - rmt->buffer_usage ); - } -} - -/* If transfer was created with WRITE|FLUSH_EXPLICIT, only the - * regions specified with this call are guaranteed to be written to - * the resource. - */ -void rm_transfer_flush_region( struct rm_context *rm_ctx, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - struct rm_transfer *rmt = rm_transfer(transfer); - - if (rmt->tex_transfer) { - /* no such action */ - } - else if (rm_ctx->rm_screen->cb.buffer_flush_mapped_range) { - rm_ctx->rm_screen->cb.buffer_flush_mapped_range( rm_ctx->rm_screen->screen, - rmt->buffer, - box->x, - box->width); - } - else { - /* no such action */ - } -} - -void rm_transfer_unmap( struct rm_context *rm_ctx, - struct pipe_transfer *transfer ) -{ - struct rm_transfer *rmt = rm_transfer(transfer); - - if (rmt->tex_transfer) { - rm_ctx->cb.transfer_unmap( rm_ctx->pipe, - rmt->tex_transfer ); - } - else { - struct pipe_buffer *buffer = rmt->buffer; - - rm_ctx->rm_screen->cb.buffer_unmap( rm_ctx->rm_screen->screen, - buffer ); - } -} - - -/* One-shot transfer operation with data supplied in a user - * pointer. XXX: strides?? - */ -void rm_transfer_inline_write( struct rm_context *rm_ctx, - struct pipe_resource *resource, - struct pipe_subresource sr, - enum pipe_transfer_usage usage, - const struct pipe_box *box, - const void *data ) -{ - struct pipe_transfer *transfer = NULL; - char *map = NULL; - - transfer = rm_get_transfer(rm_ctx, - resource, - sr, - usage, - box ); - if (transfer == NULL) - goto out; - - map = rm_transfer_map(rm_ctx, transfer); - if (map == NULL) - goto out; - - assert(box->depth == 1); /* XXX: fix me */ - - util_copy_rect(map, - resource->format, - transfer->stride, /* bytes? */ - 0, 0, - box->width, - box->height, - data, - box->width, /* bytes? texels? */ - 0, 0); - -out: - if (map) - rm_transfer_unmap(rm_ctx, transfer); - - if (transfer) - rm_transfer_destroy(rm_ctx, transfer); -} - - - -/* One-shot read transfer operation with data returned in a user - * pointer. XXX: strides?? - */ -void rm_transfer_inline_read( struct rm_context *rm_ctx, - struct pipe_resource *resource, - struct pipe_subresource sr, - enum pipe_transfer_usage usage, - const struct pipe_box *box, - void *data ) -{ - struct pipe_transfer *transfer = NULL; - char *map = NULL; - - transfer = rm_get_transfer(rm_ctx, - resource, - sr, - usage, - box ); - if (transfer == NULL) - goto out; - - map = rm_transfer_map(rm_ctx, transfer); - if (map == NULL) - goto out; - - assert(box->depth == 1); /* XXX: fix me */ - - util_copy_rect(data, - resource->format, - transfer->stride, /* bytes? */ - 0, 0, - box->width, - box->height, - map, - box->width, /* bytes? texels? */ - 0, 0); - - -out: - if (map) - rm_transfer_unmap(rm_ctx, transfer); - - if (transfer) - rm_transfer_destroy(rm_ctx, transfer); -} - - -struct rm_context * -rm_context_create( struct pipe_context *pipe, - struct rm_screen *rm_screen, - struct rm_context_callbacks *cb) -{ - struct rm_context *rm_context; - - rm_context = CALLOC_STRUCT(rm_context); - if (rm_context == NULL) - return NULL; - - rm_context->cb = *cb; - rm_context->rm_screen = rm_screen; - rm_context->pipe = pipe; - - return rm_context; -} diff --git a/src/gallium/auxiliary/piperesource/rm_public.h b/src/gallium/auxiliary/piperesource/rm_public.h deleted file mode 100644 index 105bd2382a..0000000000 --- a/src/gallium/auxiliary/piperesource/rm_public.h +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef RM_PUBLIC_H -#define RM_PUBLIC_H - -#include "pipe/p_state.h" - -/* Here are the old pipe_buffer and pipe_texture structs, almost as - * they were. Old pre-resources driver code that creates and - * manipulates these structs can be used to implement the new - * pipe_resource behaviour using this adaptor module. - */ -struct pipe_buffer -{ - struct pipe_reference reference; - struct rm_screen *screen; /* Note! */ - unsigned size; - unsigned alignment; - unsigned usage; -}; - - -struct pipe_texture -{ - struct pipe_reference reference; - struct rm_screen *screen; /* Note! */ - enum pipe_texture_target target; - enum pipe_format format; - unsigned width0; - unsigned height0; - unsigned depth0; - unsigned last_level:8; - unsigned nr_samples:8; - unsigned tex_usage; /**< bitmask of PIPE_TEXTURE_USAGE_* */ -}; - -/* Have to give the legacy transfer struct a new name to avoid - * conflicts. - */ -struct pipe_tex_transfer -{ - unsigned x; /**< x offset from start of texture image */ - unsigned y; /**< y offset from start of texture image */ - unsigned width; /**< logical width in pixels */ - unsigned height; /**< logical height in pixels */ - unsigned stride; /**< stride in bytes between rows of blocks */ - enum pipe_transfer_usage usage; /**< PIPE_TRANSFER_* */ - - struct pipe_texture *texture; /**< texture to transfer to/from */ - unsigned face; - unsigned level; - unsigned zslice; -}; - - -struct rm_resource { - struct pipe_resource base; - struct pipe_buffer *buffer; - struct pipe_texture *texture; -}; - -static INLINE struct rm_resource * -rm_resource( struct pipe_resource *resource ) -{ - return (struct rm_resource *)resource; -} - -static INLINE struct pipe_texture * -rm_texture( struct pipe_resource *resource ) -{ - return rm_resource(resource)->texture; -} - -static INLINE struct pipe_buffer * -rm_buffer( struct pipe_resource *resource ) -{ - return rm_resource(resource)->buffer; -} - - -struct rm_screen_callbacks { - struct pipe_texture * (*texture_create)(struct pipe_screen *, - const struct pipe_texture *templat); - - struct pipe_texture * (*texture_from_handle)(struct pipe_screen *, - const struct pipe_texture *templat, - struct winsys_handle *handle); - - boolean (*texture_get_handle)(struct pipe_screen *, - struct pipe_texture *tex, - struct winsys_handle *handle); - - - void (*texture_destroy)(struct pipe_screen *, - struct pipe_texture *pt); - - struct pipe_surface *(*get_tex_surface)(struct pipe_screen *, - struct pipe_texture *texture, - unsigned face, unsigned level, - unsigned zslice, - unsigned usage ); - - void (*tex_surface_destroy)(struct pipe_surface *); - - - /* Buffer functions: - */ - struct pipe_buffer *(*buffer_create)( struct pipe_screen *screen, - unsigned alignment, - unsigned usage, - unsigned size ); - - struct pipe_buffer *(*user_buffer_create)(struct pipe_screen *screen, - void *ptr, - unsigned bytes); - - void *(*buffer_map)( struct pipe_screen *screen, - struct pipe_buffer *buf, - unsigned usage ); - - void *(*buffer_map_range)( struct pipe_screen *screen, - struct pipe_buffer *buf, - unsigned offset, - unsigned length, - unsigned usage); - - void (*buffer_flush_mapped_range)( struct pipe_screen *screen, - struct pipe_buffer *buf, - unsigned offset, - unsigned length); - - void (*buffer_unmap)( struct pipe_screen *screen, - struct pipe_buffer *buf ); - - void (*buffer_destroy)( struct pipe_screen *screen, - struct pipe_buffer *buf ); -}; - - -struct rm_context_callbacks { - unsigned int (*is_texture_referenced)(struct pipe_context *pipe, - struct pipe_texture *texture, - unsigned face, unsigned level); - - unsigned int (*is_buffer_referenced)(struct pipe_context *pipe, - struct pipe_buffer *buf); - - struct pipe_tex_transfer *(*get_tex_transfer)(struct pipe_context *, - struct pipe_texture *texture, - unsigned face, unsigned level, - unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, - unsigned w, unsigned h); - - void (*transfer_destroy)(struct pipe_context *, - struct pipe_tex_transfer *); - - void *(*transfer_map)( struct pipe_context *, - struct pipe_tex_transfer *transfer ); - - void (*transfer_unmap)( struct pipe_context *, - struct pipe_tex_transfer *transfer ); -}; - - - -struct rm_screen * -rm_screen_create( struct pipe_screen *screen, - struct rm_screen_callbacks *callbacks, - unsigned default_buffer_alignment); - -struct rm_context * -rm_context_create( struct pipe_context *context, - struct rm_screen *rm_screen, - struct rm_context_callbacks *callbacks ); - - -/* This module implements the following new-style driver functions in - * terms of the old ones that are still present in most pipe drivers. - */ -struct pipe_resource *rm_resource_create(struct rm_screen *, - const struct pipe_resource *template); - -struct pipe_resource *rm_resource_from_handle(struct rm_screen *, - const struct pipe_resource *template, - struct winsys_handle *handle); - -boolean rm_resource_get_handle(struct rm_screen *, - struct pipe_resource *tex, - struct winsys_handle *handle); - - -void rm_resource_destroy(struct rm_screen *, - struct pipe_resource *pt); - -struct pipe_transfer *rm_get_transfer(struct rm_context *, - struct pipe_resource *resource, - struct pipe_subresource, - enum pipe_transfer_usage, - const struct pipe_box *); - -void rm_transfer_destroy(struct rm_context *, - struct pipe_transfer *); - -void *rm_transfer_map( struct rm_context *, - struct pipe_transfer *transfer ); - -void rm_transfer_flush_region( struct rm_context *, - struct pipe_transfer *transfer, - const struct pipe_box *); - -void rm_transfer_unmap( struct rm_context *, - struct pipe_transfer *transfer ); - - -void rm_transfer_inline_write( struct rm_context *, - struct pipe_resource *, - struct pipe_subresource, - enum pipe_transfer_usage, - const struct pipe_box *, - const void *data ); - -void rm_transfer_inline_read( struct rm_context *, - struct pipe_resource *, - struct pipe_subresource, - enum pipe_transfer_usage, - const struct pipe_box *, - void *data ); - -#endif diff --git a/src/gallium/auxiliary/piperesource/rm_screen.c b/src/gallium/auxiliary/piperesource/rm_screen.c deleted file mode 100644 index 7169fc5567..0000000000 --- a/src/gallium/auxiliary/piperesource/rm_screen.c +++ /dev/null @@ -1,130 +0,0 @@ - -#include "rm.h" -#include "util/u_inlines.h" -#include "util/u_memory.h" - -static void translate_template( const struct pipe_resource *template, - struct pipe_texture *tex ) -{ - tex->tex_usage = template->tex_usage; -} - -/* This module implements the following new-style driver functions in - * terms of the old ones that are still present in most pipe drivers. - */ -struct pipe_resource *rm_resource_create(struct rm_screen *rm_screen, - const struct pipe_resource *template) -{ - struct rm_resource *resource; - - resource = CALLOC_STRUCT(rm_resource); - if (resource == NULL) - goto fail; - - pipe_reference_init(&resource->base.reference, 1); - resource->base.screen = rm_screen->screen; - - if (template->target == PIPE_BUFFER) { - struct pipe_texture tex_template; - - translate_template(template, &tex_template); - - resource->texture = rm_screen->cb.texture_create(rm_screen->screen, - &tex_template); - if (resource->texture == NULL) - goto fail; - } - else { - resource->buffer = rm_screen->cb.buffer_create(rm_screen->screen, - rm_screen->default_buffer_alignment, - template->usage, - template->width0); - if (resource->buffer == NULL) - goto fail; - } - - return &resource->base; - -fail: - FREE(resource); - return NULL; -} - -struct pipe_resource *rm_resource_from_handle(struct rm_screen *rm_screen, - const struct pipe_resource *template, - struct winsys_handle *handle) -{ - struct rm_resource *resource; - struct pipe_texture tex_template; - - assert(template->target != PIPE_BUFFER); - - resource = CALLOC_STRUCT(rm_resource); - if (resource == NULL) - goto fail; - - translate_template(template, &tex_template); - - pipe_reference_init(&resource->base.reference, 1); - resource->base.screen = rm_screen->screen; - resource->texture = rm_screen->cb.texture_from_handle(rm_screen->screen, - &tex_template, - handle); - if (resource->texture == NULL) - goto fail; - - return &resource->base; - -fail: - FREE(resource); - return NULL; -} - -boolean rm_resource_get_handle(struct rm_screen *rm_screen, - struct pipe_resource *resource, - struct winsys_handle *handle) -{ - struct rm_resource *rmr = rm_resource(resource); - assert(rmr->texture); - return rm_screen->cb.texture_get_handle(rm_screen->screen, - rmr->texture, - handle); -} - - -void rm_resource_destroy(struct rm_screen *rm_screen, - struct pipe_resource *resource) -{ - struct rm_resource *rmr = rm_resource(resource); - - if (rmr->texture) { - rm_screen->cb.texture_destroy(rm_screen->screen, - rmr->texture); - } - - if (rmr->buffer) { - rm_screen->cb.buffer_destroy(rm_screen->screen, - rmr->buffer); - } - - FREE(rmr); -} - - -struct rm_screen * -rm_screen_create( struct pipe_screen *screen, - struct rm_screen_callbacks *cb, - unsigned default_buffer_alignment) -{ - struct rm_screen *rm_screen; - - rm_screen = CALLOC_STRUCT(rm_screen); - if (rm_screen == NULL) - return NULL; - - rm_screen->cb = *cb; - rm_screen->screen = screen; - rm_screen->default_buffer_alignment = default_buffer_alignment; - - return rm_screen; -} diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index da27637de1..f5929ed87e 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -45,6 +45,7 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "util/u_simple_shaders.h" #include "util/u_surface.h" #include "util/u_rect.h" @@ -280,6 +281,7 @@ regions_overlap(int srcX0, int srcY0, void util_blit_pixels_writemask(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -290,7 +292,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_resource *tex = NULL; + struct pipe_sampler_view *sampler_view = NULL; struct pipe_framebuffer_state fb; const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); @@ -345,6 +347,8 @@ util_blit_pixels_writemask(struct blit_state *ctx, src->texture->last_level != 0) { struct pipe_resource texTemp; + struct pipe_resource *tex; + struct pipe_sampler_view sv_templ; struct pipe_surface *texSurf; const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); @@ -376,6 +380,14 @@ util_blit_pixels_writemask(struct blit_state *ctx, if (!tex) return; + u_sampler_view_default_template(&sv_templ, tex, tex->format); + + sampler_view = ctx->pipe->create_sampler_view(ctx->pipe, tex, &sv_templ); + if (!sampler_view) { + pipe_resource_reference(&tex, NULL); + return; + } + texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, PIPE_BUFFER_USAGE_BLIT_DESTINATION); @@ -399,22 +411,25 @@ util_blit_pixels_writemask(struct blit_state *ctx, s1 = 1.0f; t0 = 0.0f; t1 = 1.0f; + + pipe_resource_reference(&tex, NULL); } else { - pipe_resource_reference(&tex, src->texture); - s0 = srcX0 / (float)tex->width0; - s1 = srcX1 / (float)tex->width0; - t0 = srcY0 / (float)tex->height0; - t1 = srcY1 / (float)tex->height0; + pipe_sampler_view_reference(&sampler_view, src_sampler_view); + s0 = srcX0 / (float)src->texture->width0; + s1 = srcX1 / (float)src->texture->width0; + t0 = srcY0 / (float)src->texture->height0; + t1 = srcY1 / (float)src->texture->height0; } + /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); @@ -447,7 +462,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_set_viewport(ctx->cso, &ctx->viewport); /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &tex); + cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view); if (ctx->fs[writemask] == NULL) ctx->fs[writemask] = @@ -486,7 +501,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_viewport(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); @@ -494,13 +509,14 @@ util_blit_pixels_writemask(struct blit_state *ctx, cso_restore_clip(ctx->cso); cso_restore_vertex_elements(ctx->cso); - pipe_resource_reference(&tex, NULL); + pipe_sampler_view_reference(&sampler_view, NULL); } void util_blit_pixels(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -508,7 +524,7 @@ util_blit_pixels(struct blit_state *ctx, int dstX1, int dstY1, float z, uint filter ) { - util_blit_pixels_writemask( ctx, src, + util_blit_pixels_writemask( ctx, src, src_sampler_view, srcX0, srcY0, srcX1, srcY1, dst, @@ -539,21 +555,23 @@ void util_blit_flush( struct blit_state *ctx ) */ void util_blit_pixels_tex(struct blit_state *ctx, - struct pipe_resource *tex, - int srcX0, int srcY0, - int srcX1, int srcY1, - struct pipe_surface *dst, - int dstX0, int dstY0, - int dstX1, int dstY1, - float z, uint filter) + struct pipe_sampler_view *src_sampler_view, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter) { struct pipe_framebuffer_state fb; float s0, t0, s1, t1; unsigned offset; + struct pipe_resource *tex = src_sampler_view->texture; assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); + assert(tex); assert(tex->width0 != 0); assert(tex->height0 != 0); @@ -572,7 +590,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -604,7 +622,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_set_viewport(ctx->cso, &ctx->viewport); /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &tex); + cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view); /* shaders */ cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]); @@ -638,7 +656,7 @@ util_blit_pixels_tex(struct blit_state *ctx, cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h index ad35ac60ce..464ff9aace 100644 --- a/src/gallium/auxiliary/util/u_blit.h +++ b/src/gallium/auxiliary/util/u_blit.h @@ -53,6 +53,7 @@ util_destroy_blit(struct blit_state *ctx); extern void util_blit_pixels(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -63,6 +64,7 @@ util_blit_pixels(struct blit_state *ctx, void util_blit_pixels_writemask(struct blit_state *ctx, struct pipe_surface *src, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, @@ -73,7 +75,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, extern void util_blit_pixels_tex(struct blit_state *ctx, - struct pipe_resource *tex, + struct pipe_sampler_view *src_sampler_view, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, diff --git a/src/gallium/auxiliary/util/u_box.h b/src/gallium/auxiliary/util/u_box.h new file mode 100644 index 0000000000..fe694a9899 --- /dev/null +++ b/src/gallium/auxiliary/util/u_box.h @@ -0,0 +1,73 @@ +#ifndef UTIL_BOX_INLINES_H +#define UTIL_BOX_INLINES_H + +#include "pipe/p_state.h" + +static INLINE +void u_box_1d( unsigned x, + unsigned w, + struct pipe_box *box ) +{ + box->x = x; + box->y = 0; + box->z = 0; + box->width = w; + box->height = 1; + box->depth = 1; +} + +static INLINE +void u_box_2d( unsigned x, + unsigned y, + unsigned w, + unsigned h, + struct pipe_box *box ) +{ + box->x = x; + box->y = y; + box->z = 0; + box->width = w; + box->height = h; + box->depth = 1; +} + +static INLINE +void u_box_orgin_2d( unsigned w, + unsigned h, + struct pipe_box *box ) +{ + box->x = 0; + box->y = 0; + box->z = 0; + box->width = w; + box->height = h; + box->depth = 1; +} + +static INLINE +void u_box_2d_zslice( unsigned x, + unsigned y, + unsigned z, + unsigned w, + unsigned h, + struct pipe_box *box ) +{ + box->x = x; + box->y = y; + box->z = z; + box->width = w; + box->height = h; + box->depth = 1; +} + +static INLINE +struct pipe_subresource u_subresource( unsigned face, + unsigned level ) +{ + struct pipe_subresource subresource; + subresource.face = face; + subresource.level = level; + return subresource; +} + +#endif diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c index 08557d5553..9e1359f9a8 100644 --- a/src/gallium/auxiliary/util/u_dump_state.c +++ b/src/gallium/auxiliary/util/u_dump_state.c @@ -262,7 +262,7 @@ util_dump_template(struct os_stream *stream, const struct pipe_resource *templat return; } - util_dump_struct_begin(stream, "pipe_texture"); + util_dump_struct_begin(stream, "pipe_resource"); util_dump_member(stream, int, templat, target); util_dump_member(stream, format, templat, format); diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv index 96a0fa6550..11243e7349 100644 --- a/src/gallium/auxiliary/util/u_format.csv +++ b/src/gallium/auxiliary/util/u_format.csv @@ -63,6 +63,7 @@ PIPE_FORMAT_A8R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , yzwx, r PIPE_FORMAT_X8R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , yzw1, rgb PIPE_FORMAT_A8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzyx, rgb PIPE_FORMAT_X8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzy1, rgb +PIPE_FORMAT_B5G5R5X1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyx1, rgb PIPE_FORMAT_B5G5R5A1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb PIPE_FORMAT_B4G4R4A4_UNORM , plain, 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb PIPE_FORMAT_B5G6R5_UNORM , plain, 1, 1, un5 , un6 , un5 , , zyx1, rgb diff --git a/src/gallium/auxiliary/util/u_format_tests.c b/src/gallium/auxiliary/util/u_format_tests.c index 182a474044..9d6debcd8c 100644 --- a/src/gallium/auxiliary/util/u_format_tests.c +++ b/src/gallium/auxiliary/util/u_format_tests.c @@ -120,6 +120,13 @@ util_format_test_cases[] = * 16-bit rendertarget formats */ + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x7c00), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x8000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}}, {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}}, diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index 5673ff5218..ae75ef4f32 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -938,6 +938,7 @@ format_to_type_comps(enum pipe_format pformat, *datatype = DTYPE_UBYTE; *comps = 4; return; + case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B5G5R5A1_UNORM: *datatype = DTYPE_USHORT_1_5_5_5_REV; *comps = 4; @@ -1460,7 +1461,7 @@ void util_gen_mipmap_flush( struct gen_mipmap_state *ctx ) * Generate mipmap images. It's assumed all needed texture memory is * already allocated. * - * \param pt the texture to generate mipmap levels for + * \param psv the sampler view to the texture to generate mipmap levels for * \param face which cube face to generate mipmaps for (0 for non-cube maps) * \param baseLevel the first mipmap level to use as a src * \param lastLevel the last mipmap level to generate @@ -1469,12 +1470,13 @@ void util_gen_mipmap_flush( struct gen_mipmap_state *ctx ) */ void util_gen_mipmap(struct gen_mipmap_state *ctx, - struct pipe_resource *pt, + struct pipe_sampler_view *psv, uint face, uint baseLevel, uint lastLevel, uint filter) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_framebuffer_state fb; + struct pipe_resource *pt = psv->texture; void *fs = (pt->target == PIPE_TEXTURE_CUBE) ? ctx->fsCube : ctx->fs2d; uint dstLevel; uint zslice = 0; @@ -1492,7 +1494,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, filter == PIPE_TEX_FILTER_NEAREST); /* check if we can render in the texture's format */ - if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D, + if (!screen->is_format_supported(screen, psv->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel); return; @@ -1503,7 +1505,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -1572,7 +1574,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_single_sampler(ctx->cso, 0, &ctx->sampler); cso_single_sampler_done(ctx->cso); - cso_set_sampler_textures(ctx->cso, 1, &pt); + cso_set_fragment_sampler_views(ctx->cso, 1, &psv); /* quad coords in clip coords */ offset = set_vertex_data(ctx, @@ -1597,7 +1599,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h index 6783325ef2..a7502b9982 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.h +++ b/src/gallium/auxiliary/util/u_gen_mipmap.h @@ -59,7 +59,7 @@ util_gen_mipmap_flush( struct gen_mipmap_state *ctx ); extern void util_gen_mipmap(struct gen_mipmap_state *ctx, - struct pipe_resource *pt, + struct pipe_sampler_view *psv, uint face, uint baseLevel, uint lastLevel, uint filter); diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h index 50f1b1670b..c5fd7a6783 100644 --- a/src/gallium/auxiliary/util/u_pack_color.h +++ b/src/gallium/auxiliary/util/u_pack_color.h @@ -92,6 +92,11 @@ util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); } return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; case PIPE_FORMAT_B5G5R5A1_UNORM: { uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); @@ -216,6 +221,15 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc, *a = (ubyte) 0xff; } return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; case PIPE_FORMAT_B5G5R5A1_UNORM: { ushort p = uc->us; @@ -361,6 +375,11 @@ util_pack_color(const float rgba[4], enum pipe_format format, union util_color * uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); } return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; case PIPE_FORMAT_B5G5R5A1_UNORM: { uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); diff --git a/src/gallium/auxiliary/util/u_resource.c b/src/gallium/auxiliary/util/u_resource.c index e0fa2dc808..c37a68bc42 100644 --- a/src/gallium/auxiliary/util/u_resource.c +++ b/src/gallium/auxiliary/util/u_resource.c @@ -75,7 +75,7 @@ void u_transfer_unmap_vtbl( struct pipe_context *pipe, void u_transfer_inline_write_vtbl( struct pipe_context *pipe, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, diff --git a/src/gallium/auxiliary/util/u_simple_screen.h b/src/gallium/auxiliary/util/u_simple_screen.h new file mode 100644 index 0000000000..e189724f63 --- /dev/null +++ b/src/gallium/auxiliary/util/u_simple_screen.h @@ -0,0 +1,184 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 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 U_SIMPLE_SCREEN_H +#define U_SIMPLE_SCREEN_H + +#include "pipe/p_format.h" + +struct pipe_screen; +struct pipe_fence_handle; +struct pipe_surface; +struct pipe_resource; + +/** + * Gallium3D drivers are (meant to be!) independent of both GL and the + * window system. The window system provides a buffer manager and a + * set of additional hooks for things like command buffer submission, + * etc. + * + * There clearly has to be some agreement between the window system + * driver and the hardware driver about the format of command buffers, + * etc. + */ +struct pipe_winsys +{ + void (*destroy)( struct pipe_winsys *ws ); + + /** Returns name of this winsys interface */ + const char *(*get_name)( struct pipe_winsys *ws ); + + /** + * Do any special operations to ensure buffer size is correct + */ + void (*update_buffer)( struct pipe_winsys *ws, + void *context_private ); + /** + * Do any special operations to ensure frontbuffer contents are + * displayed, eg copy fake frontbuffer. + */ + void (*flush_frontbuffer)( struct pipe_winsys *ws, + struct pipe_surface *surf, + void *context_private ); + + + /** + * Buffer management. Buffer attributes are mostly fixed over its lifetime. + * + * Remember that gallium gets to choose the interface it needs, and the + * window systems must then implement that interface (rather than the + * other way around...). + * + * usage is a bitmask of PIPE_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This + * usage argument is only an optimization hint, not a guarantee, therefore + * proper behavior must be observed in all circumstances. + * + * alignment indicates the client's alignment requirements, eg for + * SSE instructions. + */ + struct pipe_resource *(*buffer_create)( struct pipe_winsys *ws, + unsigned alignment, + unsigned usage, + unsigned size ); + + /** + * Create a buffer that wraps user-space data. + * + * Effectively this schedules a delayed call to buffer_create + * followed by an upload of the data at *some point in the future*, + * or perhaps never. Basically the allocate/upload is delayed + * until the buffer is actually passed to hardware. + * + * The intention is to provide a quick way to turn regular data + * into a buffer, and secondly to avoid a copy operation if that + * data subsequently turns out to be only accessed by the CPU. + * + * Common example is OpenGL vertex buffers that are subsequently + * processed either by software TNL in the driver or by passing to + * hardware. + * + * XXX: What happens if the delayed call to buffer_create() fails? + * + * Note that ptr may be accessed at any time upto the time when the + * buffer is destroyed, so the data must not be freed before then. + */ + struct pipe_resource *(*user_buffer_create)(struct pipe_winsys *ws, + void *ptr, + unsigned bytes); + + /** + * Allocate storage for a display target surface. + * + * Often surfaces which are meant to be blitted to the front screen (i.e., + * display targets) must be allocated with special characteristics, memory + * pools, or obtained directly from the windowing system. + * + * This callback is invoked by the pipe_screenwhen creating a texture marked + * with the PIPE_TEXTURE_USAGE_DISPLAY_TARGET flag to get the underlying + * buffer storage. + */ + struct pipe_resource *(*surface_buffer_create)(struct pipe_winsys *ws, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned tex_usage, + unsigned *stride); + + + /** + * Map the entire data store of a buffer object into the client's address. + * flags is bitmask of PIPE_BUFFER_USAGE_CPU_READ/WRITE flags. + */ + void *(*buffer_map)( struct pipe_winsys *ws, + struct pipe_resource *buf, + unsigned usage ); + + void (*buffer_unmap)( struct pipe_winsys *ws, + struct pipe_resource *buf ); + + void (*buffer_destroy)( struct pipe_resource *buf ); + + + /** Set ptr = fence, with reference counting */ + void (*fence_reference)( struct pipe_winsys *ws, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence ); + + /** + * Checks whether the fence has been signalled. + * \param flags driver-specific meaning + * \return zero on success. + */ + int (*fence_signalled)( struct pipe_winsys *ws, + struct pipe_fence_handle *fence, + unsigned flag ); + + /** + * Wait for the fence to finish. + * \param flags driver-specific meaning + * \return zero on success. + */ + int (*fence_finish)( struct pipe_winsys *ws, + struct pipe_fence_handle *fence, + unsigned flag ); + +}; + +/** + * The following function initializes a simple passthrough screen. + * + * All the relevant screen function pointers will forwarded to the + * winsys. + */ +void u_simple_screen_init(struct pipe_screen *screen); + +/** + * Returns the name of the winsys associated with this screen. + */ +const char* u_simple_screen_winsys_name(struct pipe_screen *screen); + +#endif diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index 26bb4771b0..61d92c954d 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -295,6 +295,55 @@ r8g8b8a8_put_tile_rgba(unsigned *dst, } +/*** PIPE_FORMAT_B5G5R5X1_UNORM ***/ + +static void +x1r5g5b5_get_tile_rgba(const ushort *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + const ushort pixel = *src++; + pRow[0] = ((pixel >> 10) & 0x1f) * (1.0f / 31.0f); + pRow[1] = ((pixel >> 5) & 0x1f) * (1.0f / 31.0f); + pRow[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f); + pRow[3] = 1.0f; + } + p += dst_stride; + } +} + + +static void +x1r5g5b5_put_tile_rgba(ushort *dst, + unsigned w, unsigned h, + const float *p, + unsigned src_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + const float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + unsigned r, g, b; + r = float_to_ubyte(pRow[0]); + g = float_to_ubyte(pRow[1]); + b = float_to_ubyte(pRow[2]); + r = r >> 3; /* 5 bits */ + g = g >> 3; /* 5 bits */ + b = b >> 3; /* 5 bits */ + *dst++ = (1 << 15) | (r << 10) | (g << 5) | b; + } + p += src_stride; + } +} + + /*** PIPE_FORMAT_B5G5R5A1_UNORM ***/ static void @@ -1174,6 +1223,9 @@ pipe_tile_raw_to_rgba(enum pipe_format format, case PIPE_FORMAT_A8B8G8R8_UNORM: r8g8b8a8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); break; + case PIPE_FORMAT_B5G5R5X1_UNORM: + x1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); + break; case PIPE_FORMAT_B5G5R5A1_UNORM: a1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); break; @@ -1368,6 +1420,9 @@ pipe_put_tile_rgba(struct pipe_context *pipe, case PIPE_FORMAT_A8B8G8R8_UNORM: r8g8b8a8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride); break; + case PIPE_FORMAT_B5G5R5X1_UNORM: + x1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride); + break; case PIPE_FORMAT_B5G5R5A1_UNORM: a1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride); break; diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c index 24a7873b34..02e714f51b 100644 --- a/src/gallium/auxiliary/util/u_transfer.c +++ b/src/gallium/auxiliary/util/u_transfer.c @@ -10,7 +10,7 @@ void u_default_transfer_inline_write( struct pipe_context *pipe, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, @@ -79,7 +79,7 @@ unsigned u_default_is_resource_referenced( struct pipe_context *pipe, struct pipe_transfer * u_default_get_transfer(struct pipe_context *context, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box) { struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer); diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h index 4d67b85a25..eb07945d15 100644 --- a/src/gallium/auxiliary/util/u_transfer.h +++ b/src/gallium/auxiliary/util/u_transfer.h @@ -16,7 +16,7 @@ boolean u_default_resource_get_handle(struct pipe_screen *screen, void u_default_transfer_inline_write( struct pipe_context *pipe, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, @@ -33,7 +33,7 @@ unsigned u_default_is_resource_referenced( struct pipe_context *pipe, struct pipe_transfer * u_default_get_transfer(struct pipe_context *context, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box); void u_default_transfer_unmap( struct pipe_context *pipe, @@ -63,7 +63,7 @@ struct u_resource_vtbl { struct pipe_transfer *(*get_transfer)(struct pipe_context *, struct pipe_resource *resource, struct pipe_subresource, - enum pipe_transfer_usage, + unsigned usage, const struct pipe_box *); void (*transfer_destroy)(struct pipe_context *, @@ -82,7 +82,7 @@ struct u_resource_vtbl { void (*transfer_inline_write)( struct pipe_context *pipe, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, @@ -110,7 +110,7 @@ unsigned u_is_resource_referenced_vtbl( struct pipe_context *pipe, struct pipe_transfer *u_get_transfer_vtbl(struct pipe_context *context, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box); void u_transfer_destroy_vtbl(struct pipe_context *pipe, @@ -129,7 +129,7 @@ void u_transfer_unmap_vtbl( struct pipe_context *rm_ctx, void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst index ef3e463931..2b0941010b 100644 --- a/src/gallium/docs/source/context.rst +++ b/src/gallium/docs/source/context.rst @@ -41,23 +41,6 @@ buffers, surfaces) are bound to the driver. * ``set_framebuffer_state`` -* ``set_fragment_sampler_views`` binds an array of sampler views to - fragment shader stage. Every binding point acquires a reference - to a respective sampler view and releases a reference to the previous - sampler view. - -* ``set_vertex_sampler_views`` binds an array of sampler views to vertex - shader stage. Every binding point acquires a reference to a respective - sampler view and releases a reference to the previous sampler view. - -* ``create_sampler_view`` creates a new sampler view. texture is associated - with the sampler view which results in sampler view holding a reference - to the texture. Format specified in template must be compatible - with texture format. - -* ``sampler_view_destroy`` destroys a sampler view and releases its reference - to associated texture. - * ``set_vertex_buffers`` @@ -67,6 +50,7 @@ Non-CSO State These pieces of state are too small, variable, and/or trivial to have CSO objects. They all follow simple, one-method binding calls, e.g. ``set_blend_color``. + * ``set_stencil_ref`` sets the stencil front and back reference values which are used as comparison values in stencil test. * ``set_blend_color`` @@ -79,6 +63,41 @@ objects. They all follow simple, one-method binding calls, e.g. * ``set_viewport_state`` +Sampler Views +^^^^^^^^^^^^^ + +These are the means to bind textures to shader stages. To create one, specify +its format, swizzle and LOD range in sampler view template. + +If texture format is different than template format, it is said the texture +is being cast to another format. Casting can be done only between compatible +formats, that is formats that have matching component order and sizes. + +Swizzle fields specify they way in which fetched texel components are placed +in the result register. For example, ``swizzle_r`` specifies what is going to be +placed in first component of result register. + +The ``first_level`` and ``last_level`` fields of sampler view template specify +the LOD range the texture is going to be constrained to. + +* ``set_fragment_sampler_views`` binds an array of sampler views to + fragment shader stage. Every binding point acquires a reference + to a respective sampler view and releases a reference to the previous + sampler view. + +* ``set_vertex_sampler_views`` binds an array of sampler views to vertex + shader stage. Every binding point acquires a reference to a respective + sampler view and releases a reference to the previous sampler view. + +* ``create_sampler_view`` creates a new sampler view. ``texture`` is associated + with the sampler view which results in sampler view holding a reference + to the texture. Format specified in template must be compatible + with texture format. + +* ``sampler_view_destroy`` destroys a sampler view and releases its reference + to associated texture. + + Clearing ^^^^^^^^ diff --git a/src/gallium/docs/source/cso/velems.rst b/src/gallium/docs/source/cso/velems.rst index 8e758fae10..92cde014fb 100644 --- a/src/gallium/docs/source/cso/velems.rst +++ b/src/gallium/docs/source/cso/velems.rst @@ -1,4 +1,4 @@ -.. _vertex,elements +.. _vertexelements: Vertex Elements =============== diff --git a/src/gallium/drivers/cell/ppu/Makefile b/src/gallium/drivers/cell/ppu/Makefile index 8769b826b5..c92f8e5cba 100644 --- a/src/gallium/drivers/cell/ppu/Makefile +++ b/src/gallium/drivers/cell/ppu/Makefile @@ -21,7 +21,6 @@ SPU_CODE_MODULE = ../spu/g3d_spu.a SOURCES = \ cell_batch.c \ - cell_buffer.c \ cell_clear.c \ cell_context.c \ cell_draw_arrays.c \ diff --git a/src/gallium/drivers/cell/ppu/cell_buffer.c b/src/gallium/drivers/cell/ppu/cell_buffer.c deleted file mode 100644 index f56a28d62e..0000000000 --- a/src/gallium/drivers/cell/ppu/cell_buffer.c +++ /dev/null @@ -1,118 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * 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 VMWARE 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 "util/u_inlines.h" -#include "util/u_memory.h" -#include "util/u_math.h" - -#include "cell_screen.h" -#include "cell_buffer.h" - - -static void * -cell_buffer_map(struct pipe_screen *screen, - struct pipe_buffer *buf, - unsigned flags) -{ - struct cell_buffer *cell_buf = cell_buffer(buf); - return cell_buf->data; -} - - -static void -cell_buffer_unmap(struct pipe_screen *screen, - struct pipe_buffer *buf) -{ -} - - -static void -cell_buffer_destroy(struct pipe_buffer *buf) -{ - struct cell_buffer *sbuf = cell_buffer(buf); - - if (!sbuf->userBuffer) - align_free(sbuf->data); - - FREE(sbuf); -} - - -static struct pipe_buffer * -cell_buffer_create(struct pipe_screen *screen, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct cell_buffer *buffer = CALLOC_STRUCT(cell_buffer); - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.screen = screen; - buffer->base.alignment = MAX2(alignment, 16); - buffer->base.usage = usage; - buffer->base.size = size; - - buffer->data = align_malloc(size, alignment); - - return &buffer->base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -cell_user_buffer_create(struct pipe_screen *screen, - void *ptr, - unsigned bytes) -{ - struct cell_buffer *buffer; - - buffer = CALLOC_STRUCT(cell_buffer); - if(!buffer) - return NULL; - - pipe_reference_init(&buffer->base.reference, 1); - buffer->base.screen = screen; - buffer->base.size = bytes; - buffer->userBuffer = TRUE; - buffer->data = ptr; - - return &buffer->base; -} - - -void -cell_init_screen_buffer_funcs(struct pipe_screen *screen) -{ - screen->buffer_create = cell_buffer_create; - screen->user_buffer_create = cell_user_buffer_create; - screen->buffer_map = cell_buffer_map; - screen->buffer_unmap = cell_buffer_unmap; - screen->buffer_destroy = cell_buffer_destroy; -} diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index f6cb1fc9be..49cece58b8 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -99,8 +99,8 @@ static const struct debug_named_value cell_debug_flags[] = { }; static unsigned int -cell_is_texture_referenced( struct pipe_context *pipe, - struct pipe_texture *texture, +cell_is_resource_referenced( struct pipe_context *pipe, + struct pipe_resource *texture, unsigned face, unsigned level) { /** @@ -110,16 +110,6 @@ cell_is_texture_referenced( struct pipe_context *pipe, return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; } -static unsigned int -cell_is_buffer_referenced( struct pipe_context *pipe, - struct pipe_buffer *buf) -{ - /** - * FIXME: Optimize. - */ - - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; -} struct pipe_context * cell_create_context(struct pipe_screen *screen, @@ -144,8 +134,7 @@ cell_create_context(struct pipe_screen *screen, cell->pipe.clear = cell_clear; cell->pipe.flush = cell_flush; - cell->pipe.is_texture_referenced = cell_is_texture_referenced; - cell->pipe.is_buffer_referenced = cell_is_buffer_referenced; + cell->pipe.is_resource_referenced = cell_is_resource_referenced; #if 0 cell->pipe.begin_query = cell_begin_query; diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index 4d87f9a038..07b6eebc69 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -97,7 +97,7 @@ struct cell_velems_state { unsigned count; struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; -} +}; /** * Per-context state, subclass of pipe_context. @@ -122,11 +122,11 @@ struct cell_context struct pipe_blend_color blend_color; struct pipe_stencil_ref stencil_ref; struct pipe_clip_state clip; - struct pipe_buffer *constants[2]; + struct pipe_resource *constants[2]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; - struct cell_texture *texture[PIPE_MAX_SAMPLERS]; + struct cell_resource *texture[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; uint num_textures; struct pipe_viewport_state viewport; diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index 15d4e8338f..80e94a79df 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -39,7 +39,7 @@ #include "cell_draw_arrays.h" #include "cell_state.h" #include "cell_flush.h" -#include "cell_buffer.h" +#include "cell_texture.h" #include "draw/draw_context.h" @@ -57,7 +57,7 @@ */ static void cell_draw_range_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned min_index, unsigned max_index, @@ -78,12 +78,12 @@ cell_draw_range_elements(struct pipe_context *pipe, * Map vertex buffers */ for (i = 0; i < cell->num_vertex_buffers; i++) { - void *buf = cell_buffer(cell->vertex_buffer[i].buffer)->data; + void *buf = cell_resource(cell->vertex_buffer[i].buffer)->data; draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ if (indexBuffer) { - void *mapped_indexes = cell_buffer(indexBuffer)->data; + void *mapped_indexes = cell_resource(indexBuffer)->data; draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { @@ -116,7 +116,7 @@ cell_draw_range_elements(struct pipe_context *pipe, static void cell_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c index 035ef41b89..eac798e8cf 100644 --- a/src/gallium/drivers/cell/ppu/cell_fence.c +++ b/src/gallium/drivers/cell/ppu/cell_fence.c @@ -82,7 +82,7 @@ cell_fence_finish(const struct cell_context *cell, struct cell_buffer_node { - struct pipe_buffer *buffer; + struct pipe_resource *buffer; struct cell_buffer_node *next; }; @@ -90,12 +90,12 @@ struct cell_buffer_node static void cell_add_buffer_to_list(struct cell_context *cell, struct cell_buffer_list *list, - struct pipe_buffer *buffer) + struct pipe_resource *buffer) { struct cell_buffer_node *node = CALLOC_STRUCT(cell_buffer_node); /* create new list node which references the buffer, insert at head */ if (node) { - pipe_buffer_reference(&node->buffer, buffer); + pipe_resource_reference(&node->buffer, buffer); node->next = list->head; list->head = node; } @@ -129,7 +129,7 @@ cell_free_fenced_buffers(struct cell_context *cell, if (node->buffer->reference.count == 1) printf(" Delete!\n"); #endif - pipe_buffer_reference(&node->buffer, NULL); + pipe_resource_reference(&node->buffer, NULL); FREE(node); node = next; } @@ -150,7 +150,7 @@ cell_add_fenced_textures(struct cell_context *cell) uint i; for (i = 0; i < cell->num_textures; i++) { - struct cell_texture *ct = cell->texture[i]; + struct cell_resource *ct = cell->texture[i]; if (ct) { #if 0 printf("Adding texture %p buffer %p to list\n", diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index 059ce8597b..8c975c6ae2 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -271,12 +271,12 @@ cell_set_fragment_sampler_views(struct pipe_context *pipe, struct pipe_sampler_view *old_view = cell->fragment_sampler_views[i]; if (old_view != new_view) { - struct pipe_texture *new_tex = new_view ? new_view->texture : NULL; + struct pipe_resource *new_tex = new_view ? new_view->texture : NULL; pipe_sampler_view_reference(&cell->fragment_sampler_views[i], views[i]); - pipe_texture_reference((struct pipe_texture **) &cell->texture[i], - (struct pipe_texture *) new_tex); + pipe_resource_reference((struct pipe_resource **) &cell->texture[i], + (struct pipe_resource *) new_tex); changed |= (1 << i); } @@ -293,7 +293,7 @@ cell_set_fragment_sampler_views(struct pipe_context *pipe, static struct pipe_sampler_view * cell_create_sampler_view(struct pipe_context *pipe, - struct pipe_texture *texture, + struct pipe_resource *texture, const struct pipe_sampler_view *templ) { struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); @@ -302,7 +302,7 @@ cell_create_sampler_view(struct pipe_context *pipe, *view = *templ; view->reference.count = 1; view->texture = NULL; - pipe_texture_reference(&view->texture, texture); + pipe_resource_reference(&view->texture, texture); view->context = pipe; } @@ -314,7 +314,7 @@ static void cell_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { - pipe_texture_reference(&view->texture, NULL); + pipe_resource_reference(&view->texture, NULL); FREE(view); } @@ -333,7 +333,7 @@ cell_map_surfaces(struct cell_context *cell) for (i = 0; i < 1; i++) { struct pipe_surface *ps = cell->framebuffer.cbufs[i]; if (ps) { - struct cell_texture *ct = cell_texture(ps->texture); + struct cell_resource *ct = cell_resource(ps->texture); #if 0 cell->cbuf_map[i] = screen->buffer_map(screen, ct->buffer, @@ -348,7 +348,7 @@ cell_map_surfaces(struct cell_context *cell) { struct pipe_surface *ps = cell->framebuffer.zsbuf; if (ps) { - struct cell_texture *ct = cell_texture(ps->texture); + struct cell_resource *ct = cell_resource(ps->texture); #if 0 cell->zsbuf_map = screen->buffer_map(screen, ct->buffer, @@ -374,7 +374,7 @@ cell_unmap_surfaces(struct cell_context *cell) for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { struct pipe_surface *ps = cell->framebuffer.cbufs[i]; if (ps && cell->cbuf_map[i]) { - /*struct cell_texture *ct = cell_texture(ps->texture);*/ + /*struct cell_resource *ct = cell_resource(ps->texture);*/ assert(ps->texture); /*assert(ct->buffer);*/ @@ -386,7 +386,7 @@ cell_unmap_surfaces(struct cell_context *cell) { struct pipe_surface *ps = cell->framebuffer.zsbuf; if (ps && cell->zsbuf_map) { - /*struct cell_texture *ct = cell_texture(ps->texture);*/ + /*struct cell_resource *ct = cell_resource(ps->texture);*/ /*screen->buffer_unmap(screen, ct->buffer);*/ cell->zsbuf_map = NULL; } diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c index 31fd963d19..5f8ca3c7d8 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.c +++ b/src/gallium/drivers/cell/ppu/cell_screen.c @@ -35,7 +35,6 @@ #include "cell_context.h" #include "cell_screen.h" #include "cell_texture.h" -#include "cell_buffer.h" #include "cell_public.h" #include "state_tracker/sw_winsys.h" @@ -142,8 +141,10 @@ cell_is_format_supported( struct pipe_screen *screen, format == PIPE_FORMAT_A8B8G8R8_SRGB) return FALSE; - if (tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { - if (!winsys->is_displaytarget_format_supported(winsys, format)) + if (tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if (!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) return FALSE; } @@ -193,7 +194,6 @@ cell_create_screen(struct sw_winsys *winsys) screen->base.context_create = cell_create_context; cell_init_screen_texture_funcs(&screen->base); - cell_init_screen_buffer_funcs(&screen->base); return &screen->base; } diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index 424e2628a9..bb11c68fa2 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -241,7 +241,7 @@ cell_emit_state(struct cell_context *cell) if (cell->dirty & (CELL_NEW_FS_CONSTANTS)) { const uint shader = PIPE_SHADER_FRAGMENT; - const uint num_const = cell->constants[shader]->size / sizeof(float); + const uint num_const = cell->constants[shader]->width0 / sizeof(float); uint i, j; float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float))); uint32_t *ibuf = (uint32_t *) buf; @@ -293,7 +293,7 @@ cell_emit_state(struct cell_context *cell) texture->opcode[0] = CELL_CMD_STATE_TEXTURE; texture->unit = i; if (cell->texture[i]) { - struct cell_texture *ct = cell->texture[i]; + struct cell_resource *ct = cell->texture[i]; uint level; for (level = 0; level < CELL_MAX_TEXTURE_LEVELS; level++) { texture->start[level] = (ct->mapped + diff --git a/src/gallium/drivers/cell/ppu/cell_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c index 9e29ddc2d4..ddf1477268 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c @@ -34,7 +34,7 @@ #include "cell_context.h" #include "cell_state.h" #include "cell_gen_fp.h" -#include "cell_buffer.h" +#include "cell_texture.h" /** cast wrapper */ @@ -183,11 +183,11 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs) static void cell_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *constants) + struct pipe_resource *constants) { struct cell_context *cell = cell_context(pipe); - unsigned size = constants ? constants->size : 0; - const void *data = constants ? cell_buffer(constants)->data : NULL; + unsigned size = constants ? constants->width0 : 0; + const void *data = constants ? cell_resource(constants)->data : NULL; assert(shader < PIPE_SHADER_TYPES); assert(index == 0); @@ -198,7 +198,7 @@ cell_set_constant_buffer(struct pipe_context *pipe, draw_flush(cell->draw); /* note: reference counting */ - pipe_buffer_reference(&cell->constants[shader], constants); + pipe_resource_reference(&cell->constants[shader], constants); if(shader == PIPE_SHADER_VERTEX) { draw_set_mapped_constant_buffer(cell->draw, PIPE_SHADER_VERTEX, 0, diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index c9326d8aa4..7b9fa3831d 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -42,17 +42,17 @@ #include "cell_context.h" #include "cell_screen.h" #include "cell_state.h" -#include "cell_texture.h" +#include "cell_resource.h" #include "state_tracker/sw_winsys.h" static boolean -cell_texture_layout(struct pipe_screen *screen, - struct cell_texture *ct) +cell_resource_layout(struct pipe_screen *screen, + struct cell_resource *ct) { - struct pipe_texture *pt = &ct->base; + struct pipe_resource *pt = &ct->base; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; @@ -98,13 +98,14 @@ cell_texture_layout(struct pipe_screen *screen, */ static boolean cell_displaytarget_layout(struct pipe_screen *screen, - struct cell_texture * ct) + struct cell_resource * ct) { struct sw_winsys *winsys = cell_screen(screen)->winsys; /* Round up the surface size to a multiple of the tile size? */ ct->dt = winsys->displaytarget_create(winsys, + ct->base->tex_usage, ct->base.format, ct->base.width0, ct->base.height0, @@ -114,11 +115,11 @@ cell_displaytarget_layout(struct pipe_screen *screen, return ct->dt != NULL; } -static struct pipe_texture * -cell_texture_create(struct pipe_screen *screen, - const struct pipe_texture *templat) +static struct pipe_resource * +cell_resource_create(struct pipe_screen *screen, + const struct pipe_resource *templat) { - struct cell_texture *ct = CALLOC_STRUCT(cell_texture); + struct cell_resource *ct = CALLOC_STRUCT(cell_resource); if (!ct) return NULL; @@ -136,7 +137,7 @@ cell_texture_create(struct pipe_screen *screen, goto fail; } - if (!cell_texture_layout(screen, ct)) + if (!cell_resource_layout(screen, ct)) goto fail; return &ct->base; @@ -154,18 +155,19 @@ fail: static void -cell_texture_destroy(struct pipe_texture *pt) +cell_resource_destroy(struct pipe_resource *pt) { struct cell_screen *screen = cell_screen(pt->screen); struct sw_winsys *winsys = screen->winsys; - struct cell_texture *ct = cell_texture(pt); + struct cell_resource *ct = cell_resource(pt); if (ct->dt) { /* display target */ winsys->displaytarget_destroy(winsys, ct->dt); } - - align_free(ct->data); + else if (!ct->userBuffer) { + align_free(ct->data); + } FREE(ct); } @@ -303,17 +305,17 @@ untwiddle_image_uint(uint w, uint h, uint tile_size, uint *dst, static struct pipe_surface * cell_get_tex_surface(struct pipe_screen *screen, - struct pipe_texture *pt, + struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned usage) { - struct cell_texture *ct = cell_texture(pt); + struct cell_resource *ct = cell_resource(pt); struct pipe_surface *ps; ps = CALLOC_STRUCT(pipe_surface); if (ps) { pipe_reference_init(&ps->reference, 1); - pipe_texture_reference(&ps->texture, pt); + pipe_resource_reference(&ps->texture, pt); ps->format = pt->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); @@ -344,7 +346,7 @@ cell_get_tex_surface(struct pipe_screen *screen, static void cell_tex_surface_destroy(struct pipe_surface *surf) { - pipe_texture_reference(&surf->texture, NULL); + pipe_resource_reference(&surf->texture, NULL); FREE(surf); } @@ -356,45 +358,47 @@ cell_tex_surface_destroy(struct pipe_surface *surf) */ static struct pipe_transfer * cell_get_transfer(struct pipe_context *ctx, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) + struct pipe_resource *resource, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) { - struct cell_texture *ct = cell_texture(texture); + struct cell_resource *ct = cell_resource(resource); struct cell_transfer *ctrans; + enum pipe_format *format = resource->format; + + assert(resource); + assert(level <= resource->last_level); - assert(texture); - assert(level <= texture->last_level); + /* make sure the requested region is in the image bounds */ + assert(box->x + box->width <= u_minify(resource->width0, sr.level)); + assert(box->y + box->height <= u_minify(resource->height0, sr.level)); + assert(box->z + box->depth <= u_minify(resource->depth0, sr.level)); ctrans = CALLOC_STRUCT(cell_transfer); if (ctrans) { struct pipe_transfer *pt = &ctrans->base; - pipe_texture_reference(&pt->texture, texture); - pt->x = x; - pt->y = y; - pt->width = w; - pt->height = h; - pt->stride = ct->stride[level]; + pipe_resource_reference(&pt->resource, resource); + pt->sr = sr; pt->usage = usage; - pt->face = face; - pt->level = level; - pt->zslice = zslice; + pt->box = *box; + pt->stride = ct->stride[sr.level]; - ctrans->offset = ct->level_offset[level]; + ctrans->offset = ct->level_offset[sr.level]; - if (texture->target == PIPE_TEXTURE_CUBE) { - unsigned h_tile = align(u_minify(texture->height0, level), TILE_SIZE); - ctrans->offset += face * util_format_get_nblocksy(texture->format, h_tile) * pt->stride; + if (resource->target == PIPE_TEXTURE_CUBE) { + unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE); + ctrans->offset += sr.face * util_format_get_nblocksy(format, h_tile) * pt->stride; } - else if (texture->target == PIPE_TEXTURE_3D) { - unsigned h_tile = align(u_minify(texture->height0, level), TILE_SIZE); - ctrans->offset += zslice * util_format_get_nblocksy(texture->format, h_tile) * pt->stride; + else if (resource->target == PIPE_TEXTURE_3D) { + unsigned h_tile = align(u_minify(resource->height0, sr.level), TILE_SIZE); + ctrans->offset += box->z * util_format_get_nblocksy(format, h_tile) * pt->stride; } else { - assert(face == 0); - assert(zslice == 0); + assert(sr.face == 0); + assert(box->z == 0); } + return pt; } return NULL; @@ -409,8 +413,8 @@ cell_transfer_destroy(struct pipe_context *ctx, struct pipe_transfer *t) * needed post-processing to put them into hardware layout, this is * where it would happen. For cell, nothing to do. */ - assert (transfer->base.texture); - pipe_texture_reference(&transfer->base.texture, NULL); + assert (transfer->base.resource); + pipe_resource_reference(&transfer->base.resource, NULL); FREE(transfer); } @@ -422,44 +426,63 @@ static void * cell_transfer_map(struct pipe_context *ctx, struct pipe_transfer *transfer) { struct cell_transfer *ctrans = cell_transfer(transfer); - struct pipe_texture *pt = transfer->texture; - struct cell_texture *ct = cell_texture(pt); - const uint level = ctrans->base.level; - const uint texWidth = u_minify(pt->width0, level); - const uint texHeight = u_minify(pt->height0, level); - const uint stride = ct->stride[level]; - unsigned size; + struct pipe_resource *pt = transfer->resource; + struct cell_resource *ct = cell_resource(pt); - assert(transfer->texture); + assert(transfer->resource); if (ct->mapped == NULL) { ct->mapped = ct->data; } - /* - * Create a buffer of ordinary memory for the linear texture. - * This is the memory that the user will read/write. + + /* Better test would be resource->is_linear */ - size = util_format_get_stride(pt->format, align(texWidth, TILE_SIZE)) * - util_format_get_nblocksy(pt->format, align(texHeight, TILE_SIZE)); - - ctrans->map = align_malloc(size, 16); - if (!ctrans->map) - return NULL; /* out of memory */ - - if (transfer->usage & PIPE_TRANSFER_READ) { - /* need to untwiddle the texture to make a linear version */ - const uint bpp = util_format_get_blocksize(ct->base.format); - if (bpp == 4) { - const uint *src = (uint *) (ct->mapped + ctrans->offset); - uint *dst = ctrans->map; - untwiddle_image_uint(texWidth, texHeight, TILE_SIZE, - dst, stride, src); - } - else { - // xxx fix + if (transfer->resource->target != PIPE_BUFFER) { + const uint level = ctrans->base.sr.level; + const uint texWidth = u_minify(pt->width0, level); + const uint texHeight = u_minify(pt->height0, level); + unsigned size; + + + /* + * Create a buffer of ordinary memory for the linear texture. + * This is the memory that the user will read/write. + */ + size = (util_format_get_stride(pt->format, align(texWidth, TILE_SIZE)) * + util_format_get_nblocksy(pt->format, align(texHeight, TILE_SIZE))); + + ctrans->map = align_malloc(size, 16); + if (!ctrans->map) + return NULL; /* out of memory */ + + if (transfer->usage & PIPE_TRANSFER_READ) { + /* Textures always stored twiddled, need to untwiddle the + * texture to make a linear version. + */ + const uint bpp = util_format_get_blocksize(ct->base.format); + if (bpp == 4) { + const uint *src = (uint *) (ct->mapped + ctrans->offset); + uint *dst = ctrans->map; + untwiddle_image_uint(texWidth, texHeight, TILE_SIZE, + dst, transfer->stride, src); + } + else { + // xxx fix + } } } + else { + unsigned stride = transfer->stride; + enum pipe_format format = pt->format; + unsigned blocksize = util_format_get_blocksize(format); + + ctrans->map = (ct->mapped + + ctrans->offset + + ctrans->base.box.y / util_format_get_blockheight(format) * stride + + ctrans->base.box.x / util_format_get_blockwidth(format) * blocksize); + } + return ctrans->map; } @@ -475,9 +498,9 @@ cell_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer *transfer) { struct cell_transfer *ctrans = cell_transfer(transfer); - struct pipe_texture *pt = transfer->texture; - struct cell_texture *ct = cell_texture(pt); - const uint level = ctrans->base.level; + struct pipe_resource *pt = transfer->resource; + struct cell_resource *ct = cell_resource(pt); + const uint level = ctrans->base.sr.level; const uint texWidth = u_minify(pt->width0, level); const uint texHeight = u_minify(pt->height0, level); const uint stride = ct->stride[level]; @@ -487,22 +510,28 @@ cell_transfer_unmap(struct pipe_context *ctx, return; } - if (transfer->usage & PIPE_TRANSFER_WRITE) { - /* The user wrote new texture data into the mapped buffer. - * We need to convert the new linear data into the twiddled/tiled format. - */ - const uint bpp = util_format_get_blocksize(ct->base.format); - if (bpp == 4) { - const uint *src = ctrans->map; - uint *dst = (uint *) (ct->mapped + ctrans->offset); - twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, stride, src); - } - else { - // xxx fix + if (pt->target != PIPE_BUFFER) { + if (transfer->usage & PIPE_TRANSFER_WRITE) { + /* The user wrote new texture data into the mapped buffer. + * We need to convert the new linear data into the twiddled/tiled format. + */ + const uint bpp = util_format_get_blocksize(ct->base.format); + if (bpp == 4) { + const uint *src = ctrans->map; + uint *dst = (uint *) (ct->mapped + ctrans->offset); + twiddle_image_uint(texWidth, texHeight, TILE_SIZE, dst, stride, src); + } + else { + // xxx fix + } } + + align_free(ctrans->map); + } + else { + /* nothing to do */ } - align_free(ctrans->map); ctrans->map = NULL; } @@ -524,7 +553,7 @@ cell_flush_frontbuffer(struct pipe_screen *_screen, { struct cell_screen *screen = cell_screen(_screen); struct sw_winsys *winsys = screen->winsys; - struct cell_texture *ct = cell_texture(surface->texture); + struct cell_resource *ct = cell_resource(surface->texture); if (!ct->dt) return; @@ -551,11 +580,46 @@ cell_flush_frontbuffer(struct pipe_screen *_screen, } + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_resource * +cell_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned usage) +{ + struct cell_resource *buffer; + + buffer = CALLOC_STRUCT(cell_resource); + if(!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ + buffer->base.usage = PIPE_BUFFER_USAGE_CPU_READ | usage; + buffer->base.width0 = bytes; + buffer->base.height0 = 1; + buffer->base.depth0 = 1; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + + + void cell_init_screen_texture_funcs(struct pipe_screen *screen) { - screen->texture_create = cell_texture_create; - screen->texture_destroy = cell_texture_destroy; + screen->resource_create = cell_resource_create; + screen->resource_destroy = cell_resource_destroy; + screen->resource_from_handle = cell_resource_from_handle; + screen->resource_get_handle = cell_resource_get_handle; + screen->user_buffer_create = cell_user_buffer_create; screen->get_tex_surface = cell_get_tex_surface; screen->tex_surface_destroy = cell_tex_surface_destroy; @@ -564,10 +628,13 @@ cell_init_screen_texture_funcs(struct pipe_screen *screen) } void -cell_init_texture_transfer_funcs(struct cell_context *cell) +cell_init_transfer_funcs(struct cell_context *cell) { cell->pipe.get_transfer = cell_get_transfer; cell->pipe.transfer_destroy = cell_transfer_destroy; cell->pipe.transfer_map = cell_transfer_map; cell->pipe.transfer_unmap = cell_transfer_unmap; + + cell->pipe.transfer_flush_region = u_default_transfer_flush_region; + cell->pipe.transfer_inline_write = u_default_transfer_inline_write; } diff --git a/src/gallium/drivers/cell/ppu/cell_texture.h b/src/gallium/drivers/cell/ppu/cell_texture.h index ac0b916775..ce70884182 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.h +++ b/src/gallium/drivers/cell/ppu/cell_texture.h @@ -37,9 +37,9 @@ struct pipe_texture; /** * Subclass of pipe_texture */ -struct cell_texture +struct cell_resource { - struct pipe_texture base; + struct pipe_resource base; unsigned long level_offset[CELL_MAX_TEXTURE_LEVELS]; unsigned long stride[CELL_MAX_TEXTURE_LEVELS]; @@ -55,6 +55,7 @@ struct cell_texture * Malloc'ed data for regular textures, or a mapping to dt above. */ void *data; + boolean userBuffer; /* Size of the linear buffer?? */ @@ -77,10 +78,10 @@ struct cell_transfer /** cast wrapper */ -static INLINE struct cell_texture * -cell_texture(struct pipe_texture *pt) +static INLINE struct cell_resource * +cell_resource(struct pipe_resource *pt) { - return (struct cell_texture *) pt; + return (struct cell_resource *) pt; } diff --git a/src/gallium/drivers/cell/spu/spu_exec.h b/src/gallium/drivers/cell/spu/spu_exec.h index 0ca92af248..da9626024e 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.h +++ b/src/gallium/drivers/cell/spu/spu_exec.h @@ -75,7 +75,7 @@ struct softpipe_tile_cache; /**< Opaque to TGSI */ struct spu_sampler { const struct pipe_sampler_state *state; - struct pipe_texture *texture; + struct pipe_resource *texture; /** Get samples for four fragments in a quad */ void (*get_samples)(struct spu_sampler *sampler, const float s[QUAD_SIZE], diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c index ecf948f09b..242b248341 100644 --- a/src/gallium/drivers/i915/i915_resource_buffer.c +++ b/src/gallium/drivers/i915/i915_resource_buffer.c @@ -75,7 +75,7 @@ static void i915_buffer_transfer_inline_write( struct pipe_context *rm_ctx, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, diff --git a/src/gallium/drivers/i965/brw_context.c b/src/gallium/drivers/i965/brw_context.c index 3dbe2b9130..227bc790de 100644 --- a/src/gallium/drivers/i965/brw_context.c +++ b/src/gallium/drivers/i965/brw_context.c @@ -39,6 +39,7 @@ #include "brw_state.h" #include "brw_batchbuffer.h" #include "brw_winsys.h" +#include "brw_resource.h" #include "brw_screen.h" @@ -118,6 +119,7 @@ struct pipe_context *brw_create_context(struct pipe_screen *screen, brw->sws = brw_screen(screen)->sws; brw->chipset = brw_screen(screen)->chipset; + brw_init_resource_functions( brw ); brw_pipe_blend_init( brw ); brw_pipe_depth_stencil_init( brw ); brw_pipe_framebuffer_init( brw ); diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index fc5aec0741..d15c9b04c7 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -738,7 +738,7 @@ static struct pipe_transfer * identity_context_get_transfer(struct pipe_context *_context, struct pipe_resource *_resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box) { struct identity_context *id_context = identity_context(_context); @@ -815,7 +815,7 @@ static void identity_context_transfer_inline_write( struct pipe_context *_context, struct pipe_resource *_resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, diff --git a/src/gallium/drivers/llvmpipe/README b/src/gallium/drivers/llvmpipe/README index bf4c9a5727..3c3fd386b5 100644 --- a/src/gallium/drivers/llvmpipe/README +++ b/src/gallium/drivers/llvmpipe/README @@ -12,7 +12,11 @@ Done so far is: - depth testing - - texture sampling (not all state/formats are supported) + - texture sampling + - 1D/2D/3D/cube maps supported + - all texture wrap modes supported + - all texture filtering modes supported + - perhaps not all texture formats yet supported - fragment shader TGSI translation - same level of support as the TGSI SSE2 exec machine, with the exception @@ -37,8 +41,6 @@ To do (probably by this order): - code generate stipple and stencil testing - - translate the remaining bits of texture sampling state - - translate TGSI control flow instructions, and all other remaining opcodes - integrate with the draw module for VS code generation @@ -57,7 +59,7 @@ Requirements See /proc/cpuinfo to know what your CPU supports. - - LLVM 2.6. + - LLVM 2.6 (or later) For Linux, on a recent Debian based distribution do: @@ -67,6 +69,9 @@ Requirements http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment variable to the extracted path. + The version of LLVM from SVN ("2.7svn") from mid-March 2010 seems pretty + stable and has some features not in version 2.6. + - scons (optional) - udis86, http://udis86.sourceforge.net/ (optional): @@ -140,11 +145,13 @@ Development Notes then skim through the lp_bld_* functions called in there, and the comments at the top of the lp_bld_*.c functions. -- All lp_bld_*.[ch] are isolated from the rest of the driver, and could/may be - put in a stand-alone Gallium state -> LLVM IR translation module. +- The driver-independent parts of the LLVM / Gallium code are found in + src/gallium/auxiliary/gallivm/. The filenames and function prefixes + need to be renamed from "lp_bld_" to something else though. - We use LLVM-C bindings for now. They are not documented, but follow the C++ interfaces very closely, and appear to be complete enough for code generation. See http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html for a stand-alone example. + See the llvm-c/Core.h file for reference. diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index 5887613120..927e472ff2 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -91,36 +91,53 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) /* struct lp_jit_context */ { - LLVMTypeRef elem_types[8]; + LLVMTypeRef elem_types[LP_JIT_CTX_COUNT]; LLVMTypeRef context_type; - elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */ - elem_types[1] = LLVMFloatType(); /* alpha_ref_value */ elem_types[2] = LLVMFloatType(); /* scissor_xmin */ - elem_types[3] = LLVMFloatType(); /* scissor_ymin */ - elem_types[4] = LLVMFloatType(); /* scissor_xmax */ - elem_types[5] = LLVMFloatType(); /* scissor_ymax */ - elem_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */ - elem_types[7] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */ + elem_types[LP_JIT_CTX_CONSTANTS] = LLVMPointerType(LLVMFloatType(), 0); + elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatType(); + elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = LLVMInt32Type(); + elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32Type(); + elem_types[LP_JIT_CTX_SCISSOR_XMIN] = LLVMFloatType(); + elem_types[LP_JIT_CTX_SCISSOR_YMIN] = LLVMFloatType(); + elem_types[LP_JIT_CTX_SCISSOR_XMAX] = LLVMFloatType(); + elem_types[LP_JIT_CTX_SCISSOR_YMAX] = LLVMFloatType(); + elem_types[LP_JIT_CTX_BLEND_COLOR] = LLVMPointerType(LLVMInt8Type(), 0); + elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type, + PIPE_MAX_SAMPLERS); context_type = LLVMStructType(elem_types, Elements(elem_types), 0); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants, - screen->target, context_type, 0); + screen->target, context_type, + LP_JIT_CTX_CONSTANTS); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value, - screen->target, context_type, 1); + screen->target, context_type, + LP_JIT_CTX_ALPHA_REF); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_front, + screen->target, context_type, + LP_JIT_CTX_STENCIL_REF_FRONT); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_back, + screen->target, context_type, + LP_JIT_CTX_STENCIL_REF_BACK); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmin, - screen->target, context_type, 2); + screen->target, context_type, + LP_JIT_CTX_SCISSOR_XMIN); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymin, - screen->target, context_type, 3); + screen->target, context_type, + LP_JIT_CTX_SCISSOR_YMIN); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmax, - screen->target, context_type, 4); + screen->target, context_type, + LP_JIT_CTX_SCISSOR_XMAX); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymax, - screen->target, context_type, 5); + screen->target, context_type, + LP_JIT_CTX_SCISSOR_YMAX); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color, - screen->target, context_type, 6); + screen->target, context_type, + LP_JIT_CTX_BLEND_COLOR); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures, screen->target, context_type, - LP_JIT_CONTEXT_TEXTURES_INDEX); + LP_JIT_CTX_TEXTURES); LP_CHECK_STRUCT_SIZE(struct lp_jit_context, screen->target, context_type); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 13167ae3bf..4930ff02e6 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -84,6 +84,8 @@ struct lp_jit_context float alpha_ref_value; + uint32_t stencil_ref_front, stencil_ref_back; + /** floats, not ints */ float scissor_xmin, scissor_ymin, scissor_xmax, scissor_ymax; @@ -94,37 +96,66 @@ struct lp_jit_context }; +/** + * These enum values must match the position of the fields in the + * lp_jit_context struct above. + */ +enum { + LP_JIT_CTX_CONSTANTS = 0, + LP_JIT_CTX_ALPHA_REF, + LP_JIT_CTX_STENCIL_REF_FRONT, + LP_JIT_CTX_STENCIL_REF_BACK, + LP_JIT_CTX_SCISSOR_XMIN, + LP_JIT_CTX_SCISSOR_YMIN, + LP_JIT_CTX_SCISSOR_XMAX, + LP_JIT_CTX_SCISSOR_YMAX, + LP_JIT_CTX_BLEND_COLOR, + LP_JIT_CTX_TEXTURES, + LP_JIT_CTX_COUNT +}; + + #define lp_jit_context_constants(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 0, "constants") + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_CONSTANTS, "constants") #define lp_jit_context_alpha_ref_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 1, "alpha_ref_value") + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_ALPHA_REF, "alpha_ref_value") + +#define lp_jit_context_stencil_ref_front_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_FRONT, "stencil_ref_front") + +#define lp_jit_context_stencil_ref_back_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_BACK, "stencil_ref_back") #define lp_jit_context_scissor_xmin_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 2, "scissor_xmin") + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_SCISSOR_XMIN, "scissor_xmin") #define lp_jit_context_scissor_ymin_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 3, "scissor_ymin") + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_SCISSOR_YMIN, "scissor_ymin") #define lp_jit_context_scissor_xmax_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 4, "scissor_xmax") + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_SCISSOR_XMAX, "scissor_xmax") #define lp_jit_context_scissor_ymax_value(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 5, "scissor_ymax") + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_SCISSOR_YMAX, "scissor_ymax") #define lp_jit_context_blend_color(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 6, "blend_color") - -#define LP_JIT_CONTEXT_TEXTURES_INDEX 7 + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_BLEND_COLOR, "blend_color") #define lp_jit_context_textures(_builder, _ptr) \ - lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures") + lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES, "textures") + + +/** Indexes into jit_function[] array */ +#define RAST_WHOLE 0 +#define RAST_EDGE_TEST 1 typedef void (*lp_jit_frag_func)(const struct lp_jit_context *context, uint32_t x, uint32_t y, + float facing, const void *a0, const void *dadx, const void *dady, diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 497bfb0994..f5f51f2222 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -312,15 +312,16 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task, depth = lp_rast_depth_pointer(rast, tile_x + x, tile_y + y); /* run shader */ - state->jit_function[0]( &state->jit_context, - tile_x + x, tile_y + y, - inputs->a0, - inputs->dadx, - inputs->dady, - color, - depth, - INT_MIN, INT_MIN, INT_MIN, - NULL, NULL, NULL ); + state->jit_function[RAST_WHOLE]( &state->jit_context, + tile_x + x, tile_y + y, + inputs->facing, + inputs->a0, + inputs->dadx, + inputs->dady, + color, + depth, + INT_MIN, INT_MIN, INT_MIN, + NULL, NULL, NULL ); } } } @@ -375,15 +376,18 @@ void lp_rast_shade_quads( struct lp_rasterizer_task *task, assert(lp_check_alignment(inputs->step[2], 16)); /* run shader */ - state->jit_function[1]( &state->jit_context, - x, y, - inputs->a0, - inputs->dadx, - inputs->dady, - color, - depth, - c1, c2, c3, - inputs->step[0], inputs->step[1], inputs->step[2]); + state->jit_function[RAST_EDGE_TEST]( &state->jit_context, + x, y, + inputs->facing, + inputs->a0, + inputs->dadx, + inputs->dady, + color, + depth, + c1, c2, c3, + inputs->step[0], + inputs->step[1], + inputs->step[2]); } diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 303f6e3f7e..ae838f3fbe 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -82,6 +82,8 @@ struct lp_rast_state { * These pointers point into the bin data buffer. */ struct lp_rast_shader_inputs { + float facing; /** Positive for front-facing, negative for back-facing */ + float (*a0)[4]; float (*dadx)[4]; float (*dady)[4]; diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index 39bf2c2587..6ee9bcaae3 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -195,6 +195,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task, /* run shader */ state->jit_function[0]( &state->jit_context, x, y, + inputs->facing, inputs->a0, inputs->dadx, inputs->dady, diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index c024953402..0614356833 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -203,8 +203,10 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen, return FALSE; } - if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { - if(!winsys->is_displaytarget_format_supported(winsys, format)) + if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) return FALSE; } diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h index d977f98cfa..af25e043cc 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.h +++ b/src/gallium/drivers/llvmpipe/lp_screen.h @@ -34,7 +34,7 @@ #ifndef LP_SCREEN_H #define LP_SCREEN_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include <llvm-c/ExecutionEngine.h> #include "pipe/p_screen.h" diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 1231a31d62..4c5bdf5cfb 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -401,6 +401,20 @@ lp_setup_set_alpha_ref_value( struct lp_setup_context *setup, } void +lp_setup_set_stencil_ref_values( struct lp_setup_context *setup, + const ubyte refs[2] ) +{ + LP_DBG(DEBUG_SETUP, "%s %d %d\n", __FUNCTION__, refs[0], refs[1]); + + if (setup->fs.current.jit_context.stencil_ref_front != refs[0] || + setup->fs.current.jit_context.stencil_ref_back != refs[1]) { + setup->fs.current.jit_context.stencil_ref_front = refs[0]; + setup->fs.current.jit_context.stencil_ref_back = refs[1]; + setup->dirty |= LP_SETUP_NEW_FS; + } +} + +void lp_setup_set_blend_color( struct lp_setup_context *setup, const struct pipe_blend_color *blend_color ) { diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 85e2984b17..4705198c60 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -113,6 +113,10 @@ lp_setup_set_alpha_ref_value( struct lp_setup_context *setup, float alpha_ref_value ); void +lp_setup_set_stencil_ref_values( struct lp_setup_context *setup, + const ubyte refs[2] ); + +void lp_setup_set_blend_color( struct lp_setup_context *setup, const struct pipe_blend_color *blend_color ); diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index ac6264dc73..ce689d3d56 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -361,6 +361,8 @@ do_triangle_ccw(struct lp_setup_context *setup, */ setup_tri_coefficients( setup, tri, oneoverarea, v1, v2, v3, frontfacing ); + tri->inputs.facing = frontfacing ? 1.0F : -1.0F; + /* half-edge constants, will be interated over the whole render target. */ tri->c1 = tri->dy12 * x1 - tri->dx12 * y1; diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index f3da3902a9..d89c28a2af 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -31,7 +31,7 @@ #ifndef LP_STATE_H #define LP_STATE_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include "pipe/p_state.h" #include "tgsi/tgsi_scan.h" @@ -67,6 +67,7 @@ struct lp_fragment_shader; struct lp_fragment_shader_variant_key { struct pipe_depth_state depth; + struct pipe_stencil_state stencil[2]; struct pipe_alpha_state alpha; struct pipe_blend_state blend; enum pipe_format zsbuf_format; diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 9c91ce9238..777871638f 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -174,9 +174,12 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) if (llvmpipe->dirty & LP_NEW_SCISSOR) lp_setup_set_scissor(llvmpipe->setup, &llvmpipe->scissor); - if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA) + if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA) { lp_setup_set_alpha_ref_value(llvmpipe->setup, llvmpipe->depth_stencil->alpha.ref_value); + lp_setup_set_stencil_ref_values(llvmpipe->setup, + llvmpipe->stencil_ref.ref_value); + } if (llvmpipe->dirty & LP_NEW_CONSTANTS) lp_setup_set_fs_constants(llvmpipe->setup, diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index a8b2c18ea0..c57b4a4258 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -137,20 +137,22 @@ generate_pos0(LLVMBuilderRef builder, /** - * Generate the depth test. + * Generate the depth /stencil test code. */ static void -generate_depth(LLVMBuilderRef builder, - const struct lp_fragment_shader_variant_key *key, - struct lp_type src_type, - struct lp_build_mask_context *mask, - LLVMValueRef src, - LLVMValueRef dst_ptr) +generate_depth_stencil(LLVMBuilderRef builder, + const struct lp_fragment_shader_variant_key *key, + struct lp_type src_type, + struct lp_build_mask_context *mask, + LLVMValueRef stencil_refs[2], + LLVMValueRef src, + LLVMValueRef dst_ptr, + LLVMValueRef facing) { const struct util_format_description *format_desc; struct lp_type dst_type; - if(!key->depth.enabled) + if (!key->depth.enabled && !key->stencil[0].enabled && !key->stencil[1].enabled) return; format_desc = util_format_description(key->zsbuf_format); @@ -177,19 +179,22 @@ generate_depth(LLVMBuilderRef builder, assert(dst_type.width == src_type.width); assert(dst_type.length == src_type.length); + /* Convert fragment Z from float to integer */ lp_build_conv(builder, src_type, dst_type, &src, 1, &src, 1); dst_ptr = LLVMBuildBitCast(builder, dst_ptr, LLVMPointerType(lp_build_vec_type(dst_type), 0), ""); - - lp_build_depth_test(builder, - &key->depth, - dst_type, - format_desc, - mask, - src, - dst_ptr); + lp_build_depth_stencil_test(builder, + &key->depth, + key->stencil, + dst_type, + format_desc, + mask, + stencil_refs, + src, + dst_ptr, + facing); } @@ -251,7 +256,7 @@ generate_tri_edge_mask(LLVMBuilderRef builder, LLVMConstInt(LLVMInt32Type(), INT_MIN, 0), ""); - in_out_mask = lp_build_int_const_scalar(i32_type, ~0); + in_out_mask = lp_build_const_int_vec(i32_type, ~0); lp_build_flow_scope_declare(flow, &in_out_mask); @@ -366,7 +371,7 @@ build_int32_vec_const(int value) i32_type.norm = FALSE; /* values are not normalized */ i32_type.width = 32; /* 32-bit int values */ i32_type.length = 4; /* 4 elements per vector */ - return lp_build_int_const_scalar(i32_type, value); + return lp_build_const_int_vec(i32_type, value); } @@ -389,6 +394,7 @@ generate_fs(struct llvmpipe_context *lp, LLVMValueRef *pmask, LLVMValueRef (*color)[4], LLVMValueRef depth_ptr, + LLVMValueRef facing, unsigned do_tri_test, LLVMValueRef c0, LLVMValueRef c1, @@ -404,15 +410,19 @@ generate_fs(struct llvmpipe_context *lp, LLVMValueRef consts_ptr; LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; LLVMValueRef z = interp->pos[2]; + LLVMValueRef stencil_refs[2]; struct lp_build_flow_context *flow; struct lp_build_mask_context mask; - boolean early_depth_test; + boolean early_depth_stencil_test; unsigned attrib; unsigned chan; unsigned cbuf; assert(i < 4); + stencil_refs[0] = lp_jit_context_stencil_ref_front_value(builder, context_ptr); + stencil_refs[1] = lp_jit_context_stencil_ref_back_value(builder, context_ptr); + elem_type = lp_build_elem_type(type); vec_type = lp_build_vec_type(type); int_vec_type = lp_build_int_vec_type(type); @@ -452,16 +462,16 @@ generate_fs(struct llvmpipe_context *lp, lp_build_mask_update(&mask, smask); } - early_depth_test = - key->depth.enabled && + early_depth_stencil_test = + (key->depth.enabled || key->stencil[0].enabled) && !key->alpha.enabled && !shader->info.uses_kill && !shader->info.writes_z; - if(early_depth_test) - generate_depth(builder, key, - type, &mask, - z, depth_ptr); + if (early_depth_stencil_test) + generate_depth_stencil(builder, key, + type, &mask, + stencil_refs, z, depth_ptr, facing); lp_build_tgsi_soa(builder, tokens, type, &mask, consts_ptr, interp->pos, interp->inputs, @@ -505,10 +515,10 @@ generate_fs(struct llvmpipe_context *lp, } } - if(!early_depth_test) - generate_depth(builder, key, - type, &mask, - z, depth_ptr); + if (!early_depth_stencil_test) + generate_depth_stencil(builder, key, + type, &mask, + stencil_refs, z, depth_ptr, facing); lp_build_mask_end(&mask); @@ -584,6 +594,20 @@ generate_blend(const struct pipe_blend_state *blend, } +/** casting function to avoid compiler warnings */ +static lp_jit_frag_func +cast_voidptr_to_lp_jit_frag_func(void *p) +{ + union { + void *v; + lp_jit_frag_func f; + } tmp; + assert(sizeof(tmp.v) == sizeof(tmp.f)); + tmp.v = p; + return tmp.f; +} + + /** * Generate the runtime callable function for the whole fragment pipeline. * Note that the function which we generate operates on a block of 16 @@ -605,7 +629,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef blend_int_vec_type; - LLVMTypeRef arg_types[14]; + LLVMTypeRef arg_types[15]; LLVMTypeRef func_type; LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type(); LLVMValueRef context_ptr; @@ -628,6 +652,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMValueRef blend_mask; LLVMValueRef blend_in_color[NUM_CHANNELS]; LLVMValueRef function; + LLVMValueRef facing; unsigned num_fs; unsigned i; unsigned chan; @@ -667,20 +692,21 @@ generate_fragment(struct llvmpipe_context *lp, arg_types[0] = screen->context_ptr_type; /* context */ arg_types[1] = LLVMInt32Type(); /* x */ arg_types[2] = LLVMInt32Type(); /* y */ - arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */ - arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */ - arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */ - arg_types[6] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ - arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ - arg_types[8] = LLVMInt32Type(); /* c0 */ - arg_types[9] = LLVMInt32Type(); /* c1 */ - arg_types[10] = LLVMInt32Type(); /* c2 */ + arg_types[3] = LLVMFloatType(); /* facing */ + arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* a0 */ + arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dadx */ + arg_types[6] = LLVMPointerType(fs_elem_type, 0); /* dady */ + arg_types[7] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ + arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ + arg_types[9] = LLVMInt32Type(); /* c0 */ + arg_types[10] = LLVMInt32Type(); /* c1 */ + arg_types[11] = LLVMInt32Type(); /* c2 */ /* Note: the step arrays are built as int32[16] but we interpret * them here as int32_vec4[4]. */ - arg_types[11] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ - arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ - arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ + arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ + arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ + arg_types[14] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); @@ -700,17 +726,18 @@ generate_fragment(struct llvmpipe_context *lp, context_ptr = LLVMGetParam(function, 0); x = LLVMGetParam(function, 1); y = LLVMGetParam(function, 2); - a0_ptr = LLVMGetParam(function, 3); - dadx_ptr = LLVMGetParam(function, 4); - dady_ptr = LLVMGetParam(function, 5); - color_ptr_ptr = LLVMGetParam(function, 6); - depth_ptr = LLVMGetParam(function, 7); - c0 = LLVMGetParam(function, 8); - c1 = LLVMGetParam(function, 9); - c2 = LLVMGetParam(function, 10); - step0_ptr = LLVMGetParam(function, 11); - step1_ptr = LLVMGetParam(function, 12); - step2_ptr = LLVMGetParam(function, 13); + facing = LLVMGetParam(function, 3); + a0_ptr = LLVMGetParam(function, 4); + dadx_ptr = LLVMGetParam(function, 5); + dady_ptr = LLVMGetParam(function, 6); + color_ptr_ptr = LLVMGetParam(function, 7); + depth_ptr = LLVMGetParam(function, 8); + c0 = LLVMGetParam(function, 9); + c1 = LLVMGetParam(function, 10); + c2 = LLVMGetParam(function, 11); + step0_ptr = LLVMGetParam(function, 12); + step1_ptr = LLVMGetParam(function, 13); + step2_ptr = LLVMGetParam(function, 14); lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); @@ -769,6 +796,7 @@ generate_fragment(struct llvmpipe_context *lp, &fs_mask[i], /* output */ out_color, depth_ptr_i, + facing, do_tri_test, c0, c1, c2, step0_ptr, step1_ptr, step2_ptr); @@ -844,10 +872,14 @@ generate_fragment(struct llvmpipe_context *lp, /* * Translate the LLVM IR into machine code. */ - variant->jit_function[do_tri_test] = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, function); + { + void *f = LLVMGetPointerToGlobal(screen->engine, function); + + variant->jit_function[do_tri_test] = cast_voidptr_to_lp_jit_frag_func(f); - if (LP_DEBUG & DEBUG_ASM) - lp_disassemble(variant->jit_function[do_tri_test]); + if (LP_DEBUG & DEBUG_ASM) + lp_disassemble(f); + } } @@ -1053,10 +1085,15 @@ make_variant_key(struct llvmpipe_context *lp, memset(key, 0, sizeof *key); - if(lp->framebuffer.zsbuf && - lp->depth_stencil->depth.enabled) { - key->zsbuf_format = lp->framebuffer.zsbuf->format; - memcpy(&key->depth, &lp->depth_stencil->depth, sizeof key->depth); + if (lp->framebuffer.zsbuf) { + if (lp->depth_stencil->depth.enabled) { + key->zsbuf_format = lp->framebuffer.zsbuf->format; + memcpy(&key->depth, &lp->depth_stencil->depth, sizeof key->depth); + } + if (lp->depth_stencil->stencil[0].enabled) { + key->zsbuf_format = lp->framebuffer.zsbuf->format; + memcpy(&key->stencil, &lp->depth_stencil->stencil, sizeof key->stencil); + } } key->alpha.enabled = lp->depth_stencil->alpha.enabled; @@ -1139,6 +1176,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) opaque = !key.blend.logicop_enable && !key.blend.rt[0].blend_enable && key.blend.rt[0].colormask == 0xf && + !key.stencil[0].enabled && !key.alpha.enabled && !key.depth.enabled && !key.scissor && @@ -1146,7 +1184,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) ? TRUE : FALSE; lp_setup_set_fs_functions(lp->setup, - shader->current->jit_function[0], - shader->current->jit_function[1], + shader->current->jit_function[RAST_WHOLE], + shader->current->jit_function[RAST_EDGE_TEST], opaque); } diff --git a/src/gallium/drivers/llvmpipe/lp_test.h b/src/gallium/drivers/llvmpipe/lp_test.h index 1df9897898..338a04a487 100644 --- a/src/gallium/drivers/llvmpipe/lp_test.h +++ b/src/gallium/drivers/llvmpipe/lp_test.h @@ -41,7 +41,7 @@ #include <stdio.h> #include <float.h> -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include <llvm-c/Analysis.h> #include <llvm-c/ExecutionEngine.h> #include <llvm-c/Target.h> diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c index 2c4d7fb6e1..fb595893bd 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_format.c +++ b/src/gallium/drivers/llvmpipe/lp_test_format.c @@ -29,7 +29,7 @@ #include <stdlib.h> #include <stdio.h> -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" #include <llvm-c/Analysis.h> #include <llvm-c/ExecutionEngine.h> #include <llvm-c/Target.h> diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample.h b/src/gallium/drivers/llvmpipe/lp_tex_sample.h index 799df182b6..1228a831f3 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample.h +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample.h @@ -29,7 +29,7 @@ #define LP_TEX_SAMPLE_H -#include "os/os_llvm.h" +#include "gallivm/lp_bld.h" struct lp_sampler_static_state; diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c index 662508af61..4715cfe4f6 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c @@ -105,7 +105,7 @@ lp_llvm_texture_member(struct lp_sampler_dynamic_state *base, /* context[0] */ indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); /* context[0].textures */ - indices[1] = LLVMConstInt(LLVMInt32Type(), LP_JIT_CONTEXT_TEXTURES_INDEX, 0); + indices[1] = LLVMConstInt(LLVMInt32Type(), LP_JIT_CTX_TEXTURES, 0); /* context[0].textures[unit] */ indices[2] = LLVMConstInt(LLVMInt32Type(), unit, 0); /* context[0].textures[unit].member */ diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index eaf1f90f31..3977a40652 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -105,6 +105,7 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, unsigned height = align(lpt->base.height0, TILE_SIZE); lpt->dt = winsys->displaytarget_create(winsys, + lpt->base.tex_usage, lpt->base.format, width, height, 16, @@ -253,6 +254,51 @@ llvmpipe_resource_unmap(struct pipe_resource *texture, } +static struct pipe_resource * +llvmpipe_resource_from_handle(struct pipe_screen *screen, + const struct pipe_resource *template, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; + struct llvmpipe_resource *lpt = CALLOC_STRUCT(llvmpipe_resource); + if (!lpt) + return NULL; + + lpt->base = *template; + pipe_reference_init(&lpt->base.reference, 1); + lpt->base.screen = screen; + + lpt->dt = winsys->displaytarget_from_handle(winsys, + template, + whandle, + &lpt->stride[0]); + if (!lpt->dt) + goto fail; + + return &lpt->base; + + fail: + FREE(lpt); + return NULL; +} + + +static boolean +llvmpipe_resource_get_handle(struct pipe_screen *screen, + struct pipe_resource *pt, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; + struct llvmpipe_resource *lpt = llvmpipe_resource(pt); + + assert(lpt->dt); + if (!lpt->dt) + return FALSE; + + return winsys->displaytarget_get_handle(winsys, lpt->dt, whandle); +} + + static struct pipe_surface * llvmpipe_get_tex_surface(struct pipe_screen *screen, struct pipe_resource *pt, @@ -297,7 +343,7 @@ static struct pipe_transfer * llvmpipe_get_transfer(struct pipe_context *pipe, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box) { struct llvmpipe_resource *lptex = llvmpipe_resource(resource); @@ -444,6 +490,8 @@ llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) { screen->resource_create = llvmpipe_resource_create; screen->resource_destroy = llvmpipe_resource_destroy; + screen->resource_from_handle = llvmpipe_resource_from_handle; + screen->resource_get_handle = llvmpipe_resource_get_handle; screen->user_buffer_create = llvmpipe_user_buffer_create; screen->get_tex_surface = llvmpipe_get_tex_surface; diff --git a/src/gallium/drivers/nouveau/Makefile b/src/gallium/drivers/nouveau/Makefile index 0e02680bc6..db591b756c 100644 --- a/src/gallium/drivers/nouveau/Makefile +++ b/src/gallium/drivers/nouveau/Makefile @@ -3,8 +3,9 @@ include $(TOP)/configs/current LIBNAME = nouveau -C_SOURCES = nouveau_screen.c \ - nouveau_context.c \ - nv04_surface_2d.c +LIBRARY_INCLUDES = \ + -I$(TOP)/src/gallium/drivers/nouveau/include + +C_SOURCES = nouveau_screen.c include ../../Makefile.template diff --git a/src/gallium/drivers/nouveau/nouveau_context.c b/src/gallium/drivers/nouveau/nouveau_context.c deleted file mode 100644 index 15174983e7..0000000000 --- a/src/gallium/drivers/nouveau/nouveau_context.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "pipe/p_defines.h" -#include "pipe/p_context.h" - -#include "nouveau/nouveau_screen.h" -#include "nouveau/nouveau_context.h" - -#include "nouveau/nouveau_bo.h" - -static unsigned int -nouveau_reference_flags(struct nouveau_bo *bo) -{ - uint32_t bo_flags; - int flags = 0; - - bo_flags = nouveau_bo_pending(bo); - if (bo_flags & NOUVEAU_BO_RD) - flags |= PIPE_REFERENCED_FOR_READ; - if (bo_flags & NOUVEAU_BO_WR) - flags |= PIPE_REFERENCED_FOR_WRITE; - - return flags; -} - -unsigned int -nouveau_is_texture_referenced(struct pipe_context *pipe, - struct pipe_texture *pt, - unsigned face, unsigned level) -{ - struct nouveau_miptree *mt = nouveau_miptree(pt); - - return nouveau_reference_flags(mt->bo); -} - -unsigned int -nouveau_is_buffer_referenced(struct pipe_context *pipe, struct pipe_buffer *pb) -{ - struct nouveau_bo *bo = nouveau_bo(pb); - - return nouveau_reference_flags(bo); -} - diff --git a/src/gallium/drivers/nouveau/nouveau_context.h b/src/gallium/drivers/nouveau/nouveau_context.h deleted file mode 100644 index 6a28d40da7..0000000000 --- a/src/gallium/drivers/nouveau/nouveau_context.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __NOUVEAU_CONTEXT_H__ -#define __NOUVEAU_CONTEXT_H__ - -unsigned int -nouveau_is_texture_referenced(struct pipe_context *, struct pipe_texture *, - unsigned face, unsigned level); - -unsigned int -nouveau_is_buffer_referenced(struct pipe_context *, struct pipe_buffer *); - -#endif diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index b1ad686022..944d2c0954 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -32,28 +32,9 @@ nouveau_screen_get_vendor(struct pipe_screen *pscreen) return "nouveau"; } -static struct pipe_buffer * -nouveau_screen_bo_skel(struct pipe_screen *pscreen, struct nouveau_bo *bo, - unsigned alignment, unsigned usage, unsigned size) -{ - struct pipe_buffer *pb; - pb = CALLOC(1, sizeof(struct pipe_buffer)+sizeof(struct nouveau_bo *)); - if (!pb) { - nouveau_bo_ref(NULL, &bo); - return NULL; - } - - pipe_reference_init(&pb->reference, 1); - pb->screen = pscreen; - pb->alignment = alignment; - pb->usage = usage; - pb->size = size; - *(struct nouveau_bo **)(pb + 1) = bo; - return pb; -} -static struct pipe_buffer * +struct nouveau_bo * nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment, unsigned usage, unsigned size) { @@ -93,10 +74,10 @@ nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment, if (ret) return NULL; - return nouveau_screen_bo_skel(pscreen, bo, alignment, usage, size); + return bo; } -static struct pipe_buffer * +struct nouveau_bo * nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; @@ -107,7 +88,7 @@ nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes) if (ret) return NULL; - return nouveau_screen_bo_skel(pscreen, bo, 0, 0, bytes); + return bo; } static inline uint32_t @@ -130,23 +111,14 @@ nouveau_screen_map_flags(unsigned pipe) return flags; } -static void * -nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb, +void * +nouveau_screen_bo_map(struct pipe_screen *pscreen, + struct nouveau_bo *pb, unsigned usage) { - struct nouveau_bo *bo = nouveau_bo(pb); struct nouveau_screen *nscreen = nouveau_screen(pscreen); int ret; - if (nscreen->pre_pipebuffer_map_callback) { - ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage); - if (ret) { - debug_printf("pre_pipebuffer_map_callback failed %d\n", - ret); - return NULL; - } - } - ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage)); if (ret) { debug_printf("map failed: %d\n", ret); @@ -156,24 +128,14 @@ nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb, return bo->map; } -static void * -nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb, +void * +nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct nouveau_bo *bo, unsigned offset, unsigned length, unsigned usage) { - struct nouveau_bo *bo = nouveau_bo(pb); struct nouveau_screen *nscreen = nouveau_screen(pscreen); uint32_t flags = nouveau_screen_map_flags(usage); int ret; - if (nscreen->pre_pipebuffer_map_callback) { - ret = nscreen->pre_pipebuffer_map_callback(pscreen, pb, usage); - if (ret) { - debug_printf("pre_pipebuffer_map_callback failed %d\n", - ret); - return NULL; - } - } - ret = nouveau_bo_map_range(bo, offset, length, flags); if (ret) { nouveau_bo_unmap(bo); @@ -185,30 +147,23 @@ nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb, return (char *)bo->map - offset; /* why gallium? why? */ } -static void -nouveau_screen_bo_map_flush(struct pipe_screen *pscreen, struct pipe_buffer *pb, - unsigned offset, unsigned length) +void +nouveau_screen_bo_map_flush_range(struct pipe_screen *pscreen, struct nouveau_bo *bo, + unsigned offset, unsigned length) { - struct nouveau_bo *bo = nouveau_bo(pb); - nouveau_bo_map_flush(bo, offset, length); } -static void -nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct pipe_buffer *pb) +void +nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct nouveau_bo *bo) { - struct nouveau_bo *bo = nouveau_bo(pb); - nouveau_bo_unmap(bo); } -static void -nouveau_screen_bo_del(struct pipe_buffer *pb) +void +nouveau_screen_bo_release(struct pipe_screen *pscreen, struct nouveau_bo *bo) { - struct nouveau_bo *bo = nouveau_bo(pb); - nouveau_bo_ref(NULL, &bo); - FREE(pb); } static void @@ -236,59 +191,32 @@ nouveau_screen_fence_finish(struct pipe_screen *screen, } -/* - * Both texture_{from|get}_handle use drm api defines directly which they - * shouldn't do. The problem is that from|get are pipe functions and as - * such they should be defined in the pipe level. If nouveau had a propper - * winsys interface we would have added from|get to that interface using - * the winsys_handle struct as done with other drivers. However this code - * calls directly into the libdrm_nouveau.so functions (nouveau_bo_*). So - * we need to translate the handle into something they understand. - */ -static struct pipe_texture * -nouveau_screen_texture_from_handle(struct pipe_screen *pscreen, - const struct pipe_texture *templ, - struct winsys_handle *whandle) +struct nouveau_bo * +nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, + struct winsys_handle *whandle, + unsigned *out_stride) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; - struct pipe_texture *pt; - struct pipe_buffer *pb; - int ret; - - pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*)); - if (!pb) - return NULL; - - ret = nouveau_bo_handle_ref(dev, whandle->handle, (struct nouveau_bo**)(pb+1)); + struct nouveau_bo *bo; + + ret = nouveau_bo_handle_ref(dev, whandle->handle, &bo); if (ret) { debug_printf("%s: ref name 0x%08x failed with %d\n", __func__, whandle->handle, ret); - FREE(pb); return NULL; } - pipe_reference_init(&pb->reference, 1); - pb->screen = pscreen; - pb->alignment = 0; - pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | - PIPE_BUFFER_USAGE_CPU_READ_WRITE; - pb->size = nouveau_bo(pb)->size; - pt = nouveau_screen(pscreen)->texture_blanket(pscreen, templ, - &whandle->stride, pb); - pipe_buffer_reference(&pb, NULL); - return pt; + *out_stride = whandle->stride; + return bo; } -static boolean -nouveau_screen_texture_get_handle(struct pipe_screen *pscreen, - struct pipe_texture *pt, - struct winsys_handle *whandle) -{ - struct nouveau_miptree *mt = nouveau_miptree(pt); - - if (!mt || !mt->bo) - return false; +boolean +nouveau_screen_bo_get_handle(struct pipe_screen *pscreen, + struct nouveau_bo *bo, + unsigned stride, + struct winsys_handle *whandle) +{ whandle->stride = util_format_get_stride(mt->base.format, mt->base.width0); if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { @@ -301,6 +229,26 @@ nouveau_screen_texture_get_handle(struct pipe_screen *pscreen, } } + +unsigned int +nouveau_reference_flags(struct nouveau_bo *bo) +{ + uint32_t bo_flags; + int flags = 0; + + bo_flags = nouveau_bo_pending(bo); + if (bo_flags & NOUVEAU_BO_RD) + flags |= PIPE_REFERENCED_FOR_READ; + if (bo_flags & NOUVEAU_BO_WR) + flags |= PIPE_REFERENCED_FOR_WRITE; + + return flags; +} + + + + + int nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) { @@ -316,21 +264,10 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) pscreen->get_name = nouveau_screen_get_name; pscreen->get_vendor = nouveau_screen_get_vendor; - pscreen->buffer_create = nouveau_screen_bo_new; - pscreen->user_buffer_create = nouveau_screen_bo_user; - pscreen->buffer_map = nouveau_screen_bo_map; - pscreen->buffer_map_range = nouveau_screen_bo_map_range; - pscreen->buffer_flush_mapped_range = nouveau_screen_bo_map_flush; - pscreen->buffer_unmap = nouveau_screen_bo_unmap; - pscreen->buffer_destroy = nouveau_screen_bo_del; - pscreen->fence_reference = nouveau_screen_fence_ref; pscreen->fence_signalled = nouveau_screen_fence_signalled; pscreen->fence_finish = nouveau_screen_fence_finish; - pscreen->texture_from_handle = nouveau_screen_texture_from_handle; - pscreen->texture_get_handle = nouveau_screen_texture_get_handle; - return 0; } diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h index f4a7a2bc23..1ba4113bfc 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.h +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -5,21 +5,6 @@ struct nouveau_screen { struct pipe_screen base; struct nouveau_device *device; struct nouveau_channel *channel; - - /** - * Create a new texture object, using the given template info, but on top of - * existing memory. - * - * It is assumed that the buffer data is layed out according to the expected - * by the hardware. NULL will be returned if any inconsistency is found. - */ - struct pipe_texture * (*texture_blanket)(struct pipe_screen *, - const struct pipe_texture *templat, - const unsigned *stride, - struct pipe_buffer *buffer); - - int (*pre_pipebuffer_map_callback) (struct pipe_screen *pscreen, - struct pipe_buffer *pb, unsigned usage); }; static inline struct nouveau_screen * @@ -28,24 +13,51 @@ nouveau_screen(struct pipe_screen *pscreen) return (struct nouveau_screen *)pscreen; } -static inline struct nouveau_bo * -nouveau_bo(struct pipe_buffer *pb) -{ - return pb ? *(struct nouveau_bo **)(pb + 1) : NULL; -} + + +/* Not really sure if this is needed, or whether the individual + * drivers are happy to talk to the bo functions themselves. In a way + * this is what we'd expect from a regular winsys interface. + */ +struct nouveau_bo * +nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment, + unsigned usage, unsigned size); +struct nouveau_bo * +nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes); +void * +nouveau_screen_bo_map(struct pipe_screen *pscreen, + struct nouveau_bo *pb, + unsigned usage); +void * +nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct nouveau_bo *bo, + unsigned offset, unsigned length, unsigned usage); +void +nouveau_screen_bo_map_flush_range(struct pipe_screen *pscreen, struct nouveau_bo *bo, + unsigned offset, unsigned length); +void +nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct nouveau_bo *bo); +void +nouveau_screen_bo_release(struct pipe_screen *pscreen, struct nouveau_bo *bo); + +boolean +nouveau_screen_bo_get_handle(struct pipe_screen *pscreen, + struct nouveau_bo *bo, + unsigned stride, + struct winsys_handle *whandle); +struct nouveau_bo * +nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, + struct winsys_handle *whandle, + unsigned *out_stride); + +unsigned int +nouveau_reference_flags(struct nouveau_bo *bo); + + int nouveau_screen_init(struct nouveau_screen *, struct nouveau_device *); void nouveau_screen_fini(struct nouveau_screen *); -struct nouveau_miptree { - struct pipe_texture base; - struct nouveau_bo *bo; -}; -static inline struct nouveau_miptree * -nouveau_miptree(struct pipe_texture *pt) -{ - return (struct nouveau_miptree *)pt; -} + #endif diff --git a/src/gallium/drivers/nouveau/nouveau_util.h b/src/gallium/drivers/nouveau/nouveau_util.h index 7f16e31c3f..ed6e643785 100644 --- a/src/gallium/drivers/nouveau/nouveau_util.h +++ b/src/gallium/drivers/nouveau/nouveau_util.h @@ -33,7 +33,7 @@ nouveau_vbuf_split(unsigned remaining, unsigned overhead, unsigned vpp, max = max - (max % 3); break; case PIPE_PRIM_QUADS: - max = max & 3; + max = max & ~3; break; case PIPE_PRIM_LINE_LOOP: case PIPE_PRIM_LINE_STRIP: @@ -98,9 +98,9 @@ struct u_split_prim { unsigned p_start; unsigned p_end; - int repeat_first:1; - int close_first:1; - int edgeflag_off:1; + uint repeat_first:1; + uint close_first:1; + uint edgeflag_off:1; }; static inline void diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index af9ddd558c..9c73a015c7 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -2,7 +2,6 @@ #define NOUVEAU_WINSYS_H #include <stdint.h> -#include "util/u_simple_screen.h" #include "pipe/p_defines.h" #include "nouveau/nouveau_bo.h" @@ -27,10 +26,7 @@ #define NOUVEAU_BUFFER_USAGE_NO_RENDER (1 << 19) extern struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *); - -extern struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *); +nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_screen * nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *); diff --git a/src/gallium/drivers/nv30/Makefile b/src/gallium/drivers/nv30/Makefile deleted file mode 100644 index 364c80d8f3..0000000000 --- a/src/gallium/drivers/nv30/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -LIBNAME = nv30 - -C_SOURCES = \ - nv30_clear.c \ - nv30_context.c \ - nv30_draw.c \ - nv30_fragprog.c \ - nv30_fragtex.c \ - nv30_miptree.c \ - nv30_query.c \ - nv30_screen.c \ - nv30_state.c \ - nv30_state_blend.c \ - nv30_state_emit.c \ - nv30_state_fb.c \ - nv30_state_rasterizer.c \ - nv30_state_scissor.c \ - nv30_state_stipple.c \ - nv30_state_viewport.c \ - nv30_state_zsa.c \ - nv30_surface.c \ - nv30_transfer.c \ - nv30_vbo.c \ - nv30_vertprog.c - -include ../../Makefile.template diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c deleted file mode 100644 index c4ba926664..0000000000 --- a/src/gallium/drivers/nv30/nv30_clear.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_clear.h" - -#include "nv30_context.h" - -void -nv30_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil) -{ - util_clear(pipe, &nv30_context(pipe)->framebuffer, buffers, rgba, depth, - stencil); -} diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c deleted file mode 100644 index 825c167b01..0000000000 --- a/src/gallium/drivers/nv30/nv30_context.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "draw/draw_context.h" -#include "pipe/p_defines.h" - -#include "nv30_context.h" -#include "nv30_screen.h" - -static void -nv30_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - - if (flags & PIPE_FLUSH_TEXTURE_CACHE) { - BEGIN_RING(chan, rankine, 0x1fd8, 1); - OUT_RING (chan, 2); - BEGIN_RING(chan, rankine, 0x1fd8, 1); - OUT_RING (chan, 1); - } - - FIRE_RING(chan); - if (fence) - *fence = NULL; -} - -static void -nv30_destroy(struct pipe_context *pipe) -{ - struct nv30_context *nv30 = nv30_context(pipe); - unsigned i; - - for (i = 0; i < NV30_STATE_MAX; i++) { - if (nv30->state.hw[i]) - so_ref(NULL, &nv30->state.hw[i]); - } - - if (nv30->draw) - draw_destroy(nv30->draw); - FREE(nv30); -} - -struct pipe_context * -nv30_create(struct pipe_screen *pscreen, void *priv) -{ - struct nv30_screen *screen = nv30_screen(pscreen); - struct pipe_winsys *ws = pscreen->winsys; - struct nv30_context *nv30; - struct nouveau_winsys *nvws = screen->nvws; - - nv30 = CALLOC(1, sizeof(struct nv30_context)); - if (!nv30) - return NULL; - nv30->screen = screen; - - nv30->nvws = nvws; - - nv30->pipe.winsys = ws; - nv30->pipe.screen = pscreen; - nv30->pipe.priv = priv; - nv30->pipe.destroy = nv30_destroy; - nv30->pipe.draw_arrays = nv30_draw_arrays; - nv30->pipe.draw_elements = nv30_draw_elements; - nv30->pipe.clear = nv30_clear; - nv30->pipe.flush = nv30_flush; - - nv30->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv30->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - - screen->base.channel->user_private = nv30; - screen->base.channel->flush_notify = nv30_state_flush_notify; - - nv30_init_query_functions(nv30); - nv30_init_surface_functions(nv30); - nv30_init_state_functions(nv30); - nv30_init_transfer_functions(nv30); - - /* Create, configure, and install fallback swtnl path */ - nv30->draw = draw_create(); - draw_wide_point_threshold(nv30->draw, 9999999.0); - draw_wide_line_threshold(nv30->draw, 9999999.0); - draw_enable_line_stipple(nv30->draw, FALSE); - draw_enable_point_sprites(nv30->draw, FALSE); - draw_set_rasterize_stage(nv30->draw, nv30_draw_render_stage(nv30)); - - return &nv30->pipe; -} diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h deleted file mode 100644 index 38a17a4455..0000000000 --- a/src/gallium/drivers/nv30/nv30_context.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef __NV30_CONTEXT_H__ -#define __NV30_CONTEXT_H__ - -#include <stdio.h> - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_inlines.h" - -#include "draw/draw_vertex.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_gldefs.h" -#include "nouveau/nouveau_context.h" -#include "nouveau/nouveau_stateobj.h" - -#include "nv30_state.h" - -#define NOUVEAU_ERR(fmt, args...) \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); -#define NOUVEAU_MSG(fmt, args...) \ - fprintf(stderr, "nouveau: "fmt, ##args); - -enum nv30_state_index { - NV30_STATE_FB = 0, - NV30_STATE_VIEWPORT = 1, - NV30_STATE_BLEND = 2, - NV30_STATE_RAST = 3, - NV30_STATE_ZSA = 4, - NV30_STATE_BCOL = 5, - NV30_STATE_CLIP = 6, - NV30_STATE_SCISSOR = 7, - NV30_STATE_STIPPLE = 8, - NV30_STATE_FRAGPROG = 9, - NV30_STATE_VERTPROG = 10, - NV30_STATE_FRAGTEX0 = 11, - NV30_STATE_FRAGTEX1 = 12, - NV30_STATE_FRAGTEX2 = 13, - NV30_STATE_FRAGTEX3 = 14, - NV30_STATE_FRAGTEX4 = 15, - NV30_STATE_FRAGTEX5 = 16, - NV30_STATE_FRAGTEX6 = 17, - NV30_STATE_FRAGTEX7 = 18, - NV30_STATE_FRAGTEX8 = 19, - NV30_STATE_FRAGTEX9 = 20, - NV30_STATE_FRAGTEX10 = 21, - NV30_STATE_FRAGTEX11 = 22, - NV30_STATE_FRAGTEX12 = 23, - NV30_STATE_FRAGTEX13 = 24, - NV30_STATE_FRAGTEX14 = 25, - NV30_STATE_FRAGTEX15 = 26, - NV30_STATE_VERTTEX0 = 27, - NV30_STATE_VERTTEX1 = 28, - NV30_STATE_VERTTEX2 = 29, - NV30_STATE_VERTTEX3 = 30, - NV30_STATE_VTXBUF = 31, - NV30_STATE_VTXFMT = 32, - NV30_STATE_VTXATTR = 33, - NV30_STATE_SR = 34, - NV30_STATE_MAX = 35 -}; - -#include "nv30_screen.h" - -#define NV30_NEW_BLEND (1 << 0) -#define NV30_NEW_RAST (1 << 1) -#define NV30_NEW_ZSA (1 << 2) -#define NV30_NEW_SAMPLER (1 << 3) -#define NV30_NEW_FB (1 << 4) -#define NV30_NEW_STIPPLE (1 << 5) -#define NV30_NEW_SCISSOR (1 << 6) -#define NV30_NEW_VIEWPORT (1 << 7) -#define NV30_NEW_BCOL (1 << 8) -#define NV30_NEW_VERTPROG (1 << 9) -#define NV30_NEW_FRAGPROG (1 << 10) -#define NV30_NEW_ARRAYS (1 << 11) -#define NV30_NEW_UCP (1 << 12) -#define NV30_NEW_SR (1 << 13) - -struct nv30_rasterizer_state { - struct pipe_rasterizer_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv30_zsa_state { - struct pipe_depth_stencil_alpha_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv30_blend_state { - struct pipe_blend_state pipe; - struct nouveau_stateobj *so; -}; - - -struct nv30_state { - unsigned scissor_enabled; - unsigned stipple_enabled; - unsigned fp_samplers; - - uint64_t dirty; - struct nouveau_stateobj *hw[NV30_STATE_MAX]; -}; - -struct nv30_vtxelt_state { - struct pipe_vertex_element pipe[16]; - unsigned num_elements; -}; - -struct nv30_context { - struct pipe_context pipe; - - struct nouveau_winsys *nvws; - struct nv30_screen *screen; - - struct draw_context *draw; - - /* HW state derived from pipe states */ - struct nv30_state state; - - /* Context state */ - unsigned dirty; - struct pipe_scissor_state scissor; - unsigned stipple[32]; - struct nv30_vertex_program *vertprog; - struct nv30_fragment_program *fragprog; - struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; - unsigned constbuf_nr[PIPE_SHADER_TYPES]; - struct nv30_rasterizer_state *rasterizer; - struct nv30_zsa_state *zsa; - struct nv30_blend_state *blend; - struct pipe_blend_color blend_colour; - struct pipe_stencil_ref stencil_ref; - struct pipe_viewport_state viewport; - struct pipe_framebuffer_state framebuffer; - struct pipe_buffer *idxbuf; - unsigned idxbuf_format; - struct nv30_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; - struct nv30_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; - struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; - unsigned nr_samplers; - unsigned nr_textures; - unsigned dirty_samplers; - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - unsigned vtxbuf_nr; - struct nv30_vtxelt_state *vtxelt; -}; - -static INLINE struct nv30_context * -nv30_context(struct pipe_context *pipe) -{ - return (struct nv30_context *)pipe; -} - -struct nv30_state_entry { - boolean (*validate)(struct nv30_context *nv30); - struct { - unsigned pipe; - unsigned hw; - } dirty; -}; - -extern void nv30_init_state_functions(struct nv30_context *nv30); -extern void nv30_init_surface_functions(struct nv30_context *nv30); -extern void nv30_init_query_functions(struct nv30_context *nv30); -extern void nv30_init_transfer_functions(struct nv30_context *nv30); - -extern void nv30_screen_init_miptree_functions(struct pipe_screen *pscreen); - -/* nv30_draw.c */ -extern struct draw_stage *nv30_draw_render_stage(struct nv30_context *nv30); - -/* nv30_vertprog.c */ -extern void nv30_vertprog_destroy(struct nv30_context *, - struct nv30_vertex_program *); - -/* nv30_fragprog.c */ -extern void nv30_fragprog_destroy(struct nv30_context *, - struct nv30_fragment_program *); - -/* nv30_fragtex.c */ -extern void nv30_fragtex_bind(struct nv30_context *); - -/* nv30_state.c and friends */ -extern boolean nv30_state_validate(struct nv30_context *nv30); -extern void nv30_state_emit(struct nv30_context *nv30); -extern void nv30_state_flush_notify(struct nouveau_channel *chan); -extern struct nv30_state_entry nv30_state_rasterizer; -extern struct nv30_state_entry nv30_state_scissor; -extern struct nv30_state_entry nv30_state_stipple; -extern struct nv30_state_entry nv30_state_fragprog; -extern struct nv30_state_entry nv30_state_vertprog; -extern struct nv30_state_entry nv30_state_blend; -extern struct nv30_state_entry nv30_state_blend_colour; -extern struct nv30_state_entry nv30_state_zsa; -extern struct nv30_state_entry nv30_state_viewport; -extern struct nv30_state_entry nv30_state_framebuffer; -extern struct nv30_state_entry nv30_state_fragtex; -extern struct nv30_state_entry nv30_state_vbo; -extern struct nv30_state_entry nv30_state_sr; - -/* nv30_vbo.c */ -extern void nv30_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv30_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, - unsigned count); - -/* nv30_clear.c */ -extern void nv30_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil); - -/* nv30_context.c */ -struct pipe_context * -nv30_create(struct pipe_screen *pscreen, void *priv); - -#endif diff --git a/src/gallium/drivers/nv30/nv30_draw.c b/src/gallium/drivers/nv30/nv30_draw.c deleted file mode 100644 index 74fc138c05..0000000000 --- a/src/gallium/drivers/nv30/nv30_draw.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "draw/draw_pipe.h" - -#include "nv30_context.h" - -struct nv30_draw_stage { - struct draw_stage draw; - struct nv30_context *nv30; -}; - -static void -nv30_draw_point(struct draw_stage *draw, struct prim_header *prim) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_line(struct draw_stage *draw, struct prim_header *prim) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_tri(struct draw_stage *draw, struct prim_header *prim) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_flush(struct draw_stage *draw, unsigned flags) -{ -} - -static void -nv30_draw_reset_stipple_counter(struct draw_stage *draw) -{ - NOUVEAU_ERR("\n"); -} - -static void -nv30_draw_destroy(struct draw_stage *draw) -{ - FREE(draw); -} - -struct draw_stage * -nv30_draw_render_stage(struct nv30_context *nv30) -{ - struct nv30_draw_stage *nv30draw = CALLOC_STRUCT(nv30_draw_stage); - - nv30draw->nv30 = nv30; - nv30draw->draw.draw = nv30->draw; - nv30draw->draw.point = nv30_draw_point; - nv30draw->draw.line = nv30_draw_line; - nv30draw->draw.tri = nv30_draw_tri; - nv30draw->draw.flush = nv30_draw_flush; - nv30draw->draw.reset_stipple_counter = nv30_draw_reset_stipple_counter; - nv30draw->draw.destroy = nv30_draw_destroy; - - return &nv30draw->draw; -} - diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c deleted file mode 100644 index 2c432c6dfa..0000000000 --- a/src/gallium/drivers/nv30/nv30_fragprog.c +++ /dev/null @@ -1,905 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_util.h" - -#include "nv30_context.h" - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 1 -#define MASK_Y 2 -#define MASK_Z 4 -#define MASK_W 8 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE NV30_FP_OP_DST_SCALE_1X -#define DEF_CTEST NV30_FP_OP_COND_TR -#include "nv30_shader.h" - -#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv30_sr_neg((s)) -#define abs(s) nv30_sr_abs((s)) -#define scale(s,v) nv30_sr_scale((s), NV30_FP_OP_DST_SCALE_##v) - -#define MAX_CONSTS 128 -#define MAX_IMM 32 -struct nv30_fpc { - struct nv30_fragment_program *fp; - - uint attrib_map[PIPE_MAX_SHADER_INPUTS]; - - int high_temp; - int temp_temp_count; - int num_regs; - - uint depth_id; - uint colour_id; - - unsigned inst_offset; - - struct { - int pipe; - float vals[4]; - } consts[MAX_CONSTS]; - int nr_consts; - - struct nv30_sreg imm[MAX_IMM]; - unsigned nr_imm; -}; - -static INLINE struct nv30_sreg -temp(struct nv30_fpc *fpc) -{ - int idx; - - idx = fpc->temp_temp_count++; - idx += fpc->high_temp + 1; - return nv30_sr(NV30SR_TEMP, idx); -} - -static INLINE struct nv30_sreg -constant(struct nv30_fpc *fpc, int pipe, float vals[4]) -{ - int idx; - - if (fpc->nr_consts == MAX_CONSTS) - assert(0); - idx = fpc->nr_consts++; - - fpc->consts[idx].pipe = pipe; - if (pipe == -1) - memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float)); - return nv30_sr(NV30SR_CONST, idx); -} - -#define arith(cc,s,o,d,m,s0,s1,s2) \ - nv30_fp_arith((cc), (s), NV30_FP_OP_OPCODE_##o, \ - (d), (m), (s0), (s1), (s2)) -#define tex(cc,s,o,u,d,m,s0,s1,s2) \ - nv30_fp_tex((cc), (s), NV30_FP_OP_OPCODE_##o, (u), \ - (d), (m), (s0), none, none) - -static void -grow_insns(struct nv30_fpc *fpc, int size) -{ - struct nv30_fragment_program *fp = fpc->fp; - - fp->insn_len += size; - fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len); -} - -static void -emit_src(struct nv30_fpc *fpc, int pos, struct nv30_sreg src) -{ - struct nv30_fragment_program *fp = fpc->fp; - uint32_t *hw = &fp->insn[fpc->inst_offset]; - uint32_t sr = 0; - - switch (src.type) { - case NV30SR_INPUT: - sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT); - hw[0] |= (src.index << NV30_FP_OP_INPUT_SRC_SHIFT); - break; - case NV30SR_OUTPUT: - sr |= NV30_FP_REG_SRC_HALF; - /* fall-through */ - case NV30SR_TEMP: - sr |= (NV30_FP_REG_TYPE_TEMP << NV30_FP_REG_TYPE_SHIFT); - sr |= (src.index << NV30_FP_REG_SRC_SHIFT); - break; - case NV30SR_CONST: - grow_insns(fpc, 4); - hw = &fp->insn[fpc->inst_offset]; - if (fpc->consts[src.index].pipe >= 0) { - struct nv30_fragment_program_data *fpd; - - fp->consts = realloc(fp->consts, ++fp->nr_consts * - sizeof(*fpd)); - fpd = &fp->consts[fp->nr_consts - 1]; - fpd->offset = fpc->inst_offset + 4; - fpd->index = fpc->consts[src.index].pipe; - memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4); - } else { - memcpy(&fp->insn[fpc->inst_offset + 4], - fpc->consts[src.index].vals, - sizeof(uint32_t) * 4); - } - - sr |= (NV30_FP_REG_TYPE_CONST << NV30_FP_REG_TYPE_SHIFT); - break; - case NV30SR_NONE: - sr |= (NV30_FP_REG_TYPE_INPUT << NV30_FP_REG_TYPE_SHIFT); - break; - default: - assert(0); - } - - if (src.negate) - sr |= NV30_FP_REG_NEGATE; - - if (src.abs) - hw[1] |= (1 << (29 + pos)); - - sr |= ((src.swz[0] << NV30_FP_REG_SWZ_X_SHIFT) | - (src.swz[1] << NV30_FP_REG_SWZ_Y_SHIFT) | - (src.swz[2] << NV30_FP_REG_SWZ_Z_SHIFT) | - (src.swz[3] << NV30_FP_REG_SWZ_W_SHIFT)); - - hw[pos + 1] |= sr; -} - -static void -emit_dst(struct nv30_fpc *fpc, struct nv30_sreg dst) -{ - struct nv30_fragment_program *fp = fpc->fp; - uint32_t *hw = &fp->insn[fpc->inst_offset]; - - switch (dst.type) { - case NV30SR_TEMP: - if (fpc->num_regs < (dst.index + 1)) - fpc->num_regs = dst.index + 1; - break; - case NV30SR_OUTPUT: - if (dst.index == 1) { - fp->fp_control |= 0xe; - } else { - hw[0] |= NV30_FP_OP_OUT_REG_HALF; - } - break; - case NV30SR_NONE: - hw[0] |= (1 << 30); - break; - default: - assert(0); - } - - hw[0] |= (dst.index << NV30_FP_OP_OUT_REG_SHIFT); -} - -static void -nv30_fp_arith(struct nv30_fpc *fpc, int sat, int op, - struct nv30_sreg dst, int mask, - struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2) -{ - struct nv30_fragment_program *fp = fpc->fp; - uint32_t *hw; - - fpc->inst_offset = fp->insn_len; - grow_insns(fpc, 4); - hw = &fp->insn[fpc->inst_offset]; - memset(hw, 0, sizeof(uint32_t) * 4); - - if (op == NV30_FP_OP_OPCODE_KIL) - fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL; - hw[0] |= (op << NV30_FP_OP_OPCODE_SHIFT); - hw[0] |= (mask << NV30_FP_OP_OUTMASK_SHIFT); - hw[2] |= (dst.dst_scale << NV30_FP_OP_DST_SCALE_SHIFT); - - if (sat) - hw[0] |= NV30_FP_OP_OUT_SAT; - - if (dst.cc_update) - hw[0] |= NV30_FP_OP_COND_WRITE_ENABLE; - hw[1] |= (dst.cc_test << NV30_FP_OP_COND_SHIFT); - hw[1] |= ((dst.cc_swz[0] << NV30_FP_OP_COND_SWZ_X_SHIFT) | - (dst.cc_swz[1] << NV30_FP_OP_COND_SWZ_Y_SHIFT) | - (dst.cc_swz[2] << NV30_FP_OP_COND_SWZ_Z_SHIFT) | - (dst.cc_swz[3] << NV30_FP_OP_COND_SWZ_W_SHIFT)); - - emit_dst(fpc, dst); - emit_src(fpc, 0, s0); - emit_src(fpc, 1, s1); - emit_src(fpc, 2, s2); -} - -static void -nv30_fp_tex(struct nv30_fpc *fpc, int sat, int op, int unit, - struct nv30_sreg dst, int mask, - struct nv30_sreg s0, struct nv30_sreg s1, struct nv30_sreg s2) -{ - struct nv30_fragment_program *fp = fpc->fp; - - nv30_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); - - fp->insn[fpc->inst_offset] |= (unit << NV30_FP_OP_TEX_UNIT_SHIFT); - fp->samplers |= (1 << unit); -} - -static INLINE struct nv30_sreg -tgsi_src(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc) -{ - struct nv30_sreg src; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - src = nv30_sr(NV30SR_INPUT, - fpc->attrib_map[fsrc->Register.Index]); - break; - case TGSI_FILE_CONSTANT: - src = constant(fpc, fsrc->Register.Index, NULL); - break; - case TGSI_FILE_IMMEDIATE: - assert(fsrc->Register.Index < fpc->nr_imm); - src = fpc->imm[fsrc->Register.Index]; - break; - case TGSI_FILE_TEMPORARY: - src = nv30_sr(NV30SR_TEMP, fsrc->Register.Index + 1); - if (fpc->high_temp < src.index) - fpc->high_temp = src.index; - break; - /* This is clearly insane, but gallium hands us shaders like this. - * Luckily fragprog results are just temp regs.. - */ - case TGSI_FILE_OUTPUT: - if (fsrc->Register.Index == fpc->colour_id) - return nv30_sr(NV30SR_OUTPUT, 0); - else - return nv30_sr(NV30SR_OUTPUT, 1); - break; - default: - NOUVEAU_ERR("bad src file\n"); - break; - } - - src.abs = fsrc->Register.Absolute; - src.negate = fsrc->Register.Negate; - src.swz[0] = fsrc->Register.SwizzleX; - src.swz[1] = fsrc->Register.SwizzleY; - src.swz[2] = fsrc->Register.SwizzleZ; - src.swz[3] = fsrc->Register.SwizzleW; - return src; -} - -static INLINE struct nv30_sreg -tgsi_dst(struct nv30_fpc *fpc, const struct tgsi_full_dst_register *fdst) { - int idx; - - switch (fdst->Register.File) { - case TGSI_FILE_OUTPUT: - if (fdst->Register.Index == fpc->colour_id) - return nv30_sr(NV30SR_OUTPUT, 0); - else - return nv30_sr(NV30SR_OUTPUT, 1); - break; - case TGSI_FILE_TEMPORARY: - idx = fdst->Register.Index + 1; - if (fpc->high_temp < idx) - fpc->high_temp = idx; - return nv30_sr(NV30SR_TEMP, idx); - case TGSI_FILE_NULL: - return nv30_sr(NV30SR_NONE, 0); - default: - NOUVEAU_ERR("bad dst file %d\n", fdst->Register.File); - return nv30_sr(NV30SR_NONE, 0); - } -} - -static INLINE int -tgsi_mask(uint tgsi) -{ - int mask = 0; - - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; - return mask; -} - -static boolean -src_native_swz(struct nv30_fpc *fpc, const struct tgsi_full_src_register *fsrc, - struct nv30_sreg *src) -{ - const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); - struct nv30_sreg tgsi = tgsi_src(fpc, fsrc); - uint mask = 0; - uint c; - - for (c = 0; c < 4; c++) { - switch (tgsi_util_get_full_src_register_swizzle(fsrc, c)) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - mask |= (1 << c); - break; - default: - assert(0); - } - } - - if (mask == MASK_ALL) - return TRUE; - - *src = temp(fpc); - - if (mask) - arith(fpc, 0, MOV, *src, mask, tgsi, none, none); - - return FALSE; -} - -static boolean -nv30_fragprog_parse_instruction(struct nv30_fpc *fpc, - const struct tgsi_full_instruction *finst) -{ - const struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); - struct nv30_sreg src[3], dst, tmp; - int mask, sat, unit = 0; - int ai = -1, ci = -1; - int i; - - if (finst->Instruction.Opcode == TGSI_OPCODE_END) - return TRUE; - - fpc->temp_temp_count = 0; - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - if (fsrc->Register.File == TGSI_FILE_TEMPORARY) { - src[i] = tgsi_src(fpc, fsrc); - } - } - - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - case TGSI_FILE_CONSTANT: - case TGSI_FILE_TEMPORARY: - if (!src_native_swz(fpc, fsrc, &src[i])) - continue; - break; - default: - break; - } - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - if (ai == -1 || ai == fsrc->Register.Index) { - ai = fsrc->Register.Index; - src[i] = tgsi_src(fpc, fsrc); - } else { - NOUVEAU_MSG("extra src attr %d\n", - fsrc->Register.Index); - src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, - tgsi_src(fpc, fsrc), none, none); - } - break; - case TGSI_FILE_CONSTANT: - case TGSI_FILE_IMMEDIATE: - if (ci == -1 || ci == fsrc->Register.Index) { - ci = fsrc->Register.Index; - src[i] = tgsi_src(fpc, fsrc); - } else { - src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, - tgsi_src(fpc, fsrc), none, none); - } - break; - case TGSI_FILE_TEMPORARY: - /* handled above */ - break; - case TGSI_FILE_SAMPLER: - unit = fsrc->Register.Index; - break; - case TGSI_FILE_OUTPUT: - break; - default: - NOUVEAU_ERR("bad src file\n"); - return FALSE; - } - } - - dst = tgsi_dst(fpc, &finst->Dst[0]); - mask = tgsi_mask(finst->Dst[0].Register.WriteMask); - sat = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE); - - switch (finst->Instruction.Opcode) { - case TGSI_OPCODE_ABS: - arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none); - break; - case TGSI_OPCODE_ADD: - arith(fpc, sat, ADD, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_CMP: - tmp = nv30_sr(NV30SR_NONE, 0); - tmp.cc_update = 1; - arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none); - dst.cc_test = NV30_VP_INST_COND_GE; - arith(fpc, sat, MOV, dst, mask, src[2], none, none); - dst.cc_test = NV30_VP_INST_COND_LT; - arith(fpc, sat, MOV, dst, mask, src[1], none, none); - break; - case TGSI_OPCODE_COS: - arith(fpc, sat, COS, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_DP3: - arith(fpc, sat, DP3, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DP4: - arith(fpc, sat, DP4, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DPH: - tmp = temp(fpc); - arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none); - arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X), - swz(src[1], W, W, W, W), none); - break; - case TGSI_OPCODE_DST: - arith(fpc, sat, DST, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_EX2: - arith(fpc, sat, EX2, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FLR: - arith(fpc, sat, FLR, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FRC: - arith(fpc, sat, FRC, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_KILP: - arith(fpc, 0, KIL, none, 0, none, none, none); - break; - case TGSI_OPCODE_KIL: - dst = nv30_sr(NV30SR_NONE, 0); - dst.cc_update = 1; - arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none); - dst.cc_update = 0; dst.cc_test = NV30_FP_OP_COND_LT; - arith(fpc, 0, KIL, dst, 0, none, none, none); - break; - case TGSI_OPCODE_LG2: - arith(fpc, sat, LG2, dst, mask, src[0], none, none); - break; -// case TGSI_OPCODE_LIT: - case TGSI_OPCODE_LRP: - arith(fpc, sat, LRP, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAD: - arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAX: - arith(fpc, sat, MAX, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MIN: - arith(fpc, sat, MIN, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MOV: - arith(fpc, sat, MOV, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_MUL: - arith(fpc, sat, MUL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_POW: - arith(fpc, sat, POW, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_RCP: - arith(fpc, sat, RCP, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_RET: - assert(0); - break; - case TGSI_OPCODE_RFL: - arith(fpc, 0, RFL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_RSQ: - arith(fpc, sat, RSQ, dst, mask, abs(swz(src[0], X, X, X, X)), none, none); - break; - case TGSI_OPCODE_SCS: - /* avoid overwriting the source */ - if(src[0].swz[SWZ_X] != SWZ_X) - { - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, - swz(src[0], X, X, X, X), none, none); - } - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, - swz(src[0], X, X, X, X), none, none); - } - } - else - { - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, - swz(src[0], X, X, X, X), none, none); - } - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, - swz(src[0], X, X, X, X), none, none); - } - } - break; - case TGSI_OPCODE_SIN: - arith(fpc, sat, SIN, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_SGE: - arith(fpc, sat, SGE, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SGT: - arith(fpc, sat, SGT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SLT: - arith(fpc, sat, SLT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SUB: - arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none); - break; - case TGSI_OPCODE_TEX: - tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_TXB: - tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_TXP: - tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_XPD: - tmp = temp(fpc); - arith(fpc, 0, MUL, tmp, mask, - swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(fpc, sat, MAD, dst, (mask & ~MASK_W), - swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), - neg(tmp)); - break; - default: - NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); - return FALSE; - } - - return TRUE; -} - -static boolean -nv30_fragprog_parse_decl_attrib(struct nv30_fpc *fpc, - const struct tgsi_full_declaration *fdec) -{ - int hw; - - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - hw = NV30_FP_OP_INPUT_SRC_POSITION; - break; - case TGSI_SEMANTIC_COLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_FP_OP_INPUT_SRC_COL0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_FP_OP_INPUT_SRC_COL1; - } else { - NOUVEAU_ERR("bad colour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_FOG: - hw = NV30_FP_OP_INPUT_SRC_FOGC; - break; - case TGSI_SEMANTIC_GENERIC: - if (fdec->Semantic.Index <= 7) { - hw = NV30_FP_OP_INPUT_SRC_TC(fdec->Semantic. - Index); - } else { - NOUVEAU_ERR("bad generic semantic index\n"); - return FALSE; - } - break; - default: - NOUVEAU_ERR("bad input semantic\n"); - return FALSE; - } - - fpc->attrib_map[fdec->Range.First] = hw; - return TRUE; -} - -static boolean -nv30_fragprog_parse_decl_output(struct nv30_fpc *fpc, - const struct tgsi_full_declaration *fdec) -{ - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - fpc->depth_id = fdec->Range.First; - break; - case TGSI_SEMANTIC_COLOR: - fpc->colour_id = fdec->Range.First; - break; - default: - NOUVEAU_ERR("bad output semantic\n"); - return FALSE; - } - - return TRUE; -} - -static boolean -nv30_fragprog_prepare(struct nv30_fpc *fpc) -{ - struct tgsi_parse_context p; - /*int high_temp = -1, i;*/ - - tgsi_parse_init(&p, fpc->fp->pipe.tokens); - while (!tgsi_parse_end_of_tokens(&p)) { - const union tgsi_full_token *tok = &p.FullToken; - - tgsi_parse_token(&p); - switch(tok->Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - { - const struct tgsi_full_declaration *fdec; - fdec = &p.FullToken.FullDeclaration; - switch (fdec->Declaration.File) { - case TGSI_FILE_INPUT: - if (!nv30_fragprog_parse_decl_attrib(fpc, fdec)) - goto out_err; - break; - case TGSI_FILE_OUTPUT: - if (!nv30_fragprog_parse_decl_output(fpc, fdec)) - goto out_err; - break; - /*case TGSI_FILE_TEMPORARY: - if (fdec->Range.Last > high_temp) { - high_temp = - fdec->Range.Last; - } - break;*/ - default: - break; - } - } - break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - { - struct tgsi_full_immediate *imm; - float vals[4]; - - imm = &p.FullToken.FullImmediate; - assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); - assert(fpc->nr_imm < MAX_IMM); - - vals[0] = imm->u[0].Float; - vals[1] = imm->u[1].Float; - vals[2] = imm->u[2].Float; - vals[3] = imm->u[3].Float; - fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals); - } - break; - default: - break; - } - } - tgsi_parse_free(&p); - - /*if (++high_temp) { - fpc->r_temp = CALLOC(high_temp, sizeof(struct nv30_sreg)); - for (i = 0; i < high_temp; i++) - fpc->r_temp[i] = temp(fpc); - fpc->r_temps_discard = 0; - }*/ - - return TRUE; - -out_err: - /*if (fpc->r_temp) - FREE(fpc->r_temp);*/ - tgsi_parse_free(&p); - return FALSE; -} - -static void -nv30_fragprog_translate(struct nv30_context *nv30, - struct nv30_fragment_program *fp) -{ - struct tgsi_parse_context parse; - struct nv30_fpc *fpc = NULL; - - tgsi_dump(fp->pipe.tokens,0); - - fpc = CALLOC(1, sizeof(struct nv30_fpc)); - if (!fpc) - return; - fpc->fp = fp; - fpc->high_temp = -1; - fpc->num_regs = 2; - - if (!nv30_fragprog_prepare(fpc)) { - FREE(fpc); - return; - } - - tgsi_parse_init(&parse, fp->pipe.tokens); - - while (!tgsi_parse_end_of_tokens(&parse)) { - tgsi_parse_token(&parse); - - switch (parse.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - const struct tgsi_full_instruction *finst; - - finst = &parse.FullToken.FullInstruction; - if (!nv30_fragprog_parse_instruction(fpc, finst)) - goto out_err; - } - break; - default: - break; - } - } - - fp->fp_control |= (fpc->num_regs-1)/2; - fp->fp_reg_control = (1<<16)|0x4; - - /* Terminate final instruction */ - fp->insn[fpc->inst_offset] |= 0x00000001; - - /* Append NOP + END instruction, may or may not be necessary. */ - fpc->inst_offset = fp->insn_len; - grow_insns(fpc, 4); - fp->insn[fpc->inst_offset + 0] = 0x00000001; - fp->insn[fpc->inst_offset + 1] = 0x00000000; - fp->insn[fpc->inst_offset + 2] = 0x00000000; - fp->insn[fpc->inst_offset + 3] = 0x00000000; - - fp->translated = TRUE; - fp->on_hw = FALSE; -out_err: - tgsi_parse_free(&parse); - FREE(fpc); -} - -static void -nv30_fragprog_upload(struct nv30_context *nv30, - struct nv30_fragment_program *fp) -{ - struct pipe_screen *pscreen = nv30->pipe.screen; - const uint32_t le = 1; - uint32_t *map; - int i; - - map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); - -#if 0 - for (i = 0; i < fp->insn_len; i++) { - fflush(stdout); fflush(stderr); - NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]); - fflush(stdout); fflush(stderr); - } -#endif - - if ((*(const uint8_t *)&le)) { - for (i = 0; i < fp->insn_len; i++) { - map[i] = fp->insn[i]; - } - } else { - /* Weird swapping for big-endian chips */ - for (i = 0; i < fp->insn_len; i++) { - map[i] = ((fp->insn[i] & 0xffff) << 16) | - ((fp->insn[i] >> 16) & 0xffff); - } - } - - pipe_buffer_unmap(pscreen, fp->buffer); -} - -static boolean -nv30_fragprog_validate(struct nv30_context *nv30) -{ - struct nv30_fragment_program *fp = nv30->fragprog; - struct pipe_buffer *constbuf = - nv30->constbuf[PIPE_SHADER_FRAGMENT]; - struct pipe_screen *pscreen = nv30->pipe.screen; - struct nouveau_stateobj *so; - boolean new_consts = FALSE; - int i; - - if (fp->translated) - goto update_constants; - - /*nv30->fallback_swrast &= ~NV30_NEW_FRAGPROG;*/ - nv30_fragprog_translate(nv30, fp); - if (!fp->translated) { - /*nv30->fallback_swrast |= NV30_NEW_FRAGPROG;*/ - return FALSE; - } - - fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4); - nv30_fragprog_upload(nv30, fp); - - so = so_new(4, 4, 1); - so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1); - so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | - NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0, - NV34TCL_FP_ACTIVE_PROGRAM_DMA1); - so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1); - so_data (so, fp->fp_control); - so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1); - so_data (so, fp->fp_reg_control); - so_method(so, nv30->screen->rankine, NV34TCL_TX_UNITS_ENABLE, 1); - so_data (so, fp->samplers); - so_ref(so, &fp->so); - so_ref(NULL, &so); - -update_constants: - if (fp->nr_consts) { - float *map; - - map = pipe_buffer_map(pscreen, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); - for (i = 0; i < fp->nr_consts; i++) { - struct nv30_fragment_program_data *fpd = &fp->consts[i]; - uint32_t *p = &fp->insn[fpd->offset]; - uint32_t *cb = (uint32_t *)&map[fpd->index * 4]; - - if (!memcmp(p, cb, 4 * sizeof(float))) - continue; - memcpy(p, cb, 4 * sizeof(float)); - new_consts = TRUE; - } - pipe_buffer_unmap(pscreen, constbuf); - - if (new_consts) - nv30_fragprog_upload(nv30, fp); - } - - if (new_consts || fp->so != nv30->state.hw[NV30_STATE_FRAGPROG]) { - so_ref(fp->so, &nv30->state.hw[NV30_STATE_FRAGPROG]); - return TRUE; - } - - return FALSE; -} - -void -nv30_fragprog_destroy(struct nv30_context *nv30, - struct nv30_fragment_program *fp) -{ - if (fp->buffer) - pipe_buffer_reference(&fp->buffer, NULL); - - if (fp->so) - so_ref(NULL, &fp->so); - - if (fp->insn_len) - FREE(fp->insn); -} - -struct nv30_state_entry nv30_state_fragprog = { - .validate = nv30_fragprog_validate, - .dirty = { - .pipe = NV30_NEW_FRAGPROG, - .hw = NV30_STATE_FRAGPROG - } -}; diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c deleted file mode 100644 index bfa27b632f..0000000000 --- a/src/gallium/drivers/nv30/nv30_miptree.c +++ /dev/null @@ -1,240 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" - -#include "nv30_context.h" -#include "../nouveau/nv04_surface_2d.h" - -static void -nv30_miptree_layout(struct nv30_miptree *nv30mt) -{ - struct pipe_texture *pt = &nv30mt->base; - uint width = pt->width0; - uint offset = 0; - int nr_faces, l, f; - uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_SCANOUT); - - if (pt->target == PIPE_TEXTURE_CUBE) { - nr_faces = 6; - } else - if (pt->target == PIPE_TEXTURE_3D) { - nr_faces = pt->depth0; - } else { - nr_faces = 1; - } - - for (l = 0; l <= pt->last_level; l++) { - if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) - nv30mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64); - else - nv30mt->level[l].pitch = util_format_get_stride(pt->format, width); - - nv30mt->level[l].image_offset = - CALLOC(nr_faces, sizeof(unsigned)); - - width = u_minify(width, 1); - } - - for (f = 0; f < nr_faces; f++) { - for (l = 0; l < pt->last_level; l++) { - nv30mt->level[l].image_offset[f] = offset; - - if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) && - u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1) - offset += align(nv30mt->level[l].pitch * u_minify(pt->height0, l), 64); - else - offset += nv30mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv30mt->level[l].image_offset[f] = offset; - offset += nv30mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv30mt->total_size = offset; -} - -static struct pipe_texture * -nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) -{ - struct nv30_miptree *mt; - unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | - NOUVEAU_BUFFER_USAGE_TEXTURE; - - mt = MALLOC(sizeof(struct nv30_miptree)); - if (!mt) - return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - - /* Swizzled textures must be POT */ - if (pt->width0 & (pt->width0 - 1) || - pt->height0 & (pt->height0 - 1)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else { - switch (pt->format) { - /* TODO: Figure out which formats can be swizzled */ - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_R16_SNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - case PIPE_FORMAT_L8A8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - { - if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - break; - } - default: - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - } - } - - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE; - - /* apparently we can't render to swizzled surfaces smaller than 64 bytes, so make them linear. - * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy. - * This also happens for small mipmaps of large textures. */ - if (pt->tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET && util_format_get_stride(pt->format, pt->width0) < 64) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - - nv30_miptree_layout(mt); - - mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage, - mt->total_size); - if (!mt->buffer) { - FREE(mt); - return NULL; - } - mt->bo = nouveau_bo(mt->buffer); - - return &mt->base; -} - -static struct pipe_texture * -nv30_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) -{ - struct nv30_miptree *mt; - - /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) - return NULL; - - mt = CALLOC_STRUCT(nv30_miptree); - if (!mt) - return NULL; - - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - mt->level[0].pitch = stride[0]; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - - /* Assume whoever created this buffer expects it to be linear for now */ - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - - pipe_buffer_reference(&mt->buffer, pb); - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; -} - -static void -nv30_miptree_destroy(struct pipe_texture *pt) -{ - struct nv30_miptree *mt = (struct nv30_miptree *)pt; - int l; - - pipe_buffer_reference(&mt->buffer, NULL); - for (l = 0; l <= pt->last_level; l++) { - if (mt->level[l].image_offset) - FREE(mt->level[l].image_offset); - } - - FREE(mt); -} - -static struct pipe_surface * -nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) -{ - struct nv30_miptree *nv30mt = (struct nv30_miptree *)pt; - struct nv04_surface *ns; - - ns = CALLOC_STRUCT(nv04_surface); - if (!ns) - return NULL; - pipe_texture_reference(&ns->base.texture, pt); - ns->base.format = pt->format; - ns->base.width = u_minify(pt->width0, level); - ns->base.height = u_minify(pt->height0, level); - ns->base.usage = flags; - pipe_reference_init(&ns->base.reference, 1); - ns->base.face = face; - ns->base.level = level; - ns->base.zslice = zslice; - ns->pitch = nv30mt->level[level].pitch; - - if (pt->target == PIPE_TEXTURE_CUBE) { - ns->base.offset = nv30mt->level[level].image_offset[face]; - } else - if (pt->target == PIPE_TEXTURE_3D) { - ns->base.offset = nv30mt->level[level].image_offset[zslice]; - } else { - ns->base.offset = nv30mt->level[level].image_offset[0]; - } - - /* create a linear temporary that we can render into if necessary. - * Note that ns->pitch is always a multiple of 64 for linear surfaces and swizzled surfaces are POT, so - * ns->pitch & 63 is equivalent to (ns->pitch < 64 && swizzled)*/ - if((ns->pitch & 63) && (ns->base.usage & (PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER)) == PIPE_BUFFER_USAGE_GPU_WRITE) - return &nv04_surface_wrap_for_render(pscreen, ((struct nv30_screen*)pscreen)->eng2d, ns)->base; - - return &ns->base; -} - -static void -nv30_miptree_surface_del(struct pipe_surface *ps) -{ - struct nv04_surface* ns = (struct nv04_surface*)ps; - if(ns->backing) - { - struct nv30_screen* screen = (struct nv30_screen*)ps->texture->screen; - if(ns->backing->base.usage & PIPE_BUFFER_USAGE_GPU_WRITE) - screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height); - nv30_miptree_surface_del(&ns->backing->base); - } - - pipe_texture_reference(&ps->texture, NULL); - FREE(ps); -} - -void -nv30_screen_init_miptree_functions(struct pipe_screen *pscreen) -{ - pscreen->texture_create = nv30_miptree_create; - pscreen->texture_destroy = nv30_miptree_destroy; - pscreen->get_tex_surface = nv30_miptree_surface_new; - pscreen->tex_surface_destroy = nv30_miptree_surface_del; - - nouveau_screen(pscreen)->texture_blanket = nv30_miptree_blanket; -} diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c deleted file mode 100644 index e27e9ccbf6..0000000000 --- a/src/gallium/drivers/nv30/nv30_query.c +++ /dev/null @@ -1,127 +0,0 @@ -#include "pipe/p_context.h" - -#include "nv30_context.h" - -struct nv30_query { - struct nouveau_resource *object; - unsigned type; - boolean ready; - uint64_t result; -}; - -static INLINE struct nv30_query * -nv30_query(struct pipe_query *pipe) -{ - return (struct nv30_query *)pipe; -} - -static struct pipe_query * -nv30_query_create(struct pipe_context *pipe, unsigned query_type) -{ - struct nv30_query *q; - - q = CALLOC(1, sizeof(struct nv30_query)); - q->type = query_type; - - return (struct pipe_query *)q; -} - -static void -nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv30_query *q = nv30_query(pq); - - if (q->object) - nouveau_resource_free(&q->object); - FREE(q); -} - -static void -nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_query *q = nv30_query(pq); - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - - assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - /* Happens when end_query() is called, then another begin_query() - * without querying the result in-between. For now we'll wait for - * the existing query to notify completion, but it could be better. - */ - if (q->object) { - uint64_t tmp; - pipe->get_query_result(pipe, pq, 1, &tmp); - } - - if (nouveau_resource_alloc(nv30->screen->query_heap, 1, NULL, &q->object)) - assert(0); - nouveau_notifier_reset(nv30->screen->query, q->object->start); - - BEGIN_RING(chan, rankine, NV34TCL_QUERY_RESET, 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, rankine, NV34TCL_QUERY_UNK17CC, 1); - OUT_RING (chan, 1); - - q->ready = FALSE; -} - -static void -nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - struct nv30_query *q = nv30_query(pq); - - BEGIN_RING(chan, rankine, NV34TCL_QUERY_GET, 1); - OUT_RING (chan, (0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) | - ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT)); - FIRE_RING(chan); -} - -static boolean -nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq, - boolean wait, uint64_t *result) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_query *q = nv30_query(pq); - - assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - if (!q->ready) { - unsigned status; - - status = nouveau_notifier_status(nv30->screen->query, - q->object->start); - if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { - if (wait == FALSE) - return FALSE; - - nouveau_notifier_wait_status(nv30->screen->query, - q->object->start, - NV_NOTIFY_STATE_STATUS_COMPLETED, 0); - } - - q->result = nouveau_notifier_return_val(nv30->screen->query, - q->object->start); - q->ready = TRUE; - nouveau_resource_free(&q->object); - } - - *result = q->result; - return TRUE; -} - -void -nv30_init_query_functions(struct nv30_context *nv30) -{ - nv30->pipe.create_query = nv30_query_create; - nv30->pipe.destroy_query = nv30_query_destroy; - nv30->pipe.begin_query = nv30_query_begin; - nv30->pipe.end_query = nv30_query_end; - nv30->pipe.get_query_result = nv30_query_result; -} diff --git a/src/gallium/drivers/nv30/nv30_shader.h b/src/gallium/drivers/nv30/nv30_shader.h deleted file mode 100644 index dd3a36f78f..0000000000 --- a/src/gallium/drivers/nv30/nv30_shader.h +++ /dev/null @@ -1,490 +0,0 @@ -#ifndef __NV30_SHADER_H__ -#define __NV30_SHADER_H__ - -/* Vertex programs instruction set - * - * 128bit opcodes, split into 4 32-bit ones for ease of use. - * - * Non-native instructions - * ABS - MOV + NV40_VP_INST0_DEST_ABS - * POW - EX2 + MUL + LG2 - * SUB - ADD, second source negated - * SWZ - MOV - * XPD - - * - * Register access - * - Only one INPUT can be accessed per-instruction (move extras into TEMPs) - * - Only one CONST can be accessed per-instruction (move extras into TEMPs) - * - * Relative Addressing - * According to the value returned for - * MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB - * - * there are only two address registers available. The destination in the - * ARL instruction is set to TEMP <n> (The temp isn't actually written). - * - * When using vanilla ARB_v_p, the proprietary driver will squish both the - * available ADDRESS regs into the first hardware reg in the X and Y - * components. - * - * To use an address reg as an index into consts, the CONST_SRC is set to - * (const_base + offset) and INDEX_CONST is set. - * - * To access the second address reg use ADDR_REG_SELECT_1. A particular - * component of the address regs is selected with ADDR_SWZ. - * - * Only one address register can be accessed per instruction. - * - * Conditional execution (see NV_vertex_program{2,3} for details) Conditional - * execution of an instruction is enabled by setting COND_TEST_ENABLE, and - * selecting the condition which will allow the test to pass with - * COND_{FL,LT,...}. It is possible to swizzle the values in the condition - * register, which allows for testing against an individual component. - * - * Branching: - * - * The BRA/CAL instructions seem to follow a slightly different opcode - * layout. The destination instruction ID (IADDR) overlaps a source field. - * Instruction ID's seem to be numbered based on the UPLOAD_FROM_ID FIFO - * command, and is incremented automatically on each UPLOAD_INST FIFO - * command. - * - * Conditional branching is achieved by using the condition tests described - * above. There doesn't appear to be dedicated looping instructions, but - * this can be done using a temp reg + conditional branching. - * - * Subroutines may be uploaded before the main program itself, but the first - * executed instruction is determined by the PROGRAM_START_ID FIFO command. - * - */ - -/* DWORD 0 */ - -#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24) -#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */ -#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */ -#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */ -#define NV30_VP_INST_VEC_RESULT (1 << 20) -#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16 -#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16) -#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15) -#define NV30_VP_INST_VEC_DEST_TEMP_MASK (0xF << 16) -#define NV30_VP_INST_COND_TEST_ENABLE (1<<14) -#define NV30_VP_INST_COND_SHIFT 11 -#define NV30_VP_INST_COND_MASK (0x07 << 11) -# define NV30_VP_INST_COND_FL 0 /* guess */ -# define NV30_VP_INST_COND_LT 1 -# define NV30_VP_INST_COND_EQ 2 -# define NV30_VP_INST_COND_LE 3 -# define NV30_VP_INST_COND_GT 4 -# define NV30_VP_INST_COND_NE 5 -# define NV30_VP_INST_COND_GE 6 -# define NV30_VP_INST_COND_TR 7 /* guess */ -#define NV30_VP_INST_COND_SWZ_X_SHIFT 9 -#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9) -#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7 -#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7) -#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5 -#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5) -#define NV30_VP_INST_COND_SWZ_W_SHIFT 3 -#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3) -#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3 -#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3) -#define NV30_VP_INST_ADDR_SWZ_SHIFT 1 -#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1) -#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0 -#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0) - -/* DWORD 1 */ -#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28 -#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28) -# define NV30_VP_INST_OP_NOP 0x00 -# define NV30_VP_INST_OP_RCP 0x02 -# define NV30_VP_INST_OP_RCC 0x03 -# define NV30_VP_INST_OP_RSQ 0x04 -# define NV30_VP_INST_OP_EXP 0x05 -# define NV30_VP_INST_OP_LOG 0x06 -# define NV30_VP_INST_OP_LIT 0x07 -# define NV30_VP_INST_OP_BRA 0x09 -# define NV30_VP_INST_OP_CAL 0x0B -# define NV30_VP_INST_OP_RET 0x0C -# define NV30_VP_INST_OP_LG2 0x0D -# define NV30_VP_INST_OP_EX2 0x0E -# define NV30_VP_INST_OP_SIN 0x0F -# define NV30_VP_INST_OP_COS 0x10 -#define NV30_VP_INST_VEC_OPCODE_SHIFT 23 -#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23) -# define NV30_VP_INST_OP_NOPV 0x00 -# define NV30_VP_INST_OP_MOV 0x01 -# define NV30_VP_INST_OP_MUL 0x02 -# define NV30_VP_INST_OP_ADD 0x03 -# define NV30_VP_INST_OP_MAD 0x04 -# define NV30_VP_INST_OP_DP3 0x05 -# define NV30_VP_INST_OP_DP4 0x07 -# define NV30_VP_INST_OP_DPH 0x06 -# define NV30_VP_INST_OP_DST 0x08 -# define NV30_VP_INST_OP_MIN 0x09 -# define NV30_VP_INST_OP_MAX 0x0A -# define NV30_VP_INST_OP_SLT 0x0B -# define NV30_VP_INST_OP_SGE 0x0C -# define NV30_VP_INST_OP_ARL 0x0D -# define NV30_VP_INST_OP_FRC 0x0E -# define NV30_VP_INST_OP_FLR 0x0F -# define NV30_VP_INST_OP_SEQ 0x10 -# define NV30_VP_INST_OP_SFL 0x11 -# define NV30_VP_INST_OP_SGT 0x12 -# define NV30_VP_INST_OP_SLE 0x13 -# define NV30_VP_INST_OP_SNE 0x14 -# define NV30_VP_INST_OP_STR 0x15 -# define NV30_VP_INST_OP_SSG 0x16 -# define NV30_VP_INST_OP_ARR 0x17 -# define NV30_VP_INST_OP_ARA 0x18 -#define NV30_VP_INST_CONST_SRC_SHIFT 14 -#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14) -#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/ -#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/ -# define NV30_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */ -# define NV30_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */ -# define NV30_VP_INST_IN_NORMAL 2 -# define NV30_VP_INST_IN_COL0 3 /* Should probably confirm them all though */ -# define NV30_VP_INST_IN_COL1 4 -# define NV30_VP_INST_IN_FOGC 5 -# define NV30_VP_INST_IN_TC0 8 -# define NV30_VP_INST_IN_TC(n) (8+n) -#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/ -#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/ - -/* Please note: the IADDR fields overlap other fields because they are used - * only for branch instructions. See Branching: label above - * - * DWORD 2 - */ -#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/ -#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /* NV30_VP_SRC0_LOW_MASK << 26 */ -#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/ -#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/ -#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/ -#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /* NV30_VP_SRC2_HIGH_MASK >> 4*/ -#define NV30_VP_INST_IADDR_SHIFT 2 -#define NV30_VP_INST_IADDR_MASK (0xF << 28) /* NV30_VP_SRC2_LOW_MASK << 28 */ - -/* DWORD 3 */ -#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/ -#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/ -#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24 -#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24) -#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20 -#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20) -#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16 -#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16) -#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/ -#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/ -#define NV30_VP_INST_DEST_SHIFT 2 -#define NV30_VP_INST_DEST_MASK (0x0F << 2) -# define NV30_VP_INST_DEST_POS 0 -# define NV30_VP_INST_DEST_BFC0 1 -# define NV30_VP_INST_DEST_BFC1 2 -# define NV30_VP_INST_DEST_COL0 3 -# define NV30_VP_INST_DEST_COL1 4 -# define NV30_VP_INST_DEST_FOGC 5 -# define NV30_VP_INST_DEST_PSZ 6 -# define NV30_VP_INST_DEST_TC(n) (8+n) - -#define NV30_VP_INST_LAST (1 << 0) - -/* Useful to split the source selection regs into their pieces */ -#define NV30_VP_SRC0_HIGH_SHIFT 6 -#define NV30_VP_SRC0_HIGH_MASK 0x00007FC0 -#define NV30_VP_SRC0_LOW_MASK 0x0000003F -#define NV30_VP_SRC2_HIGH_SHIFT 4 -#define NV30_VP_SRC2_HIGH_MASK 0x00007FF0 -#define NV30_VP_SRC2_LOW_MASK 0x0000000F - - -/* Source-register definition - matches NV20 exactly */ -#define NV30_VP_SRC_NEGATE (1<<14) -#define NV30_VP_SRC_SWZ_X_SHIFT 12 -#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12) -#define NV30_VP_SRC_SWZ_Y_SHIFT 10 -#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10) -#define NV30_VP_SRC_SWZ_Z_SHIFT 8 -#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8) -#define NV30_VP_SRC_SWZ_W_SHIFT 6 -#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6) -#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6 -#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6) -#define NV30_VP_SRC_TEMP_SRC_SHIFT 2 -#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0) -#define NV30_VP_SRC_REG_TYPE_SHIFT 0 -#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0) -#define NV30_VP_SRC_REG_TYPE_TEMP 1 -#define NV30_VP_SRC_REG_TYPE_INPUT 2 -#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */ - -/* - * Each fragment program opcode appears to be comprised of 4 32-bit values. - * - * 0 - Opcode, output reg/mask, ATTRIB source - * 1 - Source 0 - * 2 - Source 1 - * 3 - Source 2 - * - * There appears to be no special difference between result regs and temp regs. - * result.color == R0.xyzw - * result.depth == R1.z - * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0 - * otherwise it is set to 1. - * - * Constants are inserted directly after the instruction that uses them. - * - * It appears that it's not possible to use two input registers in one - * instruction as the input sourcing is done in the instruction dword - * and not the source selection dwords. As such instructions such as: - * - * ADD result.color, fragment.color, fragment.texcoord[0]; - * - * must be split into two MOV's and then an ADD (nvidia does this) but - * I'm not sure why it's not just one MOV and then source the second input - * in the ADD instruction.. - * - * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary - * negation requires multiplication with a const. - * - * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE - * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO - * is implemented simply by not writing to the relevant components of the destination. - * - * Conditional execution - * TODO - * - * Non-native instructions: - * LIT - * LRP - MAD+MAD - * SUB - ADD, negate second source - * RSQ - LG2 + EX2 - * POW - LG2 + MUL + EX2 - * SCS - COS + SIN - * XPD - */ - -//== Opcode / Destination selection == -#define NV30_FP_OP_PROGRAM_END (1 << 0) -#define NV30_FP_OP_OUT_REG_SHIFT 1 -#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */ -/* Needs to be set when writing outputs to get expected result.. */ -#define NV30_FP_OP_OUT_REG_HALF (1 << 7) -#define NV30_FP_OP_COND_WRITE_ENABLE (1 << 8) -#define NV30_FP_OP_OUTMASK_SHIFT 9 -#define NV30_FP_OP_OUTMASK_MASK (0xF << 9) -# define NV30_FP_OP_OUT_X (1<<9) -# define NV30_FP_OP_OUT_Y (1<<10) -# define NV30_FP_OP_OUT_Z (1<<11) -# define NV30_FP_OP_OUT_W (1<<12) -/* Uncertain about these, especially the input_src values.. it's possible that - * they can be dynamically changed. - */ -#define NV30_FP_OP_INPUT_SRC_SHIFT 13 -#define NV30_FP_OP_INPUT_SRC_MASK (15 << 13) -# define NV30_FP_OP_INPUT_SRC_POSITION 0x0 -# define NV30_FP_OP_INPUT_SRC_COL0 0x1 -# define NV30_FP_OP_INPUT_SRC_COL1 0x2 -# define NV30_FP_OP_INPUT_SRC_FOGC 0x3 -# define NV30_FP_OP_INPUT_SRC_TC0 0x4 -# define NV30_FP_OP_INPUT_SRC_TC(n) (0x4 + n) -#define NV30_FP_OP_TEX_UNIT_SHIFT 17 -#define NV30_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */ -#define NV30_FP_OP_PRECISION_SHIFT 22 -#define NV30_FP_OP_PRECISION_MASK (3 << 22) -# define NV30_FP_PRECISION_FP32 0 -# define NV30_FP_PRECISION_FP16 1 -# define NV30_FP_PRECISION_FX12 2 -#define NV30_FP_OP_OPCODE_SHIFT 24 -#define NV30_FP_OP_OPCODE_MASK (0x3F << 24) -# define NV30_FP_OP_OPCODE_NOP 0x00 -# define NV30_FP_OP_OPCODE_MOV 0x01 -# define NV30_FP_OP_OPCODE_MUL 0x02 -# define NV30_FP_OP_OPCODE_ADD 0x03 -# define NV30_FP_OP_OPCODE_MAD 0x04 -# define NV30_FP_OP_OPCODE_DP3 0x05 -# define NV30_FP_OP_OPCODE_DP4 0x06 -# define NV30_FP_OP_OPCODE_DST 0x07 -# define NV30_FP_OP_OPCODE_MIN 0x08 -# define NV30_FP_OP_OPCODE_MAX 0x09 -# define NV30_FP_OP_OPCODE_SLT 0x0A -# define NV30_FP_OP_OPCODE_SGE 0x0B -# define NV30_FP_OP_OPCODE_SLE 0x0C -# define NV30_FP_OP_OPCODE_SGT 0x0D -# define NV30_FP_OP_OPCODE_SNE 0x0E -# define NV30_FP_OP_OPCODE_SEQ 0x0F -# define NV30_FP_OP_OPCODE_FRC 0x10 -# define NV30_FP_OP_OPCODE_FLR 0x11 -# define NV30_FP_OP_OPCODE_KIL 0x12 -# define NV30_FP_OP_OPCODE_PK4B 0x13 -# define NV30_FP_OP_OPCODE_UP4B 0x14 -# define NV30_FP_OP_OPCODE_DDX 0x15 /* can only write XY */ -# define NV30_FP_OP_OPCODE_DDY 0x16 /* can only write XY */ -# define NV30_FP_OP_OPCODE_TEX 0x17 -# define NV30_FP_OP_OPCODE_TXP 0x18 -# define NV30_FP_OP_OPCODE_TXD 0x19 -# define NV30_FP_OP_OPCODE_RCP 0x1A -# define NV30_FP_OP_OPCODE_RSQ 0x1B -# define NV30_FP_OP_OPCODE_EX2 0x1C -# define NV30_FP_OP_OPCODE_LG2 0x1D -# define NV30_FP_OP_OPCODE_LIT 0x1E -# define NV30_FP_OP_OPCODE_LRP 0x1F -# define NV30_FP_OP_OPCODE_STR 0x20 -# define NV30_FP_OP_OPCODE_SFL 0x21 -# define NV30_FP_OP_OPCODE_COS 0x22 -# define NV30_FP_OP_OPCODE_SIN 0x23 -# define NV30_FP_OP_OPCODE_PK2H 0x24 -# define NV30_FP_OP_OPCODE_UP2H 0x25 -# define NV30_FP_OP_OPCODE_POW 0x26 -# define NV30_FP_OP_OPCODE_PK4UB 0x27 -# define NV30_FP_OP_OPCODE_UP4UB 0x28 -# define NV30_FP_OP_OPCODE_PK2US 0x29 -# define NV30_FP_OP_OPCODE_UP2US 0x2A -# define NV30_FP_OP_OPCODE_DP2A 0x2E -# define NV30_FP_OP_OPCODE_TXB 0x31 -# define NV30_FP_OP_OPCODE_RFL 0x36 -# define NV30_FP_OP_OPCODE_DIV 0x3A -#define NV30_FP_OP_OUT_SAT (1 << 31) - -/* high order bits of SRC0 */ -#define NV30_FP_OP_OUT_ABS (1 << 29) -#define NV30_FP_OP_COND_SWZ_W_SHIFT 27 -#define NV30_FP_OP_COND_SWZ_W_MASK (3 << 27) -#define NV30_FP_OP_COND_SWZ_Z_SHIFT 25 -#define NV30_FP_OP_COND_SWZ_Z_MASK (3 << 25) -#define NV30_FP_OP_COND_SWZ_Y_SHIFT 23 -#define NV30_FP_OP_COND_SWZ_Y_MASK (3 << 23) -#define NV30_FP_OP_COND_SWZ_X_SHIFT 21 -#define NV30_FP_OP_COND_SWZ_X_MASK (3 << 21) -#define NV30_FP_OP_COND_SWZ_ALL_SHIFT 21 -#define NV30_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) -#define NV30_FP_OP_COND_SHIFT 18 -#define NV30_FP_OP_COND_MASK (0x07 << 18) -# define NV30_FP_OP_COND_FL 0 -# define NV30_FP_OP_COND_LT 1 -# define NV30_FP_OP_COND_EQ 2 -# define NV30_FP_OP_COND_LE 3 -# define NV30_FP_OP_COND_GT 4 -# define NV30_FP_OP_COND_NE 5 -# define NV30_FP_OP_COND_GE 6 -# define NV30_FP_OP_COND_TR 7 - -/* high order bits of SRC1 */ -#define NV30_FP_OP_DST_SCALE_SHIFT 28 -#define NV30_FP_OP_DST_SCALE_MASK (3 << 28) -#define NV30_FP_OP_DST_SCALE_1X 0 -#define NV30_FP_OP_DST_SCALE_2X 1 -#define NV30_FP_OP_DST_SCALE_4X 2 -#define NV30_FP_OP_DST_SCALE_8X 3 -#define NV30_FP_OP_DST_SCALE_INV_2X 5 -#define NV30_FP_OP_DST_SCALE_INV_4X 6 -#define NV30_FP_OP_DST_SCALE_INV_8X 7 - - -/* high order bits of SRC2 */ -#define NV30_FP_OP_INDEX_INPUT (1 << 30) - -//== Register selection == -#define NV30_FP_REG_TYPE_SHIFT 0 -#define NV30_FP_REG_TYPE_MASK (3 << 0) -# define NV30_FP_REG_TYPE_TEMP 0 -# define NV30_FP_REG_TYPE_INPUT 1 -# define NV30_FP_REG_TYPE_CONST 2 -#define NV30_FP_REG_SRC_SHIFT 2 /* uncertain */ -#define NV30_FP_REG_SRC_MASK (31 << 2) -#define NV30_FP_REG_SRC_HALF (1 << 8) -#define NV30_FP_REG_SWZ_ALL_SHIFT 9 -#define NV30_FP_REG_SWZ_ALL_MASK (255 << 9) -#define NV30_FP_REG_SWZ_X_SHIFT 9 -#define NV30_FP_REG_SWZ_X_MASK (3 << 9) -#define NV30_FP_REG_SWZ_Y_SHIFT 11 -#define NV30_FP_REG_SWZ_Y_MASK (3 << 11) -#define NV30_FP_REG_SWZ_Z_SHIFT 13 -#define NV30_FP_REG_SWZ_Z_MASK (3 << 13) -#define NV30_FP_REG_SWZ_W_SHIFT 15 -#define NV30_FP_REG_SWZ_W_MASK (3 << 15) -# define NV30_FP_SWIZZLE_X 0 -# define NV30_FP_SWIZZLE_Y 1 -# define NV30_FP_SWIZZLE_Z 2 -# define NV30_FP_SWIZZLE_W 3 -#define NV30_FP_REG_NEGATE (1 << 17) - -#define NV30SR_NONE 0 -#define NV30SR_OUTPUT 1 -#define NV30SR_INPUT 2 -#define NV30SR_TEMP 3 -#define NV30SR_CONST 4 - -struct nv30_sreg { - int type; - int index; - - int dst_scale; - - int negate; - int abs; - int swz[4]; - - int cc_update; - int cc_update_reg; - int cc_test; - int cc_test_reg; - int cc_swz[4]; -}; - -static INLINE struct nv30_sreg -nv30_sr(int type, int index) -{ - struct nv30_sreg temp = { - .type = type, - .index = index, - .dst_scale = DEF_SCALE, - .abs = 0, - .negate = 0, - .swz = { 0, 1, 2, 3 }, - .cc_update = 0, - .cc_update_reg = 0, - .cc_test = DEF_CTEST, - .cc_test_reg = 0, - .cc_swz = { 0, 1, 2, 3 }, - }; - return temp; -} - -static INLINE struct nv30_sreg -nv30_sr_swz(struct nv30_sreg src, int x, int y, int z, int w) -{ - struct nv30_sreg dst = src; - - dst.swz[SWZ_X] = src.swz[x]; - dst.swz[SWZ_Y] = src.swz[y]; - dst.swz[SWZ_Z] = src.swz[z]; - dst.swz[SWZ_W] = src.swz[w]; - return dst; -} - -static INLINE struct nv30_sreg -nv30_sr_neg(struct nv30_sreg src) -{ - src.negate = !src.negate; - return src; -} - -static INLINE struct nv30_sreg -nv30_sr_abs(struct nv30_sreg src) -{ - src.abs = 1; - return src; -} - -static INLINE struct nv30_sreg -nv30_sr_scale(struct nv30_sreg src, int scale) -{ - src.dst_scale = scale; - return src; -} - -#endif diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c deleted file mode 100644 index fb3075f4c8..0000000000 --- a/src/gallium/drivers/nv30/nv30_state.c +++ /dev/null @@ -1,782 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" - -#include "tgsi/tgsi_parse.h" - -#include "nv30_context.h" -#include "nv30_state.h" - -static void * -nv30_blend_state_create(struct pipe_context *pipe, - const struct pipe_blend_state *cso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso)); - struct nouveau_stateobj *so = so_new(5, 8, 0); - - if (cso->rt[0].blend_enable) { - so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3); - so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | - nvgl_blend_func(cso->rt[0].rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rt[0].rgb_dst_factor)); - /* FIXME: Gallium assumes GL_EXT_blend_func_separate. - It is not the case for NV30 */ - so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); - } else { - so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, rankine, NV34TCL_COLOR_MASK, 1); - so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); - - if (cso->logicop_enable) { - so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2); - so_data (so, 1); - so_data (so, nvgl_logicop_func(cso->logicop_func)); - } else { - so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, rankine, NV34TCL_DITHER_ENABLE, 1); - so_data (so, cso->dither ? 1 : 0); - - so_ref(so, &bso->so); - so_ref(NULL, &so); - bso->pipe = *cso; - return (void *)bso; -} - -static void -nv30_blend_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->blend = hwcso; - nv30->dirty |= NV30_NEW_BLEND; -} - -static void -nv30_blend_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_blend_state *bso = hwcso; - - so_ref(NULL, &bso->so); - FREE(bso); -} - - -static INLINE unsigned -wrap_mode(unsigned wrap) { - unsigned ret; - - switch (wrap) { - case PIPE_TEX_WRAP_REPEAT: - ret = NV34TCL_TX_WRAP_S_REPEAT; - break; - case PIPE_TEX_WRAP_MIRROR_REPEAT: - ret = NV34TCL_TX_WRAP_S_MIRRORED_REPEAT; - break; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - ret = NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - ret = NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_CLAMP: - ret = NV34TCL_TX_WRAP_S_CLAMP; - break; -/* case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - ret = NV34TCL_TX_WRAP_S_MIRROR_CLAMP; - break;*/ - default: - NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); - ret = NV34TCL_TX_WRAP_S_REPEAT; - break; - } - - return ret >> NV34TCL_TX_WRAP_S_SHIFT; -} - -static void * -nv30_sampler_state_create(struct pipe_context *pipe, - const struct pipe_sampler_state *cso) -{ - struct nv30_sampler_state *ps; - uint32_t filter = 0; - - ps = MALLOC(sizeof(struct nv30_sampler_state)); - - ps->fmt = 0; - /* TODO: Not all RECTs formats have this bit set, bits 15-8 of format - are the tx format to use. We should store normalized coord flag - in sampler state structure, and set appropriate format in - nvxx_fragtex_build() - */ - /*NV34TCL_TX_FORMAT_RECT*/ - /*if (!cso->normalized_coords) { - ps->fmt |= (1<<14) ; - }*/ - - ps->wrap = ((wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) | - (wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) | - (wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT)); - - ps->en = 0; - - if (cso->max_anisotropy >= 8) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_8X; - } else - if (cso->max_anisotropy >= 4) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_4X; - } else - if (cso->max_anisotropy >= 2) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_2X; - } - - switch (cso->mag_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - filter |= NV34TCL_TX_FILTER_MAGNIFY_LINEAR; - break; - case PIPE_TEX_FILTER_NEAREST: - default: - filter |= NV34TCL_TX_FILTER_MAGNIFY_NEAREST; - break; - } - - switch (cso->min_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR; - break; - } - break; - case PIPE_TEX_FILTER_NEAREST: - default: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST; - break; - } - break; - } - - ps->filt = filter; - - { - float limit; - - limit = CLAMP(cso->lod_bias, -16.0, 15.0); - ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; - - limit = CLAMP(cso->max_lod, 0.0, 15.0); - ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/; - - limit = CLAMP(cso->min_lod, 0.0, 15.0); - ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/; - } - - if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - switch (cso->compare_func) { - case PIPE_FUNC_NEVER: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NEVER; - break; - case PIPE_FUNC_GREATER: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GREATER; - break; - case PIPE_FUNC_EQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_EQUAL; - break; - case PIPE_FUNC_GEQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_GEQUAL; - break; - case PIPE_FUNC_LESS: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LESS; - break; - case PIPE_FUNC_NOTEQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_NOTEQUAL; - break; - case PIPE_FUNC_LEQUAL: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_LEQUAL; - break; - case PIPE_FUNC_ALWAYS: - ps->wrap |= NV34TCL_TX_WRAP_RCOMP_ALWAYS; - break; - default: - break; - } - } - - ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | - (float_to_ubyte(cso->border_color[0]) << 16) | - (float_to_ubyte(cso->border_color[1]) << 8) | - (float_to_ubyte(cso->border_color[2]) << 0)); - - return (void *)ps; -} - -static void -nv30_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) -{ - struct nv30_context *nv30 = nv30_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - nv30->tex_sampler[unit] = sampler[unit]; - nv30->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv30->nr_samplers; unit++) { - nv30->tex_sampler[unit] = NULL; - nv30->dirty_samplers |= (1 << unit); - } - - nv30->nr_samplers = nr; - nv30->dirty |= NV30_NEW_SAMPLER; -} - -static void -nv30_sampler_state_delete(struct pipe_context *pipe, void *hwcso) -{ - FREE(hwcso); -} - -static void -nv30_set_fragment_sampler_views(struct pipe_context *pipe, - unsigned nr, - struct pipe_sampler_view **views) -{ - struct nv30_context *nv30 = nv30_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - pipe_sampler_view_reference(&nv30->fragment_sampler_views[unit], views[unit]); - pipe_texture_reference((struct pipe_texture **) - &nv30->tex_miptree[unit], views[unit]->texture); - nv30->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv30->nr_textures; unit++) { - pipe_sampler_view_reference(&nv30->fragment_sampler_views[unit], NULL); - pipe_texture_reference((struct pipe_texture **) - &nv30->tex_miptree[unit], NULL); - nv30->dirty_samplers |= (1 << unit); - } - - nv30->nr_textures = nr; - nv30->dirty |= NV30_NEW_SAMPLER; -} - -static struct pipe_sampler_view * -nv30_create_sampler_view(struct pipe_context *pipe, - struct pipe_texture *texture, - const struct pipe_sampler_view *templ) -{ - struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); - - if (view) { - *view = *templ; - view->reference.count = 1; - view->texture = NULL; - pipe_texture_reference(&view->texture, texture); - view->context = pipe; - } - - return view; -} - - -static void -nv30_sampler_view_destroy(struct pipe_context *pipe, - struct pipe_sampler_view *view) -{ - pipe_texture_reference(&view->texture, NULL); - FREE(view); -} - -static void * -nv30_rasterizer_state_create(struct pipe_context *pipe, - const struct pipe_rasterizer_state *cso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); - struct nouveau_stateobj *so = so_new(9, 19, 0); - struct nouveau_grobj *rankine = nv30->screen->rankine; - - /*XXX: ignored: - * light_twoside - * point_smooth -nohw - * multisample - */ - - so_method(so, rankine, NV34TCL_SHADE_MODEL, 1); - so_data (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT : - NV34TCL_SHADE_MODEL_SMOOTH); - - so_method(so, rankine, NV34TCL_LINE_WIDTH, 2); - so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff); - so_data (so, cso->line_smooth ? 1 : 0); - so_method(so, rankine, NV34TCL_LINE_STIPPLE_ENABLE, 2); - so_data (so, cso->line_stipple_enable ? 1 : 0); - so_data (so, (cso->line_stipple_pattern << 16) | - cso->line_stipple_factor); - - so_method(so, rankine, NV34TCL_POINT_SIZE, 1); - so_data (so, fui(cso->point_size)); - - so_method(so, rankine, NV34TCL_POLYGON_MODE_FRONT, 6); - if (cso->front_winding == PIPE_WINDING_CCW) { - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV34TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_CW: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV34TCL_FRONT_FACE_CCW); - } else { - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_CW: - so_data(so, NV34TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV34TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV34TCL_FRONT_FACE_CW); - } - so_data(so, cso->poly_smooth ? 1 : 0); - so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); - - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, cso->poly_stipple_enable ? 1 : 0); - - so_method(so, rankine, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) - so_data(so, 1); - else - so_data(so, 0); - if (cso->offset_cw || cso->offset_ccw) { - so_method(so, rankine, NV34TCL_POLYGON_OFFSET_FACTOR, 2); - so_data (so, fui(cso->offset_scale)); - so_data (so, fui(cso->offset_units * 2)); - } - - so_method(so, rankine, NV34TCL_POINT_SPRITE, 1); - if (cso->point_quad_rasterization) { - unsigned psctl = (1 << 0), i; - - for (i = 0; i < 8; i++) { - if ((cso->sprite_coord_enable >> i) & 1) - psctl |= (1 << (8 + i)); - } - - so_data(so, psctl); - } else { - so_data(so, 0); - } - - so_ref(so, &rsso->so); - so_ref(NULL, &so); - rsso->pipe = *cso; - return (void *)rsso; -} - -static void -nv30_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->rasterizer = hwcso; - nv30->dirty |= NV30_NEW_RAST; - /*nv30->draw_dirty |= NV30_NEW_RAST;*/ -} - -static void -nv30_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_rasterizer_state *rsso = hwcso; - - so_ref(NULL, &rsso->so); - FREE(rsso); -} - -static void * -nv30_depth_stencil_alpha_state_create(struct pipe_context *pipe, - const struct pipe_depth_stencil_alpha_state *cso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); - struct nouveau_stateobj *so = so_new(6, 20, 0); - struct nouveau_grobj *rankine = nv30->screen->rankine; - - so_method(so, rankine, NV34TCL_DEPTH_FUNC, 3); - so_data (so, nvgl_comparison_op(cso->depth.func)); - so_data (so, cso->depth.writemask ? 1 : 0); - so_data (so, cso->depth.enabled ? 1 : 0); - - so_method(so, rankine, NV34TCL_ALPHA_FUNC_ENABLE, 3); - so_data (so, cso->alpha.enabled ? 1 : 0); - so_data (so, nvgl_comparison_op(cso->alpha.func)); - so_data (so, float_to_ubyte(cso->alpha.ref_value)); - - if (cso->stencil[0].enabled) { - so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 3); - so_data (so, cso->stencil[0].enabled ? 1 : 0); - so_data (so, cso->stencil[0].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[0].func)); - so_method(so, rankine, NV34TCL_STENCIL_FRONT_FUNC_MASK, 4); - so_data (so, cso->stencil[0].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); - } else { - so_method(so, rankine, NV34TCL_STENCIL_FRONT_ENABLE, 1); - so_data (so, 0); - } - - if (cso->stencil[1].enabled) { - so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 3); - so_data (so, cso->stencil[1].enabled ? 1 : 0); - so_data (so, cso->stencil[1].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[1].func)); - so_method(so, rankine, NV34TCL_STENCIL_BACK_FUNC_MASK, 4); - so_data (so, cso->stencil[1].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); - } else { - so_method(so, rankine, NV34TCL_STENCIL_BACK_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &zsaso->so); - so_ref(NULL, &so); - zsaso->pipe = *cso; - return (void *)zsaso; -} - -static void -nv30_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->zsa = hwcso; - nv30->dirty |= NV30_NEW_ZSA; -} - -static void -nv30_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_zsa_state *zsaso = hwcso; - - so_ref(NULL, &zsaso->so); - FREE(zsaso); -} - -static void * -nv30_vp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - /*struct nv30_context *nv30 = nv30_context(pipe);*/ - struct nv30_vertex_program *vp; - - vp = CALLOC(1, sizeof(struct nv30_vertex_program)); - vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - /*vp->draw = draw_create_vertex_shader(nv30->draw, &vp->pipe);*/ - - return (void *)vp; -} - -static void -nv30_vp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->vertprog = hwcso; - nv30->dirty |= NV30_NEW_VERTPROG; - /*nv30->draw_dirty |= NV30_NEW_VERTPROG;*/ -} - -static void -nv30_vp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_vertex_program *vp = hwcso; - - /*draw_delete_vertex_shader(nv30->draw, vp->draw);*/ - nv30_vertprog_destroy(nv30, vp); - FREE((void*)vp->pipe.tokens); - FREE(vp); -} - -static void * -nv30_fp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - struct nv30_fragment_program *fp; - - fp = CALLOC(1, sizeof(struct nv30_fragment_program)); - fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - - tgsi_scan_shader(fp->pipe.tokens, &fp->info); - - return (void *)fp; -} - -static void -nv30_fp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->fragprog = hwcso; - nv30->dirty |= NV30_NEW_FRAGPROG; -} - -static void -nv30_fp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_fragment_program *fp = hwcso; - - nv30_fragprog_destroy(nv30, fp); - FREE((void*)fp->pipe.tokens); - FREE(fp); -} - -static void -nv30_set_blend_color(struct pipe_context *pipe, - const struct pipe_blend_color *bcol) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->blend_colour = *bcol; - nv30->dirty |= NV30_NEW_BCOL; -} - -static void -nv30_set_stencil_ref(struct pipe_context *pipe, - const struct pipe_stencil_ref *sr) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->stencil_ref = *sr; - nv30->dirty |= NV30_NEW_SR; -} - -static void -nv30_set_clip_state(struct pipe_context *pipe, - const struct pipe_clip_state *clip) -{ -} - -static void -nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf ) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->constbuf[shader] = buf; - nv30->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); - - if (shader == PIPE_SHADER_VERTEX) { - nv30->dirty |= NV30_NEW_VERTPROG; - } else - if (shader == PIPE_SHADER_FRAGMENT) { - nv30->dirty |= NV30_NEW_FRAGPROG; - } -} - -static void -nv30_set_framebuffer_state(struct pipe_context *pipe, - const struct pipe_framebuffer_state *fb) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->framebuffer = *fb; - nv30->dirty |= NV30_NEW_FB; -} - -static void -nv30_set_polygon_stipple(struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - memcpy(nv30->stipple, stipple->stipple, 4 * 32); - nv30->dirty |= NV30_NEW_STIPPLE; -} - -static void -nv30_set_scissor_state(struct pipe_context *pipe, - const struct pipe_scissor_state *s) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->scissor = *s; - nv30->dirty |= NV30_NEW_SCISSOR; -} - -static void -nv30_set_viewport_state(struct pipe_context *pipe, - const struct pipe_viewport_state *vpt) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->viewport = *vpt; - nv30->dirty |= NV30_NEW_VIEWPORT; - /*nv30->draw_dirty |= NV30_NEW_VIEWPORT;*/ -} - -static void -nv30_set_vertex_buffers(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_buffer *vb) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - memcpy(nv30->vtxbuf, vb, sizeof(*vb) * count); - nv30->vtxbuf_nr = count; - - nv30->dirty |= NV30_NEW_ARRAYS; - /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ -} - -static void * -nv30_vtxelts_state_create(struct pipe_context *pipe, - unsigned num_elements, - const struct pipe_vertex_element *elements) -{ - struct nv30_vtxelt_state *cso = CALLOC_STRUCT(nv30_vtxelt_state); - - assert(num_elements < 16); /* not doing fallbacks yet */ - cso->num_elements = num_elements; - memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); - -/* nv30_vtxelt_construct(cso);*/ - - return (void *)cso; -} - -static void -nv30_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) -{ - FREE(hwcso); -} - -static void -nv30_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv30_context *nv30 = nv30_context(pipe); - - nv30->vtxelt = hwcso; - nv30->dirty |= NV30_NEW_ARRAYS; - /*nv30->draw_dirty |= NV30_NEW_ARRAYS;*/ -} - -void -nv30_init_state_functions(struct nv30_context *nv30) -{ - nv30->pipe.create_blend_state = nv30_blend_state_create; - nv30->pipe.bind_blend_state = nv30_blend_state_bind; - nv30->pipe.delete_blend_state = nv30_blend_state_delete; - - nv30->pipe.create_sampler_state = nv30_sampler_state_create; - nv30->pipe.bind_fragment_sampler_states = nv30_sampler_state_bind; - nv30->pipe.delete_sampler_state = nv30_sampler_state_delete; - nv30->pipe.set_fragment_sampler_views = nv30_set_fragment_sampler_views; - nv30->pipe.create_sampler_view = nv30_create_sampler_view; - nv30->pipe.sampler_view_destroy = nv30_sampler_view_destroy; - - nv30->pipe.create_rasterizer_state = nv30_rasterizer_state_create; - nv30->pipe.bind_rasterizer_state = nv30_rasterizer_state_bind; - nv30->pipe.delete_rasterizer_state = nv30_rasterizer_state_delete; - - nv30->pipe.create_depth_stencil_alpha_state = - nv30_depth_stencil_alpha_state_create; - nv30->pipe.bind_depth_stencil_alpha_state = - nv30_depth_stencil_alpha_state_bind; - nv30->pipe.delete_depth_stencil_alpha_state = - nv30_depth_stencil_alpha_state_delete; - - nv30->pipe.create_vs_state = nv30_vp_state_create; - nv30->pipe.bind_vs_state = nv30_vp_state_bind; - nv30->pipe.delete_vs_state = nv30_vp_state_delete; - - nv30->pipe.create_fs_state = nv30_fp_state_create; - nv30->pipe.bind_fs_state = nv30_fp_state_bind; - nv30->pipe.delete_fs_state = nv30_fp_state_delete; - - nv30->pipe.set_blend_color = nv30_set_blend_color; - nv30->pipe.set_stencil_ref = nv30_set_stencil_ref; - nv30->pipe.set_clip_state = nv30_set_clip_state; - nv30->pipe.set_constant_buffer = nv30_set_constant_buffer; - nv30->pipe.set_framebuffer_state = nv30_set_framebuffer_state; - nv30->pipe.set_polygon_stipple = nv30_set_polygon_stipple; - nv30->pipe.set_scissor_state = nv30_set_scissor_state; - nv30->pipe.set_viewport_state = nv30_set_viewport_state; - - nv30->pipe.create_vertex_elements_state = nv30_vtxelts_state_create; - nv30->pipe.delete_vertex_elements_state = nv30_vtxelts_state_delete; - nv30->pipe.bind_vertex_elements_state = nv30_vtxelts_state_bind; - - nv30->pipe.set_vertex_buffers = nv30_set_vertex_buffers; -} - diff --git a/src/gallium/drivers/nv30/nv30_state.h b/src/gallium/drivers/nv30/nv30_state.h deleted file mode 100644 index 66c26360cb..0000000000 --- a/src/gallium/drivers/nv30/nv30_state.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef __NV30_STATE_H__ -#define __NV30_STATE_H__ - -#include "pipe/p_state.h" -#include "tgsi/tgsi_scan.h" - -struct nv30_sampler_state { - uint32_t fmt; - uint32_t wrap; - uint32_t en; - uint32_t filt; - uint32_t bcol; -}; - -struct nv30_vertex_program_exec { - uint32_t data[4]; - boolean has_branch_offset; - int const_index; -}; - -struct nv30_vertex_program_data { - int index; /* immediates == -1 */ - float value[4]; -}; - -struct nv30_vertex_program { - struct pipe_shader_state pipe; - - boolean translated; - - struct nv30_vertex_program_exec *insns; - unsigned nr_insns; - struct nv30_vertex_program_data *consts; - unsigned nr_consts; - - struct nouveau_resource *exec; - unsigned exec_start; - struct nouveau_resource *data; - unsigned data_start; - unsigned data_start_min; - - uint32_t ir; - uint32_t or; - struct nouveau_stateobj *so; -}; - -struct nv30_fragment_program_data { - unsigned offset; - unsigned index; -}; - -struct nv30_fragment_program { - struct pipe_shader_state pipe; - struct tgsi_shader_info info; - - boolean translated; - boolean on_hw; - unsigned samplers; - - uint32_t *insn; - int insn_len; - - struct nv30_fragment_program_data *consts; - unsigned nr_consts; - - struct pipe_buffer *buffer; - - uint32_t fp_control; - uint32_t fp_reg_control; - struct nouveau_stateobj *so; -}; - -#define NV30_MAX_TEXTURE_LEVELS 16 - -struct nv30_miptree { - struct pipe_texture base; - struct nouveau_bo *bo; - - struct pipe_buffer *buffer; - uint total_size; - - struct { - uint pitch; - uint *image_offset; - } level[NV30_MAX_TEXTURE_LEVELS]; -}; - -#endif diff --git a/src/gallium/drivers/nv30/nv30_state_blend.c b/src/gallium/drivers/nv30/nv30_state_blend.c deleted file mode 100644 index c36d58c040..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_blend.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_blend_validate(struct nv30_context *nv30) -{ - so_ref(nv30->blend->so, &nv30->state.hw[NV30_STATE_BLEND]); - return TRUE; -} - -struct nv30_state_entry nv30_state_blend = { - .validate = nv30_state_blend_validate, - .dirty = { - .pipe = NV30_NEW_BLEND, - .hw = NV30_STATE_BLEND - } -}; - -static boolean -nv30_state_blend_colour_validate(struct nv30_context *nv30) -{ - struct nouveau_stateobj *so = so_new(1, 1, 0); - struct pipe_blend_color *bcol = &nv30->blend_colour; - - so_method(so, nv30->screen->rankine, NV34TCL_BLEND_COLOR, 1); - so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | - (float_to_ubyte(bcol->color[0]) << 16) | - (float_to_ubyte(bcol->color[1]) << 8) | - (float_to_ubyte(bcol->color[2]) << 0))); - - so_ref(so, &nv30->state.hw[NV30_STATE_BCOL]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_blend_colour = { - .validate = nv30_state_blend_colour_validate, - .dirty = { - .pipe = NV30_NEW_BCOL, - .hw = NV30_STATE_BCOL - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c deleted file mode 100644 index deefe7fd8d..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_emit.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "nv30_context.h" -#include "nv30_state.h" - -static struct nv30_state_entry *render_states[] = { - &nv30_state_framebuffer, - &nv30_state_rasterizer, - &nv30_state_scissor, - &nv30_state_stipple, - &nv30_state_fragprog, - &nv30_state_fragtex, - &nv30_state_vertprog, - &nv30_state_blend, - &nv30_state_blend_colour, - &nv30_state_zsa, - &nv30_state_sr, - &nv30_state_viewport, - &nv30_state_vbo, - NULL -}; - -static void -nv30_state_do_validate(struct nv30_context *nv30, - struct nv30_state_entry **states) -{ - while (*states) { - struct nv30_state_entry *e = *states; - - if (nv30->dirty & e->dirty.pipe) { - if (e->validate(nv30)) { - nv30->state.dirty |= (1ULL << e->dirty.hw); - } - } - - states++; - } - nv30->dirty = 0; -} - -void -nv30_state_emit(struct nv30_context *nv30) -{ - struct nouveau_channel *chan = nv30->screen->base.channel; - struct nv30_state *state = &nv30->state; - struct nv30_screen *screen = nv30->screen; - unsigned i; - uint64_t states; - - /* XXX: racy! - */ - if (nv30 != screen->cur_ctx) { - for (i = 0; i < NV30_STATE_MAX; i++) { - if (state->hw[i] && screen->state[i] != state->hw[i]) - state->dirty |= (1ULL << i); - } - - screen->cur_ctx = nv30; - } - - for (i = 0, states = state->dirty; states; i++) { - if (!(states & (1ULL << i))) - continue; - so_ref (state->hw[i], &nv30->screen->state[i]); - if (state->hw[i]) - so_emit(chan, nv30->screen->state[i]); - states &= ~(1ULL << i); - } - - state->dirty = 0; -} - -void -nv30_state_flush_notify(struct nouveau_channel *chan) -{ - struct nv30_context *nv30 = chan->user_private; - struct nv30_state *state = &nv30->state; - unsigned i, samplers; - - so_emit_reloc_markers(chan, state->hw[NV30_STATE_FB]); - for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { - if (!(samplers & (1 << i))) - continue; - so_emit_reloc_markers(chan, - state->hw[NV30_STATE_FRAGTEX0+i]); - samplers &= ~(1ULL << i); - } - so_emit_reloc_markers(chan, state->hw[NV30_STATE_FRAGPROG]); - if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/) - so_emit_reloc_markers(chan, state->hw[NV30_STATE_VTXBUF]); -} - -boolean -nv30_state_validate(struct nv30_context *nv30) -{ -#if 0 - boolean was_sw = nv30->fallback_swtnl ? TRUE : FALSE; - - if (nv30->render_mode != HW) { - /* Don't even bother trying to go back to hw if none - * of the states that caused swtnl previously have changed. - */ - if ((nv30->fallback_swtnl & nv30->dirty) - != nv30->fallback_swtnl) - return FALSE; - - /* Attempt to go to hwtnl again */ - nv30->pipe.flush(&nv30->pipe, 0, NULL); - nv30->dirty |= (NV30_NEW_VIEWPORT | - NV30_NEW_VERTPROG | - NV30_NEW_ARRAYS); - nv30->render_mode = HW; - } -#endif - nv30_state_do_validate(nv30, render_states); -#if 0 - if (nv30->fallback_swtnl || nv30->fallback_swrast) - return FALSE; - - if (was_sw) - NOUVEAU_ERR("swtnl->hw\n"); -#endif - return TRUE; -} diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c deleted file mode 100644 index f7fe9833c7..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_fb.c +++ /dev/null @@ -1,173 +0,0 @@ -#include "nv30_context.h" -#include "nouveau/nouveau_util.h" - -static boolean -nv30_state_framebuffer_validate(struct nv30_context *nv30) -{ - struct pipe_framebuffer_state *fb = &nv30->framebuffer; - struct nouveau_channel *chan = nv30->screen->base.channel; - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct nv04_surface *rt[2], *zeta = NULL; - uint32_t rt_enable = 0, rt_format = 0; - int i, colour_format = 0, zeta_format = 0, depth_only = 0; - struct nouveau_stateobj *so = so_new(12, 18, 10); - unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; - unsigned w = fb->width; - unsigned h = fb->height; - struct nv30_miptree *nv30mt; - int colour_bits = 32, zeta_bits = 32; - - for (i = 0; i < fb->nr_cbufs; i++) { - if (colour_format) { - assert(colour_format == fb->cbufs[i]->format); - } else { - colour_format = fb->cbufs[i]->format; - rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i); - rt[i] = (struct nv04_surface *)fb->cbufs[i]; - } - } - - if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) - rt_enable |= NV34TCL_RT_ENABLE_MRT; - - if (fb->zsbuf) { - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0|NV34TCL_RT_ENABLE_COLOR1)) { - /* Render to at least a colour buffer */ - if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); - for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); - - rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | - (log2i(rt[0]->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | - (log2i(rt[0]->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); - } - else - rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; - } else if (fb->zsbuf) { - depth_only = 1; - - /* Render to depth buffer only */ - if (!(zeta->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); - - rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | - (log2i(zeta->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | - (log2i(zeta->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); - } - else - rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; - } else { - return FALSE; - } - - switch (colour_format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - rt_format |= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - case 0: - rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5; - colour_bits = 16; - break; - default: - assert(0); - } - - switch (zeta_format) { - case PIPE_FORMAT_Z16_UNORM: - rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16; - zeta_bits = 16; - break; - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - case 0: - rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8; - break; - default: - assert(0); - } - - if (colour_bits > zeta_bits) { - return FALSE; - } - - if (depth_only || (rt_enable & NV34TCL_RT_ENABLE_COLOR0)) { - struct nv04_surface *rt0 = (depth_only ? zeta : rt[0]); - uint32_t pitch = rt0->pitch; - - if (zeta) { - pitch |= (zeta->pitch << 16); - } else { - pitch |= (pitch << 16); - } - - nv30mt = (struct nv30_miptree *) rt0->base.texture; - so_method(so, rankine, NV34TCL_DMA_COLOR0, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, rankine, NV34TCL_COLOR0_PITCH, 2); - so_data (so, pitch); - so_reloc (so, nouveau_bo(nv30mt->buffer), rt0->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); - } - - if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { - nv30mt = (struct nv30_miptree *)rt[1]->base.texture; - so_method(so, rankine, NV34TCL_DMA_COLOR1, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, rankine, NV34TCL_COLOR1_OFFSET, 2); - so_reloc (so, nouveau_bo(nv30mt->buffer), rt[1]->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_data (so, rt[1]->pitch); - } - - if (zeta_format) { - nv30mt = (struct nv30_miptree *)zeta->base.texture; - so_method(so, rankine, NV34TCL_DMA_ZETA, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, rankine, NV34TCL_ZETA_OFFSET, 1); - so_reloc (so, nouveau_bo(nv30mt->buffer), zeta->base.offset, - rt_flags | NOUVEAU_BO_LOW, 0, 0); - /* TODO: allocate LMA depth buffer */ - } - - so_method(so, rankine, NV34TCL_RT_ENABLE, 1); - so_data (so, rt_enable); - so_method(so, rankine, NV34TCL_RT_HORIZ, 3); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_data (so, rt_format); - so_method(so, rankine, NV34TCL_VIEWPORT_HORIZ, 2); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_method(so, rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); - so_data (so, ((w - 1) << 16) | 0); - so_data (so, ((h - 1) << 16) | 0); - so_method(so, rankine, 0x1d88, 1); - so_data (so, (1 << 12) | h); - /* Wonder why this is needed, context should all be set to zero on init */ - so_method(so, rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1); - so_data (so, 0); - - so_ref(so, &nv30->state.hw[NV30_STATE_FB]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_framebuffer = { - .validate = nv30_state_framebuffer_validate, - .dirty = { - .pipe = NV30_NEW_FB, - .hw = NV30_STATE_FB - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_rasterizer.c b/src/gallium/drivers/nv30/nv30_state_rasterizer.c deleted file mode 100644 index 6d1b60e043..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_rasterizer.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_rasterizer_validate(struct nv30_context *nv30) -{ - so_ref(nv30->rasterizer->so, - &nv30->state.hw[NV30_STATE_RAST]); - return TRUE; -} - -struct nv30_state_entry nv30_state_rasterizer = { - .validate = nv30_state_rasterizer_validate, - .dirty = { - .pipe = NV30_NEW_RAST, - .hw = NV30_STATE_RAST - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_scissor.c b/src/gallium/drivers/nv30/nv30_state_scissor.c deleted file mode 100644 index ba61a9e24a..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_scissor.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_scissor_validate(struct nv30_context *nv30) -{ - struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe; - struct pipe_scissor_state *s = &nv30->scissor; - struct nouveau_stateobj *so; - - if (nv30->state.hw[NV30_STATE_SCISSOR] && - (rast->scissor == 0 && nv30->state.scissor_enabled == 0)) - return FALSE; - nv30->state.scissor_enabled = rast->scissor; - - so = so_new(1, 2, 0); - so_method(so, nv30->screen->rankine, NV34TCL_SCISSOR_HORIZ, 2); - if (nv30->state.scissor_enabled) { - so_data (so, ((s->maxx - s->minx) << 16) | s->minx); - so_data (so, ((s->maxy - s->miny) << 16) | s->miny); - } else { - so_data (so, 4096 << 16); - so_data (so, 4096 << 16); - } - - so_ref(so, &nv30->state.hw[NV30_STATE_SCISSOR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_scissor = { - .validate = nv30_state_scissor_validate, - .dirty = { - .pipe = NV30_NEW_SCISSOR | NV30_NEW_RAST, - .hw = NV30_STATE_SCISSOR - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_stipple.c b/src/gallium/drivers/nv30/nv30_state_stipple.c deleted file mode 100644 index ed520a4f43..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_stipple.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_stipple_validate(struct nv30_context *nv30) -{ - struct pipe_rasterizer_state *rast = &nv30->rasterizer->pipe; - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct nouveau_stateobj *so; - - if (nv30->state.hw[NV30_STATE_STIPPLE] && - (rast->poly_stipple_enable == 0 && nv30->state.stipple_enabled == 0)) - return FALSE; - - if (rast->poly_stipple_enable) { - unsigned i; - - so = so_new(2, 33, 0); - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 1); - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32); - for (i = 0; i < 32; i++) - so_data(so, nv30->stipple[i]); - } else { - so = so_new(1, 1, 0); - so_method(so, rankine, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &nv30->state.hw[NV30_STATE_STIPPLE]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_stipple = { - .validate = nv30_state_stipple_validate, - .dirty = { - .pipe = NV30_NEW_STIPPLE | NV30_NEW_RAST, - .hw = NV30_STATE_STIPPLE, - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_viewport.c b/src/gallium/drivers/nv30/nv30_state_viewport.c deleted file mode 100644 index 6fccd6b60e..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_viewport.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_viewport_validate(struct nv30_context *nv30) -{ - struct pipe_viewport_state *vpt = &nv30->viewport; - struct nouveau_stateobj *so; - - if (nv30->state.hw[NV30_STATE_VIEWPORT] && - !(nv30->dirty & NV30_NEW_VIEWPORT)) - return FALSE; - - so = so_new(3, 10, 0); - so_method(so, nv30->screen->rankine, - NV34TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(vpt->translate[0])); - so_data (so, fui(vpt->translate[1])); - so_data (so, fui(vpt->translate[2])); - so_data (so, fui(vpt->translate[3])); - so_data (so, fui(vpt->scale[0])); - so_data (so, fui(vpt->scale[1])); - so_data (so, fui(vpt->scale[2])); - so_data (so, fui(vpt->scale[3])); -/* so_method(so, nv30->screen->rankine, 0x1d78, 1); - so_data (so, 1); -*/ - /* TODO/FIXME: never saw value 0x0110 in renouveau dumps, only 0x0001 */ - so_method(so, nv30->screen->rankine, 0x1d78, 1); - so_data (so, 1); - - so_ref(so, &nv30->state.hw[NV30_STATE_VIEWPORT]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_viewport = { - .validate = nv30_state_viewport_validate, - .dirty = { - .pipe = NV30_NEW_VIEWPORT | NV30_NEW_RAST, - .hw = NV30_STATE_VIEWPORT - } -}; diff --git a/src/gallium/drivers/nv30/nv30_state_zsa.c b/src/gallium/drivers/nv30/nv30_state_zsa.c deleted file mode 100644 index 88cd74f180..0000000000 --- a/src/gallium/drivers/nv30/nv30_state_zsa.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv30_context.h" - -static boolean -nv30_state_zsa_validate(struct nv30_context *nv30) -{ - so_ref(nv30->zsa->so, - &nv30->state.hw[NV30_STATE_ZSA]); - return TRUE; -} - -struct nv30_state_entry nv30_state_zsa = { - .validate = nv30_state_zsa_validate, - .dirty = { - .pipe = NV30_NEW_ZSA, - .hw = NV30_STATE_ZSA - } -}; - -static boolean -nv30_state_sr_validate(struct nv30_context *nv30) -{ - struct nouveau_stateobj *so = so_new(2, 2, 0); - struct pipe_stencil_ref *sr = &nv30->stencil_ref; - - so_method(so, nv30->screen->rankine, NV34TCL_STENCIL_FRONT_FUNC_REF, 1); - so_data (so, sr->ref_value[0]); - so_method(so, nv30->screen->rankine, NV34TCL_STENCIL_BACK_FUNC_REF, 1); - so_data (so, sr->ref_value[1]); - - so_ref(so, &nv30->state.hw[NV30_STATE_SR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv30_state_entry nv30_state_sr = { - .validate = nv30_state_sr_validate, - .dirty = { - .pipe = NV30_NEW_SR, - .hw = NV30_STATE_SR - } -}; diff --git a/src/gallium/drivers/nv30/nv30_transfer.c b/src/gallium/drivers/nv30/nv30_transfer.c deleted file mode 100644 index 08cc0fa4e3..0000000000 --- a/src/gallium/drivers/nv30/nv30_transfer.c +++ /dev/null @@ -1,182 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "nouveau/nouveau_winsys.h" -#include "nv30_context.h" -#include "nv30_screen.h" -#include "nv30_state.h" - -struct nv30_transfer { - struct pipe_transfer base; - struct pipe_surface *surface; - boolean direct; -}; - -static void -nv30_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, - struct pipe_texture *template) -{ - memset(template, 0, sizeof(struct pipe_texture)); - template->target = pt->target; - template->format = pt->format; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->last_level = 0; - template->nr_samples = pt->nr_samples; - - template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | - NOUVEAU_TEXTURE_USAGE_LINEAR; -} - -static struct pipe_transfer * -nv30_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct pipe_screen *pscreen = pcontext->screen; - struct nv30_miptree *mt = (struct nv30_miptree *)pt; - struct nv30_transfer *tx; - struct pipe_texture tx_tex_template, *tx_tex; - - tx = CALLOC_STRUCT(nv30_transfer); - if (!tx) - return NULL; - - pipe_texture_reference(&tx->base.texture, pt); - tx->base.x = x; - tx->base.y = y; - tx->base.width = w; - tx->base.height = h; - tx->base.stride = mt->level[level].pitch; - tx->base.usage = usage; - tx->base.face = face; - tx->base.level = level; - tx->base.zslice = zslice; - - /* Direct access to texture */ - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || - debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && - pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) - { - tx->direct = true; - tx->surface = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - pipe_transfer_buffer_flags(&tx->base)); - return &tx->base; - } - - tx->direct = false; - - nv30_compatible_transfer_tex(pt, w, h, &tx_tex_template); - - tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); - if (!tx_tex) - { - FREE(tx); - return NULL; - } - - tx->base.stride = ((struct nv30_miptree*)tx_tex)->level[0].pitch; - - tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, - 0, 0, 0, - pipe_transfer_buffer_flags(&tx->base)); - - pipe_texture_reference(&tx_tex, NULL); - - if (!tx->surface) - { - pipe_surface_reference(&tx->surface, NULL); - FREE(tx); - return NULL; - } - - if (usage & PIPE_TRANSFER_READ) { - struct nv30_screen *nvscreen = nv30_screen(pscreen); - struct pipe_surface *src; - - src = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - PIPE_BUFFER_USAGE_GPU_READ); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - /* TODO: Check if SIFM can un-swizzle */ - nvscreen->eng2d->copy(nvscreen->eng2d, - tx->surface, 0, 0, - src, x, y, - w, h); - - pipe_surface_reference(&src, NULL); - } - - return &tx->base; -} - -static void -nv30_transfer_del(struct pipe_context *pcontext, - struct pipe_transfer *ptx) -{ - struct nv30_transfer *tx = (struct nv30_transfer *)ptx; - - if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = pcontext->screen; - struct nv30_screen *nvscreen = nv30_screen(pscreen); - struct pipe_surface *dst; - - dst = pscreen->get_tex_surface(pscreen, ptx->texture, - ptx->face, ptx->level, ptx->zslice, - PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - nvscreen->eng2d->copy(nvscreen->eng2d, - dst, tx->base.x, tx->base.y, - tx->surface, 0, 0, - tx->base.width, tx->base.height); - - pipe_surface_reference(&dst, NULL); - } - - pipe_surface_reference(&tx->surface, NULL); - pipe_texture_reference(&ptx->texture, NULL); - FREE(ptx); -} - -static void * -nv30_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) -{ - struct pipe_screen *pscreen = pcontext->screen; - struct nv30_transfer *tx = (struct nv30_transfer *)ptx; - struct nv04_surface *ns = (struct nv04_surface *)tx->surface; - struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; - void *map = pipe_buffer_map(pscreen, mt->buffer, - pipe_transfer_buffer_flags(ptx)); - - if(!tx->direct) - return map + ns->base.offset; - else - return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format); -} - -static void -nv30_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) -{ - struct pipe_screen *pscreen = pcontext->screen; - struct nv30_transfer *tx = (struct nv30_transfer *)ptx; - struct nv30_miptree *mt = (struct nv30_miptree *)tx->surface->texture; - - pipe_buffer_unmap(pscreen, mt->buffer); -} - -void -nv30_init_transfer_functions(struct nv30_context *nv30) -{ - nv30->pipe.get_transfer = nv30_transfer_new; - nv30->pipe.transfer_destroy = nv30_transfer_del; - nv30->pipe.transfer_map = nv30_transfer_map; - nv30->pipe.transfer_unmap = nv30_transfer_unmap; -} diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c deleted file mode 100644 index 809be3712d..0000000000 --- a/src/gallium/drivers/nv30/nv30_vertprog.c +++ /dev/null @@ -1,842 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_dump.h" - -#include "nv30_context.h" -#include "nv30_state.h" - -/* TODO (at least...): - * 1. Indexed consts + ARL - * 2. Arb. swz/negation - * 3. NV_vp11, NV_vp2, NV_vp3 features - * - extra arith opcodes - * - branching - * - texture sampling - * - indexed attribs - * - indexed results - * 4. bugs - */ - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 8 -#define MASK_Y 4 -#define MASK_Z 2 -#define MASK_W 1 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE 0 -#define DEF_CTEST 0 -#include "nv30_shader.h" - -#define swz(s,x,y,z,w) nv30_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv30_sr_neg((s)) -#define abs(s) nv30_sr_abs((s)) - -struct nv30_vpc { - struct nv30_vertex_program *vp; - - struct nv30_vertex_program_exec *vpi; - - unsigned output_map[PIPE_MAX_SHADER_OUTPUTS]; - - int high_temp; - int temp_temp_count; - - struct nv30_sreg *imm; - unsigned nr_imm; -}; - -static struct nv30_sreg -temp(struct nv30_vpc *vpc) -{ - int idx; - - idx = vpc->temp_temp_count++; - idx += vpc->high_temp + 1; - return nv30_sr(NV30SR_TEMP, idx); -} - -static struct nv30_sreg -constant(struct nv30_vpc *vpc, int pipe, float x, float y, float z, float w) -{ - struct nv30_vertex_program *vp = vpc->vp; - struct nv30_vertex_program_data *vpd; - int idx; - - if (pipe >= 0) { - for (idx = 0; idx < vp->nr_consts; idx++) { - if (vp->consts[idx].index == pipe) - return nv30_sr(NV30SR_CONST, idx); - } - } - - idx = vp->nr_consts++; - vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); - vpd = &vp->consts[idx]; - - vpd->index = pipe; - vpd->value[0] = x; - vpd->value[1] = y; - vpd->value[2] = z; - vpd->value[3] = w; - return nv30_sr(NV30SR_CONST, idx); -} - -#define arith(cc,s,o,d,m,s0,s1,s2) \ - nv30_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2)) - -static void -emit_src(struct nv30_vpc *vpc, uint32_t *hw, int pos, struct nv30_sreg src) -{ - struct nv30_vertex_program *vp = vpc->vp; - uint32_t sr = 0; - - switch (src.type) { - case NV30SR_TEMP: - sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT); - sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT); - break; - case NV30SR_INPUT: - sr |= (NV30_VP_SRC_REG_TYPE_INPUT << - NV30_VP_SRC_REG_TYPE_SHIFT); - vp->ir |= (1 << src.index); - hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT); - break; - case NV30SR_CONST: - sr |= (NV30_VP_SRC_REG_TYPE_CONST << - NV30_VP_SRC_REG_TYPE_SHIFT); - assert(vpc->vpi->const_index == -1 || - vpc->vpi->const_index == src.index); - vpc->vpi->const_index = src.index; - break; - case NV30SR_NONE: - sr |= (NV30_VP_SRC_REG_TYPE_INPUT << - NV30_VP_SRC_REG_TYPE_SHIFT); - break; - default: - assert(0); - } - - if (src.negate) - sr |= NV30_VP_SRC_NEGATE; - - if (src.abs) - hw[0] |= (1 << (21 + pos)); - - sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) | - (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) | - (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) | - (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT)); - -/* - * |VVV| - * d�.�b - * \u/ - * - */ - - switch (pos) { - case 0: - hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >> - NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT; - hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) << - NV30_VP_INST_SRC0L_SHIFT; - break; - case 1: - hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT; - break; - case 2: - hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >> - NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT; - hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) << - NV30_VP_INST_SRC2L_SHIFT; - break; - default: - assert(0); - } -} - -static void -emit_dst(struct nv30_vpc *vpc, uint32_t *hw, int slot, struct nv30_sreg dst) -{ - struct nv30_vertex_program *vp = vpc->vp; - - switch (dst.type) { - case NV30SR_TEMP: - hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT); - break; - case NV30SR_OUTPUT: - switch (dst.index) { - case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; - case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; - case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; - case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; - case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; - case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; - case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; - case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; - case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; - case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; - case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; - case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; - case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; - case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; - default: - break; - } - - hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT); - hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); - - /*XXX: no way this is entirely correct, someone needs to - * figure out what exactly it is. - */ - hw[3] |= 0x800; - break; - default: - assert(0); - } -} - -static void -nv30_vp_arith(struct nv30_vpc *vpc, int slot, int op, - struct nv30_sreg dst, int mask, - struct nv30_sreg s0, struct nv30_sreg s1, - struct nv30_sreg s2) -{ - struct nv30_vertex_program *vp = vpc->vp; - uint32_t *hw; - - vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); - vpc->vpi = &vp->insns[vp->nr_insns - 1]; - memset(vpc->vpi, 0, sizeof(*vpc->vpi)); - vpc->vpi->const_index = -1; - - hw = vpc->vpi->data; - - hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT); - hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) | - (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) | - (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) | - (3 << NV30_VP_INST_COND_SWZ_W_SHIFT)); - - hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT); -// hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK; -// hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT); - - if (dst.type == NV30SR_OUTPUT) { - if (slot) - hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT); - else - hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT); - } else { - if (slot) - hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT); - else - hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT); - } - - emit_dst(vpc, hw, slot, dst); - emit_src(vpc, hw, 0, s0); - emit_src(vpc, hw, 1, s1); - emit_src(vpc, hw, 2, s2); -} - -static INLINE struct nv30_sreg -tgsi_src(struct nv30_vpc *vpc, const struct tgsi_full_src_register *fsrc) { - struct nv30_sreg src; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - src = nv30_sr(NV30SR_INPUT, fsrc->Register.Index); - break; - case TGSI_FILE_CONSTANT: - src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0); - break; - case TGSI_FILE_IMMEDIATE: - src = vpc->imm[fsrc->Register.Index]; - break; - case TGSI_FILE_TEMPORARY: - if (vpc->high_temp < fsrc->Register.Index) - vpc->high_temp = fsrc->Register.Index; - src = nv30_sr(NV30SR_TEMP, fsrc->Register.Index); - break; - default: - NOUVEAU_ERR("bad src file\n"); - break; - } - - src.abs = fsrc->Register.Absolute; - src.negate = fsrc->Register.Negate; - src.swz[0] = fsrc->Register.SwizzleX; - src.swz[1] = fsrc->Register.SwizzleY; - src.swz[2] = fsrc->Register.SwizzleZ; - src.swz[3] = fsrc->Register.SwizzleW; - return src; -} - -static INLINE struct nv30_sreg -tgsi_dst(struct nv30_vpc *vpc, const struct tgsi_full_dst_register *fdst) { - struct nv30_sreg dst; - - switch (fdst->Register.File) { - case TGSI_FILE_OUTPUT: - dst = nv30_sr(NV30SR_OUTPUT, - vpc->output_map[fdst->Register.Index]); - - break; - case TGSI_FILE_TEMPORARY: - dst = nv30_sr(NV30SR_TEMP, fdst->Register.Index); - if (vpc->high_temp < dst.index) - vpc->high_temp = dst.index; - break; - default: - NOUVEAU_ERR("bad dst file\n"); - break; - } - - return dst; -} - -static INLINE int -tgsi_mask(uint tgsi) -{ - int mask = 0; - - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; - return mask; -} - -static boolean -nv30_vertprog_parse_instruction(struct nv30_vpc *vpc, - const struct tgsi_full_instruction *finst) -{ - struct nv30_sreg src[3], dst, tmp; - struct nv30_sreg none = nv30_sr(NV30SR_NONE, 0); - int mask; - int ai = -1, ci = -1; - int i; - - if (finst->Instruction.Opcode == TGSI_OPCODE_END) - return TRUE; - - vpc->temp_temp_count = 0; - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - if (fsrc->Register.File == TGSI_FILE_TEMPORARY) { - src[i] = tgsi_src(vpc, fsrc); - } - } - - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - if (ai == -1 || ai == fsrc->Register.Index) { - ai = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - /*XXX: index comparison is broken now that consts come from - * two different register files. - */ - case TGSI_FILE_CONSTANT: - case TGSI_FILE_IMMEDIATE: - if (ci == -1 || ci == fsrc->Register.Index) { - ci = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - case TGSI_FILE_TEMPORARY: - /* handled above */ - break; - default: - NOUVEAU_ERR("bad src file\n"); - return FALSE; - } - } - - dst = tgsi_dst(vpc, &finst->Dst[0]); - mask = tgsi_mask(finst->Dst[0].Register.WriteMask); - - switch (finst->Instruction.Opcode) { - case TGSI_OPCODE_ABS: - arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); - break; - case TGSI_OPCODE_ADD: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); - break; - case TGSI_OPCODE_ARL: - arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_DP3: - arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DP4: - arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DPH: - arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DST: - arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_EX2: - arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_EXP: - arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_FLR: - arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FRC: - arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_LG2: - arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LIT: - arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LOG: - arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_MAD: - arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAX: - arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MIN: - arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MOV: - arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_MUL: - arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_POW: - tmp = temp(vpc); - arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, - swz(src[0], X, X, X, X)); - arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), - swz(src[1], X, X, X, X), none); - arith(vpc, 1, OP_EX2, dst, mask, none, none, - swz(tmp, X, X, X, X)); - break; - case TGSI_OPCODE_RCP: - arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_RET: - break; - case TGSI_OPCODE_RSQ: - arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_SGE: - arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SGT: - arith(vpc, 0, OP_SGT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SLT: - arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SUB: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); - break; - case TGSI_OPCODE_XPD: - tmp = temp(vpc); - arith(vpc, 0, OP_MUL, tmp, mask, - swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), - swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), - neg(tmp)); - break; - default: - NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); - return FALSE; - } - - return TRUE; -} - -static boolean -nv30_vertprog_parse_decl_output(struct nv30_vpc *vpc, - const struct tgsi_full_declaration *fdec) -{ - int hw; - - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - hw = NV30_VP_INST_DEST_POS; - break; - case TGSI_SEMANTIC_COLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_VP_INST_DEST_COL0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_VP_INST_DEST_COL1; - } else { - NOUVEAU_ERR("bad colour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_BCOLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_VP_INST_DEST_BFC0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_VP_INST_DEST_BFC1; - } else { - NOUVEAU_ERR("bad bcolour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_FOG: - hw = NV30_VP_INST_DEST_FOGC; - break; - case TGSI_SEMANTIC_PSIZE: - hw = NV30_VP_INST_DEST_PSZ; - break; - case TGSI_SEMANTIC_GENERIC: - if (fdec->Semantic.Index <= 7) { - hw = NV30_VP_INST_DEST_TC(fdec->Semantic.Index); - } else { - NOUVEAU_ERR("bad generic semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_EDGEFLAG: - NOUVEAU_ERR("cannot handle edgeflag output\n"); - return FALSE; - default: - NOUVEAU_ERR("bad output semantic\n"); - return FALSE; - } - - vpc->output_map[fdec->Range.First] = hw; - return TRUE; -} - -static boolean -nv30_vertprog_prepare(struct nv30_vpc *vpc) -{ - struct tgsi_parse_context p; - int nr_imm = 0; - - tgsi_parse_init(&p, vpc->vp->pipe.tokens); - while (!tgsi_parse_end_of_tokens(&p)) { - const union tgsi_full_token *tok = &p.FullToken; - - tgsi_parse_token(&p); - switch(tok->Token.Type) { - case TGSI_TOKEN_TYPE_IMMEDIATE: - nr_imm++; - break; - default: - break; - } - } - tgsi_parse_free(&p); - - if (nr_imm) { - vpc->imm = CALLOC(nr_imm, sizeof(struct nv30_sreg)); - assert(vpc->imm); - } - - return TRUE; -} - -static void -nv30_vertprog_translate(struct nv30_context *nv30, - struct nv30_vertex_program *vp) -{ - struct tgsi_parse_context parse; - struct nv30_vpc *vpc = NULL; - - tgsi_dump(vp->pipe.tokens,0); - - vpc = CALLOC(1, sizeof(struct nv30_vpc)); - if (!vpc) - return; - vpc->vp = vp; - vpc->high_temp = -1; - - if (!nv30_vertprog_prepare(vpc)) { - FREE(vpc); - return; - } - - tgsi_parse_init(&parse, vp->pipe.tokens); - - while (!tgsi_parse_end_of_tokens(&parse)) { - tgsi_parse_token(&parse); - - switch (parse.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - { - const struct tgsi_full_declaration *fdec; - fdec = &parse.FullToken.FullDeclaration; - switch (fdec->Declaration.File) { - case TGSI_FILE_OUTPUT: - if (!nv30_vertprog_parse_decl_output(vpc, fdec)) - goto out_err; - break; - default: - break; - } - } - break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - { - const struct tgsi_full_immediate *imm; - - imm = &parse.FullToken.FullImmediate; - assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); - assert(imm->Immediate.NrTokens == 4 + 1); - vpc->imm[vpc->nr_imm++] = - constant(vpc, -1, - imm->u[0].Float, - imm->u[1].Float, - imm->u[2].Float, - imm->u[3].Float); - } - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - const struct tgsi_full_instruction *finst; - finst = &parse.FullToken.FullInstruction; - if (!nv30_vertprog_parse_instruction(vpc, finst)) - goto out_err; - } - break; - default: - break; - } - } - - vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST; - vp->translated = TRUE; -out_err: - tgsi_parse_free(&parse); - FREE(vpc); -} - -static boolean -nv30_vertprog_validate(struct nv30_context *nv30) -{ - struct pipe_screen *pscreen = nv30->pipe.screen; - struct nv30_screen *screen = nv30->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; - struct nv30_vertex_program *vp; - struct pipe_buffer *constbuf; - boolean upload_code = FALSE, upload_data = FALSE; - int i; - - vp = nv30->vertprog; - constbuf = nv30->constbuf[PIPE_SHADER_VERTEX]; - - /* Translate TGSI shader into hw bytecode */ - if (!vp->translated) { - nv30_vertprog_translate(nv30, vp); - if (!vp->translated) - return FALSE; - } - - /* Allocate hw vtxprog exec slots */ - if (!vp->exec) { - struct nouveau_resource *heap = nv30->screen->vp_exec_heap; - struct nouveau_stateobj *so; - uint vplen = vp->nr_insns; - - if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) { - while (heap->next && heap->size < vplen) { - struct nv30_vertex_program *evict; - - evict = heap->next->priv; - nouveau_resource_free(&evict->exec); - } - - if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) - assert(0); - } - - so = so_new(1, 1, 0); - so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1); - so_data (so, vp->exec->start); - so_ref(so, &vp->so); - so_ref(NULL, &so); - - upload_code = TRUE; - } - - /* Allocate hw vtxprog const slots */ - if (vp->nr_consts && !vp->data) { - struct nouveau_resource *heap = nv30->screen->vp_data_heap; - - if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) { - while (heap->next && heap->size < vp->nr_consts) { - struct nv30_vertex_program *evict; - - evict = heap->next->priv; - nouveau_resource_free(&evict->data); - } - - if (nouveau_resource_alloc(heap, vp->nr_consts, vp, - &vp->data)) - assert(0); - } - - /*XXX: handle this some day */ - assert(vp->data->start >= vp->data_start_min); - - upload_data = TRUE; - if (vp->data_start != vp->data->start) - upload_code = TRUE; - } - - /* If exec or data segments moved we need to patch the program to - * fixup offsets and register IDs. - */ - if (vp->exec_start != vp->exec->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv30_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->has_branch_offset) { - assert(0); - } - } - - vp->exec_start = vp->exec->start; - } - - if (vp->nr_consts && vp->data_start != vp->data->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv30_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->const_index >= 0) { - vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK; - vpi->data[1] |= - (vpi->const_index + vp->data->start) << - NV30_VP_INST_CONST_SRC_SHIFT; - - } - } - - vp->data_start = vp->data->start; - } - - /* Update + Upload constant values */ - if (vp->nr_consts) { - float *map = NULL; - - if (constbuf) { - map = pipe_buffer_map(pscreen, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); - } - - for (i = 0; i < vp->nr_consts; i++) { - struct nv30_vertex_program_data *vpd = &vp->consts[i]; - - if (vpd->index >= 0) { - if (!upload_data && - !memcmp(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float))) - continue; - memcpy(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float)); - } - - BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5); - OUT_RING (chan, i + vp->data->start); - OUT_RINGp (chan, (uint32_t *)vpd->value, 4); - } - - if (constbuf) - pipe_buffer_unmap(pscreen, constbuf); - } - - /* Upload vtxprog */ - if (upload_code) { -#if 0 - for (i = 0; i < vp->nr_insns; i++) { - NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n", - i, vp->insns[i].data[0], vp->insns[i].data[1], - vp->insns[i].data[2], vp->insns[i].data[3]); - } -#endif - BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1); - OUT_RING (chan, vp->exec->start); - for (i = 0; i < vp->nr_insns; i++) { - BEGIN_RING(chan, rankine, NV34TCL_VP_UPLOAD_INST(0), 4); - OUT_RINGp (chan, vp->insns[i].data, 4); - } - } - - if (vp->so != nv30->state.hw[NV30_STATE_VERTPROG]) { - so_ref(vp->so, &nv30->state.hw[NV30_STATE_VERTPROG]); - return TRUE; - } - - return FALSE; -} - -void -nv30_vertprog_destroy(struct nv30_context *nv30, struct nv30_vertex_program *vp) -{ - vp->translated = FALSE; - - if (vp->nr_insns) { - FREE(vp->insns); - vp->insns = NULL; - vp->nr_insns = 0; - } - - if (vp->nr_consts) { - FREE(vp->consts); - vp->consts = NULL; - vp->nr_consts = 0; - } - - nouveau_resource_free(&vp->exec); - vp->exec_start = 0; - nouveau_resource_free(&vp->data); - vp->data_start = 0; - vp->data_start_min = 0; - - vp->ir = vp->or = 0; - so_ref(NULL, &vp->so); -} - -struct nv30_state_entry nv30_state_vertprog = { - .validate = nv30_vertprog_validate, - .dirty = { - .pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/, - .hw = NV30_STATE_VERTPROG, - } -}; diff --git a/src/gallium/drivers/nv40/Makefile b/src/gallium/drivers/nv40/Makefile deleted file mode 100644 index 0ecae2b491..0000000000 --- a/src/gallium/drivers/nv40/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -LIBNAME = nv40 - -C_SOURCES = \ - nv40_clear.c \ - nv40_context.c \ - nv40_draw.c \ - nv40_fragprog.c \ - nv40_fragtex.c \ - nv40_miptree.c \ - nv40_query.c \ - nv40_screen.c \ - nv40_state.c \ - nv40_state_blend.c \ - nv40_state_emit.c \ - nv40_state_fb.c \ - nv40_state_rasterizer.c \ - nv40_state_scissor.c \ - nv40_state_stipple.c \ - nv40_state_viewport.c \ - nv40_state_zsa.c \ - nv40_surface.c \ - nv40_transfer.c \ - nv40_vbo.c \ - nv40_vertprog.c - -include ../../Makefile.template diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c deleted file mode 100644 index e828f17643..0000000000 --- a/src/gallium/drivers/nv40/nv40_context.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "draw/draw_context.h" -#include "pipe/p_defines.h" - -#include "nv40_context.h" -#include "nv40_screen.h" - -static void -nv40_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - if (flags & PIPE_FLUSH_TEXTURE_CACHE) { - BEGIN_RING(chan, curie, 0x1fd8, 1); - OUT_RING (chan, 2); - BEGIN_RING(chan, curie, 0x1fd8, 1); - OUT_RING (chan, 1); - } - - FIRE_RING(chan); - if (fence) - *fence = NULL; -} - -static void -nv40_destroy(struct pipe_context *pipe) -{ - struct nv40_context *nv40 = nv40_context(pipe); - unsigned i; - - for (i = 0; i < NV40_STATE_MAX; i++) { - if (nv40->state.hw[i]) - so_ref(NULL, &nv40->state.hw[i]); - } - - if (nv40->draw) - draw_destroy(nv40->draw); - FREE(nv40); -} - -struct pipe_context * -nv40_create(struct pipe_screen *pscreen, void *priv) -{ - struct nv40_screen *screen = nv40_screen(pscreen); - struct pipe_winsys *ws = pscreen->winsys; - struct nv40_context *nv40; - struct nouveau_winsys *nvws = screen->nvws; - - nv40 = CALLOC(1, sizeof(struct nv40_context)); - if (!nv40) - return NULL; - nv40->screen = screen; - - nv40->nvws = nvws; - - nv40->pipe.winsys = ws; - nv40->pipe.priv = priv; - nv40->pipe.screen = pscreen; - nv40->pipe.destroy = nv40_destroy; - nv40->pipe.draw_arrays = nv40_draw_arrays; - nv40->pipe.draw_elements = nv40_draw_elements; - nv40->pipe.clear = nv40_clear; - nv40->pipe.flush = nv40_flush; - - nv40->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv40->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - - screen->base.channel->user_private = nv40; - screen->base.channel->flush_notify = nv40_state_flush_notify; - - nv40_init_query_functions(nv40); - nv40_init_surface_functions(nv40); - nv40_init_state_functions(nv40); - nv40_init_transfer_functions(nv40); - - /* Create, configure, and install fallback swtnl path */ - nv40->draw = draw_create(); - draw_wide_point_threshold(nv40->draw, 9999999.0); - draw_wide_line_threshold(nv40->draw, 9999999.0); - draw_enable_line_stipple(nv40->draw, FALSE); - draw_enable_point_sprites(nv40->draw, FALSE); - draw_set_rasterize_stage(nv40->draw, nv40_draw_render_stage(nv40)); - - return &nv40->pipe; -} diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h deleted file mode 100644 index 1e1d64ee49..0000000000 --- a/src/gallium/drivers/nv40/nv40_context.h +++ /dev/null @@ -1,246 +0,0 @@ -#ifndef __NV40_CONTEXT_H__ -#define __NV40_CONTEXT_H__ - -#include <stdio.h> - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_inlines.h" - -#include "draw/draw_vertex.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_gldefs.h" -#include "nouveau/nouveau_context.h" -#include "nouveau/nouveau_stateobj.h" - -#include "nv40_state.h" - -#define NOUVEAU_ERR(fmt, args...) \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); -#define NOUVEAU_MSG(fmt, args...) \ - fprintf(stderr, "nouveau: "fmt, ##args); - -enum nv40_state_index { - NV40_STATE_FB = 0, - NV40_STATE_VIEWPORT = 1, - NV40_STATE_BLEND = 2, - NV40_STATE_RAST = 3, - NV40_STATE_ZSA = 4, - NV40_STATE_BCOL = 5, - NV40_STATE_CLIP = 6, - NV40_STATE_SCISSOR = 7, - NV40_STATE_STIPPLE = 8, - NV40_STATE_FRAGPROG = 9, - NV40_STATE_VERTPROG = 10, - NV40_STATE_FRAGTEX0 = 11, - NV40_STATE_FRAGTEX1 = 12, - NV40_STATE_FRAGTEX2 = 13, - NV40_STATE_FRAGTEX3 = 14, - NV40_STATE_FRAGTEX4 = 15, - NV40_STATE_FRAGTEX5 = 16, - NV40_STATE_FRAGTEX6 = 17, - NV40_STATE_FRAGTEX7 = 18, - NV40_STATE_FRAGTEX8 = 19, - NV40_STATE_FRAGTEX9 = 20, - NV40_STATE_FRAGTEX10 = 21, - NV40_STATE_FRAGTEX11 = 22, - NV40_STATE_FRAGTEX12 = 23, - NV40_STATE_FRAGTEX13 = 24, - NV40_STATE_FRAGTEX14 = 25, - NV40_STATE_FRAGTEX15 = 26, - NV40_STATE_VERTTEX0 = 27, - NV40_STATE_VERTTEX1 = 28, - NV40_STATE_VERTTEX2 = 29, - NV40_STATE_VERTTEX3 = 30, - NV40_STATE_VTXBUF = 31, - NV40_STATE_VTXFMT = 32, - NV40_STATE_VTXATTR = 33, - NV40_STATE_SR = 34, - NV40_STATE_MAX = 35 -}; - -#include "nv40_screen.h" - -#define NV40_NEW_BLEND (1 << 0) -#define NV40_NEW_RAST (1 << 1) -#define NV40_NEW_ZSA (1 << 2) -#define NV40_NEW_SAMPLER (1 << 3) -#define NV40_NEW_FB (1 << 4) -#define NV40_NEW_STIPPLE (1 << 5) -#define NV40_NEW_SCISSOR (1 << 6) -#define NV40_NEW_VIEWPORT (1 << 7) -#define NV40_NEW_BCOL (1 << 8) -#define NV40_NEW_VERTPROG (1 << 9) -#define NV40_NEW_FRAGPROG (1 << 10) -#define NV40_NEW_ARRAYS (1 << 11) -#define NV40_NEW_UCP (1 << 12) -#define NV40_NEW_SR (1 << 13) - -struct nv40_rasterizer_state { - struct pipe_rasterizer_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv40_zsa_state { - struct pipe_depth_stencil_alpha_state pipe; - struct nouveau_stateobj *so; -}; - -struct nv40_blend_state { - struct pipe_blend_state pipe; - struct nouveau_stateobj *so; -}; - - -struct nv40_state { - unsigned scissor_enabled; - unsigned stipple_enabled; - unsigned fp_samplers; - - uint64_t dirty; - struct nouveau_stateobj *hw[NV40_STATE_MAX]; -}; - - -struct nv40_vtxelt_state { - struct pipe_vertex_element pipe[16]; - unsigned num_elements; -}; - -struct nv40_context { - struct pipe_context pipe; - - struct nouveau_winsys *nvws; - struct nv40_screen *screen; - - struct draw_context *draw; - - /* HW state derived from pipe states */ - struct nv40_state state; - struct { - struct nv40_vertex_program *vertprog; - - unsigned nr_attribs; - unsigned hw[PIPE_MAX_SHADER_INPUTS]; - unsigned draw[PIPE_MAX_SHADER_INPUTS]; - unsigned emit[PIPE_MAX_SHADER_INPUTS]; - } swtnl; - - enum { - HW, SWTNL, SWRAST - } render_mode; - unsigned fallback_swtnl; - unsigned fallback_swrast; - - /* Context state */ - unsigned dirty, draw_dirty; - struct pipe_scissor_state scissor; - unsigned stipple[32]; - struct pipe_clip_state clip; - struct nv40_vertex_program *vertprog; - struct nv40_fragment_program *fragprog; - struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; - unsigned constbuf_nr[PIPE_SHADER_TYPES]; - struct nv40_rasterizer_state *rasterizer; - struct nv40_zsa_state *zsa; - struct nv40_blend_state *blend; - struct pipe_blend_color blend_colour; - struct pipe_stencil_ref stencil_ref; - struct pipe_viewport_state viewport; - struct pipe_framebuffer_state framebuffer; - struct pipe_buffer *idxbuf; - unsigned idxbuf_format; - struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; - struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; - struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; - unsigned nr_samplers; - unsigned nr_textures; - unsigned dirty_samplers; - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - unsigned vtxbuf_nr; - struct nv40_vtxelt_state *vtxelt; -}; - -static INLINE struct nv40_context * -nv40_context(struct pipe_context *pipe) -{ - return (struct nv40_context *)pipe; -} - -struct nv40_state_entry { - boolean (*validate)(struct nv40_context *nv40); - struct { - unsigned pipe; - unsigned hw; - } dirty; -}; - -extern void nv40_init_state_functions(struct nv40_context *nv40); -extern void nv40_init_surface_functions(struct nv40_context *nv40); -extern void nv40_init_query_functions(struct nv40_context *nv40); -extern void nv40_init_transfer_functions(struct nv40_context *nv40); - -extern void nv40_screen_init_miptree_functions(struct pipe_screen *pscreen); - -/* nv40_draw.c */ -extern struct draw_stage *nv40_draw_render_stage(struct nv40_context *nv40); -extern void nv40_draw_elements_swtnl(struct pipe_context *pipe, - struct pipe_buffer *idxbuf, - unsigned ib_size, unsigned mode, - unsigned start, unsigned count); - -/* nv40_vertprog.c */ -extern void nv40_vertprog_destroy(struct nv40_context *, - struct nv40_vertex_program *); - -/* nv40_fragprog.c */ -extern void nv40_fragprog_destroy(struct nv40_context *, - struct nv40_fragment_program *); - -/* nv40_fragtex.c */ -extern void nv40_fragtex_bind(struct nv40_context *); - -/* nv40_state.c and friends */ -extern boolean nv40_state_validate(struct nv40_context *nv40); -extern boolean nv40_state_validate_swtnl(struct nv40_context *nv40); -extern void nv40_state_emit(struct nv40_context *nv40); -extern void nv40_state_flush_notify(struct nouveau_channel *chan); -extern struct nv40_state_entry nv40_state_rasterizer; -extern struct nv40_state_entry nv40_state_scissor; -extern struct nv40_state_entry nv40_state_stipple; -extern struct nv40_state_entry nv40_state_fragprog; -extern struct nv40_state_entry nv40_state_vertprog; -extern struct nv40_state_entry nv40_state_blend; -extern struct nv40_state_entry nv40_state_blend_colour; -extern struct nv40_state_entry nv40_state_zsa; -extern struct nv40_state_entry nv40_state_viewport; -extern struct nv40_state_entry nv40_state_framebuffer; -extern struct nv40_state_entry nv40_state_fragtex; -extern struct nv40_state_entry nv40_state_vbo; -extern struct nv40_state_entry nv40_state_vtxfmt; -extern struct nv40_state_entry nv40_state_sr; - -/* nv40_vbo.c */ -extern void nv40_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv40_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, - unsigned count); - -/* nv40_clear.c */ -extern void nv40_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil); - -/* nv40_context.c */ -struct pipe_context * -nv40_create(struct pipe_screen *pscreen, void *priv); - -#endif diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c deleted file mode 100644 index 48bd84d16c..0000000000 --- a/src/gallium/drivers/nv40/nv40_draw.c +++ /dev/null @@ -1,360 +0,0 @@ -#include "pipe/p_shader_tokens.h" -#include "util/u_inlines.h" - -#include "util/u_pack_color.h" - -#include "draw/draw_context.h" -#include "draw/draw_vertex.h" -#include "draw/draw_pipe.h" - -#include "nv40_context.h" -#define NV40_SHADER_NO_FUCKEDNESS -#include "nv40_shader.h" - -/* Simple, but crappy, swtnl path, hopefully we wont need to hit this very - * often at all. Uses "quadro style" vertex submission + a fixed vertex - * layout to avoid the need to generate a vertex program or vtxfmt. - */ - -struct nv40_render_stage { - struct draw_stage stage; - struct nv40_context *nv40; - unsigned prim; -}; - -static INLINE struct nv40_render_stage * -nv40_render_stage(struct draw_stage *stage) -{ - return (struct nv40_render_stage *)stage; -} - -static INLINE void -nv40_render_vertex(struct nv40_context *nv40, const struct vertex_header *v) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned i; - - for (i = 0; i < nv40->swtnl.nr_attribs; i++) { - unsigned idx = nv40->swtnl.draw[i]; - unsigned hw = nv40->swtnl.hw[i]; - - switch (nv40->swtnl.emit[i]) { - case EMIT_OMIT: - break; - case EMIT_1F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_1F(hw), 1); - OUT_RING (chan, fui(v->data[idx][0])); - break; - case EMIT_2F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_2F_X(hw), 2); - OUT_RING (chan, fui(v->data[idx][0])); - OUT_RING (chan, fui(v->data[idx][1])); - break; - case EMIT_3F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_3F_X(hw), 3); - OUT_RING (chan, fui(v->data[idx][0])); - OUT_RING (chan, fui(v->data[idx][1])); - OUT_RING (chan, fui(v->data[idx][2])); - break; - case EMIT_4F: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_4F_X(hw), 4); - OUT_RING (chan, fui(v->data[idx][0])); - OUT_RING (chan, fui(v->data[idx][1])); - OUT_RING (chan, fui(v->data[idx][2])); - OUT_RING (chan, fui(v->data[idx][3])); - break; - case EMIT_4UB: - BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_4UB(hw), 1); - OUT_RING (chan, pack_ub4(float_to_ubyte(v->data[idx][0]), - float_to_ubyte(v->data[idx][1]), - float_to_ubyte(v->data[idx][2]), - float_to_ubyte(v->data[idx][3]))); - break; - default: - assert(0); - break; - } - } -} - -static INLINE void -nv40_render_prim(struct draw_stage *stage, struct prim_header *prim, - unsigned mode, unsigned count) -{ - struct nv40_render_stage *rs = nv40_render_stage(stage); - struct nv40_context *nv40 = rs->nv40; - - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned i; - - /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */ - if (AVAIL_RING(chan) < ((count * 20) + 6)) { - if (rs->prim != NV40TCL_BEGIN_END_STOP) { - NOUVEAU_ERR("AIII, missed flush\n"); - assert(0); - } - FIRE_RING(chan); - nv40_state_emit(nv40); - } - - /* Switch primitive modes if necessary */ - if (rs->prim != mode) { - if (rs->prim != NV40TCL_BEGIN_END_STOP) { - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, NV40TCL_BEGIN_END_STOP); - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, mode); - rs->prim = mode; - } - - /* Emit vertex data */ - for (i = 0; i < count; i++) - nv40_render_vertex(nv40, prim->v[i]); - - /* If it's likely we'll need to empty the push buffer soon, finish - * off the primitive now. - */ - if (AVAIL_RING(chan) < ((count * 20) + 6)) { - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, NV40TCL_BEGIN_END_STOP); - rs->prim = NV40TCL_BEGIN_END_STOP; - } -} - -static void -nv40_render_point(struct draw_stage *draw, struct prim_header *prim) -{ - nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_POINTS, 1); -} - -static void -nv40_render_line(struct draw_stage *draw, struct prim_header *prim) -{ - nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_LINES, 2); -} - -static void -nv40_render_tri(struct draw_stage *draw, struct prim_header *prim) -{ - nv40_render_prim(draw, prim, NV40TCL_BEGIN_END_TRIANGLES, 3); -} - -static void -nv40_render_flush(struct draw_stage *draw, unsigned flags) -{ - struct nv40_render_stage *rs = nv40_render_stage(draw); - struct nv40_context *nv40 = rs->nv40; - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - if (rs->prim != NV40TCL_BEGIN_END_STOP) { - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, NV40TCL_BEGIN_END_STOP); - rs->prim = NV40TCL_BEGIN_END_STOP; - } -} - -static void -nv40_render_reset_stipple_counter(struct draw_stage *draw) -{ -} - -static void -nv40_render_destroy(struct draw_stage *draw) -{ - FREE(draw); -} - -static INLINE void -emit_mov(struct nv40_vertex_program *vp, - unsigned dst, unsigned src, unsigned vor, unsigned mask) -{ - struct nv40_vertex_program_exec *inst; - - vp->insns = realloc(vp->insns, - sizeof(struct nv40_vertex_program_exec) * - ++vp->nr_insns); - inst = &vp->insns[vp->nr_insns - 1]; - - inst->data[0] = 0x401f9c6c; - inst->data[1] = 0x0040000d | (src << 8); - inst->data[2] = 0x8106c083; - inst->data[3] = 0x6041ff80 | (dst << 2) | (mask << 13); - inst->const_index = -1; - inst->has_branch_offset = FALSE; - - vp->ir |= (1 << src); - if (vor != ~0) - vp->or |= (1 << vor); -} - -static struct nv40_vertex_program * -create_drawvp(struct nv40_context *nv40) -{ - struct nv40_vertex_program *vp = CALLOC_STRUCT(nv40_vertex_program); - unsigned i; - - emit_mov(vp, NV40_VP_INST_DEST_POS, 0, ~0, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_COL0, 3, 0, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_COL1, 4, 1, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_BFC0, 3, 2, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_BFC1, 4, 3, 0xf); - emit_mov(vp, NV40_VP_INST_DEST_FOGC, 5, 4, 0x8); - for (i = 0; i < 8; i++) - emit_mov(vp, NV40_VP_INST_DEST_TC(i), 8 + i, 14 + i, 0xf); - - vp->insns[vp->nr_insns - 1].data[3] |= 1; - vp->translated = TRUE; - return vp; -} - -struct draw_stage * -nv40_draw_render_stage(struct nv40_context *nv40) -{ - struct nv40_render_stage *render = CALLOC_STRUCT(nv40_render_stage); - - if (!nv40->swtnl.vertprog) - nv40->swtnl.vertprog = create_drawvp(nv40); - - render->nv40 = nv40; - render->stage.draw = nv40->draw; - render->stage.point = nv40_render_point; - render->stage.line = nv40_render_line; - render->stage.tri = nv40_render_tri; - render->stage.flush = nv40_render_flush; - render->stage.reset_stipple_counter = nv40_render_reset_stipple_counter; - render->stage.destroy = nv40_render_destroy; - - return &render->stage; -} - -void -nv40_draw_elements_swtnl(struct pipe_context *pipe, - struct pipe_buffer *idxbuf, unsigned idxbuf_size, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct pipe_screen *pscreen = pipe->screen; - unsigned i; - void *map; - - if (!nv40_state_validate_swtnl(nv40)) - return; - nv40->state.dirty &= ~(1ULL << NV40_STATE_VTXBUF); - nv40_state_emit(nv40); - - for (i = 0; i < nv40->vtxbuf_nr; i++) { - map = pipe_buffer_map(pscreen, nv40->vtxbuf[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_vertex_buffer(nv40->draw, i, map); - } - - if (idxbuf) { - map = pipe_buffer_map(pscreen, idxbuf, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(nv40->draw, idxbuf_size, map); - } else { - draw_set_mapped_element_buffer(nv40->draw, 0, NULL); - } - - if (nv40->constbuf[PIPE_SHADER_VERTEX]) { - const unsigned nr = nv40->constbuf_nr[PIPE_SHADER_VERTEX]; - - map = pipe_buffer_map(pscreen, - nv40->constbuf[PIPE_SHADER_VERTEX], - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_constant_buffer(nv40->draw, PIPE_SHADER_VERTEX, 0, - map, nr); - } - - draw_arrays(nv40->draw, mode, start, count); - - for (i = 0; i < nv40->vtxbuf_nr; i++) - pipe_buffer_unmap(pscreen, nv40->vtxbuf[i].buffer); - - if (idxbuf) - pipe_buffer_unmap(pscreen, idxbuf); - - if (nv40->constbuf[PIPE_SHADER_VERTEX]) - pipe_buffer_unmap(pscreen, nv40->constbuf[PIPE_SHADER_VERTEX]); - - draw_flush(nv40->draw); - pipe->flush(pipe, 0, NULL); -} - -static INLINE void -emit_attrib(struct nv40_context *nv40, unsigned hw, unsigned emit, - unsigned semantic, unsigned index) -{ - unsigned draw_out = draw_find_shader_output(nv40->draw, semantic, index); - unsigned a = nv40->swtnl.nr_attribs++; - - nv40->swtnl.hw[a] = hw; - nv40->swtnl.emit[a] = emit; - nv40->swtnl.draw[a] = draw_out; -} - -static boolean -nv40_state_vtxfmt_validate(struct nv40_context *nv40) -{ - struct nv40_fragment_program *fp = nv40->fragprog; - unsigned colour = 0, texcoords = 0, fog = 0, i; - - /* Determine needed fragprog inputs */ - for (i = 0; i < fp->info.num_inputs; i++) { - switch (fp->info.input_semantic_name[i]) { - case TGSI_SEMANTIC_POSITION: - break; - case TGSI_SEMANTIC_COLOR: - colour |= (1 << fp->info.input_semantic_index[i]); - break; - case TGSI_SEMANTIC_GENERIC: - texcoords |= (1 << fp->info.input_semantic_index[i]); - break; - case TGSI_SEMANTIC_FOG: - fog = 1; - break; - default: - assert(0); - } - } - - nv40->swtnl.nr_attribs = 0; - - /* Map draw vtxprog output to hw attribute IDs */ - for (i = 0; i < 2; i++) { - if (!(colour & (1 << i))) - continue; - emit_attrib(nv40, 3 + i, EMIT_4UB, TGSI_SEMANTIC_COLOR, i); - } - - for (i = 0; i < 8; i++) { - if (!(texcoords & (1 << i))) - continue; - emit_attrib(nv40, 8 + i, EMIT_4F, TGSI_SEMANTIC_GENERIC, i); - } - - if (fog) { - emit_attrib(nv40, 5, EMIT_1F, TGSI_SEMANTIC_FOG, 0); - } - - emit_attrib(nv40, 0, EMIT_3F, TGSI_SEMANTIC_POSITION, 0); - - return FALSE; -} - -struct nv40_state_entry nv40_state_vtxfmt = { - .validate = nv40_state_vtxfmt_validate, - .dirty = { - .pipe = NV40_NEW_ARRAYS | NV40_NEW_FRAGPROG, - .hw = 0 - } -}; - diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c deleted file mode 100644 index 8ed4a67dd0..0000000000 --- a/src/gallium/drivers/nv40/nv40_query.c +++ /dev/null @@ -1,127 +0,0 @@ -#include "pipe/p_context.h" - -#include "nv40_context.h" - -struct nv40_query { - struct nouveau_resource *object; - unsigned type; - boolean ready; - uint64_t result; -}; - -static INLINE struct nv40_query * -nv40_query(struct pipe_query *pipe) -{ - return (struct nv40_query *)pipe; -} - -static struct pipe_query * -nv40_query_create(struct pipe_context *pipe, unsigned query_type) -{ - struct nv40_query *q; - - q = CALLOC(1, sizeof(struct nv40_query)); - q->type = query_type; - - return (struct pipe_query *)q; -} - -static void -nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv40_query *q = nv40_query(pq); - - if (q->object) - nouveau_resource_free(&q->object); - FREE(q); -} - -static void -nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_query *q = nv40_query(pq); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - /* Happens when end_query() is called, then another begin_query() - * without querying the result in-between. For now we'll wait for - * the existing query to notify completion, but it could be better. - */ - if (q->object) { - uint64_t tmp; - pipe->get_query_result(pipe, pq, 1, &tmp); - } - - if (nouveau_resource_alloc(nv40->screen->query_heap, 1, NULL, &q->object)) - assert(0); - nouveau_notifier_reset(nv40->screen->query, q->object->start); - - BEGIN_RING(chan, curie, NV40TCL_QUERY_RESET, 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, curie, NV40TCL_QUERY_UNK17CC, 1); - OUT_RING (chan, 1); - - q->ready = FALSE; -} - -static void -nv40_query_end(struct pipe_context *pipe, struct pipe_query *pq) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_query *q = nv40_query(pq); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - BEGIN_RING(chan, curie, NV40TCL_QUERY_GET, 1); - OUT_RING (chan, (0x01 << NV40TCL_QUERY_GET_UNK24_SHIFT) | - ((q->object->start * 32) << NV40TCL_QUERY_GET_OFFSET_SHIFT)); - FIRE_RING(chan); -} - -static boolean -nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq, - boolean wait, uint64_t *result) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_query *q = nv40_query(pq); - - assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); - - if (!q->ready) { - unsigned status; - - status = nouveau_notifier_status(nv40->screen->query, - q->object->start); - if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { - if (wait == FALSE) - return FALSE; - nouveau_notifier_wait_status(nv40->screen->query, - q->object->start, - NV_NOTIFY_STATE_STATUS_COMPLETED, - 0); - } - - q->result = nouveau_notifier_return_val(nv40->screen->query, - q->object->start); - q->ready = TRUE; - nouveau_resource_free(&q->object); - } - - *result = q->result; - return TRUE; -} - -void -nv40_init_query_functions(struct nv40_context *nv40) -{ - nv40->pipe.create_query = nv40_query_create; - nv40->pipe.destroy_query = nv40_query_destroy; - nv40->pipe.begin_query = nv40_query_begin; - nv40->pipe.end_query = nv40_query_end; - nv40->pipe.get_query_result = nv40_query_result; -} diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c deleted file mode 100644 index dbcc33d8d9..0000000000 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ /dev/null @@ -1,319 +0,0 @@ -#include "pipe/p_screen.h" - -#include "nv40_context.h" -#include "nv40_screen.h" - -#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf -#define NV4X_GRCLASS4497_CHIPSETS 0x00005450 -#define NV6X_GRCLASS4497_CHIPSETS 0x00000088 - -static int -nv40_screen_get_param(struct pipe_screen *pscreen, int param) -{ - struct nv40_screen *screen = nv40_screen(pscreen); - - switch (param) { - case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 16; - case PIPE_CAP_NPOT_TEXTURES: - return 1; - case PIPE_CAP_TWO_SIDED_STENCIL: - return 1; - case PIPE_CAP_GLSL: - return 0; - case PIPE_CAP_ANISOTROPIC_FILTER: - return 1; - case PIPE_CAP_POINT_SPRITE: - return 1; - case PIPE_CAP_MAX_RENDER_TARGETS: - return 4; - case PIPE_CAP_OCCLUSION_QUERY: - return 1; - case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 1; - case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 13; - case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 10; - case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 13; - case PIPE_CAP_TEXTURE_MIRROR_CLAMP: - case PIPE_CAP_TEXTURE_MIRROR_REPEAT: - return 1; - case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; /* We have 4 - but unsupported currently */ - case PIPE_CAP_TGSI_CONT_SUPPORTED: - return 0; - case PIPE_CAP_BLEND_EQUATION_SEPARATE: - return 1; - case NOUVEAU_CAP_HW_VTXBUF: - return 1; - case NOUVEAU_CAP_HW_IDXBUF: - if (screen->curie->grclass == NV40TCL) - return 1; - return 0; - case PIPE_CAP_INDEP_BLEND_ENABLE: - return 0; - case PIPE_CAP_INDEP_BLEND_FUNC: - return 0; - case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: - return 1; - case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: - return 0; - case PIPE_CAP_MAX_COMBINED_SAMPLERS: - return 16; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0; - } -} - -static float -nv40_screen_get_paramf(struct pipe_screen *pscreen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_LINE_WIDTH: - case PIPE_CAP_MAX_LINE_WIDTH_AA: - return 10.0; - case PIPE_CAP_MAX_POINT_WIDTH: - case PIPE_CAP_MAX_POINT_WIDTH_AA: - return 64.0; - case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 16.0; - case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: - return 16.0; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0.0; - } -} - -static boolean -nv40_screen_surface_format_supported(struct pipe_screen *pscreen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned tex_usage, unsigned geom_flags) -{ - if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { - switch (format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - return TRUE; - default: - break; - } - } else - if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { - switch (format) { - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - case PIPE_FORMAT_Z16_UNORM: - return TRUE; - default: - break; - } - } else { - switch (format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B5G5R5A1_UNORM: - case PIPE_FORMAT_B4G4R4A4_UNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - case PIPE_FORMAT_R16_SNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_I8_UNORM: - case PIPE_FORMAT_L8A8_UNORM: - case PIPE_FORMAT_Z16_UNORM: - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_DXT1_RGB: - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: - return TRUE; - default: - break; - } - } - - return FALSE; -} - -static struct pipe_buffer * -nv40_surface_buffer(struct pipe_surface *surf) -{ - struct nv40_miptree *mt = (struct nv40_miptree *)surf->texture; - - return mt->buffer; -} - -static void -nv40_screen_destroy(struct pipe_screen *pscreen) -{ - struct nv40_screen *screen = nv40_screen(pscreen); - unsigned i; - - for (i = 0; i < NV40_STATE_MAX; i++) { - if (screen->state[i]) - so_ref(NULL, &screen->state[i]); - } - - nouveau_resource_destroy(&screen->vp_exec_heap); - nouveau_resource_destroy(&screen->vp_data_heap); - nouveau_resource_destroy(&screen->query_heap); - nouveau_notifier_free(&screen->query); - nouveau_notifier_free(&screen->sync); - nouveau_grobj_free(&screen->curie); - nv04_surface_2d_takedown(&screen->eng2d); - - nouveau_screen_fini(&screen->base); - - FREE(pscreen); -} - -struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) -{ - struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); - struct nouveau_channel *chan; - struct pipe_screen *pscreen; - struct nouveau_stateobj *so; - unsigned curie_class = 0; - int ret; - - if (!screen) - return NULL; - pscreen = &screen->base.base; - - ret = nouveau_screen_init(&screen->base, dev); - if (ret) { - nv40_screen_destroy(pscreen); - return NULL; - } - chan = screen->base.channel; - - pscreen->winsys = ws; - pscreen->destroy = nv40_screen_destroy; - pscreen->get_param = nv40_screen_get_param; - pscreen->get_paramf = nv40_screen_get_paramf; - pscreen->is_format_supported = nv40_screen_surface_format_supported; - pscreen->context_create = nv40_create; - - nv40_screen_init_miptree_functions(pscreen); - - /* 3D object */ - switch (dev->chipset & 0xf0) { - case 0x40: - if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f))) - curie_class = NV40TCL; - else - if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) - curie_class = NV44TCL; - break; - case 0x60: - if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) - curie_class = NV44TCL; - break; - } - - if (!curie_class) { - NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", dev->chipset); - return NULL; - } - - ret = nouveau_grobj_alloc(chan, 0xbeef3097, curie_class, &screen->curie); - if (ret) { - NOUVEAU_ERR("Error creating 3D object: %d\n", ret); - return FALSE; - } - - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(&screen->base); - screen->eng2d->buf = nv40_surface_buffer; - - /* Notifier for sync purposes */ - ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); - if (ret) { - NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv40_screen_destroy(pscreen); - return NULL; - } - - /* Query objects */ - ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query); - if (ret) { - NOUVEAU_ERR("Error initialising query objects: %d\n", ret); - nv40_screen_destroy(pscreen); - return NULL; - } - - nouveau_resource_init(&screen->query_heap, 0, 32); - if (ret) { - NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); - nv40_screen_destroy(pscreen); - return NULL; - } - - /* Vtxprog resources */ - if (nouveau_resource_init(&screen->vp_exec_heap, 0, 512) || - nouveau_resource_init(&screen->vp_data_heap, 0, 256)) { - nv40_screen_destroy(pscreen); - return NULL; - } - - /* Static curie initialisation */ - so = so_new(16, 25, 0); - so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1); - so_data (so, screen->sync->handle); - so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->gart->handle); - so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1); - so_data (so, chan->vram->handle); - so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->gart->handle); - so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2); - so_data (so, 0); - so_data (so, screen->query->handle); - so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - - so_method(so, screen->curie, 0x1ea4, 3); - so_data (so, 0x00000010); - so_data (so, 0x01000100); - so_data (so, 0xff800006); - - /* vtxprog output routing */ - so_method(so, screen->curie, 0x1fc4, 1); - so_data (so, 0x06144321); - so_method(so, screen->curie, 0x1fc8, 2); - so_data (so, 0xedcba987); - so_data (so, 0x00000021); - so_method(so, screen->curie, 0x1fd0, 1); - so_data (so, 0x00171615); - so_method(so, screen->curie, 0x1fd4, 1); - so_data (so, 0x001b1a19); - - so_method(so, screen->curie, 0x1ef8, 1); - so_data (so, 0x0020ffff); - so_method(so, screen->curie, 0x1d64, 1); - so_data (so, 0x00d30000); - so_method(so, screen->curie, 0x1e94, 1); - so_data (so, 0x00000001); - - so_emit(chan, so); - so_ref(NULL, &so); - nouveau_pushbuf_flush(chan, 0); - - return pscreen; -} - diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h deleted file mode 100644 index 2765ab764a..0000000000 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __NV40_SCREEN_H__ -#define __NV40_SCREEN_H__ - -#include "nouveau/nouveau_screen.h" -#include "nouveau/nv04_surface_2d.h" - -struct nv40_screen { - struct nouveau_screen base; - - struct nouveau_winsys *nvws; - - struct nv40_context *cur_ctx; - - /* HW graphics objects */ - struct nv04_surface_2d *eng2d; - struct nouveau_grobj *curie; - struct nouveau_notifier *sync; - - /* Query object resources */ - struct nouveau_notifier *query; - struct nouveau_resource *query_heap; - - /* Vtxprog resources */ - struct nouveau_resource *vp_exec_heap; - struct nouveau_resource *vp_data_heap; - - /* Current 3D state of channel */ - struct nouveau_stateobj *state[NV40_STATE_MAX]; -}; - -static INLINE struct nv40_screen * -nv40_screen(struct pipe_screen *screen) -{ - return (struct nv40_screen *)screen; -} - -#endif diff --git a/src/gallium/drivers/nv40/nv40_shader.h b/src/gallium/drivers/nv40/nv40_shader.h deleted file mode 100644 index 854dccf548..0000000000 --- a/src/gallium/drivers/nv40/nv40_shader.h +++ /dev/null @@ -1,556 +0,0 @@ -#ifndef __NV40_SHADER_H__ -#define __NV40_SHADER_H__ - -/* Vertex programs instruction set - * - * The NV40 instruction set is very similar to NV30. Most fields are in - * a slightly different position in the instruction however. - * - * Merged instructions - * In some cases it is possible to put two instructions into one opcode - * slot. The rules for when this is OK is not entirely clear to me yet. - * - * There are separate writemasks and dest temp register fields for each - * grouping of instructions. There is however only one field with the - * ID of a result register. Writing to temp/result regs is selected by - * setting VEC_RESULT/SCA_RESULT. - * - * Temporary registers - * The source/dest temp register fields have been extended by 1 bit, to - * give a total of 32 temporary registers. - * - * Relative Addressing - * NV40 can use an address register to index into vertex attribute regs. - * This is done by putting the offset value into INPUT_SRC and setting - * the INDEX_INPUT flag. - * - * Conditional execution (see NV_vertex_program{2,3} for details) - * There is a second condition code register on NV40, it's use is enabled - * by setting the COND_REG_SELECT_1 flag. - * - * Texture lookup - * TODO - */ - -/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */ -#define NV40_VP_INST_VEC_RESULT (1 << 30) -/* uncertain.. */ -#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29) -/* use address reg as index into attribs */ -#define NV40_VP_INST_INDEX_INPUT (1 << 27) -#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25) -#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24) -#define NV40_VP_INST_SRC2_ABS (1 << 23) -#define NV40_VP_INST_SRC1_ABS (1 << 22) -#define NV40_VP_INST_SRC0_ABS (1 << 21) -#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15 -#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15) -#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13) -#define NV40_VP_INST_COND_SHIFT 10 -#define NV40_VP_INST_COND_MASK (0x7 << 10) -# define NV40_VP_INST_COND_FL 0 -# define NV40_VP_INST_COND_LT 1 -# define NV40_VP_INST_COND_EQ 2 -# define NV40_VP_INST_COND_LE 3 -# define NV40_VP_INST_COND_GT 4 -# define NV40_VP_INST_COND_NE 5 -# define NV40_VP_INST_COND_GE 6 -# define NV40_VP_INST_COND_TR 7 -#define NV40_VP_INST_COND_SWZ_X_SHIFT 8 -#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8) -#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6 -#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6) -#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4 -#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4) -#define NV40_VP_INST_COND_SWZ_W_SHIFT 2 -#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2) -#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2 -#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2) -#define NV40_VP_INST_ADDR_SWZ_SHIFT 0 -#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0) -#define NV40_VP_INST0_KNOWN ( \ - NV40_VP_INST_INDEX_INPUT | \ - NV40_VP_INST_COND_REG_SELECT_1 | \ - NV40_VP_INST_ADDR_REG_SELECT_1 | \ - NV40_VP_INST_SRC2_ABS | \ - NV40_VP_INST_SRC1_ABS | \ - NV40_VP_INST_SRC0_ABS | \ - NV40_VP_INST_VEC_DEST_TEMP_MASK | \ - NV40_VP_INST_COND_TEST_ENABLE | \ - NV40_VP_INST_COND_MASK | \ - NV40_VP_INST_COND_SWZ_ALL_MASK | \ - NV40_VP_INST_ADDR_SWZ_MASK) - -/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */ -#define NV40_VP_INST_VEC_OPCODE_SHIFT 22 -#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22) -# define NV40_VP_INST_OP_NOP 0x00 -# define NV40_VP_INST_OP_MOV 0x01 -# define NV40_VP_INST_OP_MUL 0x02 -# define NV40_VP_INST_OP_ADD 0x03 -# define NV40_VP_INST_OP_MAD 0x04 -# define NV40_VP_INST_OP_DP3 0x05 -# define NV40_VP_INST_OP_DPH 0x06 -# define NV40_VP_INST_OP_DP4 0x07 -# define NV40_VP_INST_OP_DST 0x08 -# define NV40_VP_INST_OP_MIN 0x09 -# define NV40_VP_INST_OP_MAX 0x0A -# define NV40_VP_INST_OP_SLT 0x0B -# define NV40_VP_INST_OP_SGE 0x0C -# define NV40_VP_INST_OP_ARL 0x0D -# define NV40_VP_INST_OP_FRC 0x0E -# define NV40_VP_INST_OP_FLR 0x0F -# define NV40_VP_INST_OP_SEQ 0x10 -# define NV40_VP_INST_OP_SFL 0x11 -# define NV40_VP_INST_OP_SGT 0x12 -# define NV40_VP_INST_OP_SLE 0x13 -# define NV40_VP_INST_OP_SNE 0x14 -# define NV40_VP_INST_OP_STR 0x15 -# define NV40_VP_INST_OP_SSG 0x16 -# define NV40_VP_INST_OP_ARR 0x17 -# define NV40_VP_INST_OP_ARA 0x18 -# define NV40_VP_INST_OP_TXL 0x19 -#define NV40_VP_INST_SCA_OPCODE_SHIFT 27 -#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27) -# define NV40_VP_INST_OP_NOP 0x00 -# define NV40_VP_INST_OP_MOV 0x01 -# define NV40_VP_INST_OP_RCP 0x02 -# define NV40_VP_INST_OP_RCC 0x03 -# define NV40_VP_INST_OP_RSQ 0x04 -# define NV40_VP_INST_OP_EXP 0x05 -# define NV40_VP_INST_OP_LOG 0x06 -# define NV40_VP_INST_OP_LIT 0x07 -# define NV40_VP_INST_OP_BRA 0x09 -# define NV40_VP_INST_OP_CAL 0x0B -# define NV40_VP_INST_OP_RET 0x0C -# define NV40_VP_INST_OP_LG2 0x0D -# define NV40_VP_INST_OP_EX2 0x0E -# define NV40_VP_INST_OP_SIN 0x0F -# define NV40_VP_INST_OP_COS 0x10 -# define NV40_VP_INST_OP_PUSHA 0x13 -# define NV40_VP_INST_OP_POPA 0x14 -#define NV40_VP_INST_CONST_SRC_SHIFT 12 -#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12) -#define NV40_VP_INST_INPUT_SRC_SHIFT 8 -#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8) -# define NV40_VP_INST_IN_POS 0 -# define NV40_VP_INST_IN_WEIGHT 1 -# define NV40_VP_INST_IN_NORMAL 2 -# define NV40_VP_INST_IN_COL0 3 -# define NV40_VP_INST_IN_COL1 4 -# define NV40_VP_INST_IN_FOGC 5 -# define NV40_VP_INST_IN_TC0 8 -# define NV40_VP_INST_IN_TC(n) (8+n) -#define NV40_VP_INST_SRC0H_SHIFT 0 -#define NV40_VP_INST_SRC0H_MASK (0xFF << 0) -#define NV40_VP_INST1_KNOWN ( \ - NV40_VP_INST_VEC_OPCODE_MASK | \ - NV40_VP_INST_SCA_OPCODE_MASK | \ - NV40_VP_INST_CONST_SRC_MASK | \ - NV40_VP_INST_INPUT_SRC_MASK | \ - NV40_VP_INST_SRC0H_MASK \ - ) - -/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */ -#define NV40_VP_INST_SRC0L_SHIFT 23 -#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23) -#define NV40_VP_INST_SRC1_SHIFT 6 -#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6) -#define NV40_VP_INST_SRC2H_SHIFT 0 -#define NV40_VP_INST_SRC2H_MASK (0x3F << 0) -#define NV40_VP_INST_IADDRH_SHIFT 0 -#define NV40_VP_INST_IADDRH_MASK (0x1F << 0) - -/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */ -#define NV40_VP_INST_IADDRL_SHIFT 29 -#define NV40_VP_INST_IADDRL_MASK (7 << 29) -#define NV40_VP_INST_SRC2L_SHIFT 21 -#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21) -#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17 -#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17) -# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20) -# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19) -# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18) -# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17) -#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13 -#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13) -# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16) -# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15) -# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14) -# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13) -#define NV40_VP_INST_SCA_RESULT (1 << 12) -#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7 -#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7) -#define NV40_VP_INST_DEST_SHIFT 2 -#define NV40_VP_INST_DEST_MASK (31 << 2) -# define NV40_VP_INST_DEST_POS 0 -# define NV40_VP_INST_DEST_COL0 1 -# define NV40_VP_INST_DEST_COL1 2 -# define NV40_VP_INST_DEST_BFC0 3 -# define NV40_VP_INST_DEST_BFC1 4 -# define NV40_VP_INST_DEST_FOGC 5 -# define NV40_VP_INST_DEST_PSZ 6 -# define NV40_VP_INST_DEST_TC0 7 -# define NV40_VP_INST_DEST_TC(n) (7+n) -# define NV40_VP_INST_DEST_TEMP 0x1F -#define NV40_VP_INST_INDEX_CONST (1 << 1) -#define NV40_VP_INST_LAST (1 << 0) -#define NV40_VP_INST3_KNOWN ( \ - NV40_VP_INST_SRC2L_MASK |\ - NV40_VP_INST_SCA_WRITEMASK_MASK |\ - NV40_VP_INST_VEC_WRITEMASK_MASK |\ - NV40_VP_INST_SCA_DEST_TEMP_MASK |\ - NV40_VP_INST_DEST_MASK |\ - NV40_VP_INST_INDEX_CONST) - -/* Useful to split the source selection regs into their pieces */ -#define NV40_VP_SRC0_HIGH_SHIFT 9 -#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00 -#define NV40_VP_SRC0_LOW_MASK 0x000001FF -#define NV40_VP_SRC2_HIGH_SHIFT 11 -#define NV40_VP_SRC2_HIGH_MASK 0x0001F800 -#define NV40_VP_SRC2_LOW_MASK 0x000007FF - -/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */ -#define NV40_VP_SRC_NEGATE (1 << 16) -#define NV40_VP_SRC_SWZ_X_SHIFT 14 -#define NV40_VP_SRC_SWZ_X_MASK (3 << 14) -#define NV40_VP_SRC_SWZ_Y_SHIFT 12 -#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12) -#define NV40_VP_SRC_SWZ_Z_SHIFT 10 -#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10) -#define NV40_VP_SRC_SWZ_W_SHIFT 8 -#define NV40_VP_SRC_SWZ_W_MASK (3 << 8) -#define NV40_VP_SRC_SWZ_ALL_SHIFT 8 -#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8) -#define NV40_VP_SRC_TEMP_SRC_SHIFT 2 -#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2) -#define NV40_VP_SRC_REG_TYPE_SHIFT 0 -#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0) -# define NV40_VP_SRC_REG_TYPE_UNK0 0 -# define NV40_VP_SRC_REG_TYPE_TEMP 1 -# define NV40_VP_SRC_REG_TYPE_INPUT 2 -# define NV40_VP_SRC_REG_TYPE_CONST 3 - - -/* - * Each fragment program opcode appears to be comprised of 4 32-bit values. - * - * 0 - Opcode, output reg/mask, ATTRIB source - * 1 - Source 0 - * 2 - Source 1 - * 3 - Source 2 - * - * There appears to be no special difference between result regs and temp regs. - * result.color == R0.xyzw - * result.depth == R1.z - * When the fragprog contains instructions to write depth, - * NV30_TCL_PRIMITIVE_3D_UNK1D78=0 otherwise it is set to 1. - * - * Constants are inserted directly after the instruction that uses them. - * - * It appears that it's not possible to use two input registers in one - * instruction as the input sourcing is done in the instruction dword - * and not the source selection dwords. As such instructions such as: - * - * ADD result.color, fragment.color, fragment.texcoord[0]; - * - * must be split into two MOV's and then an ADD (nvidia does this) but - * I'm not sure why it's not just one MOV and then source the second input - * in the ADD instruction.. - * - * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary - * negation requires multiplication with a const. - * - * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO and - * SWIZZLE_ONE. - * - * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as - * SWIZZLE_ZERO is implemented simply by not writing to the relevant components - * of the destination. - * - * Looping - * Loops appear to be fairly expensive on NV40 at least, the proprietary - * driver goes to a lot of effort to avoid using the native looping - * instructions. If the total number of *executed* instructions between - * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop. - * The maximum loop count is 255. - * - * Conditional execution - * TODO - * - * Non-native instructions: - * LIT - * LRP - MAD+MAD - * SUB - ADD, negate second source - * RSQ - LG2 + EX2 - * POW - LG2 + MUL + EX2 - * SCS - COS + SIN - * XPD - * DP2 - MUL + ADD - * NRM - */ - -//== Opcode / Destination selection == -#define NV40_FP_OP_PROGRAM_END (1 << 0) -#define NV40_FP_OP_OUT_REG_SHIFT 1 -#define NV40_FP_OP_OUT_REG_MASK (63 << 1) -/* Needs to be set when writing outputs to get expected result.. */ -#define NV40_FP_OP_OUT_REG_HALF (1 << 7) -#define NV40_FP_OP_COND_WRITE_ENABLE (1 << 8) -#define NV40_FP_OP_OUTMASK_SHIFT 9 -#define NV40_FP_OP_OUTMASK_MASK (0xF << 9) -# define NV40_FP_OP_OUT_X (1 << 9) -# define NV40_FP_OP_OUT_Y (1 <<10) -# define NV40_FP_OP_OUT_Z (1 <<11) -# define NV40_FP_OP_OUT_W (1 <<12) -/* Uncertain about these, especially the input_src values.. it's possible that - * they can be dynamically changed. - */ -#define NV40_FP_OP_INPUT_SRC_SHIFT 13 -#define NV40_FP_OP_INPUT_SRC_MASK (15 << 13) -# define NV40_FP_OP_INPUT_SRC_POSITION 0x0 -# define NV40_FP_OP_INPUT_SRC_COL0 0x1 -# define NV40_FP_OP_INPUT_SRC_COL1 0x2 -# define NV40_FP_OP_INPUT_SRC_FOGC 0x3 -# define NV40_FP_OP_INPUT_SRC_TC0 0x4 -# define NV40_FP_OP_INPUT_SRC_TC(n) (0x4 + n) -# define NV40_FP_OP_INPUT_SRC_FACING 0xE -#define NV40_FP_OP_TEX_UNIT_SHIFT 17 -#define NV40_FP_OP_TEX_UNIT_MASK (0xF << 17) -#define NV40_FP_OP_PRECISION_SHIFT 22 -#define NV40_FP_OP_PRECISION_MASK (3 << 22) -# define NV40_FP_PRECISION_FP32 0 -# define NV40_FP_PRECISION_FP16 1 -# define NV40_FP_PRECISION_FX12 2 -#define NV40_FP_OP_OPCODE_SHIFT 24 -#define NV40_FP_OP_OPCODE_MASK (0x3F << 24) -# define NV40_FP_OP_OPCODE_NOP 0x00 -# define NV40_FP_OP_OPCODE_MOV 0x01 -# define NV40_FP_OP_OPCODE_MUL 0x02 -# define NV40_FP_OP_OPCODE_ADD 0x03 -# define NV40_FP_OP_OPCODE_MAD 0x04 -# define NV40_FP_OP_OPCODE_DP3 0x05 -# define NV40_FP_OP_OPCODE_DP4 0x06 -# define NV40_FP_OP_OPCODE_DST 0x07 -# define NV40_FP_OP_OPCODE_MIN 0x08 -# define NV40_FP_OP_OPCODE_MAX 0x09 -# define NV40_FP_OP_OPCODE_SLT 0x0A -# define NV40_FP_OP_OPCODE_SGE 0x0B -# define NV40_FP_OP_OPCODE_SLE 0x0C -# define NV40_FP_OP_OPCODE_SGT 0x0D -# define NV40_FP_OP_OPCODE_SNE 0x0E -# define NV40_FP_OP_OPCODE_SEQ 0x0F -# define NV40_FP_OP_OPCODE_FRC 0x10 -# define NV40_FP_OP_OPCODE_FLR 0x11 -# define NV40_FP_OP_OPCODE_KIL 0x12 -# define NV40_FP_OP_OPCODE_PK4B 0x13 -# define NV40_FP_OP_OPCODE_UP4B 0x14 -/* DDX/DDY can only write to XY */ -# define NV40_FP_OP_OPCODE_DDX 0x15 -# define NV40_FP_OP_OPCODE_DDY 0x16 -# define NV40_FP_OP_OPCODE_TEX 0x17 -# define NV40_FP_OP_OPCODE_TXP 0x18 -# define NV40_FP_OP_OPCODE_TXD 0x19 -# define NV40_FP_OP_OPCODE_RCP 0x1A -# define NV40_FP_OP_OPCODE_EX2 0x1C -# define NV40_FP_OP_OPCODE_LG2 0x1D -# define NV40_FP_OP_OPCODE_STR 0x20 -# define NV40_FP_OP_OPCODE_SFL 0x21 -# define NV40_FP_OP_OPCODE_COS 0x22 -# define NV40_FP_OP_OPCODE_SIN 0x23 -# define NV40_FP_OP_OPCODE_PK2H 0x24 -# define NV40_FP_OP_OPCODE_UP2H 0x25 -# define NV40_FP_OP_OPCODE_PK4UB 0x27 -# define NV40_FP_OP_OPCODE_UP4UB 0x28 -# define NV40_FP_OP_OPCODE_PK2US 0x29 -# define NV40_FP_OP_OPCODE_UP2US 0x2A -# define NV40_FP_OP_OPCODE_DP2A 0x2E -# define NV40_FP_OP_OPCODE_TXL 0x2F -# define NV40_FP_OP_OPCODE_TXB 0x31 -# define NV40_FP_OP_OPCODE_DIV 0x3A -# define NV40_FP_OP_OPCODE_UNK_LIT 0x3C -/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/ -# define NV40_FP_OP_BRA_OPCODE_BRK 0x0 -# define NV40_FP_OP_BRA_OPCODE_CAL 0x1 -# define NV40_FP_OP_BRA_OPCODE_IF 0x2 -# define NV40_FP_OP_BRA_OPCODE_LOOP 0x3 -# define NV40_FP_OP_BRA_OPCODE_REP 0x4 -# define NV40_FP_OP_BRA_OPCODE_RET 0x5 -#define NV40_FP_OP_OUT_SAT (1 << 31) - -/* high order bits of SRC0 */ -#define NV40_FP_OP_OUT_ABS (1 << 29) -#define NV40_FP_OP_COND_SWZ_W_SHIFT 27 -#define NV40_FP_OP_COND_SWZ_W_MASK (3 << 27) -#define NV40_FP_OP_COND_SWZ_Z_SHIFT 25 -#define NV40_FP_OP_COND_SWZ_Z_MASK (3 << 25) -#define NV40_FP_OP_COND_SWZ_Y_SHIFT 23 -#define NV40_FP_OP_COND_SWZ_Y_MASK (3 << 23) -#define NV40_FP_OP_COND_SWZ_X_SHIFT 21 -#define NV40_FP_OP_COND_SWZ_X_MASK (3 << 21) -#define NV40_FP_OP_COND_SWZ_ALL_SHIFT 21 -#define NV40_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) -#define NV40_FP_OP_COND_SHIFT 18 -#define NV40_FP_OP_COND_MASK (0x07 << 18) -# define NV40_FP_OP_COND_FL 0 -# define NV40_FP_OP_COND_LT 1 -# define NV40_FP_OP_COND_EQ 2 -# define NV40_FP_OP_COND_LE 3 -# define NV40_FP_OP_COND_GT 4 -# define NV40_FP_OP_COND_NE 5 -# define NV40_FP_OP_COND_GE 6 -# define NV40_FP_OP_COND_TR 7 - -/* high order bits of SRC1 */ -#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31) -#define NV40_FP_OP_DST_SCALE_SHIFT 28 -#define NV40_FP_OP_DST_SCALE_MASK (3 << 28) -#define NV40_FP_OP_DST_SCALE_1X 0 -#define NV40_FP_OP_DST_SCALE_2X 1 -#define NV40_FP_OP_DST_SCALE_4X 2 -#define NV40_FP_OP_DST_SCALE_8X 3 -#define NV40_FP_OP_DST_SCALE_INV_2X 5 -#define NV40_FP_OP_DST_SCALE_INV_4X 6 -#define NV40_FP_OP_DST_SCALE_INV_8X 7 - -/* SRC1 LOOP */ -#define NV40_FP_OP_LOOP_INCR_SHIFT 19 -#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19) -#define NV40_FP_OP_LOOP_INDEX_SHIFT 10 -#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10) -#define NV40_FP_OP_LOOP_COUNT_SHIFT 2 -#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2) - -/* SRC1 IF */ -#define NV40_FP_OP_ELSE_ID_SHIFT 2 -#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2) - -/* SRC1 CAL */ -#define NV40_FP_OP_IADDR_SHIFT 2 -#define NV40_FP_OP_IADDR_MASK (0xFF << 2) - -/* SRC1 REP - * I have no idea why there are 3 count values here.. but they - * have always been filled with the same value in my tests so - * far.. - */ -#define NV40_FP_OP_REP_COUNT1_SHIFT 2 -#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2) -#define NV40_FP_OP_REP_COUNT2_SHIFT 10 -#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10) -#define NV40_FP_OP_REP_COUNT3_SHIFT 19 -#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19) - -/* SRC2 REP/IF */ -#define NV40_FP_OP_END_ID_SHIFT 2 -#define NV40_FP_OP_END_ID_MASK (0xFF << 2) - -// SRC2 high-order -#define NV40_FP_OP_INDEX_INPUT (1 << 30) -#define NV40_FP_OP_ADDR_INDEX_SHIFT 19 -#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19) - -//== Register selection == -#define NV40_FP_REG_TYPE_SHIFT 0 -#define NV40_FP_REG_TYPE_MASK (3 << 0) -# define NV40_FP_REG_TYPE_TEMP 0 -# define NV40_FP_REG_TYPE_INPUT 1 -# define NV40_FP_REG_TYPE_CONST 2 -#define NV40_FP_REG_SRC_SHIFT 2 -#define NV40_FP_REG_SRC_MASK (63 << 2) -#define NV40_FP_REG_SRC_HALF (1 << 8) -#define NV40_FP_REG_SWZ_ALL_SHIFT 9 -#define NV40_FP_REG_SWZ_ALL_MASK (255 << 9) -#define NV40_FP_REG_SWZ_X_SHIFT 9 -#define NV40_FP_REG_SWZ_X_MASK (3 << 9) -#define NV40_FP_REG_SWZ_Y_SHIFT 11 -#define NV40_FP_REG_SWZ_Y_MASK (3 << 11) -#define NV40_FP_REG_SWZ_Z_SHIFT 13 -#define NV40_FP_REG_SWZ_Z_MASK (3 << 13) -#define NV40_FP_REG_SWZ_W_SHIFT 15 -#define NV40_FP_REG_SWZ_W_MASK (3 << 15) -# define NV40_FP_SWIZZLE_X 0 -# define NV40_FP_SWIZZLE_Y 1 -# define NV40_FP_SWIZZLE_Z 2 -# define NV40_FP_SWIZZLE_W 3 -#define NV40_FP_REG_NEGATE (1 << 17) - -#ifndef NV40_SHADER_NO_FUCKEDNESS -#define NV40SR_NONE 0 -#define NV40SR_OUTPUT 1 -#define NV40SR_INPUT 2 -#define NV40SR_TEMP 3 -#define NV40SR_CONST 4 - -struct nv40_sreg { - int type; - int index; - - int dst_scale; - - int negate; - int abs; - int swz[4]; - - int cc_update; - int cc_update_reg; - int cc_test; - int cc_test_reg; - int cc_swz[4]; -}; - -static INLINE struct nv40_sreg -nv40_sr(int type, int index) -{ - struct nv40_sreg temp = { - .type = type, - .index = index, - .dst_scale = DEF_SCALE, - .abs = 0, - .negate = 0, - .swz = { 0, 1, 2, 3 }, - .cc_update = 0, - .cc_update_reg = 0, - .cc_test = DEF_CTEST, - .cc_test_reg = 0, - .cc_swz = { 0, 1, 2, 3 }, - }; - return temp; -} - -static INLINE struct nv40_sreg -nv40_sr_swz(struct nv40_sreg src, int x, int y, int z, int w) -{ - struct nv40_sreg dst = src; - - dst.swz[SWZ_X] = src.swz[x]; - dst.swz[SWZ_Y] = src.swz[y]; - dst.swz[SWZ_Z] = src.swz[z]; - dst.swz[SWZ_W] = src.swz[w]; - return dst; -} - -static INLINE struct nv40_sreg -nv40_sr_neg(struct nv40_sreg src) -{ - src.negate = !src.negate; - return src; -} - -static INLINE struct nv40_sreg -nv40_sr_abs(struct nv40_sreg src) -{ - src.abs = 1; - return src; -} - -static INLINE struct nv40_sreg -nv40_sr_scale(struct nv40_sreg src, int scale) -{ - src.dst_scale = scale; - return src; -} -#endif - -#endif diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c deleted file mode 100644 index 28a48a63f1..0000000000 --- a/src/gallium/drivers/nv40/nv40_state.c +++ /dev/null @@ -1,797 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" - -#include "draw/draw_context.h" - -#include "tgsi/tgsi_parse.h" - -#include "nv40_context.h" -#include "nv40_state.h" - -static void * -nv40_blend_state_create(struct pipe_context *pipe, - const struct pipe_blend_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nouveau_grobj *curie = nv40->screen->curie; - struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso)); - struct nouveau_stateobj *so = so_new(5, 8, 0); - - if (cso->rt[0].blend_enable) { - so_method(so, curie, NV40TCL_BLEND_ENABLE, 3); - so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | - nvgl_blend_func(cso->rt[0].rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rt[0].rgb_dst_factor)); - so_method(so, curie, NV40TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 | - nvgl_blend_eqn(cso->rt[0].rgb_func)); - } else { - so_method(so, curie, NV40TCL_BLEND_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, curie, NV40TCL_COLOR_MASK, 1); - so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); - - if (cso->logicop_enable) { - so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2); - so_data (so, 1); - so_data (so, nvgl_logicop_func(cso->logicop_func)); - } else { - so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1); - so_data (so, 0); - } - - so_method(so, curie, NV40TCL_DITHER_ENABLE, 1); - so_data (so, cso->dither ? 1 : 0); - - so_ref(so, &bso->so); - so_ref(NULL, &so); - bso->pipe = *cso; - return (void *)bso; -} - -static void -nv40_blend_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->blend = hwcso; - nv40->dirty |= NV40_NEW_BLEND; -} - -static void -nv40_blend_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_blend_state *bso = hwcso; - - so_ref(NULL, &bso->so); - FREE(bso); -} - - -static INLINE unsigned -wrap_mode(unsigned wrap) { - unsigned ret; - - switch (wrap) { - case PIPE_TEX_WRAP_REPEAT: - ret = NV40TCL_TEX_WRAP_S_REPEAT; - break; - case PIPE_TEX_WRAP_MIRROR_REPEAT: - ret = NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT; - break; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - ret = NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_CLAMP: - ret = NV40TCL_TEX_WRAP_S_CLAMP; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP; - break; - default: - NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); - ret = NV40TCL_TEX_WRAP_S_REPEAT; - break; - } - - return ret >> NV40TCL_TEX_WRAP_S_SHIFT; -} - -static void * -nv40_sampler_state_create(struct pipe_context *pipe, - const struct pipe_sampler_state *cso) -{ - struct nv40_sampler_state *ps; - uint32_t filter = 0; - - ps = MALLOC(sizeof(struct nv40_sampler_state)); - - ps->fmt = 0; - if (!cso->normalized_coords) - ps->fmt |= NV40TCL_TEX_FORMAT_RECT; - - ps->wrap = ((wrap_mode(cso->wrap_s) << NV40TCL_TEX_WRAP_S_SHIFT) | - (wrap_mode(cso->wrap_t) << NV40TCL_TEX_WRAP_T_SHIFT) | - (wrap_mode(cso->wrap_r) << NV40TCL_TEX_WRAP_R_SHIFT)); - - ps->en = 0; - if (cso->max_anisotropy >= 2) { - /* no idea, binary driver sets it, works without it.. meh.. */ - ps->wrap |= (1 << 5); - - if (cso->max_anisotropy >= 16) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X; - } else - if (cso->max_anisotropy >= 12) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X; - } else - if (cso->max_anisotropy >= 10) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X; - } else - if (cso->max_anisotropy >= 8) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X; - } else - if (cso->max_anisotropy >= 6) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X; - } else - if (cso->max_anisotropy >= 4) { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X; - } else { - ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X; - } - } - - switch (cso->mag_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - filter |= NV40TCL_TEX_FILTER_MAG_LINEAR; - break; - case PIPE_TEX_FILTER_NEAREST: - default: - filter |= NV40TCL_TEX_FILTER_MAG_NEAREST; - break; - } - - switch (cso->min_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV40TCL_TEX_FILTER_MIN_LINEAR; - break; - } - break; - case PIPE_TEX_FILTER_NEAREST: - default: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV40TCL_TEX_FILTER_MIN_NEAREST; - break; - } - break; - } - - ps->filt = filter; - - { - float limit; - - limit = CLAMP(cso->lod_bias, -16.0, 15.0); - ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; - - limit = CLAMP(cso->max_lod, 0.0, 15.0); - ps->en |= (int)(limit * 256.0) << 7; - - limit = CLAMP(cso->min_lod, 0.0, 15.0); - ps->en |= (int)(limit * 256.0) << 19; - } - - - if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - switch (cso->compare_func) { - case PIPE_FUNC_NEVER: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NEVER; - break; - case PIPE_FUNC_GREATER: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GREATER; - break; - case PIPE_FUNC_EQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_EQUAL; - break; - case PIPE_FUNC_GEQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GEQUAL; - break; - case PIPE_FUNC_LESS: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LESS; - break; - case PIPE_FUNC_NOTEQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL; - break; - case PIPE_FUNC_LEQUAL: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LEQUAL; - break; - case PIPE_FUNC_ALWAYS: - ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_ALWAYS; - break; - default: - break; - } - } - - ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | - (float_to_ubyte(cso->border_color[0]) << 16) | - (float_to_ubyte(cso->border_color[1]) << 8) | - (float_to_ubyte(cso->border_color[2]) << 0)); - - return (void *)ps; -} - -static void -nv40_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) -{ - struct nv40_context *nv40 = nv40_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - nv40->tex_sampler[unit] = sampler[unit]; - nv40->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv40->nr_samplers; unit++) { - nv40->tex_sampler[unit] = NULL; - nv40->dirty_samplers |= (1 << unit); - } - - nv40->nr_samplers = nr; - nv40->dirty |= NV40_NEW_SAMPLER; -} - -static void -nv40_sampler_state_delete(struct pipe_context *pipe, void *hwcso) -{ - FREE(hwcso); -} - -static void -nv40_set_fragment_sampler_views(struct pipe_context *pipe, - unsigned nr, - struct pipe_sampler_view **views) -{ - struct nv40_context *nv40 = nv40_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - pipe_sampler_view_reference(&nv40->fragment_sampler_views[unit], views[unit]); - pipe_texture_reference((struct pipe_texture **) - &nv40->tex_miptree[unit], views[unit]->texture); - nv40->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nv40->nr_textures; unit++) { - pipe_sampler_view_reference(&nv40->fragment_sampler_views[unit], NULL); - pipe_texture_reference((struct pipe_texture **) - &nv40->tex_miptree[unit], NULL); - nv40->dirty_samplers |= (1 << unit); - } - - nv40->nr_textures = nr; - nv40->dirty |= NV40_NEW_SAMPLER; -} - -static struct pipe_sampler_view * -nv40_create_sampler_view(struct pipe_context *pipe, - struct pipe_texture *texture, - const struct pipe_sampler_view *templ) -{ - struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); - - if (view) { - *view = *templ; - view->reference.count = 1; - view->texture = NULL; - pipe_texture_reference(&view->texture, texture); - view->context = pipe; - } - - return view; -} - - -static void -nv40_sampler_view_destroy(struct pipe_context *pipe, - struct pipe_sampler_view *view) -{ - pipe_texture_reference(&view->texture, NULL); - FREE(view); -} - -static void * -nv40_rasterizer_state_create(struct pipe_context *pipe, - const struct pipe_rasterizer_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); - struct nouveau_stateobj *so = so_new(9, 19, 0); - struct nouveau_grobj *curie = nv40->screen->curie; - - /*XXX: ignored: - * light_twoside - * point_smooth -nohw - * multisample - */ - - so_method(so, curie, NV40TCL_SHADE_MODEL, 1); - so_data (so, cso->flatshade ? NV40TCL_SHADE_MODEL_FLAT : - NV40TCL_SHADE_MODEL_SMOOTH); - - so_method(so, curie, NV40TCL_LINE_WIDTH, 2); - so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff); - so_data (so, cso->line_smooth ? 1 : 0); - so_method(so, curie, NV40TCL_LINE_STIPPLE_ENABLE, 2); - so_data (so, cso->line_stipple_enable ? 1 : 0); - so_data (so, (cso->line_stipple_pattern << 16) | - cso->line_stipple_factor); - - so_method(so, curie, NV40TCL_POINT_SIZE, 1); - so_data (so, fui(cso->point_size)); - - so_method(so, curie, NV40TCL_POLYGON_MODE_FRONT, 6); - if (cso->front_winding == PIPE_WINDING_CCW) { - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV40TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_CW: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV40TCL_FRONT_FACE_CCW); - } else { - so_data(so, nvgl_polygon_mode(cso->fill_cw)); - so_data(so, nvgl_polygon_mode(cso->fill_ccw)); - switch (cso->cull_mode) { - case PIPE_WINDING_CCW: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - case PIPE_WINDING_CW: - so_data(so, NV40TCL_CULL_FACE_FRONT); - break; - case PIPE_WINDING_BOTH: - so_data(so, NV40TCL_CULL_FACE_FRONT_AND_BACK); - break; - default: - so_data(so, NV40TCL_CULL_FACE_BACK); - break; - } - so_data(so, NV40TCL_FRONT_FACE_CW); - } - so_data(so, cso->poly_smooth ? 1 : 0); - so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); - - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, cso->poly_stipple_enable ? 1 : 0); - - so_method(so, curie, NV40TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) - so_data(so, 1); - else - so_data(so, 0); - if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || - (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) - so_data(so, 1); - else - so_data(so, 0); - if (cso->offset_cw || cso->offset_ccw) { - so_method(so, curie, NV40TCL_POLYGON_OFFSET_FACTOR, 2); - so_data (so, fui(cso->offset_scale)); - so_data (so, fui(cso->offset_units * 2)); - } - - so_method(so, curie, NV40TCL_POINT_SPRITE, 1); - if (cso->point_quad_rasterization) { - unsigned psctl = (1 << 0), i; - - for (i = 0; i < 8; i++) { - if ((cso->sprite_coord_enable >> i) & 1) - psctl |= (1 << (8 + i)); - } - - so_data(so, psctl); - } else { - so_data(so, 0); - } - - so_ref(so, &rsso->so); - so_ref(NULL, &so); - rsso->pipe = *cso; - return (void *)rsso; -} - -static void -nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->rasterizer = hwcso; - nv40->dirty |= NV40_NEW_RAST; - nv40->draw_dirty |= NV40_NEW_RAST; -} - -static void -nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_rasterizer_state *rsso = hwcso; - - so_ref(NULL, &rsso->so); - FREE(rsso); -} - -static void * -nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, - const struct pipe_depth_stencil_alpha_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); - struct nouveau_stateobj *so = so_new(6, 20, 0); - struct nouveau_grobj *curie = nv40->screen->curie; - - so_method(so, curie, NV40TCL_DEPTH_FUNC, 3); - so_data (so, nvgl_comparison_op(cso->depth.func)); - so_data (so, cso->depth.writemask ? 1 : 0); - so_data (so, cso->depth.enabled ? 1 : 0); - - so_method(so, curie, NV40TCL_ALPHA_TEST_ENABLE, 3); - so_data (so, cso->alpha.enabled ? 1 : 0); - so_data (so, nvgl_comparison_op(cso->alpha.func)); - so_data (so, float_to_ubyte(cso->alpha.ref_value)); - - if (cso->stencil[0].enabled) { - so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 3); - so_data (so, cso->stencil[0].enabled ? 1 : 0); - so_data (so, cso->stencil[0].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[0].func)); - so_method(so, curie, NV40TCL_STENCIL_FRONT_FUNC_MASK, 4); - so_data (so, cso->stencil[0].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); - } else { - so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1); - so_data (so, 0); - } - - if (cso->stencil[1].enabled) { - so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 3); - so_data (so, cso->stencil[1].enabled ? 1 : 0); - so_data (so, cso->stencil[1].writemask); - so_data (so, nvgl_comparison_op(cso->stencil[1].func)); - so_method(so, curie, NV40TCL_STENCIL_BACK_FUNC_MASK, 4); - so_data (so, cso->stencil[1].valuemask); - so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); - so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); - } else { - so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &zsaso->so); - so_ref(NULL, &so); - zsaso->pipe = *cso; - return (void *)zsaso; -} - -static void -nv40_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->zsa = hwcso; - nv40->dirty |= NV40_NEW_ZSA; -} - -static void -nv40_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_zsa_state *zsaso = hwcso; - - so_ref(NULL, &zsaso->so); - FREE(zsaso); -} - -static void * -nv40_vp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_vertex_program *vp; - - vp = CALLOC(1, sizeof(struct nv40_vertex_program)); - vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - vp->draw = draw_create_vertex_shader(nv40->draw, &vp->pipe); - - return (void *)vp; -} - -static void -nv40_vp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->vertprog = hwcso; - nv40->dirty |= NV40_NEW_VERTPROG; - nv40->draw_dirty |= NV40_NEW_VERTPROG; -} - -static void -nv40_vp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_vertex_program *vp = hwcso; - - draw_delete_vertex_shader(nv40->draw, vp->draw); - nv40_vertprog_destroy(nv40, vp); - FREE((void*)vp->pipe.tokens); - FREE(vp); -} - -static void * -nv40_fp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - struct nv40_fragment_program *fp; - - fp = CALLOC(1, sizeof(struct nv40_fragment_program)); - fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - - tgsi_scan_shader(fp->pipe.tokens, &fp->info); - - return (void *)fp; -} - -static void -nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->fragprog = hwcso; - nv40->dirty |= NV40_NEW_FRAGPROG; -} - -static void -nv40_fp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_fragment_program *fp = hwcso; - - nv40_fragprog_destroy(nv40, fp); - FREE((void*)fp->pipe.tokens); - FREE(fp); -} - -static void -nv40_set_blend_color(struct pipe_context *pipe, - const struct pipe_blend_color *bcol) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->blend_colour = *bcol; - nv40->dirty |= NV40_NEW_BCOL; -} - - static void -nv40_set_stencil_ref(struct pipe_context *pipe, - const struct pipe_stencil_ref *sr) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->stencil_ref = *sr; - nv40->dirty |= NV40_NEW_SR; -} - -static void -nv40_set_clip_state(struct pipe_context *pipe, - const struct pipe_clip_state *clip) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->clip = *clip; - nv40->dirty |= NV40_NEW_UCP; - nv40->draw_dirty |= NV40_NEW_UCP; -} - -static void -nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf ) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->constbuf[shader] = buf; - nv40->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); - - if (shader == PIPE_SHADER_VERTEX) { - nv40->dirty |= NV40_NEW_VERTPROG; - } else - if (shader == PIPE_SHADER_FRAGMENT) { - nv40->dirty |= NV40_NEW_FRAGPROG; - } -} - -static void -nv40_set_framebuffer_state(struct pipe_context *pipe, - const struct pipe_framebuffer_state *fb) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->framebuffer = *fb; - nv40->dirty |= NV40_NEW_FB; -} - -static void -nv40_set_polygon_stipple(struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - memcpy(nv40->stipple, stipple->stipple, 4 * 32); - nv40->dirty |= NV40_NEW_STIPPLE; -} - -static void -nv40_set_scissor_state(struct pipe_context *pipe, - const struct pipe_scissor_state *s) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->scissor = *s; - nv40->dirty |= NV40_NEW_SCISSOR; -} - -static void -nv40_set_viewport_state(struct pipe_context *pipe, - const struct pipe_viewport_state *vpt) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->viewport = *vpt; - nv40->dirty |= NV40_NEW_VIEWPORT; - nv40->draw_dirty |= NV40_NEW_VIEWPORT; -} - -static void -nv40_set_vertex_buffers(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_buffer *vb) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - memcpy(nv40->vtxbuf, vb, sizeof(*vb) * count); - nv40->vtxbuf_nr = count; - - nv40->dirty |= NV40_NEW_ARRAYS; - nv40->draw_dirty |= NV40_NEW_ARRAYS; -} - -static void * -nv40_vtxelts_state_create(struct pipe_context *pipe, - unsigned num_elements, - const struct pipe_vertex_element *elements) -{ - struct nv40_vtxelt_state *cso = CALLOC_STRUCT(nv40_vtxelt_state); - - assert(num_elements < 16); /* not doing fallbacks yet */ - cso->num_elements = num_elements; - memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); - -/* nv40_vtxelt_construct(cso);*/ - - return (void *)cso; -} - -static void -nv40_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) -{ - FREE(hwcso); -} - -static void -nv40_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv40_context *nv40 = nv40_context(pipe); - - nv40->vtxelt = hwcso; - nv40->dirty |= NV40_NEW_ARRAYS; - nv40->draw_dirty |= NV40_NEW_ARRAYS; -} - -void -nv40_init_state_functions(struct nv40_context *nv40) -{ - nv40->pipe.create_blend_state = nv40_blend_state_create; - nv40->pipe.bind_blend_state = nv40_blend_state_bind; - nv40->pipe.delete_blend_state = nv40_blend_state_delete; - - nv40->pipe.create_sampler_state = nv40_sampler_state_create; - nv40->pipe.bind_fragment_sampler_states = nv40_sampler_state_bind; - nv40->pipe.delete_sampler_state = nv40_sampler_state_delete; - nv40->pipe.set_fragment_sampler_views = nv40_set_fragment_sampler_views; - nv40->pipe.create_sampler_view = nv40_create_sampler_view; - nv40->pipe.sampler_view_destroy = nv40_sampler_view_destroy; - - nv40->pipe.create_rasterizer_state = nv40_rasterizer_state_create; - nv40->pipe.bind_rasterizer_state = nv40_rasterizer_state_bind; - nv40->pipe.delete_rasterizer_state = nv40_rasterizer_state_delete; - - nv40->pipe.create_depth_stencil_alpha_state = - nv40_depth_stencil_alpha_state_create; - nv40->pipe.bind_depth_stencil_alpha_state = - nv40_depth_stencil_alpha_state_bind; - nv40->pipe.delete_depth_stencil_alpha_state = - nv40_depth_stencil_alpha_state_delete; - - nv40->pipe.create_vs_state = nv40_vp_state_create; - nv40->pipe.bind_vs_state = nv40_vp_state_bind; - nv40->pipe.delete_vs_state = nv40_vp_state_delete; - - nv40->pipe.create_fs_state = nv40_fp_state_create; - nv40->pipe.bind_fs_state = nv40_fp_state_bind; - nv40->pipe.delete_fs_state = nv40_fp_state_delete; - - nv40->pipe.set_blend_color = nv40_set_blend_color; - nv40->pipe.set_stencil_ref = nv40_set_stencil_ref; - nv40->pipe.set_clip_state = nv40_set_clip_state; - nv40->pipe.set_constant_buffer = nv40_set_constant_buffer; - nv40->pipe.set_framebuffer_state = nv40_set_framebuffer_state; - nv40->pipe.set_polygon_stipple = nv40_set_polygon_stipple; - nv40->pipe.set_scissor_state = nv40_set_scissor_state; - nv40->pipe.set_viewport_state = nv40_set_viewport_state; - - nv40->pipe.create_vertex_elements_state = nv40_vtxelts_state_create; - nv40->pipe.delete_vertex_elements_state = nv40_vtxelts_state_delete; - nv40->pipe.bind_vertex_elements_state = nv40_vtxelts_state_bind; - - nv40->pipe.set_vertex_buffers = nv40_set_vertex_buffers; -} - diff --git a/src/gallium/drivers/nv40/nv40_state_blend.c b/src/gallium/drivers/nv40/nv40_state_blend.c deleted file mode 100644 index 3ff00a37f6..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_blend.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_blend_validate(struct nv40_context *nv40) -{ - so_ref(nv40->blend->so, &nv40->state.hw[NV40_STATE_BLEND]); - return TRUE; -} - -struct nv40_state_entry nv40_state_blend = { - .validate = nv40_state_blend_validate, - .dirty = { - .pipe = NV40_NEW_BLEND, - .hw = NV40_STATE_BLEND - } -}; - -static boolean -nv40_state_blend_colour_validate(struct nv40_context *nv40) -{ - struct nouveau_stateobj *so = so_new(1, 1, 0); - struct pipe_blend_color *bcol = &nv40->blend_colour; - - so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1); - so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | - (float_to_ubyte(bcol->color[0]) << 16) | - (float_to_ubyte(bcol->color[1]) << 8) | - (float_to_ubyte(bcol->color[2]) << 0))); - - so_ref(so, &nv40->state.hw[NV40_STATE_BCOL]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_blend_colour = { - .validate = nv40_state_blend_colour_validate, - .dirty = { - .pipe = NV40_NEW_BCOL, - .hw = NV40_STATE_BCOL - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c deleted file mode 100644 index 297d71f4fa..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_emit.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "nv40_context.h" -#include "nv40_state.h" -#include "draw/draw_context.h" - -static struct nv40_state_entry *render_states[] = { - &nv40_state_framebuffer, - &nv40_state_rasterizer, - &nv40_state_scissor, - &nv40_state_stipple, - &nv40_state_fragprog, - &nv40_state_fragtex, - &nv40_state_vertprog, - &nv40_state_blend, - &nv40_state_blend_colour, - &nv40_state_zsa, - &nv40_state_sr, - &nv40_state_viewport, - &nv40_state_vbo, - NULL -}; - -static struct nv40_state_entry *swtnl_states[] = { - &nv40_state_framebuffer, - &nv40_state_rasterizer, - &nv40_state_scissor, - &nv40_state_stipple, - &nv40_state_fragprog, - &nv40_state_fragtex, - &nv40_state_vertprog, - &nv40_state_blend, - &nv40_state_blend_colour, - &nv40_state_zsa, - &nv40_state_sr, - &nv40_state_viewport, - &nv40_state_vtxfmt, - NULL -}; - -static void -nv40_state_do_validate(struct nv40_context *nv40, - struct nv40_state_entry **states) -{ - while (*states) { - struct nv40_state_entry *e = *states; - - if (nv40->dirty & e->dirty.pipe) { - if (e->validate(nv40)) - nv40->state.dirty |= (1ULL << e->dirty.hw); - } - - states++; - } - nv40->dirty = 0; -} - -void -nv40_state_emit(struct nv40_context *nv40) -{ - struct nv40_state *state = &nv40->state; - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned i; - uint64_t states; - - /* XXX: race conditions - */ - if (nv40 != screen->cur_ctx) { - for (i = 0; i < NV40_STATE_MAX; i++) { - if (state->hw[i] && screen->state[i] != state->hw[i]) - state->dirty |= (1ULL << i); - } - - screen->cur_ctx = nv40; - } - - for (i = 0, states = state->dirty; states; i++) { - if (!(states & (1ULL << i))) - continue; - so_ref (state->hw[i], &nv40->screen->state[i]); - if (state->hw[i]) - so_emit(chan, nv40->screen->state[i]); - states &= ~(1ULL << i); - } - - if (state->dirty & ((1ULL << NV40_STATE_FRAGPROG) | - (1ULL << NV40_STATE_FRAGTEX0))) { - BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); - OUT_RING (chan, 2); - BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); - OUT_RING (chan, 1); - } - - state->dirty = 0; -} - -void -nv40_state_flush_notify(struct nouveau_channel *chan) -{ - struct nv40_context *nv40 = chan->user_private; - struct nv40_state *state = &nv40->state; - unsigned i, samplers; - - so_emit_reloc_markers(chan, state->hw[NV40_STATE_FB]); - for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { - if (!(samplers & (1 << i))) - continue; - so_emit_reloc_markers(chan, - state->hw[NV40_STATE_FRAGTEX0+i]); - samplers &= ~(1ULL << i); - } - so_emit_reloc_markers(chan, state->hw[NV40_STATE_FRAGPROG]); - if (state->hw[NV40_STATE_VTXBUF] && nv40->render_mode == HW) - so_emit_reloc_markers(chan, state->hw[NV40_STATE_VTXBUF]); -} - -boolean -nv40_state_validate(struct nv40_context *nv40) -{ - boolean was_sw = nv40->fallback_swtnl ? TRUE : FALSE; - - if (nv40->render_mode != HW) { - /* Don't even bother trying to go back to hw if none - * of the states that caused swtnl previously have changed. - */ - if ((nv40->fallback_swtnl & nv40->dirty) - != nv40->fallback_swtnl) - return FALSE; - - /* Attempt to go to hwtnl again */ - nv40->pipe.flush(&nv40->pipe, 0, NULL); - nv40->dirty |= (NV40_NEW_VIEWPORT | - NV40_NEW_VERTPROG | - NV40_NEW_ARRAYS); - nv40->render_mode = HW; - } - - nv40_state_do_validate(nv40, render_states); - if (nv40->fallback_swtnl || nv40->fallback_swrast) - return FALSE; - - if (was_sw) - NOUVEAU_ERR("swtnl->hw\n"); - - return TRUE; -} - -boolean -nv40_state_validate_swtnl(struct nv40_context *nv40) -{ - struct draw_context *draw = nv40->draw; - - /* Setup for swtnl */ - if (nv40->render_mode == HW) { - NOUVEAU_ERR("hw->swtnl 0x%08x\n", nv40->fallback_swtnl); - nv40->pipe.flush(&nv40->pipe, 0, NULL); - nv40->dirty |= (NV40_NEW_VIEWPORT | - NV40_NEW_VERTPROG | - NV40_NEW_ARRAYS); - nv40->render_mode = SWTNL; - } - - if (nv40->draw_dirty & NV40_NEW_VERTPROG) - draw_bind_vertex_shader(draw, nv40->vertprog->draw); - - if (nv40->draw_dirty & NV40_NEW_RAST) - draw_set_rasterizer_state(draw, &nv40->rasterizer->pipe); - - if (nv40->draw_dirty & NV40_NEW_UCP) - draw_set_clip_state(draw, &nv40->clip); - - if (nv40->draw_dirty & NV40_NEW_VIEWPORT) - draw_set_viewport_state(draw, &nv40->viewport); - - if (nv40->draw_dirty & NV40_NEW_ARRAYS) { - draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf); - draw_set_vertex_elements(draw, nv40->vtxelt->num_elements, nv40->vtxelt->pipe); - } - - nv40_state_do_validate(nv40, swtnl_states); - if (nv40->fallback_swrast) { - NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nv40->fallback_swrast); - return FALSE; - } - - nv40->draw_dirty = 0; - return TRUE; -} - diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c deleted file mode 100644 index fd3fdfddc0..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_fb.c +++ /dev/null @@ -1,175 +0,0 @@ -#include "nv40_context.h" -#include "nouveau/nouveau_util.h" - -static struct pipe_buffer * -nv40_do_surface_buffer(struct pipe_surface *surface) -{ - struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture; - return mt->buffer; -} - -#define nv40_surface_buffer(ps) nouveau_bo(nv40_do_surface_buffer(ps)) - -static boolean -nv40_state_framebuffer_validate(struct nv40_context *nv40) -{ - struct nouveau_channel *chan = nv40->screen->base.channel; - struct nouveau_grobj *curie = nv40->screen->curie; - struct pipe_framebuffer_state *fb = &nv40->framebuffer; - struct nv04_surface *rt[4], *zeta; - uint32_t rt_enable, rt_format; - int i, colour_format = 0, zeta_format = 0; - struct nouveau_stateobj *so = so_new(18, 24, 10); - unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; - unsigned w = fb->width; - unsigned h = fb->height; - - rt_enable = 0; - for (i = 0; i < fb->nr_cbufs; i++) { - if (colour_format) { - assert(colour_format == fb->cbufs[i]->format); - } else { - colour_format = fb->cbufs[i]->format; - rt_enable |= (NV40TCL_RT_ENABLE_COLOR0 << i); - rt[i] = (struct nv04_surface *)fb->cbufs[i]; - } - } - - if (rt_enable & (NV40TCL_RT_ENABLE_COLOR1 | NV40TCL_RT_ENABLE_COLOR2 | - NV40TCL_RT_ENABLE_COLOR3)) - rt_enable |= NV40TCL_RT_ENABLE_MRT; - - if (fb->zsbuf) { - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); - for (i = 1; i < fb->nr_cbufs; i++) - assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); - - rt_format = NV40TCL_RT_FORMAT_TYPE_SWIZZLED | - log2i(fb->width) << NV40TCL_RT_FORMAT_LOG2_WIDTH_SHIFT | - log2i(fb->height) << NV40TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT; - } - else - rt_format = NV40TCL_RT_FORMAT_TYPE_LINEAR; - - switch (colour_format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - rt_format |= NV40TCL_RT_FORMAT_COLOR_X8R8G8B8; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - case 0: - rt_format |= NV40TCL_RT_FORMAT_COLOR_A8R8G8B8; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - rt_format |= NV40TCL_RT_FORMAT_COLOR_R5G6B5; - break; - default: - assert(0); - } - - switch (zeta_format) { - case PIPE_FORMAT_Z16_UNORM: - rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16; - break; - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - case 0: - rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8; - break; - default: - assert(0); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { - so_method(so, curie, NV40TCL_DMA_COLOR0, 1); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR0_PITCH, 2); - so_data (so, rt[0]->pitch); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), - rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { - so_method(so, curie, NV40TCL_DMA_COLOR1, 1); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), - rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_data (so, rt[1]->pitch); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { - so_method(so, curie, NV40TCL_DMA_COLOR2, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR2_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), - rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_method(so, curie, NV40TCL_COLOR2_PITCH, 1); - so_data (so, rt[2]->pitch); - } - - if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { - so_method(so, curie, NV40TCL_DMA_COLOR3, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_COLOR3_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), - rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, - 0, 0); - so_method(so, curie, NV40TCL_COLOR3_PITCH, 1); - so_data (so, rt[3]->pitch); - } - - if (zeta_format) { - so_method(so, curie, NV40TCL_DMA_ZETA, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), 0, - rt_flags | NOUVEAU_BO_OR, - chan->vram->handle, chan->gart->handle); - so_method(so, curie, NV40TCL_ZETA_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), - zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); - so_method(so, curie, NV40TCL_ZETA_PITCH, 1); - so_data (so, zeta->pitch); - } - - so_method(so, curie, NV40TCL_RT_ENABLE, 1); - so_data (so, rt_enable); - so_method(so, curie, NV40TCL_RT_HORIZ, 3); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_data (so, rt_format); - so_method(so, curie, NV40TCL_VIEWPORT_HORIZ, 2); - so_data (so, (w << 16) | 0); - so_data (so, (h << 16) | 0); - so_method(so, curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2); - so_data (so, ((w - 1) << 16) | 0); - so_data (so, ((h - 1) << 16) | 0); - so_method(so, curie, 0x1d88, 1); - so_data (so, (1 << 12) | h); - - so_ref(so, &nv40->state.hw[NV40_STATE_FB]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_framebuffer = { - .validate = nv40_state_framebuffer_validate, - .dirty = { - .pipe = NV40_NEW_FB, - .hw = NV40_STATE_FB - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_rasterizer.c b/src/gallium/drivers/nv40/nv40_state_rasterizer.c deleted file mode 100644 index 9ecda5990f..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_rasterizer.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_rasterizer_validate(struct nv40_context *nv40) -{ - so_ref(nv40->rasterizer->so, - &nv40->state.hw[NV40_STATE_RAST]); - return TRUE; -} - -struct nv40_state_entry nv40_state_rasterizer = { - .validate = nv40_state_rasterizer_validate, - .dirty = { - .pipe = NV40_NEW_RAST, - .hw = NV40_STATE_RAST - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_scissor.c b/src/gallium/drivers/nv40/nv40_state_scissor.c deleted file mode 100644 index 753a505e93..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_scissor.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_scissor_validate(struct nv40_context *nv40) -{ - struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe; - struct pipe_scissor_state *s = &nv40->scissor; - struct nouveau_stateobj *so; - - if (nv40->state.hw[NV40_STATE_SCISSOR] && - (rast->scissor == 0 && nv40->state.scissor_enabled == 0)) - return FALSE; - nv40->state.scissor_enabled = rast->scissor; - - so = so_new(1, 2, 0); - so_method(so, nv40->screen->curie, NV40TCL_SCISSOR_HORIZ, 2); - if (nv40->state.scissor_enabled) { - so_data (so, ((s->maxx - s->minx) << 16) | s->minx); - so_data (so, ((s->maxy - s->miny) << 16) | s->miny); - } else { - so_data (so, 4096 << 16); - so_data (so, 4096 << 16); - } - - so_ref(so, &nv40->state.hw[NV40_STATE_SCISSOR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_scissor = { - .validate = nv40_state_scissor_validate, - .dirty = { - .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST, - .hw = NV40_STATE_SCISSOR - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_stipple.c b/src/gallium/drivers/nv40/nv40_state_stipple.c deleted file mode 100644 index 2b371ebfec..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_stipple.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_stipple_validate(struct nv40_context *nv40) -{ - struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe; - struct nouveau_grobj *curie = nv40->screen->curie; - struct nouveau_stateobj *so; - - if (nv40->state.hw[NV40_STATE_STIPPLE] && - (rast->poly_stipple_enable == 0 && nv40->state.stipple_enabled == 0)) - return FALSE; - - if (rast->poly_stipple_enable) { - unsigned i; - - so = so_new(2, 33, 0); - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 1); - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 32); - for (i = 0; i < 32; i++) - so_data(so, nv40->stipple[i]); - } else { - so = so_new(1, 1, 0); - so_method(so, curie, NV40TCL_POLYGON_STIPPLE_ENABLE, 1); - so_data (so, 0); - } - - so_ref(so, &nv40->state.hw[NV40_STATE_STIPPLE]); - return TRUE; -} - -struct nv40_state_entry nv40_state_stipple = { - .validate = nv40_state_stipple_validate, - .dirty = { - .pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST, - .hw = NV40_STATE_STIPPLE, - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_viewport.c b/src/gallium/drivers/nv40/nv40_state_viewport.c deleted file mode 100644 index 3aacb00f99..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_viewport.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_viewport_validate(struct nv40_context *nv40) -{ - struct pipe_viewport_state *vpt = &nv40->viewport; - struct nouveau_stateobj *so; - - if (nv40->state.hw[NV40_STATE_VIEWPORT] && - !(nv40->dirty & NV40_NEW_VIEWPORT)) - return FALSE; - - so = so_new(2, 9, 0); - so_method(so, nv40->screen->curie, - NV40TCL_VIEWPORT_TRANSLATE_X, 8); - so_data (so, fui(vpt->translate[0])); - so_data (so, fui(vpt->translate[1])); - so_data (so, fui(vpt->translate[2])); - so_data (so, fui(vpt->translate[3])); - so_data (so, fui(vpt->scale[0])); - so_data (so, fui(vpt->scale[1])); - so_data (so, fui(vpt->scale[2])); - so_data (so, fui(vpt->scale[3])); - so_method(so, nv40->screen->curie, 0x1d78, 1); - so_data (so, 1); - - so_ref(so, &nv40->state.hw[NV40_STATE_VIEWPORT]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_viewport = { - .validate = nv40_state_viewport_validate, - .dirty = { - .pipe = NV40_NEW_VIEWPORT | NV40_NEW_RAST, - .hw = NV40_STATE_VIEWPORT - } -}; diff --git a/src/gallium/drivers/nv40/nv40_state_zsa.c b/src/gallium/drivers/nv40/nv40_state_zsa.c deleted file mode 100644 index 9cbe7da6db..0000000000 --- a/src/gallium/drivers/nv40/nv40_state_zsa.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "nv40_context.h" - -static boolean -nv40_state_zsa_validate(struct nv40_context *nv40) -{ - so_ref(nv40->zsa->so, - &nv40->state.hw[NV40_STATE_ZSA]); - return TRUE; -} - -struct nv40_state_entry nv40_state_zsa = { - .validate = nv40_state_zsa_validate, - .dirty = { - .pipe = NV40_NEW_ZSA, - .hw = NV40_STATE_ZSA - } -}; - -static boolean -nv40_state_sr_validate(struct nv40_context *nv40) -{ - struct nouveau_stateobj *so = so_new(2, 2, 0); - struct pipe_stencil_ref *sr = &nv40->stencil_ref; - - so_method(so, nv40->screen->curie, NV40TCL_STENCIL_FRONT_FUNC_REF, 1); - so_data (so, sr->ref_value[0]); - so_method(so, nv40->screen->curie, NV40TCL_STENCIL_BACK_FUNC_REF, 1); - so_data (so, sr->ref_value[1]); - - so_ref(so, &nv40->state.hw[NV40_STATE_SR]); - so_ref(NULL, &so); - return TRUE; -} - -struct nv40_state_entry nv40_state_sr = { - .validate = nv40_state_sr_validate, - .dirty = { - .pipe = NV40_NEW_SR, - .hw = NV40_STATE_SR - } -}; diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c deleted file mode 100644 index 02ecfd7bbb..0000000000 --- a/src/gallium/drivers/nv40/nv40_surface.c +++ /dev/null @@ -1,64 +0,0 @@ - -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_defines.h" -#include "util/u_inlines.h" - -#include "util/u_tile.h" - -#include "nv40_context.h" - -static void -nv40_surface_copy(struct pipe_context *pipe, - struct pipe_surface *dest, unsigned destx, unsigned desty, - struct pipe_surface *src, unsigned srcx, unsigned srcy, - unsigned width, unsigned height) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv04_surface_2d *eng2d = nv40->screen->eng2d; - - eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); -} - -static void -nv40_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, - unsigned destx, unsigned desty, unsigned width, - unsigned height, unsigned value) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv04_surface_2d *eng2d = nv40->screen->eng2d; - - eng2d->fill(eng2d, dest, destx, desty, width, height, value); -} - -void -nv40_init_surface_functions(struct nv40_context *nv40) -{ - nv40->pipe.surface_copy = nv40_surface_copy; - nv40->pipe.surface_fill = nv40_surface_fill; -} diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nv40/nv40_transfer.c deleted file mode 100644 index e96ce2c46b..0000000000 --- a/src/gallium/drivers/nv40/nv40_transfer.c +++ /dev/null @@ -1,181 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "nouveau/nouveau_winsys.h" -#include "nv40_context.h" -#include "nv40_screen.h" -#include "nv40_state.h" - -struct nv40_transfer { - struct pipe_transfer base; - struct pipe_surface *surface; - boolean direct; -}; - -static void -nv40_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, - struct pipe_texture *template) -{ - memset(template, 0, sizeof(struct pipe_texture)); - template->target = pt->target; - template->format = pt->format; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->last_level = 0; - template->nr_samples = pt->nr_samples; - - template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | - NOUVEAU_TEXTURE_USAGE_LINEAR; -} - -static struct pipe_transfer * -nv40_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct pipe_screen *pscreen = pcontext->screen; - struct nv40_miptree *mt = (struct nv40_miptree *)pt; - struct nv40_transfer *tx; - struct pipe_texture tx_tex_template, *tx_tex; - - tx = CALLOC_STRUCT(nv40_transfer); - if (!tx) - return NULL; - - pipe_texture_reference(&tx->base.texture, pt); - tx->base.x = x; - tx->base.y = y; - tx->base.width = w; - tx->base.height = h; - tx->base.stride = mt->level[level].pitch; - tx->base.usage = usage; - tx->base.face = face; - tx->base.level = level; - tx->base.zslice = zslice; - - /* Direct access to texture */ - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || - debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && - pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) - { - tx->direct = true; - tx->surface = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - pipe_transfer_buffer_flags(&tx->base)); - return &tx->base; - } - - tx->direct = false; - - nv40_compatible_transfer_tex(pt, w, h, &tx_tex_template); - - tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); - if (!tx_tex) - { - FREE(tx); - return NULL; - } - - tx->base.stride = ((struct nv40_miptree*)tx_tex)->level[0].pitch; - - tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, - 0, 0, 0, - pipe_transfer_buffer_flags(&tx->base)); - - pipe_texture_reference(&tx_tex, NULL); - - if (!tx->surface) - { - pipe_surface_reference(&tx->surface, NULL); - FREE(tx); - return NULL; - } - - if (usage & PIPE_TRANSFER_READ) { - struct nv40_screen *nvscreen = nv40_screen(pscreen); - struct pipe_surface *src; - - src = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - PIPE_BUFFER_USAGE_GPU_READ); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - /* TODO: Check if SIFM can un-swizzle */ - nvscreen->eng2d->copy(nvscreen->eng2d, - tx->surface, 0, 0, - src, x, y, - w, h); - - pipe_surface_reference(&src, NULL); - } - - return &tx->base; -} - -static void -nv40_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx) -{ - struct nv40_transfer *tx = (struct nv40_transfer *)ptx; - - if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = pcontext->screen; - struct nv40_screen *nvscreen = nv40_screen(pscreen); - struct pipe_surface *dst; - - dst = pscreen->get_tex_surface(pscreen, ptx->texture, - ptx->face, ptx->level, ptx->zslice, - PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - nvscreen->eng2d->copy(nvscreen->eng2d, - dst, tx->base.x, tx->base.y, - tx->surface, 0, 0, - tx->base.width, tx->base.height); - - pipe_surface_reference(&dst, NULL); - } - - pipe_surface_reference(&tx->surface, NULL); - pipe_texture_reference(&ptx->texture, NULL); - FREE(ptx); -} - -static void * -nv40_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) -{ - struct pipe_screen *pscreen = pcontext->screen; - struct nv40_transfer *tx = (struct nv40_transfer *)ptx; - struct nv04_surface *ns = (struct nv04_surface *)tx->surface; - struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; - void *map = pipe_buffer_map(pscreen, mt->buffer, - pipe_transfer_buffer_flags(ptx)); - - if(!tx->direct) - return map + ns->base.offset; - else - return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format); -} - -static void -nv40_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) -{ - struct pipe_screen *pscreen = pcontext->screen; - struct nv40_transfer *tx = (struct nv40_transfer *)ptx; - struct nv40_miptree *mt = (struct nv40_miptree *)tx->surface->texture; - - pipe_buffer_unmap(pscreen, mt->buffer); -} - -void -nv40_init_transfer_functions(struct nv40_context *nv40) -{ - nv40->pipe.get_transfer = nv40_transfer_new; - nv40->pipe.transfer_destroy = nv40_transfer_del; - nv40->pipe.transfer_map = nv40_transfer_map; - nv40->pipe.transfer_unmap = nv40_transfer_unmap; -} diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c deleted file mode 100644 index fabdf4bf23..0000000000 --- a/src/gallium/drivers/nv40/nv40_vbo.c +++ /dev/null @@ -1,565 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "util/u_format.h" - -#include "nv40_context.h" -#include "nv40_state.h" - -#include "nouveau/nouveau_channel.h" -#include "nouveau/nouveau_pushbuf.h" -#include "nouveau/nouveau_util.h" - -#define FORCE_SWTNL 0 - -static INLINE int -nv40_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) -{ - switch (pipe) { - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - *fmt = NV40TCL_VTXFMT_TYPE_FLOAT; - break; - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R8G8B8A8_UNORM: - *fmt = NV40TCL_VTXFMT_TYPE_UBYTE; - break; - case PIPE_FORMAT_R16_SSCALED: - case PIPE_FORMAT_R16G16_SSCALED: - case PIPE_FORMAT_R16G16B16_SSCALED: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *fmt = NV40TCL_VTXFMT_TYPE_USHORT; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - switch (pipe) { - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R32_FLOAT: - case PIPE_FORMAT_R16_SSCALED: - *ncomp = 1; - break; - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R32G32_FLOAT: - case PIPE_FORMAT_R16G16_SSCALED: - *ncomp = 2; - break; - case PIPE_FORMAT_R8G8B8_UNORM: - case PIPE_FORMAT_R32G32B32_FLOAT: - case PIPE_FORMAT_R16G16B16_SSCALED: - *ncomp = 3; - break; - case PIPE_FORMAT_R8G8B8A8_UNORM: - case PIPE_FORMAT_R32G32B32A32_FLOAT: - case PIPE_FORMAT_R16G16B16A16_SSCALED: - *ncomp = 4; - break; - default: - NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe)); - return 1; - } - - return 0; -} - -static boolean -nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib, - unsigned ib_size) -{ - struct pipe_screen *pscreen = &nv40->screen->base.base; - unsigned type; - - if (!ib) { - nv40->idxbuf = NULL; - nv40->idxbuf_format = 0xdeadbeef; - return FALSE; - } - - if (!pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF) || ib_size == 1) - return FALSE; - - switch (ib_size) { - case 2: - type = NV40TCL_IDXBUF_FORMAT_TYPE_U16; - break; - case 4: - type = NV40TCL_IDXBUF_FORMAT_TYPE_U32; - break; - default: - return FALSE; - } - - if (ib != nv40->idxbuf || - type != nv40->idxbuf_format) { - nv40->dirty |= NV40_NEW_ARRAYS; - nv40->idxbuf = ib; - nv40->idxbuf_format = type; - } - - return TRUE; -} - -static boolean -nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so, - int attrib, struct pipe_vertex_element *ve, - struct pipe_vertex_buffer *vb) -{ - struct pipe_screen *pscreen = nv40->pipe.screen; - struct nouveau_grobj *curie = nv40->screen->curie; - unsigned type, ncomp; - void *map; - - if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) - return FALSE; - - map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); - map += vb->buffer_offset + ve->src_offset; - - switch (type) { - case NV40TCL_VTXFMT_TYPE_FLOAT: - { - float *v = map; - - switch (ncomp) { - case 4: - so_method(so, curie, NV40TCL_VTX_ATTR_4F_X(attrib), 4); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - so_data (so, fui(v[3])); - break; - case 3: - so_method(so, curie, NV40TCL_VTX_ATTR_3F_X(attrib), 3); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - so_data (so, fui(v[2])); - break; - case 2: - so_method(so, curie, NV40TCL_VTX_ATTR_2F_X(attrib), 2); - so_data (so, fui(v[0])); - so_data (so, fui(v[1])); - break; - case 1: - so_method(so, curie, NV40TCL_VTX_ATTR_1F(attrib), 1); - so_data (so, fui(v[0])); - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - } - break; - default: - pipe_buffer_unmap(pscreen, vb->buffer); - return FALSE; - } - - pipe_buffer_unmap(pscreen, vb->buffer); - - return TRUE; -} - -void -nv40_draw_arrays(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned restart; - - nv40_vbo_set_idxbuf(nv40, NULL, 0); - if (FORCE_SWTNL || !nv40_state_validate(nv40)) { - nv40_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count); - return; - } - - while (count) { - unsigned vc, nr; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, curie, NV40TCL_VB_VERTEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_VERTEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } - - pipe->flush(pipe, 0, NULL); -} - -static INLINE void -nv40_draw_elements_u08(struct nv40_context *nv40, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - while (count) { - uint8_t *elts = (uint8_t *)ib + start; - unsigned vc, push, restart; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, curie, NV40TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv40_draw_elements_u16(struct nv40_context *nv40, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - while (count) { - uint16_t *elts = (uint16_t *)ib + start; - unsigned vc, push, restart; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - if (vc & 1) { - BEGIN_RING(chan, curie, NV40TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, elts[0]); - elts++; vc--; - } - - while (vc) { - unsigned i; - - push = MIN2(vc, 2047 * 2); - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (elts[i+1] << 16) | elts[i]); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static INLINE void -nv40_draw_elements_u32(struct nv40_context *nv40, void *ib, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - - while (count) { - uint32_t *elts = (uint32_t *)ib + start; - unsigned vc, push, restart; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1, - mode, start, count, &restart); - if (vc == 0) { - FIRE_RING(chan); - continue; - } - count -= vc; - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - while (vc) { - push = MIN2(vc, 2047); - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_ELEMENT_U32, push); - OUT_RINGp (chan, elts, push); - - vc -= push; - elts += push; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - start = restart; - } -} - -static void -nv40_draw_elements_inline(struct pipe_context *pipe, - struct pipe_buffer *ib, unsigned ib_size, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct pipe_screen *pscreen = pipe->screen; - void *map; - - map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); - if (!ib) { - NOUVEAU_ERR("failed mapping ib\n"); - return; - } - - switch (ib_size) { - case 1: - nv40_draw_elements_u08(nv40, map, mode, start, count); - break; - case 2: - nv40_draw_elements_u16(nv40, map, mode, start, count); - break; - case 4: - nv40_draw_elements_u32(nv40, map, mode, start, count); - break; - default: - NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); - break; - } - - pipe_buffer_unmap(pscreen, ib); -} - -static void -nv40_draw_elements_vbo(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - unsigned restart; - - while (count) { - unsigned nr, vc; - - nv40_state_emit(nv40); - - vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, - mode, start, count, &restart); - if (!vc) { - FIRE_RING(chan); - continue; - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, nvgl_primitive(mode)); - - nr = (vc & 0xff); - if (nr) { - BEGIN_RING(chan, curie, NV40TCL_VB_INDEX_BATCH, 1); - OUT_RING (chan, ((nr - 1) << 24) | start); - start += nr; - } - - nr = vc >> 8; - while (nr) { - unsigned push = nr > 2047 ? 2047 : nr; - - nr -= push; - - BEGIN_RING_NI(chan, curie, NV40TCL_VB_INDEX_BATCH, push); - while (push--) { - OUT_RING(chan, ((0x100 - 1) << 24) | start); - start += 0x100; - } - } - - BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); - OUT_RING (chan, 0); - - count -= vc; - start = restart; - } -} - -void -nv40_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, unsigned indexSize, - unsigned mode, unsigned start, unsigned count) -{ - struct nv40_context *nv40 = nv40_context(pipe); - boolean idxbuf; - - idxbuf = nv40_vbo_set_idxbuf(nv40, indexBuffer, indexSize); - if (FORCE_SWTNL || !nv40_state_validate(nv40)) { - nv40_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count); - return; - } - - if (idxbuf) { - nv40_draw_elements_vbo(pipe, mode, start, count); - } else { - nv40_draw_elements_inline(pipe, indexBuffer, indexSize, - mode, start, count); - } - - pipe->flush(pipe, 0, NULL); -} - -static boolean -nv40_vbo_validate(struct nv40_context *nv40) -{ - struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; - struct nouveau_grobj *curie = nv40->screen->curie; - struct pipe_buffer *ib = nv40->idxbuf; - unsigned ib_format = nv40->idxbuf_format; - unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; - int hw; - - vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, curie, NV40TCL_VTXBUF_ADDRESS(0), nv40->vtxelt->num_elements); - vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, curie, NV40TCL_VTXFMT(0), nv40->vtxelt->num_elements); - - for (hw = 0; hw < nv40->vtxelt->num_elements; hw++) { - struct pipe_vertex_element *ve; - struct pipe_vertex_buffer *vb; - unsigned type, ncomp; - - ve = &nv40->vtxelt->pipe[hw]; - vb = &nv40->vtxbuf[ve->vertex_buffer_index]; - - if (!vb->stride) { - if (!sattr) - sattr = so_new(16, 16 * 4, 0); - - if (nv40_vbo_static_attrib(nv40, sattr, hw, ve, vb)) { - so_data(vtxbuf, 0); - so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT); - continue; - } - } - - if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { - nv40->fallback_swtnl |= NV40_NEW_ARRAYS; - so_ref(NULL, &vtxbuf); - so_ref(NULL, &vtxfmt); - return FALSE; - } - - so_reloc(vtxbuf, nouveau_bo(vb->buffer), - vb->buffer_offset + ve->src_offset, - vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, - 0, NV40TCL_VTXBUF_ADDRESS_DMA1); - so_data (vtxfmt, ((vb->stride << NV40TCL_VTXFMT_STRIDE_SHIFT) | - (ncomp << NV40TCL_VTXFMT_SIZE_SHIFT) | type)); - } - - if (ib) { - struct nouveau_bo *bo = nouveau_bo(ib); - - so_method(vtxbuf, curie, NV40TCL_IDXBUF_ADDRESS, 2); - so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, - 0, NV40TCL_IDXBUF_FORMAT_DMA1); - } - - so_method(vtxbuf, curie, 0x1710, 1); - so_data (vtxbuf, 0); - - so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]); - so_ref(NULL, &vtxbuf); - nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF); - so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]); - so_ref(NULL, &vtxfmt); - nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT); - so_ref(sattr, &nv40->state.hw[NV40_STATE_VTXATTR]); - so_ref(NULL, &sattr); - nv40->state.dirty |= (1ULL << NV40_STATE_VTXATTR); - return FALSE; -} - -struct nv40_state_entry nv40_state_vbo = { - .validate = nv40_vbo_validate, - .dirty = { - .pipe = NV40_NEW_ARRAYS, - .hw = 0, - } -}; - diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c deleted file mode 100644 index c93c5d127c..0000000000 --- a/src/gallium/drivers/nv40/nv40_vertprog.c +++ /dev/null @@ -1,1048 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_util.h" - -#include "nv40_context.h" -#include "nv40_state.h" - -/* TODO (at least...): - * 1. Indexed consts + ARL - * 3. NV_vp11, NV_vp2, NV_vp3 features - * - extra arith opcodes - * - branching - * - texture sampling - * - indexed attribs - * - indexed results - * 4. bugs - */ - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 8 -#define MASK_Y 4 -#define MASK_Z 2 -#define MASK_W 1 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE 0 -#define DEF_CTEST 0 -#include "nv40_shader.h" - -#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv40_sr_neg((s)) -#define abs(s) nv40_sr_abs((s)) - -#define NV40_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n)) - -struct nv40_vpc { - struct nv40_vertex_program *vp; - - struct nv40_vertex_program_exec *vpi; - - unsigned r_temps; - unsigned r_temps_discard; - struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; - struct nv40_sreg *r_address; - struct nv40_sreg *r_temp; - - struct nv40_sreg *imm; - unsigned nr_imm; - - unsigned hpos_idx; -}; - -static struct nv40_sreg -temp(struct nv40_vpc *vpc) -{ - int idx = ffs(~vpc->r_temps) - 1; - - if (idx < 0) { - NOUVEAU_ERR("out of temps!!\n"); - assert(0); - return nv40_sr(NV40SR_TEMP, 0); - } - - vpc->r_temps |= (1 << idx); - vpc->r_temps_discard |= (1 << idx); - return nv40_sr(NV40SR_TEMP, idx); -} - -static INLINE void -release_temps(struct nv40_vpc *vpc) -{ - vpc->r_temps &= ~vpc->r_temps_discard; - vpc->r_temps_discard = 0; -} - -static struct nv40_sreg -constant(struct nv40_vpc *vpc, int pipe, float x, float y, float z, float w) -{ - struct nv40_vertex_program *vp = vpc->vp; - struct nv40_vertex_program_data *vpd; - int idx; - - if (pipe >= 0) { - for (idx = 0; idx < vp->nr_consts; idx++) { - if (vp->consts[idx].index == pipe) - return nv40_sr(NV40SR_CONST, idx); - } - } - - idx = vp->nr_consts++; - vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); - vpd = &vp->consts[idx]; - - vpd->index = pipe; - vpd->value[0] = x; - vpd->value[1] = y; - vpd->value[2] = z; - vpd->value[3] = w; - return nv40_sr(NV40SR_CONST, idx); -} - -#define arith(cc,s,o,d,m,s0,s1,s2) \ - nv40_vp_arith((cc), (s), NV40_VP_INST_##o, (d), (m), (s0), (s1), (s2)) - -static void -emit_src(struct nv40_vpc *vpc, uint32_t *hw, int pos, struct nv40_sreg src) -{ - struct nv40_vertex_program *vp = vpc->vp; - uint32_t sr = 0; - - switch (src.type) { - case NV40SR_TEMP: - sr |= (NV40_VP_SRC_REG_TYPE_TEMP << NV40_VP_SRC_REG_TYPE_SHIFT); - sr |= (src.index << NV40_VP_SRC_TEMP_SRC_SHIFT); - break; - case NV40SR_INPUT: - sr |= (NV40_VP_SRC_REG_TYPE_INPUT << - NV40_VP_SRC_REG_TYPE_SHIFT); - vp->ir |= (1 << src.index); - hw[1] |= (src.index << NV40_VP_INST_INPUT_SRC_SHIFT); - break; - case NV40SR_CONST: - sr |= (NV40_VP_SRC_REG_TYPE_CONST << - NV40_VP_SRC_REG_TYPE_SHIFT); - assert(vpc->vpi->const_index == -1 || - vpc->vpi->const_index == src.index); - vpc->vpi->const_index = src.index; - break; - case NV40SR_NONE: - sr |= (NV40_VP_SRC_REG_TYPE_INPUT << - NV40_VP_SRC_REG_TYPE_SHIFT); - break; - default: - assert(0); - } - - if (src.negate) - sr |= NV40_VP_SRC_NEGATE; - - if (src.abs) - hw[0] |= (1 << (21 + pos)); - - sr |= ((src.swz[0] << NV40_VP_SRC_SWZ_X_SHIFT) | - (src.swz[1] << NV40_VP_SRC_SWZ_Y_SHIFT) | - (src.swz[2] << NV40_VP_SRC_SWZ_Z_SHIFT) | - (src.swz[3] << NV40_VP_SRC_SWZ_W_SHIFT)); - - switch (pos) { - case 0: - hw[1] |= ((sr & NV40_VP_SRC0_HIGH_MASK) >> - NV40_VP_SRC0_HIGH_SHIFT) << NV40_VP_INST_SRC0H_SHIFT; - hw[2] |= (sr & NV40_VP_SRC0_LOW_MASK) << - NV40_VP_INST_SRC0L_SHIFT; - break; - case 1: - hw[2] |= sr << NV40_VP_INST_SRC1_SHIFT; - break; - case 2: - hw[2] |= ((sr & NV40_VP_SRC2_HIGH_MASK) >> - NV40_VP_SRC2_HIGH_SHIFT) << NV40_VP_INST_SRC2H_SHIFT; - hw[3] |= (sr & NV40_VP_SRC2_LOW_MASK) << - NV40_VP_INST_SRC2L_SHIFT; - break; - default: - assert(0); - } -} - -static void -emit_dst(struct nv40_vpc *vpc, uint32_t *hw, int slot, struct nv40_sreg dst) -{ - struct nv40_vertex_program *vp = vpc->vp; - - switch (dst.type) { - case NV40SR_TEMP: - hw[3] |= NV40_VP_INST_DEST_MASK; - if (slot == 0) { - hw[0] |= (dst.index << - NV40_VP_INST_VEC_DEST_TEMP_SHIFT); - } else { - hw[3] |= (dst.index << - NV40_VP_INST_SCA_DEST_TEMP_SHIFT); - } - break; - case NV40SR_OUTPUT: - switch (dst.index) { - case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; - case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; - case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; - case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; - case NV40_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; - case NV40_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; - case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; - case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; - case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; - case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; - case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; - case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; - case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; - case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; - case NV40_VP_INST_DEST_CLIP(0): - vp->or |= (1 << 6); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE0; - dst.index = NV40_VP_INST_DEST_FOGC; - break; - case NV40_VP_INST_DEST_CLIP(1): - vp->or |= (1 << 7); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE1; - dst.index = NV40_VP_INST_DEST_FOGC; - break; - case NV40_VP_INST_DEST_CLIP(2): - vp->or |= (1 << 8); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE2; - dst.index = NV40_VP_INST_DEST_FOGC; - break; - case NV40_VP_INST_DEST_CLIP(3): - vp->or |= (1 << 9); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE3; - dst.index = NV40_VP_INST_DEST_PSZ; - break; - case NV40_VP_INST_DEST_CLIP(4): - vp->or |= (1 << 10); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE4; - dst.index = NV40_VP_INST_DEST_PSZ; - break; - case NV40_VP_INST_DEST_CLIP(5): - vp->or |= (1 << 11); - vp->clip_ctrl |= NV40TCL_CLIP_PLANE_ENABLE_PLANE5; - dst.index = NV40_VP_INST_DEST_PSZ; - break; - default: - break; - } - - hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT); - if (slot == 0) { - hw[0] |= NV40_VP_INST_VEC_RESULT; - hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); - } else { - hw[3] |= NV40_VP_INST_SCA_RESULT; - hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; - } - break; - default: - assert(0); - } -} - -static void -nv40_vp_arith(struct nv40_vpc *vpc, int slot, int op, - struct nv40_sreg dst, int mask, - struct nv40_sreg s0, struct nv40_sreg s1, - struct nv40_sreg s2) -{ - struct nv40_vertex_program *vp = vpc->vp; - uint32_t *hw; - - vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); - vpc->vpi = &vp->insns[vp->nr_insns - 1]; - memset(vpc->vpi, 0, sizeof(*vpc->vpi)); - vpc->vpi->const_index = -1; - - hw = vpc->vpi->data; - - hw[0] |= (NV40_VP_INST_COND_TR << NV40_VP_INST_COND_SHIFT); - hw[0] |= ((0 << NV40_VP_INST_COND_SWZ_X_SHIFT) | - (1 << NV40_VP_INST_COND_SWZ_Y_SHIFT) | - (2 << NV40_VP_INST_COND_SWZ_Z_SHIFT) | - (3 << NV40_VP_INST_COND_SWZ_W_SHIFT)); - - if (slot == 0) { - hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT); - hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; - hw[3] |= (mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT); - } else { - hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT); - hw[0] |= (NV40_VP_INST_VEC_DEST_TEMP_MASK | (1 << 20)); - hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT); - } - - emit_dst(vpc, hw, slot, dst); - emit_src(vpc, hw, 0, s0); - emit_src(vpc, hw, 1, s1); - emit_src(vpc, hw, 2, s2); -} - -static INLINE struct nv40_sreg -tgsi_src(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc) { - struct nv40_sreg src; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - src = nv40_sr(NV40SR_INPUT, fsrc->Register.Index); - break; - case TGSI_FILE_CONSTANT: - src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0); - break; - case TGSI_FILE_IMMEDIATE: - src = vpc->imm[fsrc->Register.Index]; - break; - case TGSI_FILE_TEMPORARY: - src = vpc->r_temp[fsrc->Register.Index]; - break; - default: - NOUVEAU_ERR("bad src file\n"); - break; - } - - src.abs = fsrc->Register.Absolute; - src.negate = fsrc->Register.Negate; - src.swz[0] = fsrc->Register.SwizzleX; - src.swz[1] = fsrc->Register.SwizzleY; - src.swz[2] = fsrc->Register.SwizzleZ; - src.swz[3] = fsrc->Register.SwizzleW; - return src; -} - -static INLINE struct nv40_sreg -tgsi_dst(struct nv40_vpc *vpc, const struct tgsi_full_dst_register *fdst) { - struct nv40_sreg dst; - - switch (fdst->Register.File) { - case TGSI_FILE_OUTPUT: - dst = vpc->r_result[fdst->Register.Index]; - break; - case TGSI_FILE_TEMPORARY: - dst = vpc->r_temp[fdst->Register.Index]; - break; - case TGSI_FILE_ADDRESS: - dst = vpc->r_address[fdst->Register.Index]; - break; - default: - NOUVEAU_ERR("bad dst file\n"); - break; - } - - return dst; -} - -static INLINE int -tgsi_mask(uint tgsi) -{ - int mask = 0; - - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; - return mask; -} - -static boolean -src_native_swz(struct nv40_vpc *vpc, const struct tgsi_full_src_register *fsrc, - struct nv40_sreg *src) -{ - const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - struct nv40_sreg tgsi = tgsi_src(vpc, fsrc); - uint mask = 0; - uint c; - - for (c = 0; c < 4; c++) { - switch (tgsi_util_get_full_src_register_swizzle(fsrc, c)) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - mask |= tgsi_mask(1 << c); - break; - default: - assert(0); - } - } - - if (mask == MASK_ALL) - return TRUE; - - *src = temp(vpc); - - if (mask) - arith(vpc, 0, OP_MOV, *src, mask, tgsi, none, none); - - return FALSE; -} - -static boolean -nv40_vertprog_parse_instruction(struct nv40_vpc *vpc, - const struct tgsi_full_instruction *finst) -{ - struct nv40_sreg src[3], dst, tmp; - struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - int mask; - int ai = -1, ci = -1, ii = -1; - int i; - - if (finst->Instruction.Opcode == TGSI_OPCODE_END) - return TRUE; - - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - if (fsrc->Register.File == TGSI_FILE_TEMPORARY) { - src[i] = tgsi_src(vpc, fsrc); - } - } - - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - case TGSI_FILE_CONSTANT: - case TGSI_FILE_TEMPORARY: - if (!src_native_swz(vpc, fsrc, &src[i])) - continue; - break; - default: - break; - } - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - if (ai == -1 || ai == fsrc->Register.Index) { - ai = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - case TGSI_FILE_CONSTANT: - if ((ci == -1 && ii == -1) || - ci == fsrc->Register.Index) { - ci = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - case TGSI_FILE_IMMEDIATE: - if ((ci == -1 && ii == -1) || - ii == fsrc->Register.Index) { - ii = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - case TGSI_FILE_TEMPORARY: - /* handled above */ - break; - default: - NOUVEAU_ERR("bad src file\n"); - return FALSE; - } - } - - dst = tgsi_dst(vpc, &finst->Dst[0]); - mask = tgsi_mask(finst->Dst[0].Register.WriteMask); - - switch (finst->Instruction.Opcode) { - case TGSI_OPCODE_ABS: - arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); - break; - case TGSI_OPCODE_ADD: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); - break; - case TGSI_OPCODE_ARL: - arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_DP3: - arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DP4: - arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DPH: - arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DST: - arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_EX2: - arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_EXP: - arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_FLR: - arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FRC: - arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_LG2: - arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LIT: - arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LOG: - arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_MAD: - arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAX: - arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MIN: - arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MOV: - arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_MUL: - arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_POW: - tmp = temp(vpc); - arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, - swz(src[0], X, X, X, X)); - arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), - swz(src[1], X, X, X, X), none); - arith(vpc, 1, OP_EX2, dst, mask, none, none, - swz(tmp, X, X, X, X)); - break; - case TGSI_OPCODE_RCP: - arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_RET: - break; - case TGSI_OPCODE_RSQ: - arith(vpc, 1, OP_RSQ, dst, mask, none, none, abs(src[0])); - break; - case TGSI_OPCODE_SGE: - arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SLT: - arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SUB: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); - break; - case TGSI_OPCODE_XPD: - tmp = temp(vpc); - arith(vpc, 0, OP_MUL, tmp, mask, - swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), - swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), - neg(tmp)); - break; - default: - NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); - return FALSE; - } - - release_temps(vpc); - return TRUE; -} - -static boolean -nv40_vertprog_parse_decl_output(struct nv40_vpc *vpc, - const struct tgsi_full_declaration *fdec) -{ - unsigned idx = fdec->Range.First; - int hw; - - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - hw = NV40_VP_INST_DEST_POS; - vpc->hpos_idx = idx; - break; - case TGSI_SEMANTIC_COLOR: - if (fdec->Semantic.Index == 0) { - hw = NV40_VP_INST_DEST_COL0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV40_VP_INST_DEST_COL1; - } else { - NOUVEAU_ERR("bad colour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_BCOLOR: - if (fdec->Semantic.Index == 0) { - hw = NV40_VP_INST_DEST_BFC0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV40_VP_INST_DEST_BFC1; - } else { - NOUVEAU_ERR("bad bcolour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_FOG: - hw = NV40_VP_INST_DEST_FOGC; - break; - case TGSI_SEMANTIC_PSIZE: - hw = NV40_VP_INST_DEST_PSZ; - break; - case TGSI_SEMANTIC_GENERIC: - if (fdec->Semantic.Index <= 7) { - hw = NV40_VP_INST_DEST_TC(fdec->Semantic.Index); - } else { - NOUVEAU_ERR("bad generic semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_EDGEFLAG: - /* not really an error just a fallback */ - NOUVEAU_ERR("cannot handle edgeflag output\n"); - return FALSE; - default: - NOUVEAU_ERR("bad output semantic\n"); - return FALSE; - } - - vpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw); - return TRUE; -} - -static boolean -nv40_vertprog_prepare(struct nv40_vpc *vpc) -{ - struct tgsi_parse_context p; - int high_temp = -1, high_addr = -1, nr_imm = 0, i; - - tgsi_parse_init(&p, vpc->vp->pipe.tokens); - while (!tgsi_parse_end_of_tokens(&p)) { - const union tgsi_full_token *tok = &p.FullToken; - - tgsi_parse_token(&p); - switch(tok->Token.Type) { - case TGSI_TOKEN_TYPE_IMMEDIATE: - nr_imm++; - break; - case TGSI_TOKEN_TYPE_DECLARATION: - { - const struct tgsi_full_declaration *fdec; - - fdec = &p.FullToken.FullDeclaration; - switch (fdec->Declaration.File) { - case TGSI_FILE_TEMPORARY: - if (fdec->Range.Last > high_temp) { - high_temp = - fdec->Range.Last; - } - break; -#if 0 /* this would be nice.. except gallium doesn't track it */ - case TGSI_FILE_ADDRESS: - if (fdec->Range.Last > high_addr) { - high_addr = - fdec->Range.Last; - } - break; -#endif - case TGSI_FILE_OUTPUT: - if (!nv40_vertprog_parse_decl_output(vpc, fdec)) - return FALSE; - break; - default: - break; - } - } - break; -#if 1 /* yay, parse instructions looking for address regs instead */ - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - const struct tgsi_full_instruction *finst; - const struct tgsi_full_dst_register *fdst; - - finst = &p.FullToken.FullInstruction; - fdst = &finst->Dst[0]; - - if (fdst->Register.File == TGSI_FILE_ADDRESS) { - if (fdst->Register.Index > high_addr) - high_addr = fdst->Register.Index; - } - - } - break; -#endif - default: - break; - } - } - tgsi_parse_free(&p); - - if (nr_imm) { - vpc->imm = CALLOC(nr_imm, sizeof(struct nv40_sreg)); - assert(vpc->imm); - } - - if (++high_temp) { - vpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg)); - for (i = 0; i < high_temp; i++) - vpc->r_temp[i] = temp(vpc); - } - - if (++high_addr) { - vpc->r_address = CALLOC(high_addr, sizeof(struct nv40_sreg)); - for (i = 0; i < high_addr; i++) - vpc->r_address[i] = temp(vpc); - } - - vpc->r_temps_discard = 0; - return TRUE; -} - -static void -nv40_vertprog_translate(struct nv40_context *nv40, - struct nv40_vertex_program *vp) -{ - struct tgsi_parse_context parse; - struct nv40_vpc *vpc = NULL; - struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - int i; - - vpc = CALLOC(1, sizeof(struct nv40_vpc)); - if (!vpc) - return; - vpc->vp = vp; - - if (!nv40_vertprog_prepare(vpc)) { - FREE(vpc); - return; - } - - /* Redirect post-transform vertex position to a temp if user clip - * planes are enabled. We need to append code to the vtxprog - * to handle clip planes later. - */ - if (vp->ucp.nr) { - vpc->r_result[vpc->hpos_idx] = temp(vpc); - vpc->r_temps_discard = 0; - } - - tgsi_parse_init(&parse, vp->pipe.tokens); - - while (!tgsi_parse_end_of_tokens(&parse)) { - tgsi_parse_token(&parse); - - switch (parse.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_IMMEDIATE: - { - const struct tgsi_full_immediate *imm; - - imm = &parse.FullToken.FullImmediate; - assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); - assert(imm->Immediate.NrTokens == 4 + 1); - vpc->imm[vpc->nr_imm++] = - constant(vpc, -1, - imm->u[0].Float, - imm->u[1].Float, - imm->u[2].Float, - imm->u[3].Float); - } - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - const struct tgsi_full_instruction *finst; - finst = &parse.FullToken.FullInstruction; - if (!nv40_vertprog_parse_instruction(vpc, finst)) - goto out_err; - } - break; - default: - break; - } - } - - /* Write out HPOS if it was redirected to a temp earlier */ - if (vpc->r_result[vpc->hpos_idx].type != NV40SR_OUTPUT) { - struct nv40_sreg hpos = nv40_sr(NV40SR_OUTPUT, - NV40_VP_INST_DEST_POS); - struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx]; - - arith(vpc, 0, OP_MOV, hpos, MASK_ALL, htmp, none, none); - } - - /* Insert code to handle user clip planes */ - for (i = 0; i < vp->ucp.nr; i++) { - struct nv40_sreg cdst = nv40_sr(NV40SR_OUTPUT, - NV40_VP_INST_DEST_CLIP(i)); - struct nv40_sreg ceqn = constant(vpc, -1, - nv40->clip.ucp[i][0], - nv40->clip.ucp[i][1], - nv40->clip.ucp[i][2], - nv40->clip.ucp[i][3]); - struct nv40_sreg htmp = vpc->r_result[vpc->hpos_idx]; - unsigned mask; - - switch (i) { - case 0: case 3: mask = MASK_Y; break; - case 1: case 4: mask = MASK_Z; break; - case 2: case 5: mask = MASK_W; break; - default: - NOUVEAU_ERR("invalid clip dist #%d\n", i); - goto out_err; - } - - arith(vpc, 0, OP_DP4, cdst, mask, htmp, ceqn, none); - } - - vp->insns[vp->nr_insns - 1].data[3] |= NV40_VP_INST_LAST; - vp->translated = TRUE; -out_err: - tgsi_parse_free(&parse); - if (vpc->r_temp) - FREE(vpc->r_temp); - if (vpc->r_address) - FREE(vpc->r_address); - if (vpc->imm) - FREE(vpc->imm); - FREE(vpc); -} - -static boolean -nv40_vertprog_validate(struct nv40_context *nv40) -{ - struct pipe_screen *pscreen = nv40->pipe.screen; - struct nv40_screen *screen = nv40->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *curie = screen->curie; - struct nv40_vertex_program *vp; - struct pipe_buffer *constbuf; - boolean upload_code = FALSE, upload_data = FALSE; - int i; - - if (nv40->render_mode == HW) { - vp = nv40->vertprog; - constbuf = nv40->constbuf[PIPE_SHADER_VERTEX]; - - if ((nv40->dirty & NV40_NEW_UCP) || - memcmp(&nv40->clip, &vp->ucp, sizeof(vp->ucp))) { - nv40_vertprog_destroy(nv40, vp); - memcpy(&vp->ucp, &nv40->clip, sizeof(vp->ucp)); - } - } else { - vp = nv40->swtnl.vertprog; - constbuf = NULL; - } - - /* Translate TGSI shader into hw bytecode */ - if (vp->translated) - goto check_gpu_resources; - - nv40->fallback_swtnl &= ~NV40_NEW_VERTPROG; - nv40_vertprog_translate(nv40, vp); - if (!vp->translated) { - nv40->fallback_swtnl |= NV40_NEW_VERTPROG; - return FALSE; - } - -check_gpu_resources: - /* Allocate hw vtxprog exec slots */ - if (!vp->exec) { - struct nouveau_resource *heap = nv40->screen->vp_exec_heap; - struct nouveau_stateobj *so; - uint vplen = vp->nr_insns; - - if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) { - while (heap->next && heap->size < vplen) { - struct nv40_vertex_program *evict; - - evict = heap->next->priv; - nouveau_resource_free(&evict->exec); - } - - if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) - assert(0); - } - - so = so_new(3, 4, 0); - so_method(so, curie, NV40TCL_VP_START_FROM_ID, 1); - so_data (so, vp->exec->start); - so_method(so, curie, NV40TCL_VP_ATTRIB_EN, 2); - so_data (so, vp->ir); - so_data (so, vp->or); - so_method(so, curie, NV40TCL_CLIP_PLANE_ENABLE, 1); - so_data (so, vp->clip_ctrl); - so_ref(so, &vp->so); - so_ref(NULL, &so); - - upload_code = TRUE; - } - - /* Allocate hw vtxprog const slots */ - if (vp->nr_consts && !vp->data) { - struct nouveau_resource *heap = nv40->screen->vp_data_heap; - - if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) { - while (heap->next && heap->size < vp->nr_consts) { - struct nv40_vertex_program *evict; - - evict = heap->next->priv; - nouveau_resource_free(&evict->data); - } - - if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) - assert(0); - } - - /*XXX: handle this some day */ - assert(vp->data->start >= vp->data_start_min); - - upload_data = TRUE; - if (vp->data_start != vp->data->start) - upload_code = TRUE; - } - - /* If exec or data segments moved we need to patch the program to - * fixup offsets and register IDs. - */ - if (vp->exec_start != vp->exec->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv40_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->has_branch_offset) { - assert(0); - } - } - - vp->exec_start = vp->exec->start; - } - - if (vp->nr_consts && vp->data_start != vp->data->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv40_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->const_index >= 0) { - vpi->data[1] &= ~NV40_VP_INST_CONST_SRC_MASK; - vpi->data[1] |= - (vpi->const_index + vp->data->start) << - NV40_VP_INST_CONST_SRC_SHIFT; - - } - } - - vp->data_start = vp->data->start; - } - - /* Update + Upload constant values */ - if (vp->nr_consts) { - float *map = NULL; - - if (constbuf) { - map = pipe_buffer_map(pscreen, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); - } - - for (i = 0; i < vp->nr_consts; i++) { - struct nv40_vertex_program_data *vpd = &vp->consts[i]; - - if (vpd->index >= 0) { - if (!upload_data && - !memcmp(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float))) - continue; - memcpy(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float)); - } - - BEGIN_RING(chan, curie, NV40TCL_VP_UPLOAD_CONST_ID, 5); - OUT_RING (chan, i + vp->data->start); - OUT_RINGp (chan, (uint32_t *)vpd->value, 4); - } - - if (constbuf) - pscreen->buffer_unmap(pscreen, constbuf); - } - - /* Upload vtxprog */ - if (upload_code) { -#if 0 - for (i = 0; i < vp->nr_insns; i++) { - NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[0]); - NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[1]); - NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[2]); - NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[3]); - } -#endif - BEGIN_RING(chan, curie, NV40TCL_VP_UPLOAD_FROM_ID, 1); - OUT_RING (chan, vp->exec->start); - for (i = 0; i < vp->nr_insns; i++) { - BEGIN_RING(chan, curie, NV40TCL_VP_UPLOAD_INST(0), 4); - OUT_RINGp (chan, vp->insns[i].data, 4); - } - } - - if (vp->so != nv40->state.hw[NV40_STATE_VERTPROG]) { - so_ref(vp->so, &nv40->state.hw[NV40_STATE_VERTPROG]); - return TRUE; - } - - return FALSE; -} - -void -nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp) -{ - vp->translated = FALSE; - - if (vp->nr_insns) { - FREE(vp->insns); - vp->insns = NULL; - vp->nr_insns = 0; - } - - if (vp->nr_consts) { - FREE(vp->consts); - vp->consts = NULL; - vp->nr_consts = 0; - } - - nouveau_resource_free(&vp->exec); - vp->exec_start = 0; - nouveau_resource_free(&vp->data); - vp->data_start = 0; - vp->data_start_min = 0; - - vp->ir = vp->or = vp->clip_ctrl = 0; - so_ref(NULL, &vp->so); -} - -struct nv40_state_entry nv40_state_vertprog = { - .validate = nv40_vertprog_validate, - .dirty = { - .pipe = NV40_NEW_VERTPROG | NV40_NEW_UCP, - .hw = NV40_STATE_VERTPROG, - } -}; - diff --git a/src/gallium/drivers/nv50/Makefile b/src/gallium/drivers/nv50/Makefile index 5d622e1c13..e31e6f8662 100644 --- a/src/gallium/drivers/nv50/Makefile +++ b/src/gallium/drivers/nv50/Makefile @@ -4,12 +4,14 @@ include $(TOP)/configs/current LIBNAME = nv50 C_SOURCES = \ + nv50_buffer.c \ nv50_clear.c \ nv50_context.c \ nv50_draw.c \ nv50_miptree.c \ nv50_query.c \ nv50_program.c \ + nv50_resource.c \ nv50_screen.c \ nv50_state.c \ nv50_state_validate.c \ diff --git a/src/gallium/drivers/nv50/nv50_buffer.c b/src/gallium/drivers/nv50/nv50_buffer.c new file mode 100644 index 0000000000..3b2e58116d --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_buffer.c @@ -0,0 +1,147 @@ + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "nouveau/nouveau_screen.h" +#include "nv50_resource.h" + + + +static void nv50_buffer_destroy(struct pipe_screen *pscreen, + struct pipe_resource *presource) +{ + struct nv50_resource *buffer = nv50_resource(presource); + + nouveau_screen_bo_release(pscreen, buffer->bo); + FREE(buffer); +} + + + + +/* Utility functions for transfer create/destroy are hooked in and + * just record the arguments to those functions. + */ +static void * +nv50_buffer_transfer_map( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct nv50_resource *buffer = nv50_resource(transfer->resource); + uint8_t *map; + + map = nouveau_screen_bo_map_range( pipe->screen, + buffer->bo, + transfer->box.x, + transfer->box.width, + transfer->usage ); + if (map == NULL) + return NULL; + + return map + transfer->box.x; +} + + + +static void nv50_buffer_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + struct nv50_resource *buffer = nv50_resource(transfer->resource); + + nouveau_screen_bo_map_flush_range(pipe->screen, + buffer->bo, + transfer->box.x + box->x, + box->width); +} + +static void nv50_buffer_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct nv50_resource *buffer = nv50_resource(transfer->resource); + + nouveau_screen_bo_unmap(pipe->screen, buffer->bo); +} + + + + +struct u_resource_vtbl nv50_buffer_vtbl = +{ + u_default_resource_get_handle, /* get_handle */ + nv50_buffer_destroy, /* resource_destroy */ + NULL, /* is_resource_referenced */ + u_default_get_transfer, /* get_transfer */ + u_default_transfer_destroy, /* transfer_destroy */ + nv50_buffer_transfer_map, /* transfer_map */ + nv50_buffer_transfer_flush_region, /* transfer_flush_region */ + nv50_buffer_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + + +struct pipe_resource * +nv50_buffer_create(struct pipe_screen *pscreen, + const struct pipe_resource *template) +{ + struct nv50_resource *buffer; + + buffer = CALLOC_STRUCT(nv50_resource); + if (!buffer) + return NULL; + + buffer->base = *template; + buffer->vtbl = &nv50_buffer_vtbl; + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = pscreen; + + buffer->bo = nouveau_screen_bo_new(pscreen, + 16, + buffer->base.usage, + buffer->base.width0); + + if (buffer->bo == NULL) + goto fail; + + return &buffer->base; + +fail: + FREE(buffer); + return NULL; +} + + +struct pipe_resource * +nv50_user_buffer_create(struct pipe_screen *pscreen, + void *ptr, + unsigned bytes, + unsigned usage) +{ + struct nv50_resource *buffer; + + buffer = CALLOC_STRUCT(nv50_resource); + if (!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->vtbl = &nv50_buffer_vtbl; + buffer->base.screen = pscreen; + buffer->base.format = PIPE_FORMAT_R8_UNORM; + buffer->base.usage = usage; + buffer->base.width0 = bytes; + buffer->base.height0 = 1; + buffer->base.depth0 = 1; + + buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes); + if (!buffer->bo) + goto fail; + + return &buffer->base; + +fail: + FREE(buffer); + return NULL; +} + diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c index 8afc95c9fc..5447904e9c 100644 --- a/src/gallium/drivers/nv50/nv50_clear.c +++ b/src/gallium/drivers/nv50/nv50_clear.c @@ -35,7 +35,10 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, struct nouveau_grobj *tesla = nv50->screen->tesla; struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned mode = 0, i; + const unsigned dirty = nv50->dirty; + /* don't need NEW_BLEND, NV50TCL_COLOR_MASK doesn't affect CLEAR_BUFFERS */ + nv50->dirty &= NV50_NEW_FRAMEBUFFER | NV50_NEW_SCISSOR; if (!nv50_state_validate(nv50, 64)) return; @@ -64,5 +67,6 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1); OUT_RING (chan, (i << 6) | 0x3c); } + nv50->dirty = dirty; } diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index aa14e17872..7a3da01866 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -89,9 +89,6 @@ nv50_create(struct pipe_screen *pscreen, void *priv) nv50->pipe.flush = nv50_flush; - nv50->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv50->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - screen->base.channel->user_private = nv50; nv50_init_surface_functions(nv50); diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index bc7831d9ac..8bf465378e 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -16,7 +16,6 @@ #include "nouveau/nouveau_winsys.h" #include "nouveau/nouveau_gldefs.h" #include "nouveau/nouveau_stateobj.h" -#include "nouveau/nouveau_context.h" #include "nv50_screen.h" #include "nv50_program.h" @@ -101,27 +100,6 @@ get_tile_depth(uint32_t tile_mode) return 1 << (tile_mode >> 4); } -struct nv50_miptree_level { - int *image_offset; - unsigned pitch; - unsigned tile_mode; -}; - -#define NV50_MAX_TEXTURE_LEVELS 16 - -struct nv50_miptree { - struct nouveau_miptree base; - - struct nv50_miptree_level level[NV50_MAX_TEXTURE_LEVELS]; - int image_nr; - int total_size; -}; - -static INLINE struct nv50_miptree * -nv50_miptree(struct pipe_texture *pt) -{ - return (struct nv50_miptree *)pt; -} struct nv50_surface { struct pipe_surface base; @@ -165,7 +143,7 @@ struct nv50_context { struct nv50_program *vertprog; struct nv50_program *fragprog; struct nv50_program *geomprog; - struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; + struct pipe_resource *constbuf[PIPE_SHADER_TYPES]; struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; unsigned vtxbuf_nr; struct nv50_vtxelt_stateobj *vtxelt; @@ -206,12 +184,12 @@ extern void nv50_draw_arrays_instanced(struct pipe_context *, unsigned mode, unsigned startInstance, unsigned instanceCount); extern void nv50_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count); extern void nv50_draw_elements_instanced(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count, @@ -222,7 +200,7 @@ extern struct nouveau_stateobj *nv50_vbo_validate(struct nv50_context *nv50); /* nv50_push.c */ extern void -nv50_push_elements_instanced(struct pipe_context *, struct pipe_buffer *, +nv50_push_elements_instanced(struct pipe_context *, struct pipe_resource *, unsigned idxsize, unsigned mode, unsigned start, unsigned count, unsigned i_start, unsigned i_count); @@ -258,13 +236,6 @@ extern boolean nv50_tex_construct(struct nv50_sampler_view *view); extern void nv50_tex_relocs(struct nv50_context *); extern struct nouveau_stateobj *nv50_tex_validate(struct nv50_context *); -/* nv50_transfer.c */ -extern void -nv50_upload_sifc(struct nv50_context *nv50, - struct nouveau_bo *bo, unsigned dst_offset, unsigned reloc, - unsigned dst_format, int dst_w, int dst_h, int dst_pitch, - void *src, unsigned src_format, int src_pitch, - int x, int y, int w, int h, int cpp); /* nv50_context.c */ struct pipe_context * diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index e091cae602..8186938b79 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -26,6 +26,8 @@ #include "util/u_format.h" #include "nv50_context.h" +#include "nv50_resource.h" +#include "nv50_transfer.h" /* The restrictions in tile mode selection probably aren't necessary. */ static INLINE uint32_t @@ -70,12 +72,66 @@ get_zslice_offset(unsigned tile_mode, unsigned z, unsigned pitch, unsigned nb_h) return (z % tile_d) * pitch_2d + (z / tile_d) * pitch_3d; } -static struct pipe_texture * -nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) + + + +static void +nv50_miptree_destroy(struct pipe_screen *pscreen, + struct pipe_resource *pt) +{ + struct nv50_miptree *mt = nv50_miptree(pt); + unsigned l; + + for (l = 0; l <= pt->last_level; ++l) + FREE(mt->level[l].image_offset); + + nouveau_screen_bo_release(pscreen, mt->base.bo); + FREE(mt); +} + +static boolean +nv50_miptree_get_handle(struct pipe_screen *pscreen, + struct pipe_resource *pt, + struct winsys_handle *whandle) +{ + struct nv50_miptree *mt = nv50_miptree(pt); + unsigned stride; + + + if (!mt || !mt->base.bo) + return FALSE; + + stride = util_format_get_stride(mt->base.base.format, + mt->base.base.width0); + + return nouveau_screen_bo_get_handle(pscreen, + mt->base.bo, + stride, + whandle); +} + + +struct u_resource_vtbl nv50_miptree_vtbl = +{ + nv50_miptree_get_handle, /* get_handle */ + nv50_miptree_destroy, /* resource_destroy */ + NULL, /* is_resource_referenced */ + nv50_miptree_transfer_new, /* get_transfer */ + nv50_miptree_transfer_del, /* transfer_destroy */ + nv50_miptree_transfer_map, /* transfer_map */ + u_default_transfer_flush_region, /* transfer_flush_region */ + nv50_miptree_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + +struct pipe_resource * +nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *tmp) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); - struct pipe_texture *pt = &mt->base.base; + struct pipe_resource *pt = &mt->base.base; unsigned width = tmp->width0, height = tmp->height0; unsigned depth = tmp->depth0, image_alignment; uint32_t tile_flags; @@ -165,49 +221,53 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) return pt; } -static struct pipe_texture * -nv50_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) + +struct pipe_resource * +nv50_miptree_from_handle(struct pipe_screen *pscreen, + const struct pipe_resource *template, + struct winsys_handle *whandle) { - struct nouveau_bo *bo = nouveau_bo(pb); struct nv50_miptree *mt; + unsigned stride; /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) + if (template->target != PIPE_TEXTURE_2D || + template->last_level != 0 || + template->depth0 != 1) return NULL; mt = CALLOC_STRUCT(nv50_miptree); if (!mt) return NULL; - mt->base.base = *pt; + mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride); + if (mt->base.bo == NULL) { + FREE(mt); + return NULL; + } + + + mt->base.base = *template; pipe_reference_init(&mt->base.base.reference, 1); mt->base.base.screen = pscreen; mt->image_nr = 1; - mt->level[0].pitch = *stride; + mt->level[0].pitch = stride; mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - mt->level[0].tile_mode = bo->tile_mode; + mt->level[0].tile_mode = mt->base.bo->tile_mode; - nouveau_bo_ref(bo, &mt->base.bo); + /* XXX: Need to adjust bo refcount?? + */ + /* nouveau_bo_ref(bo, &mt->base.bo); */ return &mt->base.base; } -static void -nv50_miptree_destroy(struct pipe_texture *pt) -{ - struct nv50_miptree *mt = nv50_miptree(pt); - unsigned l; - for (l = 0; l <= pt->last_level; ++l) - FREE(mt->level[l].image_offset); - nouveau_bo_ref(NULL, &mt->base.bo); - FREE(mt); -} +/* Surface functions + */ -static struct pipe_surface * -nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, +struct pipe_surface * +nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { @@ -222,7 +282,7 @@ nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, ps = CALLOC_STRUCT(pipe_surface); if (!ps) return NULL; - pipe_texture_reference(&ps->texture, pt); + pipe_resource_reference(&ps->texture, pt); ps->format = pt->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); @@ -242,23 +302,11 @@ nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, return ps; } -static void +void nv50_miptree_surface_del(struct pipe_surface *ps) { struct nv50_surface *s = nv50_surface(ps); - pipe_texture_reference(&ps->texture, NULL); + pipe_resource_reference(&ps->texture, NULL); FREE(s); } - -void -nv50_screen_init_miptree_functions(struct pipe_screen *pscreen) -{ - pscreen->texture_create = nv50_miptree_create; - pscreen->texture_destroy = nv50_miptree_destroy; - pscreen->get_tex_surface = nv50_miptree_surface_new; - pscreen->tex_surface_destroy = nv50_miptree_surface_del; - - nouveau_screen(pscreen)->texture_blanket = nv50_miptree_blanket; -} - diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index c857816b31..bcf41073d5 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -30,6 +30,7 @@ #include "tgsi/tgsi_util.h" #include "nv50_context.h" +#include "nv50_transfer.h" #define NV50_SU_MAX_TEMP 127 #define NV50_SU_MAX_ADDR 4 @@ -4157,7 +4158,8 @@ nv50_program_upload_data(struct nv50_context *nv50, uint32_t *map, static void nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) { - struct pipe_screen *pscreen = nv50->pipe.screen; + struct pipe_context *pipe = &nv50->pipe; + struct pipe_transfer *transfer; if (!p->data[0] && p->immd_nr) { struct nouveau_resource *heap = nv50->screen->immd_heap[0]; @@ -4182,9 +4184,10 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) if (p->param_nr) { unsigned cb; - uint32_t *map = pipe_buffer_map(pscreen, + uint32_t *map = pipe_buffer_map(pipe, nv50->constbuf[p->type], - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_TRANSFER_READ, + &transfer); switch (p->type) { case PIPE_SHADER_GEOMETRY: cb = NV50_CB_PGP; break; case PIPE_SHADER_FRAGMENT: cb = NV50_CB_PFP; break; @@ -4195,7 +4198,8 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) } nv50_program_upload_data(nv50, map, 0, p->param_nr, cb); - pipe_buffer_unmap(pscreen, nv50->constbuf[p->type]); + pipe_buffer_unmap(pipe, nv50->constbuf[p->type], + transfer); } } diff --git a/src/gallium/drivers/nv50/nv50_push.c b/src/gallium/drivers/nv50/nv50_push.c index 96a1f32d30..6981e5b919 100644 --- a/src/gallium/drivers/nv50/nv50_push.c +++ b/src/gallium/drivers/nv50/nv50_push.c @@ -5,6 +5,7 @@ #include "nouveau/nouveau_util.h" #include "nv50_context.h" +#include "nv50_resource.h" struct push_context { struct nv50_context *nv50; @@ -171,7 +172,7 @@ emit_verts(void *priv, unsigned start, unsigned count) void nv50_push_elements_instanced(struct pipe_context *pipe, - struct pipe_buffer *idxbuf, unsigned idxsize, + struct pipe_resource *idxbuf, unsigned idxsize, unsigned mode, unsigned start, unsigned count, unsigned i_start, unsigned i_count) { @@ -199,7 +200,7 @@ nv50_push_elements_instanced(struct pipe_context *pipe, for (i = 0; i < nv50->vtxelt->num_elements; i++) { struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - struct nouveau_bo *bo = nouveau_bo(vb->buffer); + struct nouveau_bo *bo = nv50_resource(vb->buffer)->bo; unsigned size, nr_components, n; if (!(nv50->vbo_fifo & (1 << i))) @@ -260,7 +261,7 @@ nv50_push_elements_instanced(struct pipe_context *pipe, /* map index buffer, if present */ if (idxbuf) { - struct nouveau_bo *bo = nouveau_bo(idxbuf); + struct nouveau_bo *bo = nv50_resource(idxbuf)->bo; if (nouveau_bo_map(bo, NOUVEAU_BO_RD)) { assert(bo->map); diff --git a/src/gallium/drivers/nv50/nv50_resource.c b/src/gallium/drivers/nv50/nv50_resource.c new file mode 100644 index 0000000000..cfdb60418b --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_resource.c @@ -0,0 +1,67 @@ + +#include "pipe/p_context.h" +#include "nv50_resource.h" +#include "nouveau/nouveau_screen.h" + + +/* This doesn't look quite right - this query is supposed to ask + * whether the particular context has references to the resource in + * any unflushed rendering command buffer, and hence requires a + * pipe->flush() for serializing some modification to that resource. + * + * This seems to be answering the question of whether the resource is + * currently on hardware. + */ +static unsigned int +nv50_resource_is_referenced(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned face, unsigned level) +{ + return nouveau_reference_flags(nv50_resource(resource)->bo); +} + +static struct pipe_resource * +nv50_resource_create(struct pipe_screen *screen, + const struct pipe_resource *template) +{ + if (template->target == PIPE_BUFFER) + return nv50_buffer_create(screen, template); + else + return nv50_miptree_create(screen, template); +} + +static struct pipe_resource * +nv50_resource_from_handle(struct pipe_screen * screen, + const struct pipe_resource *template, + struct winsys_handle *whandle) +{ + if (template->target == PIPE_BUFFER) + return NULL; + else + return nv50_miptree_from_handle(screen, template, whandle); +} + +void +nv50_init_resource_functions(struct pipe_context *pcontext) +{ + pcontext->get_transfer = u_get_transfer_vtbl; + pcontext->transfer_map = u_transfer_map_vtbl; + pcontext->transfer_flush_region = u_transfer_flush_region_vtbl; + pcontext->transfer_unmap = u_transfer_unmap_vtbl; + pcontext->transfer_destroy = u_transfer_destroy_vtbl; + pcontext->transfer_inline_write = u_transfer_inline_write_vtbl; + pcontext->is_resource_referenced = nv50_resource_is_referenced; +} + +void +nv50_screen_init_resource_functions(struct pipe_screen *pscreen) +{ + pscreen->resource_create = nv50_resource_create; + pscreen->resource_from_handle = nv50_resource_from_handle; + pscreen->resource_get_handle = u_resource_get_handle_vtbl; + pscreen->resource_destroy = u_resource_destroy_vtbl; + pscreen->user_buffer_create = nv50_user_buffer_create; + + pscreen->get_tex_surface = nv50_miptree_surface_new; + pscreen->tex_surface_destroy = nv50_miptree_surface_del; +} diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h new file mode 100644 index 0000000000..963a1100ce --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_resource.h @@ -0,0 +1,90 @@ + +#ifndef NV50_RESOURCE_H +#define NV50_RESOURCE_H + +#include "util/u_transfer.h" + +struct pipe_resource; +struct nouveau_bo; + + +/* This gets further specialized into either buffer or texture + * structures. In the future we'll want to remove much of that + * distinction, but for now try to keep as close to the existing code + * as possible and use the vtbl struct to choose between the two + * underlying implementations. + */ +struct nv50_resource { + struct pipe_resource base; + struct u_resource_vtbl *vtbl; + struct nouveau_bo *bo; +}; + +struct nv50_miptree_level { + int *image_offset; + unsigned pitch; + unsigned tile_mode; +}; + +#define NV50_MAX_TEXTURE_LEVELS 16 + +struct nv50_miptree { + struct nv50_resource base; + + struct nv50_miptree_level level[NV50_MAX_TEXTURE_LEVELS]; + int image_nr; + int total_size; +}; + +static INLINE struct nv50_miptree * +nv50_miptree(struct pipe_resource *pt) +{ + return (struct nv50_miptree *)pt; +} + + +static INLINE +struct nv50_resource *nv50_resource(struct pipe_resource *resource) +{ + return (struct nv50_resource *)resource; +} + + +void +nv50_init_resource_functions(struct pipe_context *pcontext); + +void +nv50_screen_init_resource_functions(struct pipe_screen *pscreen); + +/* Internal functions + */ +struct pipe_resource * +nv50_miptree_create(struct pipe_screen *pscreen, + const struct pipe_resource *tmp); + +struct pipe_resource * +nv50_miptree_from_handle(struct pipe_screen *pscreen, + const struct pipe_resource *template, + struct winsys_handle *whandle); + +struct pipe_resource * +nv50_buffer_create(struct pipe_screen *pscreen, + const struct pipe_resource *template); + +struct pipe_resource * +nv50_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned usage); + + +struct pipe_surface * +nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, + unsigned face, unsigned level, unsigned zslice, + unsigned flags); + +void +nv50_miptree_surface_del(struct pipe_surface *ps); + + +#endif diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index d7f5863fb7..1a4606d9e2 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -109,7 +109,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_TWO_SIDED_STENCIL: return 1; case PIPE_CAP_GLSL: - return 0; + return 1; case PIPE_CAP_ANISOTROPIC_FILTER: return 1; case PIPE_CAP_POINT_SPRITE: @@ -190,8 +190,6 @@ nv50_screen_destroy(struct pipe_screen *pscreen) nouveau_bo_ref(NULL, &screen->tic); if (screen->tsc) nouveau_bo_ref(NULL, &screen->tsc); - if (screen->static_init) - so_ref(NULL, &screen->static_init); nouveau_notifier_free(&screen->sync); nouveau_grobj_free(&screen->tesla); @@ -204,16 +202,65 @@ nv50_screen_destroy(struct pipe_screen *pscreen) FREE(screen); } +#define BGN_RELOC(ch, bo, gr, m, n, fl) \ + OUT_RELOC(ch, bo, (n << 18) | (gr->subc << 13) | m, fl, 0, 0) + +void +nv50_screen_relocs(struct nv50_screen *screen) +{ + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *tesla = screen->tesla; + unsigned i; + const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY; + + MARK_RING (chan, 28, 26); + + /* cause grobj autobind */ + BEGIN_RING(chan, tesla, 0x0100, 1); + OUT_RING (chan, 0); + + BGN_RELOC (chan, screen->tic, tesla, NV50TCL_TIC_ADDRESS_HIGH, 2, rl); + OUT_RELOCh(chan, screen->tic, 0, rl); + OUT_RELOCl(chan, screen->tic, 0, rl); + + BGN_RELOC (chan, screen->tsc, tesla, NV50TCL_TSC_ADDRESS_HIGH, 2, rl); + OUT_RELOCh(chan, screen->tsc, 0, rl); + OUT_RELOCl(chan, screen->tsc, 0, rl); + + BGN_RELOC (chan, screen->constbuf_misc[0], + tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl); + OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl); + OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl); + OUT_RELOC (chan, screen->constbuf_misc[0], + (NV50_CB_PMISC << 16) | 0x0200, rl, 0, 0); + + BGN_RELOC (chan, screen->constbuf_misc[0], + tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl); + OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl); + OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl); + OUT_RELOC (chan, screen->constbuf_misc[0], + (NV50_CB_AUX << 16) | 0x0200, rl, 0, 0); + + for (i = 0; i < 3; ++i) { + BGN_RELOC (chan, screen->constbuf_parm[i], + tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3, rl); + OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl); + OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl); + OUT_RELOC (chan, screen->constbuf_parm[i], + ((NV50_CB_PVP + i) << 16) | 0x0800, rl, 0, 0); + } +} + struct pipe_screen * nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen); struct nouveau_channel *chan; struct pipe_screen *pscreen; - struct nouveau_stateobj *so; unsigned chipset = dev->chipset; unsigned tesla_class = 0; int ret, i; + const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; if (!screen) return NULL; @@ -296,64 +343,58 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) } /* Static M2MF init */ - so = so_new(1, 3, 0); - so_method(so, screen->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); - so_data (so, screen->sync->handle); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - so_emit(chan, so); - so_ref (NULL, &so); + BEGIN_RING(chan, screen->m2mf, + NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); + OUT_RING (chan, screen->sync->handle); + OUT_RING (chan, chan->vram->handle); + OUT_RING (chan, chan->vram->handle); /* Static 2D init */ - so = so_new(4, 7, 0); - so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4); - so_data (so, screen->sync->handle); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - so_data (so, chan->vram->handle); - so_method(so, screen->eng2d, NV50_2D_OPERATION, 1); - so_data (so, NV50_2D_OPERATION_SRCCOPY); - so_method(so, screen->eng2d, NV50_2D_CLIP_ENABLE, 1); - so_data (so, 0); - so_method(so, screen->eng2d, 0x0888, 1); - so_data (so, 1); - so_emit(chan, so); - so_ref(NULL, &so); + BEGIN_RING(chan, screen->eng2d, NV50_2D_DMA_NOTIFY, 4); + OUT_RING (chan, screen->sync->handle); + OUT_RING (chan, chan->vram->handle); + OUT_RING (chan, chan->vram->handle); + OUT_RING (chan, chan->vram->handle); + BEGIN_RING(chan, screen->eng2d, NV50_2D_OPERATION, 1); + OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY); + BEGIN_RING(chan, screen->eng2d, NV50_2D_CLIP_ENABLE, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, screen->eng2d, 0x0888, 1); + OUT_RING (chan, 1); /* Static tesla init */ - so = so_new(47, 95, 24); - - so_method(so, screen->tesla, NV50TCL_COND_MODE, 1); - so_data (so, NV50TCL_COND_MODE_ALWAYS); - so_method(so, screen->tesla, NV50TCL_DMA_NOTIFY, 1); - so_data (so, screen->sync->handle); - so_method(so, screen->tesla, NV50TCL_DMA_ZETA, 11); + BEGIN_RING(chan, screen->tesla, NV50TCL_COND_MODE, 1); + OUT_RING (chan, NV50TCL_COND_MODE_ALWAYS); + BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_NOTIFY, 1); + OUT_RING (chan, screen->sync->handle); + BEGIN_RING(chan, screen->tesla, NV50TCL_DMA_ZETA, 11); for (i = 0; i < 11; i++) - so_data(so, chan->vram->handle); - so_method(so, screen->tesla, NV50TCL_DMA_COLOR(0), - NV50TCL_DMA_COLOR__SIZE); + OUT_RING (chan, chan->vram->handle); + BEGIN_RING(chan, screen->tesla, + NV50TCL_DMA_COLOR(0), NV50TCL_DMA_COLOR__SIZE); for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++) - so_data(so, chan->vram->handle); - so_method(so, screen->tesla, NV50TCL_RT_CONTROL, 1); - so_data (so, 1); + OUT_RING (chan, chan->vram->handle); + + BEGIN_RING(chan, screen->tesla, NV50TCL_RT_CONTROL, 1); + OUT_RING (chan, 1); /* activate all 32 lanes (threads) in a warp */ - so_method(so, screen->tesla, NV50TCL_WARP_HALVES, 1); - so_data (so, 0x2); - so_method(so, screen->tesla, 0x1400, 1); - so_data (so, 0xf); + BEGIN_RING(chan, screen->tesla, NV50TCL_WARP_HALVES, 1); + OUT_RING (chan, 2); + BEGIN_RING(chan, screen->tesla, 0x1400, 1); + OUT_RING (chan, 0xf); /* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */ for (i = 0; i < 3; ++i) { - so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(i), 1); - so_data (so, 0x54); + BEGIN_RING(chan, screen->tesla, NV50TCL_TEX_LIMITS(i), 1); + OUT_RING (chan, 0x54); } /* origin is top left (set to 1 for bottom left) */ - so_method(so, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1); - so_data (so, 0); - so_method(so, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1); - so_data (so, 8); + BEGIN_RING(chan, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, screen->tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1); + OUT_RING (chan, 8); /* constant buffers for immediates and VP/FP parameters */ ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (32 * 4) * 4, @@ -362,6 +403,14 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) nv50_screen_destroy(pscreen); return NULL; } + BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); + OUT_RELOCh(chan, screen->constbuf_misc[0], 0, rl); + OUT_RELOCl(chan, screen->constbuf_misc[0], 0, rl); + OUT_RING (chan, (NV50_CB_PMISC << 16) | 0x0200); + BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); + OUT_RELOCh(chan, screen->constbuf_misc[0], 0x200, rl); + OUT_RELOCl(chan, screen->constbuf_misc[0], 0x200, rl); + OUT_RING (chan, (NV50_CB_AUX << 16) | 0x0200); for (i = 0; i < 3; i++) { ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4, @@ -370,6 +419,10 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) nv50_screen_destroy(pscreen); return NULL; } + BEGIN_RING(chan, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); + OUT_RELOCh(chan, screen->constbuf_parm[i], 0, rl); + OUT_RELOCl(chan, screen->constbuf_parm[i], 0, rl); + OUT_RING (chan, ((NV50_CB_PVP + i) << 16) | 0x0800); } if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) || @@ -381,80 +434,16 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) return NULL; } - /* - // map constant buffers: - // B = buffer ID (maybe more than 1 byte) - // N = CB index used in shader instruction - // P = program type (0 = VP, 2 = GP, 3 = FP) - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x000BBNP1); - */ - - so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); - so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, (NV50_CB_PMISC << 16) | 0x00000200); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000001 | (NV50_CB_PMISC << 12)); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000021 | (NV50_CB_PMISC << 12)); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000031 | (NV50_CB_PMISC << 12)); - - /* bind auxiliary constbuf to immediate data bo */ - so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); - so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, (NV50_CB_AUX << 16) | 0x00000200); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000201 | (NV50_CB_AUX << 12)); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000221 | (NV50_CB_AUX << 12)); - - so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); - so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, (NV50_CB_PVP << 16) | 0x00000800); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000101 | (NV50_CB_PVP << 12)); - - so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); - so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, (NV50_CB_PGP << 16) | 0x00000800); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000121 | (NV50_CB_PGP << 12)); - - so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); - so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0, - NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, (NV50_CB_PFP << 16) | 0x00000800); - so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); - so_data (so, 0x00000131 | (NV50_CB_PFP << 12)); - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4), &screen->tic); if (ret) { nv50_screen_destroy(pscreen); return NULL; } - - so_method(so, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3); - so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, 3 * 32 - 1); + BEGIN_RING(chan, screen->tesla, NV50TCL_TIC_ADDRESS_HIGH, 3); + OUT_RELOCh(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RING (chan, 3 * 32 - 1); ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 3 * 32 * (8 * 4), &screen->tsc); @@ -462,37 +451,50 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) nv50_screen_destroy(pscreen); return NULL; } - - so_method(so, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3); - so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, 0x00000000); /* ignored if TSC_LINKED (0x1234) = 1 */ - + BEGIN_RING(chan, screen->tesla, NV50TCL_TSC_ADDRESS_HIGH, 3); + OUT_RELOCh(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCl(chan, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RING (chan, 0); /* ignored if TSC_LINKED (0x1234) == 1 */ + + /* map constant buffers: + * B = buffer ID (maybe more than 1 byte) + * N = CB index used in shader instruction + * P = program type (0 = VP, 2 = GP, 3 = FP) + * SET_PROGRAM_CB = 0x000BBNP1 + */ + BEGIN_RING_NI(chan, screen->tesla, NV50TCL_SET_PROGRAM_CB, 8); + /* bind immediate buffer */ + OUT_RING (chan, 0x001 | (NV50_CB_PMISC << 12)); + OUT_RING (chan, 0x021 | (NV50_CB_PMISC << 12)); + OUT_RING (chan, 0x031 | (NV50_CB_PMISC << 12)); + /* bind auxiliary constbuf to immediate data bo */ + OUT_RING (chan, 0x201 | (NV50_CB_AUX << 12)); + OUT_RING (chan, 0x221 | (NV50_CB_AUX << 12)); + /* bind parameter buffers */ + OUT_RING (chan, 0x101 | (NV50_CB_PVP << 12)); + OUT_RING (chan, 0x121 | (NV50_CB_PGP << 12)); + OUT_RING (chan, 0x131 | (NV50_CB_PFP << 12)); /* Vertex array limits - max them out */ for (i = 0; i < 16; i++) { - so_method(so, screen->tesla, NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2); - so_data (so, 0x000000ff); - so_data (so, 0xffffffff); + BEGIN_RING(chan, screen->tesla, + NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2); + OUT_RING (chan, 0x000000ff); + OUT_RING (chan, 0xffffffff); } - so_method(so, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2); - so_data (so, fui(0.0)); - so_data (so, fui(1.0)); + BEGIN_RING(chan, screen->tesla, NV50TCL_DEPTH_RANGE_NEAR(0), 2); + OUT_RINGf (chan, 0.0f); + OUT_RINGf (chan, 1.0f); /* no dynamic combination of TIC & TSC entries => only BIND_TIC used */ - so_method(so, screen->tesla, NV50TCL_LINKED_TSC, 1); - so_data (so, 1); + BEGIN_RING(chan, screen->tesla, NV50TCL_LINKED_TSC, 1); + OUT_RING (chan, 1); - so_method(so, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1); - so_data (so, 1); /* default edgeflag to TRUE */ + BEGIN_RING(chan, screen->tesla, NV50TCL_EDGEFLAG_ENABLE, 1); + OUT_RING (chan, 1); /* default edgeflag to TRUE */ - so_emit(chan, so); - so_ref (so, &screen->static_init); - so_ref (NULL, &so); - nouveau_pushbuf_flush(chan, 0); + FIRE_RING (chan); screen->force_push = debug_get_bool_option("NV50_ALWAYS_PUSH", FALSE); return pscreen; diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index ec19ea655b..092333a3b1 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -22,13 +22,11 @@ struct nv50_screen { struct nouveau_resource *immd_heap[1]; struct nouveau_resource *parm_heap[PIPE_SHADER_TYPES]; - struct pipe_buffer *strm_vbuf[16]; + struct pipe_resource *strm_vbuf[16]; struct nouveau_bo *tic; struct nouveau_bo *tsc; - struct nouveau_stateobj *static_init; - boolean force_push; }; @@ -38,4 +36,6 @@ nv50_screen(struct pipe_screen *screen) return (struct nv50_screen *)screen; } +extern void nv50_screen_relocs(struct nv50_screen *); + #endif diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index c162808928..e885a2b719 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -310,13 +310,13 @@ static void nv50_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { - pipe_texture_reference(&view->texture, NULL); + pipe_resource_reference(&view->texture, NULL); FREE(nv50_sampler_view(view)); } static struct pipe_sampler_view * nv50_create_sampler_view(struct pipe_context *pipe, - struct pipe_texture *texture, + struct pipe_resource *texture, const struct pipe_sampler_view *templ) { struct nv50_sampler_view *view = CALLOC_STRUCT(nv50_sampler_view); @@ -324,7 +324,7 @@ nv50_create_sampler_view(struct pipe_context *pipe, view->pipe = *templ; view->pipe.reference.count = 1; view->pipe.texture = NULL; - pipe_texture_reference(&view->pipe.texture, texture); + pipe_resource_reference(&view->pipe.texture, texture); view->pipe.context = pipe; if (!nv50_tex_construct(view)) { @@ -690,7 +690,7 @@ nv50_set_clip_state(struct pipe_context *pipe, static void nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf ) + struct pipe_resource *buf ) { struct nv50_context *nv50 = nv50_context(pipe); diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index 63d73b5ce8..565cf2f8b3 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -23,6 +23,7 @@ #include "util/u_format.h" #include "nv50_context.h" +#include "nv50_resource.h" #include "nouveau/nouveau_stateobj.h" static struct nouveau_stateobj * @@ -43,7 +44,7 @@ validate_fb(struct nv50_context *nv50) (4 << 16) | (5 << 19) | (6 << 22) | (7 << 25)); for (i = 0; i < fb->nr_cbufs; i++) { - struct pipe_texture *pt = fb->cbufs[i]->texture; + struct pipe_resource *pt = fb->cbufs[i]->texture; struct nouveau_bo *bo = nv50_miptree(pt)->base.bo; if (!gw) { @@ -104,7 +105,7 @@ validate_fb(struct nv50_context *nv50) } if (fb->zsbuf) { - struct pipe_texture *pt = fb->zsbuf->texture; + struct pipe_resource *pt = fb->zsbuf->texture; struct nouveau_bo *bo = nv50_miptree(pt)->base.bo; if (!gw) { @@ -435,7 +436,7 @@ nv50_state_validate(struct nv50_context *nv50, unsigned wait_dwords) so_emit_reloc_markers(chan, nv50->state.hw[3]); /* vp */ so_emit_reloc_markers(chan, nv50->state.hw[4]); /* fp */ so_emit_reloc_markers(chan, nv50->state.hw[17]); /* vb */ - so_emit_reloc_markers(chan, nv50->screen->static_init); + nv50_screen_relocs(nv50->screen); /* No idea.. */ BEGIN_RING(chan, tesla, 0x142c, 1); diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index cabd148bc5..2bab023397 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -24,10 +24,12 @@ #include <stdint.h> #include "nouveau/nouveau_pushbuf.h" #include "nv50_context.h" +#include "nv50_resource.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_tile.h" +#include "util/u_format.h" static INLINE int nv50_format(enum pipe_format format) @@ -37,10 +39,35 @@ nv50_format(enum pipe_format format) return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM; case PIPE_FORMAT_B8G8R8X8_UNORM: return NV50_2D_DST_FORMAT_X8R8G8B8_UNORM; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return NV50_2D_DST_FORMAT_A8R8G8B8_SRGB; + case PIPE_FORMAT_B8G8R8X8_SRGB: + return NV50_2D_DST_FORMAT_X8R8G8B8_SRGB; case PIPE_FORMAT_B5G6R5_UNORM: return NV50_2D_DST_FORMAT_R5G6B5_UNORM; + case PIPE_FORMAT_B5G5R5A1_UNORM: + return NV50_2D_DST_FORMAT_A1R5G5B5_UNORM; case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8_UNORM: return NV50_2D_DST_FORMAT_R8_UNORM; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return NV50_2D_DST_FORMAT_R32G32B32A32_FLOAT; + case PIPE_FORMAT_R32G32B32_FLOAT: + return NV50_2D_DST_FORMAT_R32G32B32X32_FLOAT; + case PIPE_FORMAT_Z32_FLOAT: + return NV50_2D_DST_FORMAT_R32_FLOAT; + + /* only because we require src format == dst format: */ + case PIPE_FORMAT_R16G16_SNORM: + case PIPE_FORMAT_R16G16_UNORM: + case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_Z24S8_UNORM: + return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM; + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_B4G4R4A4_UNORM: + return NV50_2D_DST_FORMAT_R16_UNORM; + default: return -1; } @@ -57,8 +84,11 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD); format = nv50_format(ps->format); - if (format < 0) + if (format < 0) { + NOUVEAU_ERR("invalid/unsupported surface format: %s\n", + util_format_name(ps->format)); return 1; + } if (!bo->tile_flags) { MARK_RING (chan, 9, 2); /* flush on lack of space or relocs */ diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index 85ab947c00..ea539635ae 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -22,6 +22,7 @@ #include "nv50_context.h" #include "nv50_texture.h" +#include "nv50_resource.h" #include "nouveau/nouveau_stateobj.h" #include "nouveau/nouveau_reloc.h" diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index c30b787167..314b7b4c0b 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -5,6 +5,8 @@ #include "util/u_math.h" #include "nv50_context.h" +#include "nv50_transfer.h" +#include "nv50_resource.h" struct nv50_transfer { struct pipe_transfer base; @@ -120,44 +122,51 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, } } -static struct pipe_transfer * -nv50_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) +struct pipe_transfer * +nv50_miptree_transfer_new(struct pipe_context *pcontext, + struct pipe_resource *pt, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) { struct pipe_screen *pscreen = pcontext->screen; struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = nv50_miptree(pt); - struct nv50_miptree_level *lvl = &mt->level[level]; + struct nv50_miptree_level *lvl = &mt->level[sr.level]; struct nv50_transfer *tx; unsigned nx, ny, image = 0; int ret; if (pt->target == PIPE_TEXTURE_CUBE) - image = face; + image = sr.face; tx = CALLOC_STRUCT(nv50_transfer); if (!tx) return NULL; - pipe_texture_reference(&tx->base.texture, pt); - tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, level)); - tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, level)); - tx->base.width = w; - tx->base.height = h; + /* Don't handle 3D transfers yet. + */ + assert(box->depth == 1); + + + pipe_resource_reference(&tx->base.resource, pt); + tx->base.sr = sr; + tx->base.usage = usage; + tx->base.box = *box; + tx->nblocksx = util_format_get_nblocksx(pt->format, u_minify(pt->width0, sr.level)); + tx->nblocksy = util_format_get_nblocksy(pt->format, u_minify(pt->height0, sr.level)); tx->base.stride = tx->nblocksx * util_format_get_blocksize(pt->format); tx->base.usage = usage; tx->level_pitch = lvl->pitch; - tx->level_width = u_minify(mt->base.base.width0, level); - tx->level_height = u_minify(mt->base.base.height0, level); - tx->level_depth = u_minify(mt->base.base.depth0, level); + tx->level_width = u_minify(mt->base.base.width0, sr.level); + tx->level_height = u_minify(mt->base.base.height0, sr.level); + tx->level_depth = u_minify(mt->base.base.depth0, sr.level); tx->level_offset = lvl->image_offset[image]; tx->level_tiling = lvl->tile_mode; - tx->level_z = zslice; - tx->level_x = util_format_get_nblocksx(pt->format, x); - tx->level_y = util_format_get_nblocksy(pt->format, y); + tx->level_z = box->z; + tx->level_x = util_format_get_nblocksx(pt->format, box->x); + tx->level_y = util_format_get_nblocksy(pt->format, box->y); ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, tx->nblocksy * tx->base.stride, &tx->bo); if (ret) { @@ -166,12 +175,12 @@ nv50_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, } if (usage & PIPE_TRANSFER_READ) { - nx = util_format_get_nblocksx(pt->format, tx->base.width); - ny = util_format_get_nblocksy(pt->format, tx->base.height); + nx = util_format_get_nblocksx(pt->format, box->width); + ny = util_format_get_nblocksy(pt->format, box->height); nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset, tx->level_pitch, tx->level_tiling, - x, y, zslice, + box->x, box->y, box->z, tx->nblocksx, tx->nblocksy, tx->level_depth, tx->bo, 0, @@ -186,15 +195,16 @@ nv50_transfer_new(struct pipe_context *pcontext, struct pipe_texture *pt, return &tx->base; } -static void -nv50_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx) +void +nv50_miptree_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; - struct nv50_miptree *mt = nv50_miptree(ptx->texture); - struct pipe_texture *pt = ptx->texture; + struct nv50_miptree *mt = nv50_miptree(ptx->resource); + struct pipe_resource *pt = ptx->resource; - unsigned nx = util_format_get_nblocksx(pt->format, tx->base.width); - unsigned ny = util_format_get_nblocksy(pt->format, tx->base.height); + unsigned nx = util_format_get_nblocksx(pt->format, tx->base.box.width); + unsigned ny = util_format_get_nblocksy(pt->format, tx->base.box.height); if (ptx->usage & PIPE_TRANSFER_WRITE) { struct pipe_screen *pscreen = pcontext->screen; @@ -214,12 +224,13 @@ nv50_transfer_del(struct pipe_context *pcontext, struct pipe_transfer *ptx) } nouveau_bo_ref(NULL, &tx->bo); - pipe_texture_reference(&ptx->texture, NULL); + pipe_resource_reference(&ptx->resource, NULL); FREE(ptx); } -static void * -nv50_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) +void * +nv50_miptree_transfer_map(struct pipe_context *pcontext, + struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; unsigned flags = 0; @@ -236,22 +247,15 @@ nv50_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) return tx->bo->map; } -static void -nv50_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) +void +nv50_miptree_transfer_unmap(struct pipe_context *pcontext, + struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; nouveau_bo_unmap(tx->bo); } -void -nv50_init_transfer_functions(struct nv50_context *nv50) -{ - nv50->pipe.get_transfer = nv50_transfer_new; - nv50->pipe.transfer_destroy = nv50_transfer_del; - nv50->pipe.transfer_map = nv50_transfer_map; - nv50->pipe.transfer_unmap = nv50_transfer_unmap; -} void nv50_upload_sifc(struct nv50_context *nv50, diff --git a/src/gallium/drivers/nv50/nv50_transfer.h b/src/gallium/drivers/nv50/nv50_transfer.h new file mode 100644 index 0000000000..663503547c --- /dev/null +++ b/src/gallium/drivers/nv50/nv50_transfer.h @@ -0,0 +1,31 @@ + +#ifndef NV50_TRANSFER_H +#define NV50_TRANSFER_H + +#include "pipe/p_state.h" + + +struct pipe_transfer * +nv50_miptree_transfer_new(struct pipe_context *pcontext, + struct pipe_resource *pt, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box); +void +nv50_miptree_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void * +nv50_miptree_transfer_map(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void +nv50_miptree_transfer_unmap(struct pipe_context *pcontext, + struct pipe_transfer *ptx); + +extern void +nv50_upload_sifc(struct nv50_context *nv50, + struct nouveau_bo *bo, unsigned dst_offset, unsigned reloc, + unsigned dst_format, int dst_w, int dst_h, int dst_pitch, + void *src, unsigned src_format, int src_pitch, + int x, int y, int w, int h, int cpp); + +#endif diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 6b9c1ee231..72b796edf6 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -27,6 +27,7 @@ #include "nouveau/nouveau_util.h" #include "nv50_context.h" +#include "nv50_resource.h" static INLINE uint32_t nv50_vbo_type_to_hw(enum pipe_format format) @@ -139,7 +140,7 @@ instance_init(struct nv50_context *nv50, struct instance *a, unsigned first) if (a[i].divisor) { vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - a[i].bo = nouveau_bo(vb->buffer); + a[i].bo = nv50_resource(vb->buffer)->bo; a[i].stride = vb->stride; a[i].step = first % a[i].divisor; a[i].delta = vb->buffer_offset + ve->src_offset + @@ -307,14 +308,14 @@ inline_edgeflag(void *priv, boolean enabled) static void nv50_draw_elements_inline(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, unsigned indexSize, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count, unsigned startInstance, unsigned instanceCount) { - struct pipe_screen *pscreen = pipe->screen; struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; + struct pipe_transfer *transfer; struct instance a[16]; struct inline_ctx ctx; struct u_split_prim s; @@ -337,7 +338,7 @@ nv50_draw_elements_inline(struct pipe_context *pipe, s.edge = inline_edgeflag; ctx.nv50 = nv50; - ctx.map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); + ctx.map = pipe_buffer_map(pipe, indexBuffer, PIPE_TRANSFER_READ, &transfer); assert(ctx.map); if (!ctx.map) return; @@ -380,12 +381,12 @@ nv50_draw_elements_inline(struct pipe_context *pipe, nzi = TRUE; } - pipe_buffer_unmap(pscreen, indexBuffer); + pipe_buffer_unmap(pipe, indexBuffer, transfer); } void nv50_draw_elements_instanced(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count, unsigned startInstance, unsigned instanceCount) @@ -431,7 +432,8 @@ nv50_draw_elements_instanced(struct pipe_context *pipe, if (indexSize == 4) { BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32 | 0x30000, 0); OUT_RING (chan, count); - nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), + nouveau_pushbuf_submit(chan, + nv50_resource(indexBuffer)->bo, start << 2, count << 2); } else if (indexSize == 2) { @@ -443,7 +445,8 @@ nv50_draw_elements_instanced(struct pipe_context *pipe, OUT_RING (chan, ((start & 1) << 31) | count); BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x30000, 0); OUT_RING (chan, dwords); - nouveau_pushbuf_submit(chan, nouveau_bo(indexBuffer), + nouveau_pushbuf_submit(chan, + nv50_resource(indexBuffer)->bo, vb_start << 1, dwords << 2); BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16_SETUP, 1); OUT_RING (chan, 0); @@ -457,7 +460,7 @@ nv50_draw_elements_instanced(struct pipe_context *pipe, void nv50_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, unsigned indexSize, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { nv50_draw_elements_instanced(pipe, indexBuffer, indexSize, @@ -473,7 +476,7 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, { struct nouveau_stateobj *so; struct nouveau_grobj *tesla = nv50->screen->tesla; - struct nouveau_bo *bo = nouveau_bo(vb->buffer); + struct nouveau_bo *bo = nv50_resource(vb->buffer)->bo; float v[4]; int ret; unsigned nr_components = util_format_get_nr_components(ve->src_format); @@ -549,6 +552,7 @@ nv50_vbo_validate(struct nv50_context *nv50) if (nv50->vtxbuf_nr == 0) return NULL; + nv50->vbo_fifo = 0; if (nv50->screen->force_push || nv50->vertprog->cfg.edgeflag_in < 16) nv50->vbo_fifo = 0xffff; @@ -570,7 +574,7 @@ nv50_vbo_validate(struct nv50_context *nv50) struct pipe_vertex_element *ve = &nv50->vtxelt->pipe[i]; struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - struct nouveau_bo *bo = nouveau_bo(vb->buffer); + struct nouveau_bo *bo = nv50_resource(vb->buffer)->bo; uint32_t hw = nv50->vtxelt->hw[i]; if (!vb->stride && @@ -607,10 +611,10 @@ nv50_vbo_validate(struct nv50_context *nv50) /* vertex array limits */ so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_LIMIT_HIGH(i), 2); - so_reloc (vtxbuf, bo, vb->buffer->size - 1, + so_reloc (vtxbuf, bo, vb->buffer->width0 - 1, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (vtxbuf, bo, vb->buffer->size - 1, + so_reloc (vtxbuf, bo, vb->buffer->width0 - 1, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); } diff --git a/src/gallium/drivers/nvfx/Makefile b/src/gallium/drivers/nvfx/Makefile new file mode 100644 index 0000000000..c1d57ca396 --- /dev/null +++ b/src/gallium/drivers/nvfx/Makefile @@ -0,0 +1,37 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nvfx + +C_SOURCES = \ + nv04_surface_2d.c \ + nvfx_buffer.c \ + nvfx_context.c \ + nvfx_clear.c \ + nvfx_draw.c \ + nvfx_fragprog.c \ + nvfx_fragtex.c \ + nv30_fragtex.c \ + nv40_fragtex.c \ + nvfx_miptree.c \ + nvfx_query.c \ + nvfx_resource.c \ + nvfx_screen.c \ + nvfx_state.c \ + nvfx_state_blend.c \ + nvfx_state_emit.c \ + nvfx_state_fb.c \ + nvfx_state_rasterizer.c \ + nvfx_state_scissor.c \ + nvfx_state_stipple.c \ + nvfx_state_viewport.c \ + nvfx_state_zsa.c \ + nvfx_surface.c \ + nvfx_transfer.c \ + nvfx_vbo.c \ + nvfx_vertprog.c + +LIBRARY_INCLUDES = \ + -I$(TOP)/src/gallium/drivers/nouveau/include + +include ../../Makefile.template diff --git a/src/gallium/drivers/nouveau/nv04_surface_2d.c b/src/gallium/drivers/nvfx/nv04_surface_2d.c index 93114465d5..c0b7ee25c2 100644 --- a/src/gallium/drivers/nouveau/nv04_surface_2d.c +++ b/src/gallium/drivers/nvfx/nv04_surface_2d.c @@ -125,8 +125,8 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, struct nouveau_channel *chan = ctx->swzsurf->channel; struct nouveau_grobj *swzsurf = ctx->swzsurf; struct nouveau_grobj *sifm = ctx->sifm; - struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); - struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); + struct nouveau_bo *src_bo = ctx->buf(src); + struct nouveau_bo *dst_bo = ctx->buf(dst); const unsigned src_pitch = ((struct nv04_surface *)src)->pitch; /* Max width & height may not be the same on all HW, but must be POT */ const unsigned max_w = 1024; @@ -205,8 +205,8 @@ nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx, { struct nouveau_channel *chan = ctx->m2mf->channel; struct nouveau_grobj *m2mf = ctx->m2mf; - struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); - struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); + struct nouveau_bo *src_bo = ctx->buf(src); + struct nouveau_bo *dst_bo = ctx->buf(dst); unsigned src_pitch = ((struct nv04_surface *)src)->pitch; unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; unsigned dst_offset = dst->offset + dy * dst_pitch + @@ -252,8 +252,8 @@ nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst, struct nouveau_channel *chan = ctx->surf2d->channel; struct nouveau_grobj *surf2d = ctx->surf2d; struct nouveau_grobj *blit = ctx->blit; - struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); - struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); + struct nouveau_bo *src_bo = ctx->buf(src); + struct nouveau_bo *dst_bo = ctx->buf(dst); unsigned src_pitch = ((struct nv04_surface *)src)->pitch; unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; int format; @@ -317,7 +317,7 @@ nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst, struct nouveau_channel *chan = ctx->surf2d->channel; struct nouveau_grobj *surf2d = ctx->surf2d; struct nouveau_grobj *rect = ctx->rect; - struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); + struct nouveau_bo *dst_bo = ctx->buf(dst); unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; int cs2d_format, gdirect_format; @@ -507,10 +507,10 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d // printf("creating temp, flags is %i!\n", flags); - if(ns->base.usage & PIPE_BUFFER_USAGE_DISCARD) + if(0 /*ns->base.usage & PIPE_BUFFER_USAGE_DISCARD*/) { temp_flags = ns->base.usage | PIPE_BUFFER_USAGE_GPU_READ; - ns->base.usage = PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER | PIPE_BUFFER_USAGE_DISCARD; + ns->base.usage = PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER /*| PIPE_BUFFER_USAGE_DISCARD */; } else { @@ -520,7 +520,7 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d ns->base.usage = PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE; - struct pipe_texture templ; + struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.format = ns->base.texture->format; templ.target = PIPE_TEXTURE_2D; @@ -534,7 +534,7 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d templ.tex_usage = ns->base.texture->tex_usage | PIPE_TEXTURE_USAGE_RENDER_TARGET; - struct pipe_texture* temp_tex = pscreen->texture_create(pscreen, &templ); + struct pipe_resource* temp_tex = pscreen->resource_create(pscreen, &templ); struct nv04_surface* temp_ns = (struct nv04_surface*)pscreen->get_tex_surface(pscreen, temp_tex, 0, 0, 0, temp_flags); temp_ns->backing = ns; @@ -543,4 +543,3 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d return temp_ns; } - diff --git a/src/gallium/drivers/nouveau/nv04_surface_2d.h b/src/gallium/drivers/nvfx/nv04_surface_2d.h index ce696a11a3..dbc9e50af1 100644 --- a/src/gallium/drivers/nouveau/nv04_surface_2d.h +++ b/src/gallium/drivers/nvfx/nv04_surface_2d.h @@ -16,7 +16,7 @@ struct nv04_surface_2d { struct nouveau_grobj *blit; struct nouveau_grobj *sifm; - struct pipe_buffer *(*buf)(struct pipe_surface *); + struct nouveau_bo *(*buf)(struct pipe_surface *); void (*copy)(struct nv04_surface_2d *, struct pipe_surface *dst, int dx, int dy, struct pipe_surface *src, int sx, int sy, diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c index f7d98f3f20..40cdde3f63 100644 --- a/src/gallium/drivers/nv30/nv30_fragtex.c +++ b/src/gallium/drivers/nvfx/nv30_fragtex.c @@ -1,7 +1,38 @@ #include "util/u_format.h" -#include "nv30_context.h" +#include "nvfx_context.h" #include "nouveau/nouveau_util.h" +#include "nvfx_tex.h" +#include "nvfx_resource.h" + +void +nv30_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso) +{ + if (cso->max_anisotropy >= 8) { + ps->en |= NV34TCL_TX_ENABLE_ANISO_8X; + } else + if (cso->max_anisotropy >= 4) { + ps->en |= NV34TCL_TX_ENABLE_ANISO_4X; + } else + if (cso->max_anisotropy >= 2) { + ps->en |= NV34TCL_TX_ENABLE_ANISO_2X; + } + + { + float limit; + + limit = CLAMP(cso->lod_bias, -16.0, 15.0); + ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + + limit = CLAMP(cso->max_lod, 0.0, 15.0); + ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/; + + limit = CLAMP(cso->min_lod, 0.0, 15.0); + ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/; + } +} #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \ { \ @@ -57,13 +88,13 @@ nv30_fragtex_format(uint pipe_format) } -static struct nouveau_stateobj * -nv30_fragtex_build(struct nv30_context *nv30, int unit) +struct nouveau_stateobj * +nv30_fragtex_build(struct nvfx_context *nvfx, int unit) { - struct nv30_sampler_state *ps = nv30->tex_sampler[unit]; - struct nv30_miptree *nv30mt = nv30->tex_miptree[unit]; - struct pipe_texture *pt = &nv30mt->base; - struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer); + struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; + struct nvfx_miptree *nv30mt = nvfx->tex_miptree[unit]; + struct pipe_resource *pt = &nv30mt->base.base; + struct nouveau_bo *bo = nv30mt->base.bo; struct nv30_texture_format *tf; struct nouveau_stateobj *so; uint32_t txf, txs; @@ -101,7 +132,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) txs = tf->swizzle; so = so_new(1, 8, 2); - so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_OFFSET(unit), 8); so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR, NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); @@ -115,47 +146,3 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) return so; } - -static boolean -nv30_fragtex_validate(struct nv30_context *nv30) -{ - struct nv30_fragment_program *fp = nv30->fragprog; - struct nv30_state *state = &nv30->state; - struct nouveau_stateobj *so; - unsigned samplers, unit; - - samplers = state->fp_samplers & ~fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = so_new(1, 1, 0); - so_method(so, nv30->screen->rankine, NV34TCL_TX_ENABLE(unit), 1); - so_data (so, 0); - so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]); - so_ref(NULL, &so); - state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit)); - } - - samplers = nv30->dirty_samplers & fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = nv30_fragtex_build(nv30, unit); - so_ref(so, &nv30->state.hw[NV30_STATE_FRAGTEX0 + unit]); - so_ref(NULL, &so); - state->dirty |= (1ULL << (NV30_STATE_FRAGTEX0 + unit)); - } - - nv30->state.fp_samplers = fp->samplers; - return FALSE; -} - -struct nv30_state_entry nv30_state_fragtex = { - .validate = nv30_fragtex_validate, - .dirty = { - .pipe = NV30_NEW_SAMPLER | NV30_NEW_FRAGPROG, - .hw = 0 - } -}; diff --git a/src/gallium/drivers/nvfx/nv30_vertprog.h b/src/gallium/drivers/nvfx/nv30_vertprog.h new file mode 100644 index 0000000000..ec0444c07f --- /dev/null +++ b/src/gallium/drivers/nvfx/nv30_vertprog.h @@ -0,0 +1,169 @@ +#ifndef __NV30_SHADER_H__ +#define __NV30_SHADER_H__ + +/* Vertex programs instruction set + * + * 128bit opcodes, split into 4 32-bit ones for ease of use. + * + * Non-native instructions + * ABS - MOV + NV40_VP_INST0_DEST_ABS + * POW - EX2 + MUL + LG2 + * SUB - ADD, second source negated + * SWZ - MOV + * XPD - + * + * Register access + * - Only one INPUT can be accessed per-instruction (move extras into TEMPs) + * - Only one CONST can be accessed per-instruction (move extras into TEMPs) + * + * Relative Addressing + * According to the value returned for + * MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB + * + * there are only two address registers available. The destination in the + * ARL instruction is set to TEMP <n> (The temp isn't actually written). + * + * When using vanilla ARB_v_p, the proprietary driver will squish both the + * available ADDRESS regs into the first hardware reg in the X and Y + * components. + * + * To use an address reg as an index into consts, the CONST_SRC is set to + * (const_base + offset) and INDEX_CONST is set. + * + * To access the second address reg use ADDR_REG_SELECT_1. A particular + * component of the address regs is selected with ADDR_SWZ. + * + * Only one address register can be accessed per instruction. + * + * Conditional execution (see NV_vertex_program{2,3} for details) Conditional + * execution of an instruction is enabled by setting COND_TEST_ENABLE, and + * selecting the condition which will allow the test to pass with + * COND_{FL,LT,...}. It is possible to swizzle the values in the condition + * register, which allows for testing against an individual component. + * + * Branching: + * + * The BRA/CAL instructions seem to follow a slightly different opcode + * layout. The destination instruction ID (IADDR) overlaps a source field. + * Instruction ID's seem to be numbered based on the UPLOAD_FROM_ID FIFO + * command, and is incremented automatically on each UPLOAD_INST FIFO + * command. + * + * Conditional branching is achieved by using the condition tests described + * above. There doesn't appear to be dedicated looping instructions, but + * this can be done using a temp reg + conditional branching. + * + * Subroutines may be uploaded before the main program itself, but the first + * executed instruction is determined by the PROGRAM_START_ID FIFO command. + * + */ + +/* DWORD 0 */ + +#define NV30_VP_INST_ADDR_REG_SELECT_1 (1 << 24) +#define NV30_VP_INST_SRC2_ABS (1 << 23) /* guess */ +#define NV30_VP_INST_SRC1_ABS (1 << 22) /* guess */ +#define NV30_VP_INST_SRC0_ABS (1 << 21) /* guess */ +#define NV30_VP_INST_VEC_RESULT (1 << 20) +#define NV30_VP_INST_DEST_TEMP_ID_SHIFT 16 +#define NV30_VP_INST_DEST_TEMP_ID_MASK (0x0F << 16) +#define NV30_VP_INST_COND_UPDATE_ENABLE (1<<15) +#define NV30_VP_INST_VEC_DEST_TEMP_MASK (0xF << 16) +#define NV30_VP_INST_COND_TEST_ENABLE (1<<14) +#define NV30_VP_INST_COND_SHIFT 11 +#define NV30_VP_INST_COND_MASK (0x07 << 11) +#define NV30_VP_INST_COND_SWZ_X_SHIFT 9 +#define NV30_VP_INST_COND_SWZ_X_MASK (0x03 << 9) +#define NV30_VP_INST_COND_SWZ_Y_SHIFT 7 +#define NV30_VP_INST_COND_SWZ_Y_MASK (0x03 << 7) +#define NV30_VP_INST_COND_SWZ_Z_SHIFT 5 +#define NV30_VP_INST_COND_SWZ_Z_MASK (0x03 << 5) +#define NV30_VP_INST_COND_SWZ_W_SHIFT 3 +#define NV30_VP_INST_COND_SWZ_W_MASK (0x03 << 3) +#define NV30_VP_INST_COND_SWZ_ALL_SHIFT 3 +#define NV30_VP_INST_COND_SWZ_ALL_MASK (0xFF << 3) +#define NV30_VP_INST_ADDR_SWZ_SHIFT 1 +#define NV30_VP_INST_ADDR_SWZ_MASK (0x03 << 1) +#define NV30_VP_INST_SCA_OPCODEH_SHIFT 0 +#define NV30_VP_INST_SCA_OPCODEH_MASK (0x01 << 0) + +/* DWORD 1 */ +#define NV30_VP_INST_SCA_OPCODEL_SHIFT 28 +#define NV30_VP_INST_SCA_OPCODEL_MASK (0x0F << 28) +#define NV30_VP_INST_VEC_OPCODE_SHIFT 23 +#define NV30_VP_INST_VEC_OPCODE_MASK (0x1F << 23) +#define NV30_VP_INST_CONST_SRC_SHIFT 14 +#define NV30_VP_INST_CONST_SRC_MASK (0xFF << 14) +#define NV30_VP_INST_INPUT_SRC_SHIFT 9 /*NV20*/ +#define NV30_VP_INST_INPUT_SRC_MASK (0x0F << 9) /*NV20*/ +#define NV30_VP_INST_SRC0H_SHIFT 0 /*NV20*/ +#define NV30_VP_INST_SRC0H_MASK (0x1FF << 0) /*NV20*/ + +/* Please note: the IADDR fields overlap other fields because they are used + * only for branch instructions. See Branching: label above + * + * DWORD 2 + */ +#define NV30_VP_INST_SRC0L_SHIFT 26 /*NV20*/ +#define NV30_VP_INST_SRC0L_MASK (0x3F <<26) /* NV30_VP_SRC0_LOW_MASK << 26 */ +#define NV30_VP_INST_SRC1_SHIFT 11 /*NV20*/ +#define NV30_VP_INST_SRC1_MASK (0x7FFF<<11) /*NV20*/ +#define NV30_VP_INST_SRC2H_SHIFT 0 /*NV20*/ +#define NV30_VP_INST_SRC2H_MASK (0x7FF << 0) /* NV30_VP_SRC2_HIGH_MASK >> 4*/ +#define NV30_VP_INST_IADDR_SHIFT 2 +#define NV30_VP_INST_IADDR_MASK (0xF << 28) /* NV30_VP_SRC2_LOW_MASK << 28 */ + +/* DWORD 3 */ +#define NV30_VP_INST_SRC2L_SHIFT 28 /*NV20*/ +#define NV30_VP_INST_SRC2L_MASK (0x0F <<28) /*NV20*/ +#define NV30_VP_INST_STEMP_WRITEMASK_SHIFT 24 +#define NV30_VP_INST_STEMP_WRITEMASK_MASK (0x0F << 24) +#define NV30_VP_INST_VTEMP_WRITEMASK_SHIFT 20 +#define NV30_VP_INST_VTEMP_WRITEMASK_MASK (0x0F << 20) +#define NV30_VP_INST_SDEST_WRITEMASK_SHIFT 16 +#define NV30_VP_INST_SDEST_WRITEMASK_MASK (0x0F << 16) +#define NV30_VP_INST_VDEST_WRITEMASK_SHIFT 12 /*NV20*/ +#define NV30_VP_INST_VDEST_WRITEMASK_MASK (0x0F << 12) /*NV20*/ +#define NV30_VP_INST_DEST_SHIFT 2 +#define NV30_VP_INST_DEST_MASK (0x0F << 2) +# define NV30_VP_INST_DEST_POS 0 +# define NV30_VP_INST_DEST_BFC0 1 +# define NV30_VP_INST_DEST_BFC1 2 +# define NV30_VP_INST_DEST_COL0 3 +# define NV30_VP_INST_DEST_COL1 4 +# define NV30_VP_INST_DEST_FOGC 5 +# define NV30_VP_INST_DEST_PSZ 6 +# define NV30_VP_INST_DEST_TC(n) (8+n) + +/* Useful to split the source selection regs into their pieces */ +#define NV30_VP_SRC0_HIGH_SHIFT 6 +#define NV30_VP_SRC0_HIGH_MASK 0x00007FC0 +#define NV30_VP_SRC0_LOW_MASK 0x0000003F +#define NV30_VP_SRC2_HIGH_SHIFT 4 +#define NV30_VP_SRC2_HIGH_MASK 0x00007FF0 +#define NV30_VP_SRC2_LOW_MASK 0x0000000F + + +/* Source-register definition - matches NV20 exactly */ +#define NV30_VP_SRC_NEGATE (1<<14) +#define NV30_VP_SRC_SWZ_X_SHIFT 12 +#define NV30_VP_SRC_REG_SWZ_X_MASK (0x03 <<12) +#define NV30_VP_SRC_SWZ_Y_SHIFT 10 +#define NV30_VP_SRC_REG_SWZ_Y_MASK (0x03 <<10) +#define NV30_VP_SRC_SWZ_Z_SHIFT 8 +#define NV30_VP_SRC_REG_SWZ_Z_MASK (0x03 << 8) +#define NV30_VP_SRC_SWZ_W_SHIFT 6 +#define NV30_VP_SRC_REG_SWZ_W_MASK (0x03 << 6) +#define NV30_VP_SRC_REG_SWZ_ALL_SHIFT 6 +#define NV30_VP_SRC_REG_SWZ_ALL_MASK (0xFF << 6) +#define NV30_VP_SRC_TEMP_SRC_SHIFT 2 +#define NV30_VP_SRC_REG_TEMP_ID_MASK (0x0F << 0) +#define NV30_VP_SRC_REG_TYPE_SHIFT 0 +#define NV30_VP_SRC_REG_TYPE_MASK (0x03 << 0) +#define NV30_VP_SRC_REG_TYPE_TEMP 1 +#define NV30_VP_SRC_REG_TYPE_INPUT 2 +#define NV30_VP_SRC_REG_TYPE_CONST 3 /* guess */ + +#include "nvfx_shader.h" + +#endif diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c index b60118922a..3f03afe9f1 100644 --- a/src/gallium/drivers/nv40/nv40_fragtex.c +++ b/src/gallium/drivers/nvfx/nv40_fragtex.c @@ -1,18 +1,64 @@ #include "util/u_format.h" +#include "nvfx_context.h" +#include "nvfx_tex.h" +#include "nvfx_resource.h" + +void +nv40_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso) +{ + if (cso->max_anisotropy >= 2) { + /* no idea, binary driver sets it, works without it.. meh.. */ + ps->wrap |= (1 << 5); + + if (cso->max_anisotropy >= 16) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X; + } else + if (cso->max_anisotropy >= 12) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X; + } else + if (cso->max_anisotropy >= 10) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X; + } else + if (cso->max_anisotropy >= 8) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X; + } else + if (cso->max_anisotropy >= 6) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X; + } else + if (cso->max_anisotropy >= 4) { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X; + } else { + ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X; + } + } + + { + float limit; + + limit = CLAMP(cso->lod_bias, -16.0, 15.0); + ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + + limit = CLAMP(cso->max_lod, 0.0, 15.0); + ps->en |= (int)(limit * 256.0) << 7; -#include "nv40_context.h" + limit = CLAMP(cso->min_lod, 0.0, 15.0); + ps->en |= (int)(limit * 256.0) << 19; + } +} #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw) \ { \ TRUE, \ PIPE_FORMAT_##m, \ NV40TCL_TEX_FORMAT_FORMAT_##tf, \ - (NV40TCL_TEX_SWIZZLE_S0_X_##ts0x | NV40TCL_TEX_SWIZZLE_S0_Y_##ts0y | \ - NV40TCL_TEX_SWIZZLE_S0_Z_##ts0z | NV40TCL_TEX_SWIZZLE_S0_W_##ts0w | \ - NV40TCL_TEX_SWIZZLE_S1_X_##ts1x | NV40TCL_TEX_SWIZZLE_S1_Y_##ts1y | \ - NV40TCL_TEX_SWIZZLE_S1_Z_##ts1z | NV40TCL_TEX_SWIZZLE_S1_W_##ts1w), \ - ((NV40TCL_TEX_FILTER_SIGNED_RED*sx) | (NV40TCL_TEX_FILTER_SIGNED_GREEN*sy) | \ - (NV40TCL_TEX_FILTER_SIGNED_BLUE*sz) | (NV40TCL_TEX_FILTER_SIGNED_ALPHA*sw)) \ + (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \ + NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \ + NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \ + NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w), \ + ((NV34TCL_TX_FILTER_SIGNED_RED*sx) | (NV34TCL_TX_FILTER_SIGNED_GREEN*sy) | \ + (NV34TCL_TX_FILTER_SIGNED_BLUE*sz) | (NV34TCL_TX_FILTER_SIGNED_ALPHA*sw)) \ } struct nv40_texture_format { @@ -60,13 +106,13 @@ nv40_fragtex_format(uint pipe_format) } -static struct nouveau_stateobj * -nv40_fragtex_build(struct nv40_context *nv40, int unit) +struct nouveau_stateobj * +nv40_fragtex_build(struct nvfx_context *nvfx, int unit) { - struct nv40_sampler_state *ps = nv40->tex_sampler[unit]; - struct nv40_miptree *nv40mt = nv40->tex_miptree[unit]; - struct nouveau_bo *bo = nouveau_bo(nv40mt->buffer); - struct pipe_texture *pt = &nv40mt->base; + struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; + struct nvfx_miptree *nv40mt = nvfx->tex_miptree[unit]; + struct nouveau_bo *bo = nv40mt->base.bo; + struct pipe_resource *pt = &nv40mt->base.base; struct nv40_texture_format *tf; struct nouveau_stateobj *so; uint32_t txf, txs, txp; @@ -81,20 +127,20 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT); if (1) /* XXX */ - txf |= NV40TCL_TEX_FORMAT_NO_BORDER; + txf |= NV34TCL_TX_FORMAT_NO_BORDER; switch (pt->target) { case PIPE_TEXTURE_CUBE: - txf |= NV40TCL_TEX_FORMAT_CUBIC; + txf |= NV34TCL_TX_FORMAT_CUBIC; /* fall-through */ case PIPE_TEXTURE_2D: - txf |= NV40TCL_TEX_FORMAT_DIMS_2D; + txf |= NV34TCL_TX_FORMAT_DIMS_2D; break; case PIPE_TEXTURE_3D: - txf |= NV40TCL_TEX_FORMAT_DIMS_3D; + txf |= NV34TCL_TX_FORMAT_DIMS_3D; break; case PIPE_TEXTURE_1D: - txf |= NV40TCL_TEX_FORMAT_DIMS_1D; + txf |= NV34TCL_TX_FORMAT_DIMS_1D; break; default: NOUVEAU_ERR("Unknown target %d\n", pt->target); @@ -111,63 +157,19 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) txs = tf->swizzle; so = so_new(2, 9, 2); - so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_OFFSET(unit), 8); so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR, - NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1); + NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); so_data (so, ps->wrap); so_data (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en); so_data (so, txs); so_data (so, ps->filt | tf->sign | 0x2000 /*voodoo*/); - so_data (so, (pt->width0 << NV40TCL_TEX_SIZE0_W_SHIFT) | + so_data (so, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pt->height0); so_data (so, ps->bcol); - so_method(so, nv40->screen->curie, NV40TCL_TEX_SIZE1(unit), 1); + so_method(so, nvfx->screen->eng3d, NV40TCL_TEX_SIZE1(unit), 1); so_data (so, (pt->depth0 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp); return so; } - -static boolean -nv40_fragtex_validate(struct nv40_context *nv40) -{ - struct nv40_fragment_program *fp = nv40->fragprog; - struct nv40_state *state = &nv40->state; - struct nouveau_stateobj *so; - unsigned samplers, unit; - - samplers = state->fp_samplers & ~fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = so_new(1, 1, 0); - so_method(so, nv40->screen->curie, NV40TCL_TEX_ENABLE(unit), 1); - so_data (so, 0); - so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]); - state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit)); - } - - samplers = nv40->dirty_samplers & fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - so = nv40_fragtex_build(nv40, unit); - so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]); - so_ref(NULL, &so); - state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit)); - } - - nv40->state.fp_samplers = fp->samplers; - return FALSE; -} - -struct nv40_state_entry nv40_state_fragtex = { - .validate = nv40_fragtex_validate, - .dirty = { - .pipe = NV40_NEW_SAMPLER | NV40_NEW_FRAGPROG, - .hw = 0 - } -}; - diff --git a/src/gallium/drivers/nvfx/nv40_vertprog.h b/src/gallium/drivers/nvfx/nv40_vertprog.h new file mode 100644 index 0000000000..7337293bab --- /dev/null +++ b/src/gallium/drivers/nvfx/nv40_vertprog.h @@ -0,0 +1,177 @@ +#ifndef __NV40_SHADER_H__ +#define __NV40_SHADER_H__ + +/* Vertex programs instruction set + * + * The NV40 instruction set is very similar to NV30. Most fields are in + * a slightly different position in the instruction however. + * + * Merged instructions + * In some cases it is possible to put two instructions into one opcode + * slot. The rules for when this is OK is not entirely clear to me yet. + * + * There are separate writemasks and dest temp register fields for each + * grouping of instructions. There is however only one field with the + * ID of a result register. Writing to temp/result regs is selected by + * setting VEC_RESULT/SCA_RESULT. + * + * Temporary registers + * The source/dest temp register fields have been extended by 1 bit, to + * give a total of 32 temporary registers. + * + * Relative Addressing + * NV40 can use an address register to index into vertex attribute regs. + * This is done by putting the offset value into INPUT_SRC and setting + * the INDEX_INPUT flag. + * + * Conditional execution (see NV_vertex_program{2,3} for details) + * There is a second condition code register on NV40, it's use is enabled + * by setting the COND_REG_SELECT_1 flag. + * + * Texture lookup + * TODO + */ + +/* ---- OPCODE BITS 127:96 / data DWORD 0 --- */ +#define NV40_VP_INST_VEC_RESULT (1 << 30) +/* uncertain.. */ +#define NV40_VP_INST_COND_UPDATE_ENABLE ((1 << 14)|1<<29) +/* use address reg as index into attribs */ +#define NV40_VP_INST_INDEX_INPUT (1 << 27) +#define NV40_VP_INST_COND_REG_SELECT_1 (1 << 25) +#define NV40_VP_INST_ADDR_REG_SELECT_1 (1 << 24) +#define NV40_VP_INST_SRC2_ABS (1 << 23) +#define NV40_VP_INST_SRC1_ABS (1 << 22) +#define NV40_VP_INST_SRC0_ABS (1 << 21) +#define NV40_VP_INST_VEC_DEST_TEMP_SHIFT 15 +#define NV40_VP_INST_VEC_DEST_TEMP_MASK (0x1F << 15) +#define NV40_VP_INST_COND_TEST_ENABLE (1 << 13) +#define NV40_VP_INST_COND_SHIFT 10 +#define NV40_VP_INST_COND_MASK (0x7 << 10) +#define NV40_VP_INST_COND_SWZ_X_SHIFT 8 +#define NV40_VP_INST_COND_SWZ_X_MASK (3 << 8) +#define NV40_VP_INST_COND_SWZ_Y_SHIFT 6 +#define NV40_VP_INST_COND_SWZ_Y_MASK (3 << 6) +#define NV40_VP_INST_COND_SWZ_Z_SHIFT 4 +#define NV40_VP_INST_COND_SWZ_Z_MASK (3 << 4) +#define NV40_VP_INST_COND_SWZ_W_SHIFT 2 +#define NV40_VP_INST_COND_SWZ_W_MASK (3 << 2) +#define NV40_VP_INST_COND_SWZ_ALL_SHIFT 2 +#define NV40_VP_INST_COND_SWZ_ALL_MASK (0xFF << 2) +#define NV40_VP_INST_ADDR_SWZ_SHIFT 0 +#define NV40_VP_INST_ADDR_SWZ_MASK (0x03 << 0) +#define NV40_VP_INST0_KNOWN ( \ + NV40_VP_INST_INDEX_INPUT | \ + NV40_VP_INST_COND_REG_SELECT_1 | \ + NV40_VP_INST_ADDR_REG_SELECT_1 | \ + NV40_VP_INST_SRC2_ABS | \ + NV40_VP_INST_SRC1_ABS | \ + NV40_VP_INST_SRC0_ABS | \ + NV40_VP_INST_VEC_DEST_TEMP_MASK | \ + NV40_VP_INST_COND_TEST_ENABLE | \ + NV40_VP_INST_COND_MASK | \ + NV40_VP_INST_COND_SWZ_ALL_MASK | \ + NV40_VP_INST_ADDR_SWZ_MASK) + +/* ---- OPCODE BITS 95:64 / data DWORD 1 --- */ +#define NV40_VP_INST_VEC_OPCODE_SHIFT 22 +#define NV40_VP_INST_VEC_OPCODE_MASK (0x1F << 22) +#define NV40_VP_INST_SCA_OPCODE_SHIFT 27 +#define NV40_VP_INST_SCA_OPCODE_MASK (0x1F << 27) +#define NV40_VP_INST_CONST_SRC_SHIFT 12 +#define NV40_VP_INST_CONST_SRC_MASK (0xFF << 12) +#define NV40_VP_INST_INPUT_SRC_SHIFT 8 +#define NV40_VP_INST_INPUT_SRC_MASK (0x0F << 8) +#define NV40_VP_INST_SRC0H_SHIFT 0 +#define NV40_VP_INST_SRC0H_MASK (0xFF << 0) +#define NV40_VP_INST1_KNOWN ( \ + NV40_VP_INST_VEC_OPCODE_MASK | \ + NV40_VP_INST_SCA_OPCODE_MASK | \ + NV40_VP_INST_CONST_SRC_MASK | \ + NV40_VP_INST_INPUT_SRC_MASK | \ + NV40_VP_INST_SRC0H_MASK \ + ) + +/* ---- OPCODE BITS 63:32 / data DWORD 2 --- */ +#define NV40_VP_INST_SRC0L_SHIFT 23 +#define NV40_VP_INST_SRC0L_MASK (0x1FF << 23) +#define NV40_VP_INST_SRC1_SHIFT 6 +#define NV40_VP_INST_SRC1_MASK (0x1FFFF << 6) +#define NV40_VP_INST_SRC2H_SHIFT 0 +#define NV40_VP_INST_SRC2H_MASK (0x3F << 0) +#define NV40_VP_INST_IADDRH_SHIFT 0 +#define NV40_VP_INST_IADDRH_MASK (0x1F << 0) + +/* ---- OPCODE BITS 31:0 / data DWORD 3 --- */ +#define NV40_VP_INST_IADDRL_SHIFT 29 +#define NV40_VP_INST_IADDRL_MASK (7 << 29) +#define NV40_VP_INST_SRC2L_SHIFT 21 +#define NV40_VP_INST_SRC2L_MASK (0x7FF << 21) +#define NV40_VP_INST_SCA_WRITEMASK_SHIFT 17 +#define NV40_VP_INST_SCA_WRITEMASK_MASK (0xF << 17) +# define NV40_VP_INST_SCA_WRITEMASK_X (1 << 20) +# define NV40_VP_INST_SCA_WRITEMASK_Y (1 << 19) +# define NV40_VP_INST_SCA_WRITEMASK_Z (1 << 18) +# define NV40_VP_INST_SCA_WRITEMASK_W (1 << 17) +#define NV40_VP_INST_VEC_WRITEMASK_SHIFT 13 +#define NV40_VP_INST_VEC_WRITEMASK_MASK (0xF << 13) +# define NV40_VP_INST_VEC_WRITEMASK_X (1 << 16) +# define NV40_VP_INST_VEC_WRITEMASK_Y (1 << 15) +# define NV40_VP_INST_VEC_WRITEMASK_Z (1 << 14) +# define NV40_VP_INST_VEC_WRITEMASK_W (1 << 13) +#define NV40_VP_INST_SCA_RESULT (1 << 12) +#define NV40_VP_INST_SCA_DEST_TEMP_SHIFT 7 +#define NV40_VP_INST_SCA_DEST_TEMP_MASK (0x1F << 7) +#define NV40_VP_INST_DEST_SHIFT 2 +#define NV40_VP_INST_DEST_MASK (31 << 2) +# define NV40_VP_INST_DEST_POS 0 +# define NV40_VP_INST_DEST_COL0 1 +# define NV40_VP_INST_DEST_COL1 2 +# define NV40_VP_INST_DEST_BFC0 3 +# define NV40_VP_INST_DEST_BFC1 4 +# define NV40_VP_INST_DEST_FOGC 5 +# define NV40_VP_INST_DEST_PSZ 6 +# define NV40_VP_INST_DEST_TC0 7 +# define NV40_VP_INST_DEST_TC(n) (7+n) +# define NV40_VP_INST_DEST_TEMP 0x1F +#define NV40_VP_INST_INDEX_CONST (1 << 1) +#define NV40_VP_INST3_KNOWN ( \ + NV40_VP_INST_SRC2L_MASK |\ + NV40_VP_INST_SCA_WRITEMASK_MASK |\ + NV40_VP_INST_VEC_WRITEMASK_MASK |\ + NV40_VP_INST_SCA_DEST_TEMP_MASK |\ + NV40_VP_INST_DEST_MASK |\ + NV40_VP_INST_INDEX_CONST) + +/* Useful to split the source selection regs into their pieces */ +#define NV40_VP_SRC0_HIGH_SHIFT 9 +#define NV40_VP_SRC0_HIGH_MASK 0x0001FE00 +#define NV40_VP_SRC0_LOW_MASK 0x000001FF +#define NV40_VP_SRC2_HIGH_SHIFT 11 +#define NV40_VP_SRC2_HIGH_MASK 0x0001F800 +#define NV40_VP_SRC2_LOW_MASK 0x000007FF + +/* Source selection - these are the bits you fill NV40_VP_INST_SRCn with */ +#define NV40_VP_SRC_NEGATE (1 << 16) +#define NV40_VP_SRC_SWZ_X_SHIFT 14 +#define NV40_VP_SRC_SWZ_X_MASK (3 << 14) +#define NV40_VP_SRC_SWZ_Y_SHIFT 12 +#define NV40_VP_SRC_SWZ_Y_MASK (3 << 12) +#define NV40_VP_SRC_SWZ_Z_SHIFT 10 +#define NV40_VP_SRC_SWZ_Z_MASK (3 << 10) +#define NV40_VP_SRC_SWZ_W_SHIFT 8 +#define NV40_VP_SRC_SWZ_W_MASK (3 << 8) +#define NV40_VP_SRC_SWZ_ALL_SHIFT 8 +#define NV40_VP_SRC_SWZ_ALL_MASK (0xFF << 8) +#define NV40_VP_SRC_TEMP_SRC_SHIFT 2 +#define NV40_VP_SRC_TEMP_SRC_MASK (0x1F << 2) +#define NV40_VP_SRC_REG_TYPE_SHIFT 0 +#define NV40_VP_SRC_REG_TYPE_MASK (3 << 0) +# define NV40_VP_SRC_REG_TYPE_UNK0 0 +# define NV40_VP_SRC_REG_TYPE_TEMP 1 +# define NV40_VP_SRC_REG_TYPE_INPUT 2 +# define NV40_VP_SRC_REG_TYPE_CONST 3 + +#include "nvfx_shader.h" + +#endif diff --git a/src/gallium/drivers/nvfx/nvfx_buffer.c b/src/gallium/drivers/nvfx/nvfx_buffer.c new file mode 100644 index 0000000000..8efb84a5ad --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_buffer.c @@ -0,0 +1,151 @@ + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "nouveau/nouveau_screen.h" +#include "nvfx_resource.h" + + +/* Currently using separate implementations for buffers and textures, + * even though gallium has a unified abstraction of these objects. + * Eventually these should be combined, and mechanisms like transfers + * be adapted to work for both buffer and texture uploads. + */ +static void nvfx_buffer_destroy(struct pipe_screen *pscreen, + struct pipe_resource *presource) +{ + struct nvfx_resource *buffer = nvfx_resource(presource); + + nouveau_screen_bo_release(pscreen, buffer->bo); + FREE(buffer); +} + + + + +/* Utility functions for transfer create/destroy are hooked in and + * just record the arguments to those functions. + */ +static void * +nvfx_buffer_transfer_map( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct nvfx_resource *buffer = nvfx_resource(transfer->resource); + uint8_t *map; + + map = nouveau_screen_bo_map_range( pipe->screen, + buffer->bo, + transfer->box.x, + transfer->box.width, + transfer->usage ); + if (map == NULL) + return NULL; + + return map + transfer->box.x; +} + + + +static void nvfx_buffer_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + struct nvfx_resource *buffer = nvfx_resource(transfer->resource); + + nouveau_screen_bo_map_flush_range(pipe->screen, + buffer->bo, + transfer->box.x + box->x, + box->width); +} + +static void nvfx_buffer_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct nvfx_resource *buffer = nvfx_resource(transfer->resource); + + nouveau_screen_bo_unmap(pipe->screen, buffer->bo); +} + + + + +struct u_resource_vtbl nvfx_buffer_vtbl = +{ + u_default_resource_get_handle, /* get_handle */ + nvfx_buffer_destroy, /* resource_destroy */ + NULL, /* is_resource_referenced */ + u_default_get_transfer, /* get_transfer */ + u_default_transfer_destroy, /* transfer_destroy */ + nvfx_buffer_transfer_map, /* transfer_map */ + nvfx_buffer_transfer_flush_region, /* transfer_flush_region */ + nvfx_buffer_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + + +struct pipe_resource * +nvfx_buffer_create(struct pipe_screen *pscreen, + const struct pipe_resource *template) +{ + struct nvfx_resource *buffer; + + buffer = CALLOC_STRUCT(nvfx_resource); + if (!buffer) + return NULL; + + buffer->base = *template; + buffer->vtbl = &nvfx_buffer_vtbl; + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = pscreen; + + buffer->bo = nouveau_screen_bo_new(pscreen, + 16, + buffer->base.usage, + buffer->base.width0); + + if (buffer->bo == NULL) + goto fail; + + return &buffer->base; + +fail: + FREE(buffer); + return NULL; +} + + +struct pipe_resource * +nvfx_user_buffer_create(struct pipe_screen *pscreen, + void *ptr, + unsigned bytes, + unsigned usage) +{ + struct nvfx_resource *buffer; + + buffer = CALLOC_STRUCT(nvfx_resource); + if (!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->vtbl = &nvfx_buffer_vtbl; + buffer->base.screen = pscreen; + buffer->base.format = PIPE_FORMAT_R8_UNORM; + buffer->base.usage = usage; + buffer->base.width0 = bytes; + buffer->base.height0 = 1; + buffer->base.depth0 = 1; + + buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes); + if (!buffer->bo) + goto fail; + + return &buffer->base; + +fail: + FREE(buffer); + return NULL; +} + diff --git a/src/gallium/drivers/nv40/nv40_clear.c b/src/gallium/drivers/nvfx/nvfx_clear.c index ddf13addf3..2be70fcee4 100644 --- a/src/gallium/drivers/nv40/nv40_clear.c +++ b/src/gallium/drivers/nvfx/nvfx_clear.c @@ -3,12 +3,12 @@ #include "pipe/p_state.h" #include "util/u_clear.h" -#include "nv40_context.h" +#include "nvfx_context.h" void -nv40_clear(struct pipe_context *pipe, unsigned buffers, +nvfx_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil) { - util_clear(pipe, &nv40_context(pipe)->framebuffer, buffers, rgba, depth, + util_clear(pipe, &nvfx_context(pipe)->framebuffer, buffers, rgba, depth, stencil); } diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c new file mode 100644 index 0000000000..1420484aa2 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_context.c @@ -0,0 +1,87 @@ +#include "draw/draw_context.h" +#include "pipe/p_defines.h" + +#include "nvfx_context.h" +#include "nvfx_screen.h" + +static void +nvfx_flush(struct pipe_context *pipe, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + if (flags & PIPE_FLUSH_TEXTURE_CACHE) { + BEGIN_RING(chan, eng3d, 0x1fd8, 1); + OUT_RING (chan, 2); + BEGIN_RING(chan, eng3d, 0x1fd8, 1); + OUT_RING (chan, 1); + } + + FIRE_RING(chan); + if (fence) + *fence = NULL; +} + +static void +nvfx_destroy(struct pipe_context *pipe) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned i; + + for (i = 0; i < NVFX_STATE_MAX; i++) { + if (nvfx->state.hw[i]) + so_ref(NULL, &nvfx->state.hw[i]); + } + + if (nvfx->draw) + draw_destroy(nvfx->draw); + FREE(nvfx); +} + +struct pipe_context * +nvfx_create(struct pipe_screen *pscreen, void *priv) +{ + struct nvfx_screen *screen = nvfx_screen(pscreen); + struct pipe_winsys *ws = pscreen->winsys; + struct nvfx_context *nvfx; + struct nouveau_winsys *nvws = screen->nvws; + + nvfx = CALLOC(1, sizeof(struct nvfx_context)); + if (!nvfx) + return NULL; + nvfx->screen = screen; + + nvfx->nvws = nvws; + + nvfx->pipe.winsys = ws; + nvfx->pipe.screen = pscreen; + nvfx->pipe.priv = priv; + nvfx->pipe.destroy = nvfx_destroy; + nvfx->pipe.draw_arrays = nvfx_draw_arrays; + nvfx->pipe.draw_elements = nvfx_draw_elements; + nvfx->pipe.clear = nvfx_clear; + nvfx->pipe.flush = nvfx_flush; + + screen->base.channel->user_private = nvfx; + screen->base.channel->flush_notify = nvfx_state_flush_notify; + + nvfx->is_nv4x = screen->is_nv4x; + + nvfx_init_query_functions(nvfx); + nvfx_init_surface_functions(nvfx); + nvfx_init_state_functions(nvfx); + nvfx_init_transfer_functions(nvfx); + + /* Create, configure, and install fallback swtnl path */ + nvfx->draw = draw_create(); + draw_wide_point_threshold(nvfx->draw, 9999999.0); + draw_wide_line_threshold(nvfx->draw, 9999999.0); + draw_enable_line_stipple(nvfx->draw, FALSE); + draw_enable_point_sprites(nvfx->draw, FALSE); + draw_set_rasterize_stage(nvfx->draw, nvfx_draw_render_stage(nvfx)); + + return &nvfx->pipe; +} diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h new file mode 100644 index 0000000000..63d66a7801 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -0,0 +1,264 @@ +#ifndef __NVFX_CONTEXT_H__ +#define __NVFX_CONTEXT_H__ + +#include <stdio.h> + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_compiler.h" + +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_inlines.h" + +#include "draw/draw_vertex.h" + +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_gldefs.h" +#include "nouveau/nouveau_stateobj.h" + +#include "nvfx_state.h" + +#define NOUVEAU_ERR(fmt, args...) \ + fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); +#define NOUVEAU_MSG(fmt, args...) \ + fprintf(stderr, "nouveau: "fmt, ##args); + +enum nvfx_state_index { + NVFX_STATE_FB = 0, + NVFX_STATE_VIEWPORT = 1, + NVFX_STATE_BLEND = 2, + NVFX_STATE_RAST = 3, + NVFX_STATE_ZSA = 4, + NVFX_STATE_BCOL = 5, + NVFX_STATE_CLIP = 6, + NVFX_STATE_SCISSOR = 7, + NVFX_STATE_STIPPLE = 8, + NVFX_STATE_FRAGPROG = 9, + NVFX_STATE_VERTPROG = 10, + NVFX_STATE_FRAGTEX0 = 11, + NVFX_STATE_FRAGTEX1 = 12, + NVFX_STATE_FRAGTEX2 = 13, + NVFX_STATE_FRAGTEX3 = 14, + NVFX_STATE_FRAGTEX4 = 15, + NVFX_STATE_FRAGTEX5 = 16, + NVFX_STATE_FRAGTEX6 = 17, + NVFX_STATE_FRAGTEX7 = 18, + NVFX_STATE_FRAGTEX8 = 19, + NVFX_STATE_FRAGTEX9 = 20, + NVFX_STATE_FRAGTEX10 = 21, + NVFX_STATE_FRAGTEX11 = 22, + NVFX_STATE_FRAGTEX12 = 23, + NVFX_STATE_FRAGTEX13 = 24, + NVFX_STATE_FRAGTEX14 = 25, + NVFX_STATE_FRAGTEX15 = 26, + NVFX_STATE_VERTTEX0 = 27, + NVFX_STATE_VERTTEX1 = 28, + NVFX_STATE_VERTTEX2 = 29, + NVFX_STATE_VERTTEX3 = 30, + NVFX_STATE_VTXBUF = 31, + NVFX_STATE_VTXFMT = 32, + NVFX_STATE_VTXATTR = 33, + NVFX_STATE_SR = 34, + NVFX_STATE_MAX = 35 +}; + +#include "nvfx_screen.h" + +#define NVFX_NEW_BLEND (1 << 0) +#define NVFX_NEW_RAST (1 << 1) +#define NVFX_NEW_ZSA (1 << 2) +#define NVFX_NEW_SAMPLER (1 << 3) +#define NVFX_NEW_FB (1 << 4) +#define NVFX_NEW_STIPPLE (1 << 5) +#define NVFX_NEW_SCISSOR (1 << 6) +#define NVFX_NEW_VIEWPORT (1 << 7) +#define NVFX_NEW_BCOL (1 << 8) +#define NVFX_NEW_VERTPROG (1 << 9) +#define NVFX_NEW_FRAGPROG (1 << 10) +#define NVFX_NEW_ARRAYS (1 << 11) +#define NVFX_NEW_UCP (1 << 12) +#define NVFX_NEW_SR (1 << 13) + +struct nvfx_rasterizer_state { + struct pipe_rasterizer_state pipe; + struct nouveau_stateobj *so; +}; + +struct nvfx_zsa_state { + struct pipe_depth_stencil_alpha_state pipe; + struct nouveau_stateobj *so; +}; + +struct nvfx_blend_state { + struct pipe_blend_state pipe; + struct nouveau_stateobj *so; +}; + + +struct nvfx_state { + unsigned scissor_enabled; + unsigned stipple_enabled; + unsigned fp_samplers; + + uint64_t dirty; + struct nouveau_stateobj *hw[NVFX_STATE_MAX]; +}; + +struct nvfx_vtxelt_state { + struct pipe_vertex_element pipe[16]; + unsigned num_elements; +}; + +struct nvfx_context { + struct pipe_context pipe; + + struct nouveau_winsys *nvws; + struct nvfx_screen *screen; + + unsigned is_nv4x; /* either 0 or ~0 */ + + struct draw_context *draw; + + /* HW state derived from pipe states */ + struct nvfx_state state; + struct { + struct nvfx_vertex_program *vertprog; + + unsigned nr_attribs; + unsigned hw[PIPE_MAX_SHADER_INPUTS]; + unsigned draw[PIPE_MAX_SHADER_INPUTS]; + unsigned emit[PIPE_MAX_SHADER_INPUTS]; + } swtnl; + + enum { + HW, SWTNL, SWRAST + } render_mode; + unsigned fallback_swtnl; + unsigned fallback_swrast; + + /* Context state */ + unsigned dirty, draw_dirty; + struct pipe_scissor_state scissor; + unsigned stipple[32]; + struct pipe_clip_state clip; + struct nvfx_vertex_program *vertprog; + struct nvfx_fragment_program *fragprog; + struct pipe_resource *constbuf[PIPE_SHADER_TYPES]; + unsigned constbuf_nr[PIPE_SHADER_TYPES]; + struct nvfx_rasterizer_state *rasterizer; + struct nvfx_zsa_state *zsa; + struct nvfx_blend_state *blend; + struct pipe_blend_color blend_colour; + struct pipe_stencil_ref stencil_ref; + struct pipe_viewport_state viewport; + struct pipe_framebuffer_state framebuffer; + struct pipe_resource *idxbuf; + unsigned idxbuf_format; + struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; + struct nvfx_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers; + unsigned nr_textures; + unsigned dirty_samplers; + struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; + unsigned vtxbuf_nr; + struct nvfx_vtxelt_state *vtxelt; +}; + +static INLINE struct nvfx_context * +nvfx_context(struct pipe_context *pipe) +{ + return (struct nvfx_context *)pipe; +} + +struct nvfx_state_entry { + boolean (*validate)(struct nvfx_context *nvfx); + struct { + unsigned pipe; + unsigned hw; + } dirty; +}; + +extern struct nvfx_state_entry nvfx_state_blend; +extern struct nvfx_state_entry nvfx_state_blend_colour; +extern struct nvfx_state_entry nvfx_state_fragprog; +extern struct nvfx_state_entry nvfx_state_fragtex; +extern struct nvfx_state_entry nvfx_state_framebuffer; +extern struct nvfx_state_entry nvfx_state_rasterizer; +extern struct nvfx_state_entry nvfx_state_scissor; +extern struct nvfx_state_entry nvfx_state_sr; +extern struct nvfx_state_entry nvfx_state_stipple; +extern struct nvfx_state_entry nvfx_state_vbo; +extern struct nvfx_state_entry nvfx_state_vertprog; +extern struct nvfx_state_entry nvfx_state_viewport; +extern struct nvfx_state_entry nvfx_state_vtxfmt; +extern struct nvfx_state_entry nvfx_state_zsa; + +extern void nvfx_init_query_functions(struct nvfx_context *nvfx); +extern void nvfx_init_surface_functions(struct nvfx_context *nvfx); + +/* nvfx_context.c */ +struct pipe_context * +nvfx_create(struct pipe_screen *pscreen, void *priv); + +/* nvfx_clear.c */ +extern void nvfx_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); + +/* nvfx_draw.c */ +extern struct draw_stage *nvfx_draw_render_stage(struct nvfx_context *nvfx); +extern void nvfx_draw_elements_swtnl(struct pipe_context *pipe, + struct pipe_resource *idxbuf, + unsigned ib_size, unsigned mode, + unsigned start, unsigned count); + +/* nvfx_fragprog.c */ +extern void nvfx_fragprog_destroy(struct nvfx_context *, + struct nvfx_fragment_program *); + +/* nv30_fragtex.c */ +extern void +nv30_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso); +extern void nv30_fragtex_bind(struct nvfx_context *); +extern struct nouveau_stateobj * +nv30_fragtex_build(struct nvfx_context *nvfx, int unit); + +/* nv40_fragtex.c */ +extern void +nv40_sampler_state_init(struct pipe_context *pipe, + struct nvfx_sampler_state *ps, + const struct pipe_sampler_state *cso); +extern void nv40_fragtex_bind(struct nvfx_context *); +extern struct nouveau_stateobj * +nv40_fragtex_build(struct nvfx_context *nvfx, int unit); + +/* nvfx_state.c */ +extern void nvfx_init_state_functions(struct nvfx_context *nvfx); + +/* nvfx_state_emit.c */ +extern void nvfx_state_flush_notify(struct nouveau_channel *chan); +extern boolean nvfx_state_validate(struct nvfx_context *nvfx); +extern boolean nvfx_state_validate_swtnl(struct nvfx_context *nvfx); +extern void nvfx_state_emit(struct nvfx_context *nvfx); + +/* nvfx_transfer.c */ +extern void nvfx_init_transfer_functions(struct nvfx_context *nvfx); + +/* nvfx_vbo.c */ +extern void nvfx_draw_arrays(struct pipe_context *, unsigned mode, + unsigned start, unsigned count); +extern void nvfx_draw_elements(struct pipe_context *pipe, + struct pipe_resource *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, + unsigned count); + +/* nvfx_vertprog.c */ +extern void nvfx_vertprog_destroy(struct nvfx_context *, + struct nvfx_vertex_program *); + +#endif diff --git a/src/gallium/drivers/nvfx/nvfx_draw.c b/src/gallium/drivers/nvfx/nvfx_draw.c new file mode 100644 index 0000000000..9ef6918b7f --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_draw.c @@ -0,0 +1,356 @@ +#include "pipe/p_shader_tokens.h" +#include "util/u_inlines.h" +#include "tgsi/tgsi_ureg.h" + +#include "util/u_pack_color.h" + +#include "draw/draw_context.h" +#include "draw/draw_vertex.h" +#include "draw/draw_pipe.h" + +#include "nvfx_context.h" +#include "nv30_vertprog.h" +#include "nv40_vertprog.h" + +/* Simple, but crappy, swtnl path, hopefully we wont need to hit this very + * often at all. Uses "quadro style" vertex submission + a fixed vertex + * layout to avoid the need to generate a vertex program or vtxfmt. + */ + +struct nvfx_render_stage { + struct draw_stage stage; + struct nvfx_context *nvfx; + unsigned prim; +}; + +static INLINE struct nvfx_render_stage * +nvfx_render_stage(struct draw_stage *stage) +{ + return (struct nvfx_render_stage *)stage; +} + +static INLINE void +nvfx_render_vertex(struct nvfx_context *nvfx, const struct vertex_header *v) +{ + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned i; + + for (i = 0; i < nvfx->swtnl.nr_attribs; i++) { + unsigned idx = nvfx->swtnl.draw[i]; + unsigned hw = nvfx->swtnl.hw[i]; + + switch (nvfx->swtnl.emit[i]) { + case EMIT_OMIT: + break; + case EMIT_1F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_1F(hw), 1); + OUT_RING (chan, fui(v->data[idx][0])); + break; + case EMIT_2F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_2F_X(hw), 2); + OUT_RING (chan, fui(v->data[idx][0])); + OUT_RING (chan, fui(v->data[idx][1])); + break; + case EMIT_3F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_3F_X(hw), 3); + OUT_RING (chan, fui(v->data[idx][0])); + OUT_RING (chan, fui(v->data[idx][1])); + OUT_RING (chan, fui(v->data[idx][2])); + break; + case EMIT_4F: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4F_X(hw), 4); + OUT_RING (chan, fui(v->data[idx][0])); + OUT_RING (chan, fui(v->data[idx][1])); + OUT_RING (chan, fui(v->data[idx][2])); + OUT_RING (chan, fui(v->data[idx][3])); + break; + case 0xff: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4F_X(hw), 4); + OUT_RING (chan, fui(v->data[idx][0] / v->data[idx][3])); + OUT_RING (chan, fui(v->data[idx][1] / v->data[idx][3])); + OUT_RING (chan, fui(v->data[idx][2] / v->data[idx][3])); + OUT_RING (chan, fui(1.0f / v->data[idx][3])); + break; + case EMIT_4UB: + BEGIN_RING(chan, eng3d, NV34TCL_VTX_ATTR_4UB(hw), 1); + OUT_RING (chan, pack_ub4(float_to_ubyte(v->data[idx][0]), + float_to_ubyte(v->data[idx][1]), + float_to_ubyte(v->data[idx][2]), + float_to_ubyte(v->data[idx][3]))); + break; + default: + assert(0); + break; + } + } +} + +static INLINE void +nvfx_render_prim(struct draw_stage *stage, struct prim_header *prim, + unsigned mode, unsigned count) +{ + struct nvfx_render_stage *rs = nvfx_render_stage(stage); + struct nvfx_context *nvfx = rs->nvfx; + + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned i; + + /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */ + if (AVAIL_RING(chan) < ((count * 20) + 6)) { + if (rs->prim != NV34TCL_VERTEX_BEGIN_END_STOP) { + NOUVEAU_ERR("AIII, missed flush\n"); + assert(0); + } + FIRE_RING(chan); + nvfx_state_emit(nvfx); + } + + /* Switch primitive modes if necessary */ + if (rs->prim != mode) { + if (rs->prim != NV34TCL_VERTEX_BEGIN_END_STOP) { + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, NV34TCL_VERTEX_BEGIN_END_STOP); + } + + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, mode); + rs->prim = mode; + } + + /* Emit vertex data */ + for (i = 0; i < count; i++) + nvfx_render_vertex(nvfx, prim->v[i]); + + /* If it's likely we'll need to empty the push buffer soon, finish + * off the primitive now. + */ + if (AVAIL_RING(chan) < ((count * 20) + 6)) { + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, NV34TCL_VERTEX_BEGIN_END_STOP); + rs->prim = NV34TCL_VERTEX_BEGIN_END_STOP; + } +} + +static void +nvfx_render_point(struct draw_stage *draw, struct prim_header *prim) +{ + nvfx_render_prim(draw, prim, NV34TCL_VERTEX_BEGIN_END_POINTS, 1); +} + +static void +nvfx_render_line(struct draw_stage *draw, struct prim_header *prim) +{ + nvfx_render_prim(draw, prim, NV34TCL_VERTEX_BEGIN_END_LINES, 2); +} + +static void +nvfx_render_tri(struct draw_stage *draw, struct prim_header *prim) +{ + nvfx_render_prim(draw, prim, NV34TCL_VERTEX_BEGIN_END_TRIANGLES, 3); +} + +static void +nvfx_render_flush(struct draw_stage *draw, unsigned flags) +{ + struct nvfx_render_stage *rs = nvfx_render_stage(draw); + struct nvfx_context *nvfx = rs->nvfx; + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + if (rs->prim != NV34TCL_VERTEX_BEGIN_END_STOP) { + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); + OUT_RING (chan, NV34TCL_VERTEX_BEGIN_END_STOP); + rs->prim = NV34TCL_VERTEX_BEGIN_END_STOP; + } +} + +static void +nvfx_render_reset_stipple_counter(struct draw_stage *draw) +{ +} + +static void +nvfx_render_destroy(struct draw_stage *draw) +{ + FREE(draw); +} + +static struct nvfx_vertex_program * +nvfx_create_drawvp(struct nvfx_context *nvfx) +{ + struct ureg_program *ureg; + uint i; + + ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + if (ureg == NULL) + return NULL; + + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0), ureg_DECL_vs_input(ureg, 0)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0), ureg_DECL_vs_input(ureg, 3)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1), ureg_DECL_vs_input(ureg, 4)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_BCOLOR, 0), ureg_DECL_vs_input(ureg, 3)); + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_BCOLOR, 1), ureg_DECL_vs_input(ureg, 4)); + ureg_MOV(ureg, + ureg_writemask(ureg_DECL_output(ureg, TGSI_SEMANTIC_FOG, 1), TGSI_WRITEMASK_X), + ureg_DECL_vs_input(ureg, 5)); + for (i = 0; i < 8; ++i) + ureg_MOV(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, i), ureg_DECL_vs_input(ureg, 8 + i)); + + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, &nvfx->pipe ); +} + +struct draw_stage * +nvfx_draw_render_stage(struct nvfx_context *nvfx) +{ + struct nvfx_render_stage *render = CALLOC_STRUCT(nvfx_render_stage); + + if (!nvfx->swtnl.vertprog) + nvfx->swtnl.vertprog = nvfx_create_drawvp(nvfx); + + render->nvfx = nvfx; + render->stage.draw = nvfx->draw; + render->stage.point = nvfx_render_point; + render->stage.line = nvfx_render_line; + render->stage.tri = nvfx_render_tri; + render->stage.flush = nvfx_render_flush; + render->stage.reset_stipple_counter = nvfx_render_reset_stipple_counter; + render->stage.destroy = nvfx_render_destroy; + + return &render->stage; +} + +void +nvfx_draw_elements_swtnl(struct pipe_context *pipe, + struct pipe_resource *idxbuf, unsigned idxbuf_size, + unsigned mode, unsigned start, unsigned count) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; + struct pipe_transfer *ib_transfer; + struct pipe_transfer *cb_transfer; + unsigned i; + void *map; + + if (!nvfx_state_validate_swtnl(nvfx)) + return; + nvfx->state.dirty &= ~(1ULL << NVFX_STATE_VTXBUF); + nvfx_state_emit(nvfx); + + for (i = 0; i < nvfx->vtxbuf_nr; i++) { + map = pipe_buffer_map(pipe, nvfx->vtxbuf[i].buffer, + PIPE_BUFFER_USAGE_CPU_READ, + &vb_transfer[i]); + draw_set_mapped_vertex_buffer(nvfx->draw, i, map); + } + + if (idxbuf) { + map = pipe_buffer_map(pipe, idxbuf, + PIPE_BUFFER_USAGE_CPU_READ, + &ib_transfer); + draw_set_mapped_element_buffer(nvfx->draw, idxbuf_size, map); + } else { + draw_set_mapped_element_buffer(nvfx->draw, 0, NULL); + } + + if (nvfx->constbuf[PIPE_SHADER_VERTEX]) { + const unsigned nr = nvfx->constbuf_nr[PIPE_SHADER_VERTEX]; + + map = pipe_buffer_map(pipe, + nvfx->constbuf[PIPE_SHADER_VERTEX], + PIPE_BUFFER_USAGE_CPU_READ, + &cb_transfer); + draw_set_mapped_constant_buffer(nvfx->draw, PIPE_SHADER_VERTEX, 0, + map, nr); + } + + draw_arrays(nvfx->draw, mode, start, count); + + for (i = 0; i < nvfx->vtxbuf_nr; i++) + pipe_buffer_unmap(pipe, nvfx->vtxbuf[i].buffer, vb_transfer[i]); + + if (idxbuf) + pipe_buffer_unmap(pipe, idxbuf, ib_transfer); + + if (nvfx->constbuf[PIPE_SHADER_VERTEX]) + pipe_buffer_unmap(pipe, nvfx->constbuf[PIPE_SHADER_VERTEX], + cb_transfer); + + draw_flush(nvfx->draw); + pipe->flush(pipe, 0, NULL); +} + +static INLINE void +emit_attrib(struct nvfx_context *nvfx, unsigned hw, unsigned emit, + unsigned semantic, unsigned index) +{ + unsigned draw_out = draw_find_shader_output(nvfx->draw, semantic, index); + unsigned a = nvfx->swtnl.nr_attribs++; + + nvfx->swtnl.hw[a] = hw; + nvfx->swtnl.emit[a] = emit; + nvfx->swtnl.draw[a] = draw_out; +} + +static boolean +nvfx_state_vtxfmt_validate(struct nvfx_context *nvfx) +{ + struct nvfx_fragment_program *fp = nvfx->fragprog; + unsigned colour = 0, texcoords = 0, fog = 0, i; + + /* Determine needed fragprog inputs */ + for (i = 0; i < fp->info.num_inputs; i++) { + switch (fp->info.input_semantic_name[i]) { + case TGSI_SEMANTIC_POSITION: + break; + case TGSI_SEMANTIC_COLOR: + colour |= (1 << fp->info.input_semantic_index[i]); + break; + case TGSI_SEMANTIC_GENERIC: + texcoords |= (1 << fp->info.input_semantic_index[i]); + break; + case TGSI_SEMANTIC_FOG: + fog = 1; + break; + default: + assert(0); + } + } + + nvfx->swtnl.nr_attribs = 0; + + /* Map draw vtxprog output to hw attribute IDs */ + for (i = 0; i < 2; i++) { + if (!(colour & (1 << i))) + continue; + emit_attrib(nvfx, 3 + i, EMIT_4F, TGSI_SEMANTIC_COLOR, i); + } + + for (i = 0; i < 8; i++) { + if (!(texcoords & (1 << i))) + continue; + emit_attrib(nvfx, 8 + i, EMIT_4F, TGSI_SEMANTIC_GENERIC, i); + } + + if (fog) { + emit_attrib(nvfx, 5, EMIT_1F, TGSI_SEMANTIC_FOG, 0); + } + + emit_attrib(nvfx, 0, 0xff, TGSI_SEMANTIC_POSITION, 0); + + return FALSE; +} + +struct nvfx_state_entry nvfx_state_vtxfmt = { + .validate = nvfx_state_vtxfmt_validate, + .dirty = { + .pipe = NVFX_NEW_ARRAYS | NVFX_NEW_FRAGPROG, + .hw = 0 + } +}; diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nvfx/nvfx_fragprog.c index dc24f9b08a..d85484dbe6 100644 --- a/src/gallium/drivers/nv40/nv40_fragprog.c +++ b/src/gallium/drivers/nvfx/nvfx_fragprog.c @@ -7,37 +7,21 @@ #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" -#include "nv40_context.h" - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 1 -#define MASK_Y 2 -#define MASK_Z 4 -#define MASK_W 8 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE NV40_FP_OP_DST_SCALE_1X -#define DEF_CTEST NV40_FP_OP_COND_TR -#include "nv40_shader.h" - -#define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv40_sr_neg((s)) -#define abs(s) nv40_sr_abs((s)) -#define scale(s,v) nv40_sr_scale((s), NV40_FP_OP_DST_SCALE_##v) +#include "nvfx_context.h" +#include "nvfx_shader.h" +#include "nvfx_resource.h" #define MAX_CONSTS 128 #define MAX_IMM 32 -struct nv40_fpc { - struct nv40_fragment_program *fp; +struct nvfx_fpc { + struct nvfx_fragment_program *fp; uint attrib_map[PIPE_MAX_SHADER_INPUTS]; unsigned r_temps; unsigned r_temps_discard; - struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; - struct nv40_sreg *r_temp; + struct nvfx_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; + struct nvfx_sreg *r_temp; int num_regs; @@ -50,35 +34,35 @@ struct nv40_fpc { } consts[MAX_CONSTS]; int nr_consts; - struct nv40_sreg imm[MAX_IMM]; + struct nvfx_sreg imm[MAX_IMM]; unsigned nr_imm; }; -static INLINE struct nv40_sreg -temp(struct nv40_fpc *fpc) +static INLINE struct nvfx_sreg +temp(struct nvfx_fpc *fpc) { int idx = ffs(~fpc->r_temps) - 1; if (idx < 0) { NOUVEAU_ERR("out of temps!!\n"); assert(0); - return nv40_sr(NV40SR_TEMP, 0); + return nvfx_sr(NVFXSR_TEMP, 0); } fpc->r_temps |= (1 << idx); fpc->r_temps_discard |= (1 << idx); - return nv40_sr(NV40SR_TEMP, idx); + return nvfx_sr(NVFXSR_TEMP, idx); } static INLINE void -release_temps(struct nv40_fpc *fpc) +release_temps(struct nvfx_fpc *fpc) { fpc->r_temps &= ~fpc->r_temps_discard; fpc->r_temps_discard = 0; } -static INLINE struct nv40_sreg -constant(struct nv40_fpc *fpc, int pipe, float vals[4]) +static INLINE struct nvfx_sreg +constant(struct nvfx_fpc *fpc, int pipe, float vals[4]) { int idx; @@ -89,45 +73,45 @@ constant(struct nv40_fpc *fpc, int pipe, float vals[4]) fpc->consts[idx].pipe = pipe; if (pipe == -1) memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float)); - return nv40_sr(NV40SR_CONST, idx); + return nvfx_sr(NVFXSR_CONST, idx); } #define arith(cc,s,o,d,m,s0,s1,s2) \ - nv40_fp_arith((cc), (s), NV40_FP_OP_OPCODE_##o, \ + nvfx_fp_arith((cc), (s), NVFX_FP_OP_OPCODE_##o, \ (d), (m), (s0), (s1), (s2)) #define tex(cc,s,o,u,d,m,s0,s1,s2) \ - nv40_fp_tex((cc), (s), NV40_FP_OP_OPCODE_##o, (u), \ + nvfx_fp_tex((cc), (s), NVFX_FP_OP_OPCODE_##o, (u), \ (d), (m), (s0), none, none) static void -grow_insns(struct nv40_fpc *fpc, int size) +grow_insns(struct nvfx_fpc *fpc, int size) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; fp->insn_len += size; fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len); } static void -emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src) +emit_src(struct nvfx_fpc *fpc, int pos, struct nvfx_sreg src) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; uint32_t *hw = &fp->insn[fpc->inst_offset]; uint32_t sr = 0; switch (src.type) { - case NV40SR_INPUT: - sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT); - hw[0] |= (src.index << NV40_FP_OP_INPUT_SRC_SHIFT); + case NVFXSR_INPUT: + sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT); + hw[0] |= (src.index << NVFX_FP_OP_INPUT_SRC_SHIFT); break; - case NV40SR_OUTPUT: - sr |= NV40_FP_REG_SRC_HALF; + case NVFXSR_OUTPUT: + sr |= NVFX_FP_REG_SRC_HALF; /* fall-through */ - case NV40SR_TEMP: - sr |= (NV40_FP_REG_TYPE_TEMP << NV40_FP_REG_TYPE_SHIFT); - sr |= (src.index << NV40_FP_REG_SRC_SHIFT); + case NVFXSR_TEMP: + sr |= (NVFX_FP_REG_TYPE_TEMP << NVFX_FP_REG_TYPE_SHIFT); + sr |= (src.index << NVFX_FP_REG_SRC_SHIFT); break; - case NV40SR_CONST: + case NVFXSR_CONST: if (!fpc->have_const) { grow_insns(fpc, 4); fpc->have_const = 1; @@ -135,7 +119,7 @@ emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src) hw = &fp->insn[fpc->inst_offset]; if (fpc->consts[src.index].pipe >= 0) { - struct nv40_fragment_program_data *fpd; + struct nvfx_fragment_program_data *fpd; fp->consts = realloc(fp->consts, ++fp->nr_consts * sizeof(*fpd)); @@ -149,63 +133,63 @@ emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src) sizeof(uint32_t) * 4); } - sr |= (NV40_FP_REG_TYPE_CONST << NV40_FP_REG_TYPE_SHIFT); + sr |= (NVFX_FP_REG_TYPE_CONST << NVFX_FP_REG_TYPE_SHIFT); break; - case NV40SR_NONE: - sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT); + case NVFXSR_NONE: + sr |= (NVFX_FP_REG_TYPE_INPUT << NVFX_FP_REG_TYPE_SHIFT); break; default: assert(0); } if (src.negate) - sr |= NV40_FP_REG_NEGATE; + sr |= NVFX_FP_REG_NEGATE; if (src.abs) hw[1] |= (1 << (29 + pos)); - sr |= ((src.swz[0] << NV40_FP_REG_SWZ_X_SHIFT) | - (src.swz[1] << NV40_FP_REG_SWZ_Y_SHIFT) | - (src.swz[2] << NV40_FP_REG_SWZ_Z_SHIFT) | - (src.swz[3] << NV40_FP_REG_SWZ_W_SHIFT)); + sr |= ((src.swz[0] << NVFX_FP_REG_SWZ_X_SHIFT) | + (src.swz[1] << NVFX_FP_REG_SWZ_Y_SHIFT) | + (src.swz[2] << NVFX_FP_REG_SWZ_Z_SHIFT) | + (src.swz[3] << NVFX_FP_REG_SWZ_W_SHIFT)); hw[pos + 1] |= sr; } static void -emit_dst(struct nv40_fpc *fpc, struct nv40_sreg dst) +emit_dst(struct nvfx_fpc *fpc, struct nvfx_sreg dst) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; uint32_t *hw = &fp->insn[fpc->inst_offset]; switch (dst.type) { - case NV40SR_TEMP: + case NVFXSR_TEMP: if (fpc->num_regs < (dst.index + 1)) fpc->num_regs = dst.index + 1; break; - case NV40SR_OUTPUT: + case NVFXSR_OUTPUT: if (dst.index == 1) { fp->fp_control |= 0xe; } else { - hw[0] |= NV40_FP_OP_OUT_REG_HALF; + hw[0] |= NVFX_FP_OP_OUT_REG_HALF; } break; - case NV40SR_NONE: + case NVFXSR_NONE: hw[0] |= (1 << 30); break; default: assert(0); } - hw[0] |= (dst.index << NV40_FP_OP_OUT_REG_SHIFT); + hw[0] |= (dst.index << NVFX_FP_OP_OUT_REG_SHIFT); } static void -nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op, - struct nv40_sreg dst, int mask, - struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2) +nvfx_fp_arith(struct nvfx_fpc *fpc, int sat, int op, + struct nvfx_sreg dst, int mask, + struct nvfx_sreg s0, struct nvfx_sreg s1, struct nvfx_sreg s2) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; uint32_t *hw; fpc->inst_offset = fp->insn_len; @@ -214,22 +198,22 @@ nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op, hw = &fp->insn[fpc->inst_offset]; memset(hw, 0, sizeof(uint32_t) * 4); - if (op == NV40_FP_OP_OPCODE_KIL) - fp->fp_control |= NV40TCL_FP_CONTROL_KIL; - hw[0] |= (op << NV40_FP_OP_OPCODE_SHIFT); - hw[0] |= (mask << NV40_FP_OP_OUTMASK_SHIFT); - hw[2] |= (dst.dst_scale << NV40_FP_OP_DST_SCALE_SHIFT); + if (op == NVFX_FP_OP_OPCODE_KIL) + fp->fp_control |= NV34TCL_FP_CONTROL_USES_KIL; + hw[0] |= (op << NVFX_FP_OP_OPCODE_SHIFT); + hw[0] |= (mask << NVFX_FP_OP_OUTMASK_SHIFT); + hw[2] |= (dst.dst_scale << NVFX_FP_OP_DST_SCALE_SHIFT); if (sat) - hw[0] |= NV40_FP_OP_OUT_SAT; + hw[0] |= NVFX_FP_OP_OUT_SAT; if (dst.cc_update) - hw[0] |= NV40_FP_OP_COND_WRITE_ENABLE; - hw[1] |= (dst.cc_test << NV40_FP_OP_COND_SHIFT); - hw[1] |= ((dst.cc_swz[0] << NV40_FP_OP_COND_SWZ_X_SHIFT) | - (dst.cc_swz[1] << NV40_FP_OP_COND_SWZ_Y_SHIFT) | - (dst.cc_swz[2] << NV40_FP_OP_COND_SWZ_Z_SHIFT) | - (dst.cc_swz[3] << NV40_FP_OP_COND_SWZ_W_SHIFT)); + hw[0] |= NVFX_FP_OP_COND_WRITE_ENABLE; + hw[1] |= (dst.cc_test << NVFX_FP_OP_COND_SHIFT); + hw[1] |= ((dst.cc_swz[0] << NVFX_FP_OP_COND_SWZ_X_SHIFT) | + (dst.cc_swz[1] << NVFX_FP_OP_COND_SWZ_Y_SHIFT) | + (dst.cc_swz[2] << NVFX_FP_OP_COND_SWZ_Z_SHIFT) | + (dst.cc_swz[3] << NVFX_FP_OP_COND_SWZ_W_SHIFT)); emit_dst(fpc, dst); emit_src(fpc, 0, s0); @@ -238,26 +222,26 @@ nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op, } static void -nv40_fp_tex(struct nv40_fpc *fpc, int sat, int op, int unit, - struct nv40_sreg dst, int mask, - struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2) +nvfx_fp_tex(struct nvfx_fpc *fpc, int sat, int op, int unit, + struct nvfx_sreg dst, int mask, + struct nvfx_sreg s0, struct nvfx_sreg s1, struct nvfx_sreg s2) { - struct nv40_fragment_program *fp = fpc->fp; + struct nvfx_fragment_program *fp = fpc->fp; - nv40_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); + nvfx_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2); - fp->insn[fpc->inst_offset] |= (unit << NV40_FP_OP_TEX_UNIT_SHIFT); + fp->insn[fpc->inst_offset] |= (unit << NVFX_FP_OP_TEX_UNIT_SHIFT); fp->samplers |= (1 << unit); } -static INLINE struct nv40_sreg -tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc) +static INLINE struct nvfx_sreg +tgsi_src(struct nvfx_fpc *fpc, const struct tgsi_full_src_register *fsrc) { - struct nv40_sreg src; + struct nvfx_sreg src; switch (fsrc->Register.File) { case TGSI_FILE_INPUT: - src = nv40_sr(NV40SR_INPUT, + src = nvfx_sr(NVFXSR_INPUT, fpc->attrib_map[fsrc->Register.Index]); break; case TGSI_FILE_CONSTANT: @@ -288,18 +272,18 @@ tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc) return src; } -static INLINE struct nv40_sreg -tgsi_dst(struct nv40_fpc *fpc, const struct tgsi_full_dst_register *fdst) { +static INLINE struct nvfx_sreg +tgsi_dst(struct nvfx_fpc *fpc, const struct tgsi_full_dst_register *fdst) { switch (fdst->Register.File) { case TGSI_FILE_OUTPUT: return fpc->r_result[fdst->Register.Index]; case TGSI_FILE_TEMPORARY: return fpc->r_temp[fdst->Register.Index]; case TGSI_FILE_NULL: - return nv40_sr(NV40SR_NONE, 0); + return nvfx_sr(NVFXSR_NONE, 0); default: NOUVEAU_ERR("bad dst file %d\n", fdst->Register.File); - return nv40_sr(NV40SR_NONE, 0); + return nvfx_sr(NVFXSR_NONE, 0); } } @@ -308,52 +292,19 @@ tgsi_mask(uint tgsi) { int mask = 0; - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; + if (tgsi & TGSI_WRITEMASK_X) mask |= NVFX_FP_MASK_X; + if (tgsi & TGSI_WRITEMASK_Y) mask |= NVFX_FP_MASK_Y; + if (tgsi & TGSI_WRITEMASK_Z) mask |= NVFX_FP_MASK_Z; + if (tgsi & TGSI_WRITEMASK_W) mask |= NVFX_FP_MASK_W; return mask; } static boolean -src_native_swz(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc, - struct nv40_sreg *src) -{ - const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - struct nv40_sreg tgsi = tgsi_src(fpc, fsrc); - uint mask = 0; - uint c; - - for (c = 0; c < 4; c++) { - switch (tgsi_util_get_full_src_register_swizzle(fsrc, c)) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - mask |= (1 << c); - break; - default: - assert(0); - } - } - - if (mask == MASK_ALL) - return TRUE; - - *src = temp(fpc); - - if (mask) - arith(fpc, 0, MOV, *src, mask, tgsi, none, none); - - return FALSE; -} - -static boolean -nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, +nvfx_fragprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_fpc *fpc, const struct tgsi_full_instruction *finst) { - const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0); - struct nv40_sreg src[3], dst, tmp; + const struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0); + struct nvfx_sreg src[3], dst, tmp; int mask, sat, unit; int ai = -1, ci = -1, ii = -1; int i; @@ -377,23 +328,12 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, switch (fsrc->Register.File) { case TGSI_FILE_INPUT: - case TGSI_FILE_CONSTANT: - case TGSI_FILE_TEMPORARY: - if (!src_native_swz(fpc, fsrc, &src[i])) - continue; - break; - default: - break; - } - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: if (ai == -1 || ai == fsrc->Register.Index) { ai = fsrc->Register.Index; src[i] = tgsi_src(fpc, fsrc); } else { src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, + arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none); } break; @@ -404,7 +344,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, src[i] = tgsi_src(fpc, fsrc); } else { src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, + arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none); } break; @@ -415,7 +355,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, src[i] = tgsi_src(fpc, fsrc); } else { src[i] = temp(fpc); - arith(fpc, 0, MOV, src[i], MASK_ALL, + arith(fpc, 0, MOV, src[i], NVFX_FP_MASK_ALL, tgsi_src(fpc, fsrc), none, none); } break; @@ -445,25 +385,25 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, arith(fpc, sat, ADD, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_CMP: - tmp = nv40_sr(NV40SR_NONE, 0); + tmp = nvfx_sr(NVFXSR_NONE, 0); tmp.cc_update = 1; arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none); - dst.cc_test = NV40_VP_INST_COND_GE; + dst.cc_test = NVFX_COND_GE; arith(fpc, sat, MOV, dst, mask, src[2], none, none); - dst.cc_test = NV40_VP_INST_COND_LT; + dst.cc_test = NVFX_COND_LT; arith(fpc, sat, MOV, dst, mask, src[1], none, none); break; case TGSI_OPCODE_COS: arith(fpc, sat, COS, dst, mask, src[0], none, none); break; case TGSI_OPCODE_DDX: - if (mask & (MASK_Z | MASK_W)) { + if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) { tmp = temp(fpc); - arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, + arith(fpc, sat, DDX, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none); - arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W, + arith(fpc, 0, MOV, tmp, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none); - arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, src[0], + arith(fpc, sat, DDX, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none); arith(fpc, 0, MOV, dst, mask, tmp, none, none); } else { @@ -471,13 +411,13 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, } break; case TGSI_OPCODE_DDY: - if (mask & (MASK_Z | MASK_W)) { + if (mask & (NVFX_FP_MASK_Z | NVFX_FP_MASK_W)) { tmp = temp(fpc); - arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, + arith(fpc, sat, DDY, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, swz(src[0], Z, W, Z, W), none, none); - arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W, + arith(fpc, 0, MOV, tmp, NVFX_FP_MASK_Z | NVFX_FP_MASK_W, swz(tmp, X, Y, X, Y), none, none); - arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, src[0], + arith(fpc, sat, DDY, tmp, NVFX_FP_MASK_X | NVFX_FP_MASK_Y, src[0], none, none); arith(fpc, 0, MOV, dst, mask, tmp, none, none); } else { @@ -492,7 +432,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, break; case TGSI_OPCODE_DPH: tmp = temp(fpc); - arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none); + arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_X, src[0], src[1], none); arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X), swz(src[1], W, W, W, W), none); break; @@ -512,10 +452,10 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, arith(fpc, 0, KIL, none, 0, none, none, none); break; case TGSI_OPCODE_KIL: - dst = nv40_sr(NV40SR_NONE, 0); + dst = nvfx_sr(NVFXSR_NONE, 0); dst.cc_update = 1; - arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none); - dst.cc_update = 0; dst.cc_test = NV40_FP_OP_COND_LT; + arith(fpc, 0, MOV, dst, NVFX_FP_MASK_ALL, src[0], none, none); + dst.cc_update = 0; dst.cc_test = NVFX_COND_LT; arith(fpc, 0, KIL, dst, 0, none, none, none); break; case TGSI_OPCODE_LG2: @@ -523,9 +463,13 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, break; // case TGSI_OPCODE_LIT: case TGSI_OPCODE_LRP: - tmp = temp(fpc); - arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]); - arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp); + if(!nvfx->is_nv4x) + arith(fpc, sat, LRP_NV30, dst, mask, src[0], src[1], src[2]); + else { + tmp = temp(fpc); + arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]); + arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp); + } break; case TGSI_OPCODE_MAD: arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]); @@ -543,13 +487,17 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, arith(fpc, sat, MUL, dst, mask, src[0], src[1], none); break; case TGSI_OPCODE_POW: - tmp = temp(fpc); - arith(fpc, 0, LG2, tmp, MASK_X, - swz(src[0], X, X, X, X), none, none); - arith(fpc, 0, MUL, tmp, MASK_X, swz(tmp, X, X, X, X), - swz(src[1], X, X, X, X), none); - arith(fpc, sat, EX2, dst, mask, - swz(tmp, X, X, X, X), none, none); + if(!nvfx->is_nv4x) + arith(fpc, sat, POW_NV30, dst, mask, src[0], src[1], none); + else { + tmp = temp(fpc); + arith(fpc, 0, LG2, tmp, NVFX_FP_MASK_X, + swz(src[0], X, X, X, X), none, none); + arith(fpc, 0, MUL, tmp, NVFX_FP_MASK_X, swz(tmp, X, X, X, X), + swz(src[1], X, X, X, X), none); + arith(fpc, sat, EX2, dst, mask, + swz(tmp, X, X, X, X), none, none); + } break; case TGSI_OPCODE_RCP: arith(fpc, sat, RCP, dst, mask, src[0], none, none); @@ -558,42 +506,50 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, assert(0); break; case TGSI_OPCODE_RFL: - tmp = temp(fpc); - arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[0], none); - arith(fpc, 0, DP3, tmp, MASK_Y, src[0], src[1], none); - arith(fpc, 0, DIV, scale(tmp, 2X), MASK_Z, - swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none); - arith(fpc, sat, MAD, dst, mask, - swz(tmp, Z, Z, Z, Z), src[0], neg(src[1])); + if(!nvfx->is_nv4x) + arith(fpc, 0, RFL_NV30, dst, mask, src[0], src[1], none); + else { + tmp = temp(fpc); + arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_X, src[0], src[0], none); + arith(fpc, 0, DP3, tmp, NVFX_FP_MASK_Y, src[0], src[1], none); + arith(fpc, 0, DIV, scale(tmp, 2X), NVFX_FP_MASK_Z, + swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none); + arith(fpc, sat, MAD, dst, mask, + swz(tmp, Z, Z, Z, Z), src[0], neg(src[1])); + } break; case TGSI_OPCODE_RSQ: - tmp = temp(fpc); - arith(fpc, 0, LG2, scale(tmp, INV_2X), MASK_X, - abs(swz(src[0], X, X, X, X)), none, none); - arith(fpc, sat, EX2, dst, mask, - neg(swz(tmp, X, X, X, X)), none, none); + if(!nvfx->is_nv4x) + arith(fpc, sat, RSQ_NV30, dst, mask, abs(swz(src[0], X, X, X, X)), none, none); + else { + tmp = temp(fpc); + arith(fpc, 0, LG2, scale(tmp, INV_2X), NVFX_FP_MASK_X, + abs(swz(src[0], X, X, X, X)), none, none); + arith(fpc, sat, EX2, dst, mask, + neg(swz(tmp, X, X, X, X)), none, none); + } break; case TGSI_OPCODE_SCS: /* avoid overwriting the source */ - if(src[0].swz[SWZ_X] != SWZ_X) + if(src[0].swz[NVFX_SWZ_X] != NVFX_SWZ_X) { - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, + if (mask & NVFX_FP_MASK_X) { + arith(fpc, sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none); } - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, + if (mask & NVFX_FP_MASK_Y) { + arith(fpc, sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none); } } else { - if (mask & MASK_Y) { - arith(fpc, sat, SIN, dst, MASK_Y, + if (mask & NVFX_FP_MASK_Y) { + arith(fpc, sat, SIN, dst, NVFX_FP_MASK_Y, swz(src[0], X, X, X, X), none, none); } - if (mask & MASK_X) { - arith(fpc, sat, COS, dst, MASK_X, + if (mask & NVFX_FP_MASK_X) { + arith(fpc, sat, COS, dst, NVFX_FP_MASK_X, swz(src[0], X, X, X, X), none, none); } } @@ -641,7 +597,7 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, tmp = temp(fpc); arith(fpc, 0, MUL, tmp, mask, swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(fpc, sat, MAD, dst, (mask & ~MASK_W), + arith(fpc, sat, MAD, dst, (mask & ~NVFX_FP_MASK_W), swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), neg(tmp)); break; @@ -655,32 +611,32 @@ nv40_fragprog_parse_instruction(struct nv40_fpc *fpc, } static boolean -nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc, +nvfx_fragprog_parse_decl_attrib(struct nvfx_context* nvfx, struct nvfx_fpc *fpc, const struct tgsi_full_declaration *fdec) { int hw; switch (fdec->Semantic.Name) { case TGSI_SEMANTIC_POSITION: - hw = NV40_FP_OP_INPUT_SRC_POSITION; + hw = NVFX_FP_OP_INPUT_SRC_POSITION; break; case TGSI_SEMANTIC_COLOR: if (fdec->Semantic.Index == 0) { - hw = NV40_FP_OP_INPUT_SRC_COL0; + hw = NVFX_FP_OP_INPUT_SRC_COL0; } else if (fdec->Semantic.Index == 1) { - hw = NV40_FP_OP_INPUT_SRC_COL1; + hw = NVFX_FP_OP_INPUT_SRC_COL1; } else { NOUVEAU_ERR("bad colour semantic index\n"); return FALSE; } break; case TGSI_SEMANTIC_FOG: - hw = NV40_FP_OP_INPUT_SRC_FOGC; + hw = NVFX_FP_OP_INPUT_SRC_FOGC; break; case TGSI_SEMANTIC_GENERIC: if (fdec->Semantic.Index <= 7) { - hw = NV40_FP_OP_INPUT_SRC_TC(fdec->Semantic. + hw = NVFX_FP_OP_INPUT_SRC_TC(fdec->Semantic. Index); } else { NOUVEAU_ERR("bad generic semantic index\n"); @@ -697,7 +653,7 @@ nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc, } static boolean -nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc, +nvfx_fragprog_parse_decl_output(struct nvfx_context* nvfx, struct nvfx_fpc *fpc, const struct tgsi_full_declaration *fdec) { unsigned idx = fdec->Range.First; @@ -708,12 +664,14 @@ nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc, hw = 1; break; case TGSI_SEMANTIC_COLOR: + hw = ~0; switch (fdec->Semantic.Index) { case 0: hw = 0; break; case 1: hw = 2; break; case 2: hw = 3; break; case 3: hw = 4; break; - default: + } + if(hw > ((nvfx->is_nv4x) ? 4 : 2)) { NOUVEAU_ERR("bad rcol index\n"); return FALSE; } @@ -723,13 +681,13 @@ nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc, return FALSE; } - fpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw); + fpc->r_result[idx] = nvfx_sr(NVFXSR_OUTPUT, hw); fpc->r_temps |= (1 << hw); return TRUE; } static boolean -nv40_fragprog_prepare(struct nv40_fpc *fpc) +nvfx_fragprog_prepare(struct nvfx_context* nvfx, struct nvfx_fpc *fpc) { struct tgsi_parse_context p; int high_temp = -1, i; @@ -746,11 +704,11 @@ nv40_fragprog_prepare(struct nv40_fpc *fpc) fdec = &p.FullToken.FullDeclaration; switch (fdec->Declaration.File) { case TGSI_FILE_INPUT: - if (!nv40_fragprog_parse_decl_attrib(fpc, fdec)) + if (!nvfx_fragprog_parse_decl_attrib(nvfx, fpc, fdec)) goto out_err; break; case TGSI_FILE_OUTPUT: - if (!nv40_fragprog_parse_decl_output(fpc, fdec)) + if (!nvfx_fragprog_parse_decl_output(nvfx, fpc, fdec)) goto out_err; break; case TGSI_FILE_TEMPORARY: @@ -787,7 +745,7 @@ nv40_fragprog_prepare(struct nv40_fpc *fpc) tgsi_parse_free(&p); if (++high_temp) { - fpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg)); + fpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_sreg)); for (i = 0; i < high_temp; i++) fpc->r_temp[i] = temp(fpc); fpc->r_temps_discard = 0; @@ -803,19 +761,19 @@ out_err: } static void -nv40_fragprog_translate(struct nv40_context *nv40, - struct nv40_fragment_program *fp) +nvfx_fragprog_translate(struct nvfx_context *nvfx, + struct nvfx_fragment_program *fp) { struct tgsi_parse_context parse; - struct nv40_fpc *fpc = NULL; + struct nvfx_fpc *fpc = NULL; - fpc = CALLOC(1, sizeof(struct nv40_fpc)); + fpc = CALLOC(1, sizeof(struct nvfx_fpc)); if (!fpc) return; fpc->fp = fp; fpc->num_regs = 2; - if (!nv40_fragprog_prepare(fpc)) { + if (!nvfx_fragprog_prepare(nvfx, fpc)) { FREE(fpc); return; } @@ -831,7 +789,7 @@ nv40_fragprog_translate(struct nv40_context *nv40, const struct tgsi_full_instruction *finst; finst = &parse.FullToken.FullInstruction; - if (!nv40_fragprog_parse_instruction(fpc, finst)) + if (!nvfx_fragprog_parse_instruction(nvfx, fpc, finst)) goto out_err; } break; @@ -840,7 +798,10 @@ nv40_fragprog_translate(struct nv40_context *nv40, } } - fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT; + if(!nvfx->is_nv4x) + fp->fp_control |= (fpc->num_regs-1)/2; + else + fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT; /* Terminate final instruction */ fp->insn[fpc->inst_offset] |= 0x00000001; @@ -862,15 +823,11 @@ out_err: } static void -nv40_fragprog_upload(struct nv40_context *nv40, - struct nv40_fragment_program *fp) +nvfx_fragprog_upload(struct nvfx_context *nvfx, + struct nvfx_fragment_program *fp) { - struct pipe_screen *pscreen = nv40->pipe.screen; + struct pipe_context *pipe = &nvfx->pipe; const uint32_t le = 1; - uint32_t *map; - int i; - - map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); #if 0 for (i = 0; i < fp->insn_len; i++) { @@ -881,27 +838,39 @@ nv40_fragprog_upload(struct nv40_context *nv40, #endif if ((*(const uint8_t *)&le)) { - for (i = 0; i < fp->insn_len; i++) { - map[i] = fp->insn[i]; - } + /* Can do this with an inline transfer */ + pipe_buffer_write(pipe, + fp->buffer, + 0, + fp->insn_len * sizeof fp->insn[0], + fp->insn); } else { + struct pipe_transfer *transfer; + uint32_t *map; + int i; + + map = pipe_buffer_map(pipe, fp->buffer, + PIPE_BUFFER_USAGE_CPU_WRITE, + &transfer); + /* Weird swapping for big-endian chips */ for (i = 0; i < fp->insn_len; i++) { map[i] = ((fp->insn[i] & 0xffff) << 16) | ((fp->insn[i] >> 16) & 0xffff); } - } - pipe_buffer_unmap(pscreen, fp->buffer); + pipe_buffer_unmap(pipe, fp->buffer, transfer); + } } static boolean -nv40_fragprog_validate(struct nv40_context *nv40) +nvfx_fragprog_validate(struct nvfx_context *nvfx) { - struct nv40_fragment_program *fp = nv40->fragprog; - struct pipe_buffer *constbuf = - nv40->constbuf[PIPE_SHADER_FRAGMENT]; - struct pipe_screen *pscreen = nv40->pipe.screen; + struct pipe_context *pipe = &nvfx->pipe; + struct nvfx_fragment_program *fp = nvfx->fragprog; + struct pipe_resource *constbuf = + nvfx->constbuf[PIPE_SHADER_FRAGMENT]; + struct pipe_screen *pscreen = nvfx->pipe.screen; struct nouveau_stateobj *so; boolean new_consts = FALSE; int i; @@ -909,35 +878,50 @@ nv40_fragprog_validate(struct nv40_context *nv40) if (fp->translated) goto update_constants; - nv40->fallback_swrast &= ~NV40_NEW_FRAGPROG; - nv40_fragprog_translate(nv40, fp); + nvfx->fallback_swrast &= ~NVFX_NEW_FRAGPROG; + nvfx_fragprog_translate(nvfx, fp); if (!fp->translated) { - nv40->fallback_swrast |= NV40_NEW_FRAGPROG; + nvfx->fallback_swrast |= NVFX_NEW_FRAGPROG; return FALSE; } - fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4); - nv40_fragprog_upload(nv40, fp); + fp->buffer = pipe_buffer_create(pscreen, 0x100, 0, fp->insn_len * 4); + nvfx_fragprog_upload(nvfx, fp); - so = so_new(2, 2, 1); - so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1); - so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM | + so = so_new(4, 4, 1); + so_method(so, nvfx->screen->eng3d, NV34TCL_FP_ACTIVE_PROGRAM, 1); + so_reloc (so, nvfx_resource(fp->buffer)->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | - NOUVEAU_BO_OR, NV40TCL_FP_ADDRESS_DMA0, - NV40TCL_FP_ADDRESS_DMA1); - so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1); + NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0, + NV34TCL_FP_ACTIVE_PROGRAM_DMA1); + so_method(so, nvfx->screen->eng3d, NV34TCL_FP_CONTROL, 1); so_data (so, fp->fp_control); + if(!nvfx->is_nv4x) { + so_method(so, nvfx->screen->eng3d, NV34TCL_FP_REG_CONTROL, 1); + so_data (so, (1<<16)|0x4); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_UNITS_ENABLE, 1); + so_data (so, fp->samplers); + } + so_ref(so, &fp->so); so_ref(NULL, &so); update_constants: if (fp->nr_consts) { + struct pipe_transfer *transfer; float *map; - map = pipe_buffer_map(pscreen, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pipe, constbuf, + PIPE_TRANSFER_READ, + &transfer); + + /* XXX: probably a bad idea to be reading back data + * from a buffer the gpu has been using. Not really + * sure what this code is doing though, or how to + * avoid it - kw. + */ for (i = 0; i < fp->nr_consts; i++) { - struct nv40_fragment_program_data *fpd = &fp->consts[i]; + struct nvfx_fragment_program_data *fpd = &fp->consts[i]; uint32_t *p = &fp->insn[fpd->offset]; uint32_t *cb = (uint32_t *)&map[fpd->index * 4]; @@ -946,14 +930,14 @@ update_constants: memcpy(p, cb, 4 * sizeof(float)); new_consts = TRUE; } - pipe_buffer_unmap(pscreen, constbuf); + pipe_buffer_unmap(pipe, constbuf, transfer); if (new_consts) - nv40_fragprog_upload(nv40, fp); + nvfx_fragprog_upload(nvfx, fp); } - if (new_consts || fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) { - so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]); + if (new_consts || fp->so != nvfx->state.hw[NVFX_STATE_FRAGPROG]) { + so_ref(fp->so, &nvfx->state.hw[NVFX_STATE_FRAGPROG]); return TRUE; } @@ -961,11 +945,11 @@ update_constants: } void -nv40_fragprog_destroy(struct nv40_context *nv40, - struct nv40_fragment_program *fp) +nvfx_fragprog_destroy(struct nvfx_context *nvfx, + struct nvfx_fragment_program *fp) { if (fp->buffer) - pipe_buffer_reference(&fp->buffer, NULL); + pipe_resource_reference(&fp->buffer, NULL); if (fp->so) so_ref(NULL, &fp->so); @@ -974,11 +958,10 @@ nv40_fragprog_destroy(struct nv40_context *nv40, FREE(fp->insn); } -struct nv40_state_entry nv40_state_fragprog = { - .validate = nv40_fragprog_validate, +struct nvfx_state_entry nvfx_state_fragprog = { + .validate = nvfx_fragprog_validate, .dirty = { - .pipe = NV40_NEW_FRAGPROG, - .hw = NV40_STATE_FRAGPROG + .pipe = NVFX_NEW_FRAGPROG, + .hw = NVFX_STATE_FRAGPROG } }; - diff --git a/src/gallium/drivers/nvfx/nvfx_fragtex.c b/src/gallium/drivers/nvfx/nvfx_fragtex.c new file mode 100644 index 0000000000..84e4eb1004 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_fragtex.c @@ -0,0 +1,49 @@ +#include "nvfx_context.h" + +static boolean +nvfx_fragtex_validate(struct nvfx_context *nvfx) +{ + struct nvfx_fragment_program *fp = nvfx->fragprog; + struct nvfx_state *state = &nvfx->state; + struct nouveau_stateobj *so; + unsigned samplers, unit; + + samplers = state->fp_samplers & ~fp->samplers; + while (samplers) { + unit = ffs(samplers) - 1; + samplers &= ~(1 << unit); + + so = so_new(1, 1, 0); + so_method(so, nvfx->screen->eng3d, NV34TCL_TX_ENABLE(unit), 1); + so_data (so, 0); + so_ref(so, &nvfx->state.hw[NVFX_STATE_FRAGTEX0 + unit]); + so_ref(NULL, &so); + state->dirty |= (1ULL << (NVFX_STATE_FRAGTEX0 + unit)); + } + + samplers = nvfx->dirty_samplers & fp->samplers; + while (samplers) { + unit = ffs(samplers) - 1; + samplers &= ~(1 << unit); + + if(!nvfx->is_nv4x) + so = nv30_fragtex_build(nvfx, unit); + else + so = nv40_fragtex_build(nvfx, unit); + + so_ref(so, &nvfx->state.hw[NVFX_STATE_FRAGTEX0 + unit]); + so_ref(NULL, &so); + state->dirty |= (1ULL << (NVFX_STATE_FRAGTEX0 + unit)); + } + + nvfx->state.fp_samplers = fp->samplers; + return FALSE; +} + +struct nvfx_state_entry nvfx_state_fragtex = { + .validate = nvfx_fragtex_validate, + .dirty = { + .pipe = NVFX_NEW_SAMPLER | NVFX_NEW_FRAGPROG, + .hw = 0 + } +}; diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c index 62e97bcea4..0999dd9106 100644 --- a/src/gallium/drivers/nv40/nv40_miptree.c +++ b/src/gallium/drivers/nvfx/nvfx_miptree.c @@ -4,15 +4,23 @@ #include "util/u_format.h" #include "util/u_math.h" -#include "nv40_context.h" -#include "../nouveau/nv04_surface_2d.h" +#include "nvfx_context.h" +#include "nvfx_resource.h" +#include "nvfx_transfer.h" +#include "nv04_surface_2d.h" +#include "nouveau/nouveau_util.h" +/* Currently using separate implementations for buffers and textures, + * even though gallium has a unified abstraction of these objects. + * Eventually these should be combined, and mechanisms like transfers + * be adapted to work for both buffer and texture uploads. + */ static void -nv40_miptree_layout(struct nv40_miptree *mt) +nvfx_miptree_layout(struct nvfx_miptree *mt) { - struct pipe_texture *pt = &mt->base; + struct pipe_resource *pt = &mt->base.base; uint width = pt->width0; uint offset = 0; int nr_faces, l, f; @@ -61,45 +69,109 @@ nv40_miptree_layout(struct nv40_miptree *mt) mt->total_size = offset; } -static struct pipe_texture * -nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +static boolean +nvfx_miptree_get_handle(struct pipe_screen *pscreen, + struct pipe_resource *ptexture, + struct winsys_handle *whandle) { - struct nv40_miptree *mt; + struct nvfx_miptree* mt = (struct nvfx_miptree*)ptexture; + + if (!mt || !mt->base.bo) + return FALSE; + + return nouveau_screen_bo_get_handle(pscreen, + mt->base.bo, + mt->level[0].pitch, + whandle); +} + + +static void +nvfx_miptree_destroy(struct pipe_screen *screen, struct pipe_resource *pt) +{ + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; + int l; + + nouveau_screen_bo_release(screen, mt->base.bo); + + for (l = 0; l <= pt->last_level; l++) { + if (mt->level[l].image_offset) + FREE(mt->level[l].image_offset); + } + + FREE(mt); +} + + + + +struct u_resource_vtbl nvfx_miptree_vtbl = +{ + nvfx_miptree_get_handle, /* get_handle */ + nvfx_miptree_destroy, /* resource_destroy */ + NULL, /* is_resource_referenced */ + nvfx_miptree_transfer_new, /* get_transfer */ + nvfx_miptree_transfer_del, /* transfer_destroy */ + nvfx_miptree_transfer_map, /* transfer_map */ + u_default_transfer_flush_region, /* transfer_flush_region */ + nvfx_miptree_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + +struct pipe_resource * +nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt) +{ + struct nvfx_miptree *mt; unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | NOUVEAU_BUFFER_USAGE_TEXTURE; - mt = MALLOC(sizeof(struct nv40_miptree)); + mt = CALLOC_STRUCT(nvfx_miptree); if (!mt) return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; + + mt->base.base = *pt; + pipe_reference_init(&mt->base.base.reference, 1); + mt->base.base.screen = pscreen; /* Swizzled textures must be POT */ if (pt->width0 & (pt->width0 - 1) || pt->height0 & (pt->height0 - 1)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else if (pt->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; else { switch (pt->format) { + case PIPE_FORMAT_B5G6R5_UNORM: + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + /* TODO: we can actually swizzle these formats on nv40, we + are just preserving the pre-unification behavior. + The whole 2D code is going to be rewritten anyway. */ + if(nvfx_screen(pscreen)->is_nv4x) { + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + break; + } /* TODO: Figure out which formats can be swizzled */ case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: case PIPE_FORMAT_R16_SNORM: { if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; break; } default: - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; } } @@ -110,75 +182,78 @@ nv40_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy. * This also happens for small mipmaps of large textures. */ if (pt->tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET && util_format_get_stride(pt->format, pt->width0) < 64) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - nv40_miptree_layout(mt); + nvfx_miptree_layout(mt); - mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage, mt->total_size); - if (!mt->buffer) { + mt->base.bo = nouveau_screen_bo_new(pscreen, 256, buf_usage, mt->total_size); + if (!mt->base.bo) { FREE(mt); return NULL; } - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; + return &mt->base.base; } -static struct pipe_texture * -nv40_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) + + + +struct pipe_resource * +nvfx_miptree_from_handle(struct pipe_screen *pscreen, + const struct pipe_resource *template, + struct winsys_handle *whandle) { - struct nv40_miptree *mt; + struct nvfx_miptree *mt; + unsigned stride; /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) + if (template->target != PIPE_TEXTURE_2D || + template->last_level != 0 || + template->depth0 != 1) return NULL; - mt = CALLOC_STRUCT(nv40_miptree); + mt = CALLOC_STRUCT(nvfx_miptree); if (!mt) return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - mt->level[0].pitch = stride[0]; + mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride); + if (mt->base.bo == NULL) { + FREE(mt); + return NULL; + } + + mt->base.base = *template; + pipe_reference_init(&mt->base.base.reference, 1); + mt->base.base.screen = pscreen; + mt->level[0].pitch = stride; mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); /* Assume whoever created this buffer expects it to be linear for now */ - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + mt->base.base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - pipe_buffer_reference(&mt->buffer, pb); - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; + /* XXX: Need to adjust bo refcount?? + */ + /* nouveau_bo_ref(bo, &mt->base.bo); */ + return &mt->base.base; } -static void -nv40_miptree_destroy(struct pipe_texture *pt) -{ - struct nv40_miptree *mt = (struct nv40_miptree *)pt; - int l; - pipe_buffer_reference(&mt->buffer, NULL); - for (l = 0; l <= pt->last_level; l++) { - if (mt->level[l].image_offset) - FREE(mt->level[l].image_offset); - } - FREE(mt); -} -static struct pipe_surface * -nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, + +/* Surface helpers, not strictly required to implement the resource vtbl: + */ +struct pipe_surface * +nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { - struct nv40_miptree *mt = (struct nv40_miptree *)pt; + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; struct nv04_surface *ns; ns = CALLOC_STRUCT(nv04_surface); if (!ns) return NULL; - pipe_texture_reference(&ns->base.texture, pt); + pipe_resource_reference(&ns->base.texture, pt); ns->base.format = pt->format; ns->base.width = u_minify(pt->width0, level); ns->base.height = u_minify(pt->height0, level); @@ -202,35 +277,23 @@ nv40_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, * Note that ns->pitch is always a multiple of 64 for linear surfaces and swizzled surfaces are POT, so * ns->pitch & 63 is equivalent to (ns->pitch < 64 && swizzled)*/ if((ns->pitch & 63) && (ns->base.usage & (PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER)) == PIPE_BUFFER_USAGE_GPU_WRITE) - return &nv04_surface_wrap_for_render(pscreen, ((struct nv40_screen*)pscreen)->eng2d, ns)->base; + return &nv04_surface_wrap_for_render(pscreen, ((struct nvfx_screen*)pscreen)->eng2d, ns)->base; return &ns->base; } -static void -nv40_miptree_surface_del(struct pipe_surface *ps) +void +nvfx_miptree_surface_del(struct pipe_surface *ps) { struct nv04_surface* ns = (struct nv04_surface*)ps; if(ns->backing) { - struct nv40_screen* screen = (struct nv40_screen*)ps->texture->screen; + struct nvfx_screen* screen = (struct nvfx_screen*)ps->texture->screen; if(ns->backing->base.usage & PIPE_BUFFER_USAGE_GPU_WRITE) screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height); - nv40_miptree_surface_del(&ns->backing->base); + nvfx_miptree_surface_del(&ns->backing->base); } - pipe_texture_reference(&ps->texture, NULL); + pipe_resource_reference(&ps->texture, NULL); FREE(ps); } - -void -nv40_screen_init_miptree_functions(struct pipe_screen *pscreen) -{ - pscreen->texture_create = nv40_miptree_create; - pscreen->texture_destroy = nv40_miptree_destroy; - pscreen->get_tex_surface = nv40_miptree_surface_new; - pscreen->tex_surface_destroy = nv40_miptree_surface_del; - - nouveau_screen(pscreen)->texture_blanket = nv40_miptree_blanket; -} - diff --git a/src/gallium/drivers/nvfx/nvfx_query.c b/src/gallium/drivers/nvfx/nvfx_query.c new file mode 100644 index 0000000000..acbaf75a23 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_query.c @@ -0,0 +1,127 @@ +#include "pipe/p_context.h" + +#include "nvfx_context.h" + +struct nvfx_query { + struct nouveau_resource *object; + unsigned type; + boolean ready; + uint64_t result; +}; + +static INLINE struct nvfx_query * +nvfx_query(struct pipe_query *pipe) +{ + return (struct nvfx_query *)pipe; +} + +static struct pipe_query * +nvfx_query_create(struct pipe_context *pipe, unsigned query_type) +{ + struct nvfx_query *q; + + q = CALLOC(1, sizeof(struct nvfx_query)); + q->type = query_type; + + return (struct pipe_query *)q; +} + +static void +nvfx_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) +{ + struct nvfx_query *q = nvfx_query(pq); + + if (q->object) + nouveau_resource_free(&q->object); + FREE(q); +} + +static void +nvfx_query_begin(struct pipe_context *pipe, struct pipe_query *pq) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_query *q = nvfx_query(pq); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + + assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); + + /* Happens when end_query() is called, then another begin_query() + * without querying the result in-between. For now we'll wait for + * the existing query to notify completion, but it could be better. + */ + if (q->object) { + uint64_t tmp; + pipe->get_query_result(pipe, pq, 1, &tmp); + } + + if (nouveau_resource_alloc(nvfx->screen->query_heap, 1, NULL, &q->object)) + assert(0); + nouveau_notifier_reset(nvfx->screen->query, q->object->start); + + BEGIN_RING(chan, eng3d, NV34TCL_QUERY_RESET, 1); + OUT_RING (chan, 1); + BEGIN_RING(chan, eng3d, NV34TCL_QUERY_UNK17CC, 1); + OUT_RING (chan, 1); + + q->ready = FALSE; +} + +static void +nvfx_query_end(struct pipe_context *pipe, struct pipe_query *pq) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + struct nvfx_query *q = nvfx_query(pq); + + BEGIN_RING(chan, eng3d, NV34TCL_QUERY_GET, 1); + OUT_RING (chan, (0x01 << NV34TCL_QUERY_GET_UNK24_SHIFT) | + ((q->object->start * 32) << NV34TCL_QUERY_GET_OFFSET_SHIFT)); + FIRE_RING(chan); +} + +static boolean +nvfx_query_result(struct pipe_context *pipe, struct pipe_query *pq, + boolean wait, uint64_t *result) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_query *q = nvfx_query(pq); + + assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); + + if (!q->ready) { + unsigned status; + + status = nouveau_notifier_status(nvfx->screen->query, + q->object->start); + if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { + if (wait == FALSE) + return FALSE; + + nouveau_notifier_wait_status(nvfx->screen->query, + q->object->start, + NV_NOTIFY_STATE_STATUS_COMPLETED, 0); + } + + q->result = nouveau_notifier_return_val(nvfx->screen->query, + q->object->start); + q->ready = TRUE; + nouveau_resource_free(&q->object); + } + + *result = q->result; + return TRUE; +} + +void +nvfx_init_query_functions(struct nvfx_context *nvfx) +{ + nvfx->pipe.create_query = nvfx_query_create; + nvfx->pipe.destroy_query = nvfx_query_destroy; + nvfx->pipe.begin_query = nvfx_query_begin; + nvfx->pipe.end_query = nvfx_query_end; + nvfx->pipe.get_query_result = nvfx_query_result; +} diff --git a/src/gallium/drivers/nvfx/nvfx_resource.c b/src/gallium/drivers/nvfx/nvfx_resource.c new file mode 100644 index 0000000000..5bf1e5cb65 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_resource.c @@ -0,0 +1,67 @@ + +#include "pipe/p_context.h" +#include "nvfx_resource.h" +#include "nouveau/nouveau_screen.h" + + +/* This doesn't look quite right - this query is supposed to ask + * whether the particular context has references to the resource in + * any unflushed rendering command buffer, and hence requires a + * pipe->flush() for serializing some modification to that resource. + * + * This seems to be answering the question of whether the resource is + * currently on hardware. + */ +static unsigned int +nvfx_resource_is_referenced(struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned face, unsigned level) +{ + return nouveau_reference_flags(nvfx_resource(resource)->bo); +} + +static struct pipe_resource * +nvfx_resource_create(struct pipe_screen *screen, + const struct pipe_resource *template) +{ + if (template->target == PIPE_BUFFER) + return nvfx_buffer_create(screen, template); + else + return nvfx_miptree_create(screen, template); +} + +static struct pipe_resource * +nvfx_resource_from_handle(struct pipe_screen * screen, + const struct pipe_resource *template, + struct winsys_handle *whandle) +{ + if (template->target == PIPE_BUFFER) + return NULL; + else + return nvfx_miptree_from_handle(screen, template, whandle); +} + +void +nvfx_init_resource_functions(struct pipe_context *pcontext) +{ + pcontext->get_transfer = u_get_transfer_vtbl; + pcontext->transfer_map = u_transfer_map_vtbl; + pcontext->transfer_flush_region = u_transfer_flush_region_vtbl; + pcontext->transfer_unmap = u_transfer_unmap_vtbl; + pcontext->transfer_destroy = u_transfer_destroy_vtbl; + pcontext->transfer_inline_write = u_transfer_inline_write_vtbl; + pcontext->is_resource_referenced = nvfx_resource_is_referenced; +} + +void +nvfx_screen_init_resource_functions(struct pipe_screen *pscreen) +{ + pscreen->resource_create = nvfx_resource_create; + pscreen->resource_from_handle = nvfx_resource_from_handle; + pscreen->resource_get_handle = u_resource_get_handle_vtbl; + pscreen->resource_destroy = u_resource_destroy_vtbl; + pscreen->user_buffer_create = nvfx_user_buffer_create; + + pscreen->get_tex_surface = nvfx_miptree_surface_new; + pscreen->tex_surface_destroy = nvfx_miptree_surface_del; +} diff --git a/src/gallium/drivers/nvfx/nvfx_resource.h b/src/gallium/drivers/nvfx/nvfx_resource.h new file mode 100644 index 0000000000..93133e8eed --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_resource.h @@ -0,0 +1,91 @@ + +#ifndef NVFX_RESOURCE_H +#define NVFX_RESOURCE_H + +#include "util/u_transfer.h" + +struct pipe_resource; +struct nouveau_bo; + + +/* This gets further specialized into either buffer or texture + * structures. In the future we'll want to remove much of that + * distinction, but for now try to keep as close to the existing code + * as possible and use the vtbl struct to choose between the two + * underlying implementations. + */ +struct nvfx_resource { + struct pipe_resource base; + struct u_resource_vtbl *vtbl; + struct nouveau_bo *bo; +}; + +#define NVFX_MAX_TEXTURE_LEVELS 16 + +struct nvfx_miptree { + struct nvfx_resource base; + uint total_size; + + struct { + uint pitch; + uint *image_offset; + } level[NVFX_MAX_TEXTURE_LEVELS]; + + unsigned image_nr; +}; + +static INLINE +struct nvfx_resource *nvfx_resource(struct pipe_resource *resource) +{ + return (struct nvfx_resource *)resource; +} + +static INLINE struct nouveau_bo * +nvfx_surface_buffer(struct pipe_surface *surf) +{ + struct nvfx_resource *mt = nvfx_resource(surf->texture); + + return mt->bo; +} + + +void +nvfx_init_resource_functions(struct pipe_context *pcontext); + +void +nvfx_screen_init_resource_functions(struct pipe_screen *pscreen); + + +/* Internal: + */ + +struct pipe_resource * +nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt); + +struct pipe_resource * +nvfx_miptree_from_handle(struct pipe_screen *pscreen, + const struct pipe_resource *template, + struct winsys_handle *whandle); + +struct pipe_resource * +nvfx_buffer_create(struct pipe_screen *pscreen, + const struct pipe_resource *template); + +struct pipe_resource * +nvfx_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned usage); + + + +void +nvfx_miptree_surface_del(struct pipe_surface *ps); + +struct pipe_surface * +nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, + unsigned face, unsigned level, unsigned zslice, + unsigned flags); + + +#endif diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index db24335b7c..ee95972e73 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -1,20 +1,22 @@ #include "pipe/p_screen.h" #include "pipe/p_state.h" +#include "util/u_simple_screen.h" #include "nouveau/nouveau_screen.h" -#include "nv30_context.h" -#include "nv30_screen.h" +#include "nvfx_context.h" +#include "nvfx_screen.h" +#include "nvfx_resource.h" #define NV30TCL_CHIPSET_3X_MASK 0x00000003 #define NV34TCL_CHIPSET_3X_MASK 0x00000010 #define NV35TCL_CHIPSET_3X_MASK 0x000001e0 /* FIXME: It seems I should not include directly ../../winsys/drm/nouveau/drm/nouveau_drm_api.h - * to get the pointer to the context front buffer, so I copied nouveau_winsys here. - * nv30_screen_surface_format_supported() can then use it to enforce creating fbo - * with same number of bits everywhere. - */ +* to get the pointer to the context front buffer, so I copied nouveau_winsys here. +* nv30_screen_surface_format_supported() can then use it to enforce creating fbo +* with same number of bits everywhere. +*/ struct nouveau_winsys { struct pipe_winsys base; @@ -22,15 +24,21 @@ struct nouveau_winsys { struct pipe_surface *front; }; +#define NV4X_GRCLASS4097_CHIPSETS 0x00000baf +#define NV4X_GRCLASS4497_CHIPSETS 0x00005450 +#define NV6X_GRCLASS4497_CHIPSETS 0x00000088 static int -nv30_screen_get_param(struct pipe_screen *pscreen, int param) +nvfx_screen_get_param(struct pipe_screen *pscreen, int param) { + struct nvfx_screen *screen = nvfx_screen(pscreen); + switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 8; + /* TODO: check this */ + return screen->is_nv4x ? 16 : 8; case PIPE_CAP_NPOT_TEXTURES: - return 0; + return !!screen->is_nv4x; case PIPE_CAP_TWO_SIDED_STENCIL: return 1; case PIPE_CAP_GLSL: @@ -40,7 +48,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_POINT_SPRITE: return 1; case PIPE_CAP_MAX_RENDER_TARGETS: - return 2; + return screen->is_nv4x ? 4 : 2; case PIPE_CAP_OCCLUSION_QUERY: return 1; case PIPE_CAP_TEXTURE_SHADOW_MAP: @@ -52,21 +60,26 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 13; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: - return 0; + return !!screen->is_nv4x; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: return 1; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; + return 0; /* We have 4 on nv40 - but unsupported currently */ case PIPE_CAP_TGSI_CONT_SUPPORTED: return 0; case PIPE_CAP_BLEND_EQUATION_SEPARATE: - return 0; + return !!screen->is_nv4x; case NOUVEAU_CAP_HW_VTXBUF: + /* TODO: this is almost surely wrong */ + return !!screen->is_nv4x; case NOUVEAU_CAP_HW_IDXBUF: - return 1; + /* TODO: this is also almost surely wrong */ + return screen->is_nv4x && screen->eng3d->grclass == NV40TCL; case PIPE_CAP_MAX_COMBINED_SAMPLERS: return 16; case PIPE_CAP_INDEP_BLEND_ENABLE: + /* TODO: on nv40 we have separate color masks */ + /* TODO: nv40 mrt blending is probably broken */ return 0; case PIPE_CAP_INDEP_BLEND_FUNC: return 0; @@ -83,8 +96,10 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) } static float -nv30_screen_get_paramf(struct pipe_screen *pscreen, int param) +nvfx_screen_get_paramf(struct pipe_screen *pscreen, int param) { + struct nvfx_screen *screen = nvfx_screen(pscreen); + switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: case PIPE_CAP_MAX_LINE_WIDTH_AA: @@ -93,9 +108,9 @@ nv30_screen_get_paramf(struct pipe_screen *pscreen, int param) case PIPE_CAP_MAX_POINT_WIDTH_AA: return 64.0; case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 8.0; + return screen->is_nv4x ? 16.0 : 8.0; case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: - return 4.0; + return screen->is_nv4x ? 16.0 : 4.0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0.0; @@ -103,11 +118,12 @@ nv30_screen_get_paramf(struct pipe_screen *pscreen, int param) } static boolean -nv30_screen_surface_format_supported(struct pipe_screen *pscreen, +nvfx_screen_surface_format_supported(struct pipe_screen *pscreen, enum pipe_format format, enum pipe_texture_target target, unsigned tex_usage, unsigned geom_flags) { + struct nvfx_screen *screen = nvfx_screen(pscreen); struct pipe_surface *front = ((struct nouveau_winsys *) pscreen->winsys)->front; if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { @@ -125,9 +141,9 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_X8Z24_UNORM: return TRUE; case PIPE_FORMAT_Z16_UNORM: - if (front) { + /* TODO: this nv30 limitation probably does not exist */ + if (!screen->is_nv4x && front) return (front->format == PIPE_FORMAT_B5G6R5_UNORM); - } return TRUE; default: break; @@ -144,7 +160,14 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_L8A8_UNORM: case PIPE_FORMAT_Z16_UNORM: case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: return TRUE; + /* TODO: does nv30 support this? */ + case PIPE_FORMAT_R16_SNORM: + return !!screen->is_nv4x; default: break; } @@ -153,21 +176,14 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen, return FALSE; } -static struct pipe_buffer * -nv30_surface_buffer(struct pipe_surface *surf) -{ - struct nv30_miptree *mt = (struct nv30_miptree *)surf->texture; - - return mt->buffer; -} static void -nv30_screen_destroy(struct pipe_screen *pscreen) +nvfx_screen_destroy(struct pipe_screen *pscreen) { - struct nv30_screen *screen = nv30_screen(pscreen); + struct nvfx_screen *screen = nvfx_screen(pscreen); unsigned i; - for (i = 0; i < NV30_STATE_MAX; i++) { + for (i = 0; i < NVFX_STATE_MAX; i++) { if (screen->state[i]) so_ref(NULL, &screen->state[i]); } @@ -177,7 +193,7 @@ nv30_screen_destroy(struct pipe_screen *pscreen) nouveau_resource_destroy(&screen->query_heap); nouveau_notifier_free(&screen->query); nouveau_notifier_free(&screen->sync); - nouveau_grobj_free(&screen->rankine); + nouveau_grobj_free(&screen->eng3d); nv04_surface_2d_takedown(&screen->eng2d); nouveau_screen_fini(&screen->base); @@ -185,59 +201,155 @@ nv30_screen_destroy(struct pipe_screen *pscreen) FREE(pscreen); } +static void nv30_screen_init(struct nvfx_screen *screen, struct nouveau_stateobj* so) +{ + int i; + + /* TODO: perhaps we should do some of this on nv40 too? */ + for (i=1; i<8; i++) { + so_method(so, screen->eng3d, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1); + so_data (so, 0); + so_method(so, screen->eng3d, NV34TCL_VIEWPORT_CLIP_VERT(i), 1); + so_data (so, 0); + } + + so_method(so, screen->eng3d, 0x220, 1); + so_data (so, 1); + + so_method(so, screen->eng3d, 0x03b0, 1); + so_data (so, 0x00100000); + so_method(so, screen->eng3d, 0x1454, 1); + so_data (so, 0); + so_method(so, screen->eng3d, 0x1d80, 1); + so_data (so, 3); + so_method(so, screen->eng3d, 0x1450, 1); + so_data (so, 0x00030004); + + /* NEW */ + so_method(so, screen->eng3d, 0x1e98, 1); + so_data (so, 0); + so_method(so, screen->eng3d, 0x17e0, 3); + so_data (so, fui(0.0)); + so_data (so, fui(0.0)); + so_data (so, fui(1.0)); + so_method(so, screen->eng3d, 0x1f80, 16); + for (i=0; i<16; i++) { + so_data (so, (i==8) ? 0x0000ffff : 0); + } + + so_method(so, screen->eng3d, 0x120, 3); + so_data (so, 0); + so_data (so, 1); + so_data (so, 2); + + so_method(so, screen->eng3d, 0x1d88, 1); + so_data (so, 0x00001200); + + so_method(so, screen->eng3d, NV34TCL_RC_ENABLE, 1); + so_data (so, 0); + + so_method(so, screen->eng3d, NV34TCL_DEPTH_RANGE_NEAR, 2); + so_data (so, fui(0.0)); + so_data (so, fui(1.0)); + + so_method(so, screen->eng3d, NV34TCL_MULTISAMPLE_CONTROL, 1); + so_data (so, 0xffff0000); + + /* enables use of vp rather than fixed-function somehow */ + so_method(so, screen->eng3d, 0x1e94, 1); + so_data (so, 0x13); +} + +static void nv40_screen_init(struct nvfx_screen *screen, struct nouveau_stateobj* so) +{ + so_method(so, screen->eng3d, NV40TCL_DMA_COLOR2, 2); + so_data (so, screen->base.channel->vram->handle); + so_data (so, screen->base.channel->vram->handle); + + so_method(so, screen->eng3d, 0x1ea4, 3); + so_data (so, 0x00000010); + so_data (so, 0x01000100); + so_data (so, 0xff800006); + + /* vtxprog output routing */ + so_method(so, screen->eng3d, 0x1fc4, 1); + so_data (so, 0x06144321); + so_method(so, screen->eng3d, 0x1fc8, 2); + so_data (so, 0xedcba987); + so_data (so, 0x00000021); + so_method(so, screen->eng3d, 0x1fd0, 1); + so_data (so, 0x00171615); + so_method(so, screen->eng3d, 0x1fd4, 1); + so_data (so, 0x001b1a19); + + so_method(so, screen->eng3d, 0x1ef8, 1); + so_data (so, 0x0020ffff); + so_method(so, screen->eng3d, 0x1d64, 1); + so_data (so, 0x00d30000); + so_method(so, screen->eng3d, 0x1e94, 1); + so_data (so, 0x00000001); +} + struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) +nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { - struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen); + struct nvfx_screen *screen = CALLOC_STRUCT(nvfx_screen); struct nouveau_channel *chan; struct pipe_screen *pscreen; struct nouveau_stateobj *so; - unsigned rankine_class = 0; - int ret, i; + unsigned eng3d_class = 0; + int ret; if (!screen) return NULL; + pscreen = &screen->base.base; ret = nouveau_screen_init(&screen->base, dev); if (ret) { - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } chan = screen->base.channel; pscreen->winsys = ws; - pscreen->destroy = nv30_screen_destroy; - pscreen->get_param = nv30_screen_get_param; - pscreen->get_paramf = nv30_screen_get_paramf; - pscreen->is_format_supported = nv30_screen_surface_format_supported; - pscreen->context_create = nv30_create; + pscreen->destroy = nvfx_screen_destroy; + pscreen->get_param = nvfx_screen_get_param; + pscreen->get_paramf = nvfx_screen_get_paramf; + pscreen->is_format_supported = nvfx_screen_surface_format_supported; + pscreen->context_create = nvfx_create; - nv30_screen_init_miptree_functions(pscreen); - - /* 3D object */ switch (dev->chipset & 0xf0) { case 0x30: if (NV30TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) - rankine_class = 0x0397; - else - if (NV34TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) - rankine_class = 0x0697; - else - if (NV35TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) - rankine_class = 0x0497; + eng3d_class = 0x0397; + else if (NV34TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) + eng3d_class = 0x0697; + else if (NV35TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) + eng3d_class = 0x0497; break; - default: + case 0x40: + if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f))) + eng3d_class = NV40TCL; + else if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) + eng3d_class = NV44TCL; + screen->is_nv4x = ~0; + break; + case 0x60: + if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) + eng3d_class = NV44TCL; + screen->is_nv4x = ~0; break; } - if (!rankine_class) { - NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", dev->chipset); + if (!eng3d_class) { + NOUVEAU_ERR("Unknown nv3x/nv4x chipset: nv%02x\n", dev->chipset); return NULL; } - ret = nouveau_grobj_alloc(chan, 0xbeef3097, rankine_class, - &screen->rankine); + nvfx_screen_init_resource_functions(pscreen); + + ret = nouveau_grobj_alloc(chan, 0xbeef3097, eng3d_class, &screen->eng3d); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return FALSE; @@ -245,13 +357,13 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) /* 2D engine setup */ screen->eng2d = nv04_surface_2d_init(&screen->base); - screen->eng2d->buf = nv30_surface_buffer; + screen->eng2d->buf = nvfx_surface_buffer; /* Notifier for sync purposes */ ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } @@ -259,99 +371,54 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query); if (ret) { NOUVEAU_ERR("Error initialising query objects: %d\n", ret); - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } ret = nouveau_resource_init(&screen->query_heap, 0, 32); if (ret) { NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } /* Vtxprog resources */ - if (nouveau_resource_init(&screen->vp_exec_heap, 0, 256) || + if (nouveau_resource_init(&screen->vp_exec_heap, 0, screen->is_nv4x ? 512 : 256) || nouveau_resource_init(&screen->vp_data_heap, 0, 256)) { - nv30_screen_destroy(pscreen); + nvfx_screen_destroy(pscreen); return NULL; } - /* Static rankine initialisation */ - so = so_new(36, 60, 0); - so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1); + /* Static eng3d initialisation */ + /* make the so big and don't worry about exact values + since we it will be thrown away immediately after use */ + so = so_new(256, 256, 0); + so_method(so, screen->eng3d, NV34TCL_DMA_NOTIFY, 1); so_data (so, screen->sync->handle); - so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2); + so_method(so, screen->eng3d, NV34TCL_DMA_TEXTURE0, 2); so_data (so, chan->vram->handle); so_data (so, chan->gart->handle); - so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1); + so_method(so, screen->eng3d, NV34TCL_DMA_COLOR1, 1); so_data (so, chan->vram->handle); - so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2); + so_method(so, screen->eng3d, NV34TCL_DMA_COLOR0, 2); so_data (so, chan->vram->handle); so_data (so, chan->vram->handle); - so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2); + so_method(so, screen->eng3d, NV34TCL_DMA_VTXBUF0, 2); so_data (so, chan->vram->handle); so_data (so, chan->gart->handle); -/* so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2); - so_data (so, 0); - so_data (so, screen->query->handle);*/ - so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1); - so_data (so, chan->vram->handle); - so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1); - so_data (so, chan->vram->handle); - - for (i=1; i<8; i++) { - so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1); - so_data (so, 0); - so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_VERT(i), 1); - so_data (so, 0); - } - - so_method(so, screen->rankine, 0x220, 1); - so_data (so, 1); - - so_method(so, screen->rankine, 0x03b0, 1); - so_data (so, 0x00100000); - so_method(so, screen->rankine, 0x1454, 1); - so_data (so, 0); - so_method(so, screen->rankine, 0x1d80, 1); - so_data (so, 3); - so_method(so, screen->rankine, 0x1450, 1); - so_data (so, 0x00030004); - - /* NEW */ - so_method(so, screen->rankine, 0x1e98, 1); - so_data (so, 0); - so_method(so, screen->rankine, 0x17e0, 3); - so_data (so, fui(0.0)); - so_data (so, fui(0.0)); - so_data (so, fui(1.0)); - so_method(so, screen->rankine, 0x1f80, 16); - for (i=0; i<16; i++) { - so_data (so, (i==8) ? 0x0000ffff : 0); - } - - so_method(so, screen->rankine, 0x120, 3); - so_data (so, 0); - so_data (so, 1); - so_data (so, 2); - - so_method(so, screen->rankine, 0x1d88, 1); - so_data (so, 0x00001200); - so_method(so, screen->rankine, NV34TCL_RC_ENABLE, 1); + so_method(so, screen->eng3d, NV34TCL_DMA_FENCE, 2); so_data (so, 0); + so_data (so, screen->query->handle); - so_method(so, screen->rankine, NV34TCL_DEPTH_RANGE_NEAR, 2); - so_data (so, fui(0.0)); - so_data (so, fui(1.0)); - - so_method(so, screen->rankine, NV34TCL_MULTISAMPLE_CONTROL, 1); - so_data (so, 0xffff0000); + so_method(so, screen->eng3d, NV34TCL_DMA_IN_MEMORY7, 2); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); - /* enables use of vp rather than fixed-function somehow */ - so_method(so, screen->rankine, 0x1e94, 1); - so_data (so, 0x13); + if(!screen->is_nv4x) + nv30_screen_init(screen, so); + else + nv40_screen_init(screen, so); so_emit(chan, so); so_ref(NULL, &so); diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nvfx/nvfx_screen.h index b7856cdf00..a83dffe0af 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nvfx/nvfx_screen.h @@ -1,20 +1,22 @@ -#ifndef __NV30_SCREEN_H__ -#define __NV30_SCREEN_H__ +#ifndef __NVFX_SCREEN_H__ +#define __NVFX_SCREEN_H__ #include "nouveau/nouveau_screen.h" +#include "nv04_surface_2d.h" +#include "nvfx_context.h" -#include "nouveau/nv04_surface_2d.h" - -struct nv30_screen { +struct nvfx_screen { struct nouveau_screen base; struct nouveau_winsys *nvws; - struct nv30_context *cur_ctx; + struct nvfx_context *cur_ctx; + + unsigned is_nv4x; /* either 0 or ~0 */ /* HW graphics objects */ struct nv04_surface_2d *eng2d; - struct nouveau_grobj *rankine; + struct nouveau_grobj *eng3d; struct nouveau_notifier *sync; /* Query object resources */ @@ -26,13 +28,13 @@ struct nv30_screen { struct nouveau_resource *vp_data_heap; /* Current 3D state of channel */ - struct nouveau_stateobj *state[NV30_STATE_MAX]; + struct nouveau_stateobj *state[NVFX_STATE_MAX]; }; -static INLINE struct nv30_screen * -nv30_screen(struct pipe_screen *screen) +static INLINE struct nvfx_screen * +nvfx_screen(struct pipe_screen *screen) { - return (struct nv30_screen *)screen; + return (struct nvfx_screen *)screen; } #endif diff --git a/src/gallium/drivers/nvfx/nvfx_shader.h b/src/gallium/drivers/nvfx/nvfx_shader.h new file mode 100644 index 0000000000..0b2f044f7f --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_shader.h @@ -0,0 +1,429 @@ +#ifndef __NVFX_SHADER_H__ +#define __NVFX_SHADER_H__ + +/* this will resolve to either the NV30 or the NV40 version + * depending on the current hardware */ +/* unusual, but very fast and compact method */ +#define NVFX_VP(c) ((NV30_VP_##c) + (nvfx->is_nv4x & ((NV40_VP_##c) - (NV30_VP_##c)))) + +#define NVFX_VP_INST_SLOT_VEC 0 +#define NVFX_VP_INST_SLOT_SCA 1 + +#define NVFX_VP_INST_IN_POS 0 /* These seem to match the bindings specified in */ +#define NVFX_VP_INST_IN_WEIGHT 1 /* the ARB_v_p spec (2.14.3.1) */ +#define NVFX_VP_INST_IN_NORMAL 2 +#define NVFX_VP_INST_IN_COL0 3 /* Should probably confirm them all though */ +#define NVFX_VP_INST_IN_COL1 4 +#define NVFX_VP_INST_IN_FOGC 5 +#define NVFX_VP_INST_IN_TC0 8 +#define NVFX_VP_INST_IN_TC(n) (8+n) + +#define NVFX_VP_INST_SCA_OP_NOP 0x00 +#define NVFX_VP_INST_SCA_OP_MOV 0x01 +#define NVFX_VP_INST_SCA_OP_RCP 0x02 +#define NVFX_VP_INST_SCA_OP_RCC 0x03 +#define NVFX_VP_INST_SCA_OP_RSQ 0x04 +#define NVFX_VP_INST_SCA_OP_EXP 0x05 +#define NVFX_VP_INST_SCA_OP_LOG 0x06 +#define NVFX_VP_INST_SCA_OP_LIT 0x07 +#define NVFX_VP_INST_SCA_OP_BRA 0x09 +#define NVFX_VP_INST_SCA_OP_CAL 0x0B +#define NVFX_VP_INST_SCA_OP_RET 0x0C +#define NVFX_VP_INST_SCA_OP_LG2 0x0D +#define NVFX_VP_INST_SCA_OP_EX2 0x0E +#define NVFX_VP_INST_SCA_OP_SIN 0x0F +#define NVFX_VP_INST_SCA_OP_COS 0x10 + +#define NV40_VP_INST_SCA_OP_PUSHA 0x13 +#define NV40_VP_INST_SCA_OP_POPA 0x14 + +#define NVFX_VP_INST_VEC_OP_NOP 0x00 +#define NVFX_VP_INST_VEC_OP_MOV 0x01 +#define NVFX_VP_INST_VEC_OP_MUL 0x02 +#define NVFX_VP_INST_VEC_OP_ADD 0x03 +#define NVFX_VP_INST_VEC_OP_MAD 0x04 +#define NVFX_VP_INST_VEC_OP_DP3 0x05 +#define NVFX_VP_INST_VEC_OP_DPH 0x06 +#define NVFX_VP_INST_VEC_OP_DP4 0x07 +#define NVFX_VP_INST_VEC_OP_DST 0x08 +#define NVFX_VP_INST_VEC_OP_MIN 0x09 +#define NVFX_VP_INST_VEC_OP_MAX 0x0A +#define NVFX_VP_INST_VEC_OP_SLT 0x0B +#define NVFX_VP_INST_VEC_OP_SGE 0x0C +#define NVFX_VP_INST_VEC_OP_ARL 0x0D +#define NVFX_VP_INST_VEC_OP_FRC 0x0E +#define NVFX_VP_INST_VEC_OP_FLR 0x0F +#define NVFX_VP_INST_VEC_OP_SEQ 0x10 +#define NVFX_VP_INST_VEC_OP_SFL 0x11 +#define NVFX_VP_INST_VEC_OP_SGT 0x12 +#define NVFX_VP_INST_VEC_OP_SLE 0x13 +#define NVFX_VP_INST_VEC_OP_SNE 0x14 +#define NVFX_VP_INST_VEC_OP_STR 0x15 +#define NVFX_VP_INST_VEC_OP_SSG 0x16 +#define NVFX_VP_INST_VEC_OP_ARR 0x17 +#define NVFX_VP_INST_VEC_OP_ARA 0x18 + +#define NV40_VP_INST_VEC_OP_TXL 0x19 + +/* DWORD 3 */ +#define NVFX_VP_INST_LAST (1 << 0) + +/* + * Each fragment program opcode appears to be comprised of 4 32-bit values. + * + * 0 - Opcode, output reg/mask, ATTRIB source + * 1 - Source 0 + * 2 - Source 1 + * 3 - Source 2 + * + * There appears to be no special difference between result regs and temp regs. + * result.color == R0.xyzw + * result.depth == R1.z + * When the fragprog contains instructions to write depth, NV30_TCL_PRIMITIVE_3D_UNK1D78=0 + * otherwise it is set to 1. + * + * Constants are inserted directly after the instruction that uses them. + * + * It appears that it's not possible to use two input registers in one + * instruction as the input sourcing is done in the instruction dword + * and not the source selection dwords. As such instructions such as: + * + * ADD result.color, fragment.color, fragment.texcoord[0]; + * + * must be split into two MOV's and then an ADD (nvidia does this) but + * I'm not sure why it's not just one MOV and then source the second input + * in the ADD instruction.. + * + * Negation of the full source is done with NV30_FP_REG_NEGATE, arbitrary + * negation requires multiplication with a const. + * + * Arbitrary swizzling is supported with the exception of SWIZZLE_ZERO/SWIZZLE_ONE + * The temp/result regs appear to be initialised to (0.0, 0.0, 0.0, 0.0) as SWIZZLE_ZERO + * is implemented simply by not writing to the relevant components of the destination. + * + * Conditional execution + * TODO + * + * Non-native instructions: + * LIT + * LRP - MAD+MAD + * SUB - ADD, negate second source + * RSQ - LG2 + EX2 + * POW - LG2 + MUL + EX2 + * SCS - COS + SIN + * XPD + * + * NV40 Looping + * Loops appear to be fairly expensive on NV40 at least, the proprietary + * driver goes to a lot of effort to avoid using the native looping + * instructions. If the total number of *executed* instructions between + * REP/ENDREP or LOOP/ENDLOOP is <=500, the driver will unroll the loop. + * The maximum loop count is 255. + * + */ + +//== Opcode / Destination selection == +#define NVFX_FP_OP_PROGRAM_END (1 << 0) +#define NVFX_FP_OP_OUT_REG_SHIFT 1 +#define NV30_FP_OP_OUT_REG_MASK (31 << 1) /* uncertain */ +#define NV40_FP_OP_OUT_REG_MASK (63 << 1) +/* Needs to be set when writing outputs to get expected result.. */ +#define NVFX_FP_OP_OUT_REG_HALF (1 << 7) +#define NVFX_FP_OP_COND_WRITE_ENABLE (1 << 8) +#define NVFX_FP_OP_OUTMASK_SHIFT 9 +#define NVFX_FP_OP_OUTMASK_MASK (0xF << 9) +# define NVFX_FP_OP_OUT_X (1<<9) +# define NVFX_FP_OP_OUT_Y (1<<10) +# define NVFX_FP_OP_OUT_Z (1<<11) +# define NVFX_FP_OP_OUT_W (1<<12) +/* Uncertain about these, especially the input_src values.. it's possible that + * they can be dynamically changed. + */ +#define NVFX_FP_OP_INPUT_SRC_SHIFT 13 +#define NVFX_FP_OP_INPUT_SRC_MASK (15 << 13) +# define NVFX_FP_OP_INPUT_SRC_POSITION 0x0 +# define NVFX_FP_OP_INPUT_SRC_COL0 0x1 +# define NVFX_FP_OP_INPUT_SRC_COL1 0x2 +# define NVFX_FP_OP_INPUT_SRC_FOGC 0x3 +# define NVFX_FP_OP_INPUT_SRC_TC0 0x4 +# define NVFX_FP_OP_INPUT_SRC_TC(n) (0x4 + n) +# define NV40_FP_OP_INPUT_SRC_FACING 0xE +#define NVFX_FP_OP_TEX_UNIT_SHIFT 17 +#define NVFX_FP_OP_TEX_UNIT_MASK (0xF << 17) /* guess */ +#define NVFX_FP_OP_PRECISION_SHIFT 22 +#define NVFX_FP_OP_PRECISION_MASK (3 << 22) +# define NVFX_FP_PRECISION_FP32 0 +# define NVFX_FP_PRECISION_FP16 1 +# define NVFX_FP_PRECISION_FX12 2 +#define NVFX_FP_OP_OPCODE_SHIFT 24 +#define NVFX_FP_OP_OPCODE_MASK (0x3F << 24) +/* NV30/NV40 fragment program opcodes */ +#define NVFX_FP_OP_OPCODE_NOP 0x00 +#define NVFX_FP_OP_OPCODE_MOV 0x01 +#define NVFX_FP_OP_OPCODE_MUL 0x02 +#define NVFX_FP_OP_OPCODE_ADD 0x03 +#define NVFX_FP_OP_OPCODE_MAD 0x04 +#define NVFX_FP_OP_OPCODE_DP3 0x05 +#define NVFX_FP_OP_OPCODE_DP4 0x06 +#define NVFX_FP_OP_OPCODE_DST 0x07 +#define NVFX_FP_OP_OPCODE_MIN 0x08 +#define NVFX_FP_OP_OPCODE_MAX 0x09 +#define NVFX_FP_OP_OPCODE_SLT 0x0A +#define NVFX_FP_OP_OPCODE_SGE 0x0B +#define NVFX_FP_OP_OPCODE_SLE 0x0C +#define NVFX_FP_OP_OPCODE_SGT 0x0D +#define NVFX_FP_OP_OPCODE_SNE 0x0E +#define NVFX_FP_OP_OPCODE_SEQ 0x0F +#define NVFX_FP_OP_OPCODE_FRC 0x10 +#define NVFX_FP_OP_OPCODE_FLR 0x11 +#define NVFX_FP_OP_OPCODE_KIL 0x12 +#define NVFX_FP_OP_OPCODE_PK4B 0x13 +#define NVFX_FP_OP_OPCODE_UP4B 0x14 +#define NVFX_FP_OP_OPCODE_DDX 0x15 /* can only write XY */ +#define NVFX_FP_OP_OPCODE_DDY 0x16 /* can only write XY */ +#define NVFX_FP_OP_OPCODE_TEX 0x17 +#define NVFX_FP_OP_OPCODE_TXP 0x18 +#define NVFX_FP_OP_OPCODE_TXD 0x19 +#define NVFX_FP_OP_OPCODE_RCP 0x1A +#define NVFX_FP_OP_OPCODE_EX2 0x1C +#define NVFX_FP_OP_OPCODE_LG2 0x1D +#define NVFX_FP_OP_OPCODE_STR 0x20 +#define NVFX_FP_OP_OPCODE_SFL 0x21 +#define NVFX_FP_OP_OPCODE_COS 0x22 +#define NVFX_FP_OP_OPCODE_SIN 0x23 +#define NVFX_FP_OP_OPCODE_PK2H 0x24 +#define NVFX_FP_OP_OPCODE_UP2H 0x25 +#define NVFX_FP_OP_OPCODE_PK4UB 0x27 +#define NVFX_FP_OP_OPCODE_UP4UB 0x28 +#define NVFX_FP_OP_OPCODE_PK2US 0x29 +#define NVFX_FP_OP_OPCODE_UP2US 0x2A +#define NVFX_FP_OP_OPCODE_DP2A 0x2E +#define NVFX_FP_OP_OPCODE_TXB 0x31 +#define NVFX_FP_OP_OPCODE_DIV 0x3A + +/* NV30 only fragment program opcodes */ +#define NVFX_FP_OP_OPCODE_RSQ_NV30 0x1B +#define NVFX_FP_OP_OPCODE_LIT_NV30 0x1E +#define NVFX_FP_OP_OPCODE_LRP_NV30 0x1F +#define NVFX_FP_OP_OPCODE_POW_NV30 0x26 +#define NVFX_FP_OP_OPCODE_RFL_NV30 0x36 + +/* NV40 only fragment program opcodes */ +#define NVFX_FP_OP_OPCODE_TXL_NV40 0x31 +/* The use of these instructions appears to be indicated by bit 31 of DWORD 2.*/ +#define NV40_FP_OP_BRA_OPCODE_BRK 0x0 +#define NV40_FP_OP_BRA_OPCODE_CAL 0x1 +#define NV40_FP_OP_BRA_OPCODE_IF 0x2 +#define NV40_FP_OP_BRA_OPCODE_LOOP 0x3 +#define NV40_FP_OP_BRA_OPCODE_REP 0x4 +#define NV40_FP_OP_BRA_OPCODE_RET 0x5 + +#define NVFX_FP_OP_OUT_SAT (1 << 31) + +/* high order bits of SRC0 */ +#define NVFX_FP_OP_OUT_ABS (1 << 29) +#define NVFX_FP_OP_COND_SWZ_W_SHIFT 27 +#define NVFX_FP_OP_COND_SWZ_W_MASK (3 << 27) +#define NVFX_FP_OP_COND_SWZ_Z_SHIFT 25 +#define NVFX_FP_OP_COND_SWZ_Z_MASK (3 << 25) +#define NVFX_FP_OP_COND_SWZ_Y_SHIFT 23 +#define NVFX_FP_OP_COND_SWZ_Y_MASK (3 << 23) +#define NVFX_FP_OP_COND_SWZ_X_SHIFT 21 +#define NVFX_FP_OP_COND_SWZ_X_MASK (3 << 21) +#define NVFX_FP_OP_COND_SWZ_ALL_SHIFT 21 +#define NVFX_FP_OP_COND_SWZ_ALL_MASK (0xFF << 21) +#define NVFX_FP_OP_COND_SHIFT 18 +#define NVFX_FP_OP_COND_MASK (0x07 << 18) +# define NVFX_FP_OP_COND_FL 0 +# define NVFX_FP_OP_COND_LT 1 +# define NVFX_FP_OP_COND_EQ 2 +# define NVFX_FP_OP_COND_LE 3 +# define NVFX_FP_OP_COND_GT 4 +# define NVFX_FP_OP_COND_NE 5 +# define NVFX_FP_OP_COND_GE 6 +# define NVFX_FP_OP_COND_TR 7 + +/* high order bits of SRC1 */ +#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31) +#define NVFX_FP_OP_DST_SCALE_SHIFT 28 +#define NVFX_FP_OP_DST_SCALE_MASK (3 << 28) +#define NVFX_FP_OP_DST_SCALE_1X 0 +#define NVFX_FP_OP_DST_SCALE_2X 1 +#define NVFX_FP_OP_DST_SCALE_4X 2 +#define NVFX_FP_OP_DST_SCALE_8X 3 +#define NVFX_FP_OP_DST_SCALE_INV_2X 5 +#define NVFX_FP_OP_DST_SCALE_INV_4X 6 +#define NVFX_FP_OP_DST_SCALE_INV_8X 7 + +/* SRC1 LOOP */ +#define NV40_FP_OP_LOOP_INCR_SHIFT 19 +#define NV40_FP_OP_LOOP_INCR_MASK (0xFF << 19) +#define NV40_FP_OP_LOOP_INDEX_SHIFT 10 +#define NV40_FP_OP_LOOP_INDEX_MASK (0xFF << 10) +#define NV40_FP_OP_LOOP_COUNT_SHIFT 2 +#define NV40_FP_OP_LOOP_COUNT_MASK (0xFF << 2) + +/* SRC1 IF */ +#define NV40_FP_OP_ELSE_ID_SHIFT 2 +#define NV40_FP_OP_ELSE_ID_MASK (0xFF << 2) + +/* SRC1 CAL */ +#define NV40_FP_OP_IADDR_SHIFT 2 +#define NV40_FP_OP_IADDR_MASK (0xFF << 2) + +/* SRC1 REP + * I have no idea why there are 3 count values here.. but they + * have always been filled with the same value in my tests so + * far.. + */ +#define NV40_FP_OP_REP_COUNT1_SHIFT 2 +#define NV40_FP_OP_REP_COUNT1_MASK (0xFF << 2) +#define NV40_FP_OP_REP_COUNT2_SHIFT 10 +#define NV40_FP_OP_REP_COUNT2_MASK (0xFF << 10) +#define NV40_FP_OP_REP_COUNT3_SHIFT 19 +#define NV40_FP_OP_REP_COUNT3_MASK (0xFF << 19) + +/* SRC2 REP/IF */ +#define NV40_FP_OP_END_ID_SHIFT 2 +#define NV40_FP_OP_END_ID_MASK (0xFF << 2) + +/* high order bits of SRC2 */ +#define NVFX_FP_OP_INDEX_INPUT (1 << 30) +#define NV40_FP_OP_ADDR_INDEX_SHIFT 19 +#define NV40_FP_OP_ADDR_INDEX_MASK (0xF << 19) + +//== Register selection == +#define NVFX_FP_REG_TYPE_SHIFT 0 +#define NVFX_FP_REG_TYPE_MASK (3 << 0) +# define NVFX_FP_REG_TYPE_TEMP 0 +# define NVFX_FP_REG_TYPE_INPUT 1 +# define NVFX_FP_REG_TYPE_CONST 2 +#define NVFX_FP_REG_SRC_SHIFT 2 +#define NV30_FP_REG_SRC_MASK (31 << 2) +#define NV40_FP_REG_SRC_MASK (63 << 2) +#define NVFX_FP_REG_SRC_HALF (1 << 8) +#define NVFX_FP_REG_SWZ_ALL_SHIFT 9 +#define NVFX_FP_REG_SWZ_ALL_MASK (255 << 9) +#define NVFX_FP_REG_SWZ_X_SHIFT 9 +#define NVFX_FP_REG_SWZ_X_MASK (3 << 9) +#define NVFX_FP_REG_SWZ_Y_SHIFT 11 +#define NVFX_FP_REG_SWZ_Y_MASK (3 << 11) +#define NVFX_FP_REG_SWZ_Z_SHIFT 13 +#define NVFX_FP_REG_SWZ_Z_MASK (3 << 13) +#define NVFX_FP_REG_SWZ_W_SHIFT 15 +#define NVFX_FP_REG_SWZ_W_MASK (3 << 15) +# define NVFX_FP_SWIZZLE_X 0 +# define NVFX_FP_SWIZZLE_Y 1 +# define NVFX_FP_SWIZZLE_Z 2 +# define NVFX_FP_SWIZZLE_W 3 +#define NVFX_FP_REG_NEGATE (1 << 17) + +#define NVFXSR_NONE 0 +#define NVFXSR_OUTPUT 1 +#define NVFXSR_INPUT 2 +#define NVFXSR_TEMP 3 +#define NVFXSR_CONST 4 + +#define NVFX_COND_FL 0 +#define NVFX_COND_LT 1 +#define NVFX_COND_EQ 2 +#define NVFX_COND_LE 3 +#define NVFX_COND_GT 4 +#define NVFX_COND_NE 5 +#define NVFX_COND_GE 6 +#define NVFX_COND_TR 7 + +/* Yes, this are ordered differently... */ + +#define NVFX_VP_MASK_X 8 +#define NVFX_VP_MASK_Y 4 +#define NVFX_VP_MASK_Z 2 +#define NVFX_VP_MASK_W 1 +#define NVFX_VP_MASK_ALL 0xf + +#define NVFX_FP_MASK_X 1 +#define NVFX_FP_MASK_Y 2 +#define NVFX_FP_MASK_Z 4 +#define NVFX_FP_MASK_W 8 +#define NVFX_FP_MASK_ALL 0xf + +#define NVFX_SWZ_X 0 +#define NVFX_SWZ_Y 1 +#define NVFX_SWZ_Z 2 +#define NVFX_SWZ_W 3 + +#define swz(s,x,y,z,w) nvfx_sr_swz((s), NVFX_SWZ_##x, NVFX_SWZ_##y, NVFX_SWZ_##z, NVFX_SWZ_##w) +#define neg(s) nvfx_sr_neg((s)) +#define abs(s) nvfx_sr_abs((s)) +#define scale(s,v) nvfx_sr_scale((s), NVFX_FP_OP_DST_SCALE_##v) + +struct nvfx_sreg { + int type; + int index; + + int dst_scale; + + int negate; + int abs; + int swz[4]; + + int cc_update; + int cc_update_reg; + int cc_test; + int cc_test_reg; + int cc_swz[4]; +}; + +static INLINE struct nvfx_sreg +nvfx_sr(int type, int index) +{ + struct nvfx_sreg temp = { + .type = type, + .index = index, + .dst_scale = 0, + .abs = 0, + .negate = 0, + .swz = { 0, 1, 2, 3 }, + .cc_update = 0, + .cc_update_reg = 0, + .cc_test = NVFX_COND_TR, + .cc_test_reg = 0, + .cc_swz = { 0, 1, 2, 3 }, + }; + return temp; +} + +static INLINE struct nvfx_sreg +nvfx_sr_swz(struct nvfx_sreg src, int x, int y, int z, int w) +{ + struct nvfx_sreg dst = src; + + dst.swz[NVFX_SWZ_X] = src.swz[x]; + dst.swz[NVFX_SWZ_Y] = src.swz[y]; + dst.swz[NVFX_SWZ_Z] = src.swz[z]; + dst.swz[NVFX_SWZ_W] = src.swz[w]; + return dst; +} + +static INLINE struct nvfx_sreg +nvfx_sr_neg(struct nvfx_sreg src) +{ + src.negate = !src.negate; + return src; +} + +static INLINE struct nvfx_sreg +nvfx_sr_abs(struct nvfx_sreg src) +{ + src.abs = 1; + return src; +} + +static INLINE struct nvfx_sreg +nvfx_sr_scale(struct nvfx_sreg src, int scale) +{ + src.dst_scale = scale; + return src; +} + +#endif diff --git a/src/gallium/drivers/nvfx/nvfx_state.c b/src/gallium/drivers/nvfx/nvfx_state.c new file mode 100644 index 0000000000..e11ab46c42 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state.c @@ -0,0 +1,650 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "draw/draw_context.h" + +#include "tgsi/tgsi_parse.h" + +#include "nvfx_context.h" +#include "nvfx_state.h" +#include "nvfx_tex.h" + +static void * +nvfx_blend_state_create(struct pipe_context *pipe, + const struct pipe_blend_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct nvfx_blend_state *bso = CALLOC(1, sizeof(*bso)); + struct nouveau_stateobj *so = so_new(5, 8, 0); + + if (cso->rt[0].blend_enable) { + so_method(so, eng3d, NV34TCL_BLEND_FUNC_ENABLE, 3); + so_data (so, 1); + so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | + nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | + nvgl_blend_func(cso->rt[0].rgb_dst_factor)); + if(nvfx->screen->base.device->chipset < 0x40) { + so_method(so, eng3d, NV34TCL_BLEND_EQUATION, 1); + so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); + } else { + so_method(so, eng3d, NV40TCL_BLEND_EQUATION, 1); + so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 | + nvgl_blend_eqn(cso->rt[0].rgb_func)); + } + } else { + so_method(so, eng3d, NV34TCL_BLEND_FUNC_ENABLE, 1); + so_data (so, 0); + } + + so_method(so, eng3d, NV34TCL_COLOR_MASK, 1); + so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); + + /* TODO: add NV40 MRT color mask */ + + if (cso->logicop_enable) { + so_method(so, eng3d, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2); + so_data (so, 1); + so_data (so, nvgl_logicop_func(cso->logicop_func)); + } else { + so_method(so, eng3d, NV34TCL_COLOR_LOGIC_OP_ENABLE, 1); + so_data (so, 0); + } + + so_method(so, eng3d, NV34TCL_DITHER_ENABLE, 1); + so_data (so, cso->dither ? 1 : 0); + + so_ref(so, &bso->so); + so_ref(NULL, &so); + bso->pipe = *cso; + return (void *)bso; +} + +static void +nvfx_blend_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->blend = hwcso; + nvfx->dirty |= NVFX_NEW_BLEND; +} + +static void +nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_blend_state *bso = hwcso; + + so_ref(NULL, &bso->so); + FREE(bso); +} + +static void * +nvfx_sampler_state_create(struct pipe_context *pipe, + const struct pipe_sampler_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_sampler_state *ps; + + ps = MALLOC(sizeof(struct nvfx_sampler_state)); + + /* on nv30, we use this as an internal flag */ + ps->fmt = cso->normalized_coords ? 0 : NV40TCL_TEX_FORMAT_RECT; + ps->en = 0; + ps->filt = nvfx_tex_filter(cso); + ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) | + (nvfx_tex_wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) | + (nvfx_tex_wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT) | + nvfx_tex_wrap_compare_mode(cso); + ps->bcol = nvfx_tex_border_color(cso->border_color); + + if(nvfx->is_nv4x) + nv40_sampler_state_init(pipe, ps, cso); + else + nv30_sampler_state_init(pipe, ps, cso); + + return (void *)ps; +} + +static void +nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + nvfx->tex_sampler[unit] = sampler[unit]; + nvfx->dirty_samplers |= (1 << unit); + } + + for (unit = nr; unit < nvfx->nr_samplers; unit++) { + nvfx->tex_sampler[unit] = NULL; + nvfx->dirty_samplers |= (1 << unit); + } + + nvfx->nr_samplers = nr; + nvfx->dirty |= NVFX_NEW_SAMPLER; +} + +static void +nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void +nvfx_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], + views[unit]); + nvfx->dirty_samplers |= (1 << unit); + } + + for (unit = nr; unit < nvfx->nr_textures; unit++) { + pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], + NULL); + nvfx->dirty_samplers |= (1 << unit); + } + + nvfx->nr_textures = nr; + nvfx->dirty |= NVFX_NEW_SAMPLER; +} + + +static struct pipe_sampler_view * +nvfx_create_sampler_view(struct pipe_context *pipe, + struct pipe_resource *texture, + const struct pipe_sampler_view *templ) +{ + struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + + if (view) { + *view = *templ; + view->reference.count = 1; + view->texture = NULL; + pipe_resource_reference(&view->texture, texture); + view->context = pipe; + } + + return view; +} + + +static void +nvfx_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_resource_reference(&view->texture, NULL); + FREE(view); +} + +static void * +nvfx_rasterizer_state_create(struct pipe_context *pipe, + const struct pipe_rasterizer_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_rasterizer_state *rsso = CALLOC(1, sizeof(*rsso)); + struct nouveau_stateobj *so = so_new(9, 19, 0); + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + + /*XXX: ignored: + * light_twoside + * point_smooth -nohw + * multisample + */ + + so_method(so, eng3d, NV34TCL_SHADE_MODEL, 1); + so_data (so, cso->flatshade ? NV34TCL_SHADE_MODEL_FLAT : + NV34TCL_SHADE_MODEL_SMOOTH); + + so_method(so, eng3d, NV34TCL_LINE_WIDTH, 2); + so_data (so, (unsigned char)(cso->line_width * 8.0) & 0xff); + so_data (so, cso->line_smooth ? 1 : 0); + so_method(so, eng3d, NV34TCL_LINE_STIPPLE_ENABLE, 2); + so_data (so, cso->line_stipple_enable ? 1 : 0); + so_data (so, (cso->line_stipple_pattern << 16) | + cso->line_stipple_factor); + + so_method(so, eng3d, NV34TCL_POINT_SIZE, 1); + so_data (so, fui(cso->point_size)); + + so_method(so, eng3d, NV34TCL_POLYGON_MODE_FRONT, 6); + if (cso->front_winding == PIPE_WINDING_CCW) { + so_data(so, nvgl_polygon_mode(cso->fill_ccw)); + so_data(so, nvgl_polygon_mode(cso->fill_cw)); + switch (cso->cull_mode) { + case PIPE_WINDING_CCW: + so_data(so, NV34TCL_CULL_FACE_FRONT); + break; + case PIPE_WINDING_CW: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + case PIPE_WINDING_BOTH: + so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); + break; + default: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + } + so_data(so, NV34TCL_FRONT_FACE_CCW); + } else { + so_data(so, nvgl_polygon_mode(cso->fill_cw)); + so_data(so, nvgl_polygon_mode(cso->fill_ccw)); + switch (cso->cull_mode) { + case PIPE_WINDING_CCW: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + case PIPE_WINDING_CW: + so_data(so, NV34TCL_CULL_FACE_FRONT); + break; + case PIPE_WINDING_BOTH: + so_data(so, NV34TCL_CULL_FACE_FRONT_AND_BACK); + break; + default: + so_data(so, NV34TCL_CULL_FACE_BACK); + break; + } + so_data(so, NV34TCL_FRONT_FACE_CW); + } + so_data(so, cso->poly_smooth ? 1 : 0); + so_data(so, (cso->cull_mode != PIPE_WINDING_NONE) ? 1 : 0); + + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); + so_data (so, cso->poly_stipple_enable ? 1 : 0); + + so_method(so, eng3d, NV34TCL_POLYGON_OFFSET_POINT_ENABLE, 3); + if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_POINT) || + (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_POINT)) + so_data(so, 1); + else + so_data(so, 0); + if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_LINE) || + (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_LINE)) + so_data(so, 1); + else + so_data(so, 0); + if ((cso->offset_cw && cso->fill_cw == PIPE_POLYGON_MODE_FILL) || + (cso->offset_ccw && cso->fill_ccw == PIPE_POLYGON_MODE_FILL)) + so_data(so, 1); + else + so_data(so, 0); + if (cso->offset_cw || cso->offset_ccw) { + so_method(so, eng3d, NV34TCL_POLYGON_OFFSET_FACTOR, 2); + so_data (so, fui(cso->offset_scale)); + so_data (so, fui(cso->offset_units * 2)); + } + + so_method(so, eng3d, NV34TCL_POINT_SPRITE, 1); + if (cso->point_quad_rasterization) { + unsigned psctl = (1 << 0), i; + + for (i = 0; i < 8; i++) { + if ((cso->sprite_coord_enable >> i) & 1) + psctl |= (1 << (8 + i)); + } + + so_data(so, psctl); + } else { + so_data(so, 0); + } + + so_ref(so, &rsso->so); + so_ref(NULL, &so); + rsso->pipe = *cso; + return (void *)rsso; +} + +static void +nvfx_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->rasterizer = hwcso; + nvfx->dirty |= NVFX_NEW_RAST; + nvfx->draw_dirty |= NVFX_NEW_RAST; +} + +static void +nvfx_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_rasterizer_state *rsso = hwcso; + + so_ref(NULL, &rsso->so); + FREE(rsso); +} + +static void * +nvfx_depth_stencil_alpha_state_create(struct pipe_context *pipe, + const struct pipe_depth_stencil_alpha_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); + struct nouveau_stateobj *so = so_new(6, 20, 0); + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + + so_method(so, eng3d, NV34TCL_DEPTH_FUNC, 3); + so_data (so, nvgl_comparison_op(cso->depth.func)); + so_data (so, cso->depth.writemask ? 1 : 0); + so_data (so, cso->depth.enabled ? 1 : 0); + + so_method(so, eng3d, NV34TCL_ALPHA_FUNC_ENABLE, 3); + so_data (so, cso->alpha.enabled ? 1 : 0); + so_data (so, nvgl_comparison_op(cso->alpha.func)); + so_data (so, float_to_ubyte(cso->alpha.ref_value)); + + if (cso->stencil[0].enabled) { + so_method(so, eng3d, NV34TCL_STENCIL_FRONT_ENABLE, 3); + so_data (so, cso->stencil[0].enabled ? 1 : 0); + so_data (so, cso->stencil[0].writemask); + so_data (so, nvgl_comparison_op(cso->stencil[0].func)); + so_method(so, eng3d, NV34TCL_STENCIL_FRONT_FUNC_MASK, 4); + so_data (so, cso->stencil[0].valuemask); + so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); + } else { + so_method(so, eng3d, NV34TCL_STENCIL_FRONT_ENABLE, 1); + so_data (so, 0); + } + + if (cso->stencil[1].enabled) { + so_method(so, eng3d, NV34TCL_STENCIL_BACK_ENABLE, 3); + so_data (so, cso->stencil[1].enabled ? 1 : 0); + so_data (so, cso->stencil[1].writemask); + so_data (so, nvgl_comparison_op(cso->stencil[1].func)); + so_method(so, eng3d, NV34TCL_STENCIL_BACK_FUNC_MASK, 4); + so_data (so, cso->stencil[1].valuemask); + so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); + so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); + } else { + so_method(so, eng3d, NV34TCL_STENCIL_BACK_ENABLE, 1); + so_data (so, 0); + } + + so_ref(so, &zsaso->so); + so_ref(NULL, &so); + zsaso->pipe = *cso; + return (void *)zsaso; +} + +static void +nvfx_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->zsa = hwcso; + nvfx->dirty |= NVFX_NEW_ZSA; +} + +static void +nvfx_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_zsa_state *zsaso = hwcso; + + so_ref(NULL, &zsaso->so); + FREE(zsaso); +} + +static void * +nvfx_vp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_vertex_program *vp; + + vp = CALLOC(1, sizeof(struct nvfx_vertex_program)); + vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + vp->draw = draw_create_vertex_shader(nvfx->draw, &vp->pipe); + + return (void *)vp; +} + +static void +nvfx_vp_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->vertprog = hwcso; + nvfx->dirty |= NVFX_NEW_VERTPROG; + nvfx->draw_dirty |= NVFX_NEW_VERTPROG; +} + +static void +nvfx_vp_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_vertex_program *vp = hwcso; + + draw_delete_vertex_shader(nvfx->draw, vp->draw); + nvfx_vertprog_destroy(nvfx, vp); + FREE((void*)vp->pipe.tokens); + FREE(vp); +} + +static void * +nvfx_fp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + struct nvfx_fragment_program *fp; + + fp = CALLOC(1, sizeof(struct nvfx_fragment_program)); + fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); + + tgsi_scan_shader(fp->pipe.tokens, &fp->info); + + return (void *)fp; +} + +static void +nvfx_fp_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->fragprog = hwcso; + nvfx->dirty |= NVFX_NEW_FRAGPROG; +} + +static void +nvfx_fp_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_fragment_program *fp = hwcso; + + nvfx_fragprog_destroy(nvfx, fp); + FREE((void*)fp->pipe.tokens); + FREE(fp); +} + +static void +nvfx_set_blend_color(struct pipe_context *pipe, + const struct pipe_blend_color *bcol) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->blend_colour = *bcol; + nvfx->dirty |= NVFX_NEW_BCOL; +} + +static void +nvfx_set_stencil_ref(struct pipe_context *pipe, + const struct pipe_stencil_ref *sr) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->stencil_ref = *sr; + nvfx->dirty |= NVFX_NEW_SR; +} + +static void +nvfx_set_clip_state(struct pipe_context *pipe, + const struct pipe_clip_state *clip) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->clip = *clip; + nvfx->dirty |= NVFX_NEW_UCP; + nvfx->draw_dirty |= NVFX_NEW_UCP; +} + +static void +nvfx_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, + struct pipe_resource *buf ) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->constbuf[shader] = buf; + nvfx->constbuf_nr[shader] = buf->width0 / (4 * sizeof(float)); + + if (shader == PIPE_SHADER_VERTEX) { + nvfx->dirty |= NVFX_NEW_VERTPROG; + } else + if (shader == PIPE_SHADER_FRAGMENT) { + nvfx->dirty |= NVFX_NEW_FRAGPROG; + } +} + +static void +nvfx_set_framebuffer_state(struct pipe_context *pipe, + const struct pipe_framebuffer_state *fb) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->framebuffer = *fb; + nvfx->dirty |= NVFX_NEW_FB; +} + +static void +nvfx_set_polygon_stipple(struct pipe_context *pipe, + const struct pipe_poly_stipple *stipple) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + memcpy(nvfx->stipple, stipple->stipple, 4 * 32); + nvfx->dirty |= NVFX_NEW_STIPPLE; +} + +static void +nvfx_set_scissor_state(struct pipe_context *pipe, + const struct pipe_scissor_state *s) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->scissor = *s; + nvfx->dirty |= NVFX_NEW_SCISSOR; +} + +static void +nvfx_set_viewport_state(struct pipe_context *pipe, + const struct pipe_viewport_state *vpt) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->viewport = *vpt; + nvfx->dirty |= NVFX_NEW_VIEWPORT; + nvfx->draw_dirty |= NVFX_NEW_VIEWPORT; +} + +static void +nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count, + const struct pipe_vertex_buffer *vb) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + memcpy(nvfx->vtxbuf, vb, sizeof(*vb) * count); + nvfx->vtxbuf_nr = count; + + nvfx->dirty |= NVFX_NEW_ARRAYS; + nvfx->draw_dirty |= NVFX_NEW_ARRAYS; +} + +static void * +nvfx_vtxelts_state_create(struct pipe_context *pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct nvfx_vtxelt_state *cso = CALLOC_STRUCT(nvfx_vtxelt_state); + + assert(num_elements < 16); /* not doing fallbacks yet */ + cso->num_elements = num_elements; + memcpy(cso->pipe, elements, num_elements * sizeof(*elements)); + +/* nvfx_vtxelt_construct(cso);*/ + + return (void *)cso; +} + +static void +nvfx_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void +nvfx_vtxelts_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + nvfx->vtxelt = hwcso; + nvfx->dirty |= NVFX_NEW_ARRAYS; + /*nvfx->draw_dirty |= NVFX_NEW_ARRAYS;*/ +} + +void +nvfx_init_state_functions(struct nvfx_context *nvfx) +{ + nvfx->pipe.create_blend_state = nvfx_blend_state_create; + nvfx->pipe.bind_blend_state = nvfx_blend_state_bind; + nvfx->pipe.delete_blend_state = nvfx_blend_state_delete; + + nvfx->pipe.create_sampler_state = nvfx_sampler_state_create; + nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind; + nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete; + nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views; + nvfx->pipe.create_sampler_view = nvfx_create_sampler_view; + nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy; + + nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create; + nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind; + nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete; + + nvfx->pipe.create_depth_stencil_alpha_state = + nvfx_depth_stencil_alpha_state_create; + nvfx->pipe.bind_depth_stencil_alpha_state = + nvfx_depth_stencil_alpha_state_bind; + nvfx->pipe.delete_depth_stencil_alpha_state = + nvfx_depth_stencil_alpha_state_delete; + + nvfx->pipe.create_vs_state = nvfx_vp_state_create; + nvfx->pipe.bind_vs_state = nvfx_vp_state_bind; + nvfx->pipe.delete_vs_state = nvfx_vp_state_delete; + + nvfx->pipe.create_fs_state = nvfx_fp_state_create; + nvfx->pipe.bind_fs_state = nvfx_fp_state_bind; + nvfx->pipe.delete_fs_state = nvfx_fp_state_delete; + + nvfx->pipe.set_blend_color = nvfx_set_blend_color; + nvfx->pipe.set_stencil_ref = nvfx_set_stencil_ref; + nvfx->pipe.set_clip_state = nvfx_set_clip_state; + nvfx->pipe.set_constant_buffer = nvfx_set_constant_buffer; + nvfx->pipe.set_framebuffer_state = nvfx_set_framebuffer_state; + nvfx->pipe.set_polygon_stipple = nvfx_set_polygon_stipple; + nvfx->pipe.set_scissor_state = nvfx_set_scissor_state; + nvfx->pipe.set_viewport_state = nvfx_set_viewport_state; + + nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create; + nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete; + nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind; + + nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers; +} diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nvfx/nvfx_state.h index e2e69420ea..1f612ea95f 100644 --- a/src/gallium/drivers/nv40/nv40_state.h +++ b/src/gallium/drivers/nvfx/nvfx_state.h @@ -1,29 +1,21 @@ -#ifndef __NV40_STATE_H__ -#define __NV40_STATE_H__ +#ifndef __NVFX_STATE_H__ +#define __NVFX_STATE_H__ #include "pipe/p_state.h" #include "tgsi/tgsi_scan.h" -struct nv40_sampler_state { - uint32_t fmt; - uint32_t wrap; - uint32_t en; - uint32_t filt; - uint32_t bcol; -}; - -struct nv40_vertex_program_exec { +struct nvfx_vertex_program_exec { uint32_t data[4]; boolean has_branch_offset; int const_index; }; -struct nv40_vertex_program_data { +struct nvfx_vertex_program_data { int index; /* immediates == -1 */ float value[4]; }; -struct nv40_vertex_program { +struct nvfx_vertex_program { struct pipe_shader_state pipe; struct draw_vertex_shader *draw; @@ -32,9 +24,9 @@ struct nv40_vertex_program { struct pipe_clip_state ucp; - struct nv40_vertex_program_exec *insns; + struct nvfx_vertex_program_exec *insns; unsigned nr_insns; - struct nv40_vertex_program_data *consts; + struct nvfx_vertex_program_data *consts; unsigned nr_consts; struct nouveau_resource *exec; @@ -49,12 +41,12 @@ struct nv40_vertex_program { struct nouveau_stateobj *so; }; -struct nv40_fragment_program_data { +struct nvfx_fragment_program_data { unsigned offset; unsigned index; }; -struct nv40_fragment_program { +struct nvfx_fragment_program { struct pipe_shader_state pipe; struct tgsi_shader_info info; @@ -64,28 +56,16 @@ struct nv40_fragment_program { uint32_t *insn; int insn_len; - struct nv40_fragment_program_data *consts; + struct nvfx_fragment_program_data *consts; unsigned nr_consts; - - struct pipe_buffer *buffer; + + /* XXX: just use a nouveau_bo for this? + */ + struct pipe_resource *buffer; uint32_t fp_control; struct nouveau_stateobj *so; }; -#define NV40_MAX_TEXTURE_LEVELS 16 - -struct nv40_miptree { - struct pipe_texture base; - struct nouveau_bo *bo; - - struct pipe_buffer *buffer; - uint total_size; - - struct { - uint pitch; - uint *image_offset; - } level[NV40_MAX_TEXTURE_LEVELS]; -}; #endif diff --git a/src/gallium/drivers/nvfx/nvfx_state_blend.c b/src/gallium/drivers/nvfx/nvfx_state_blend.c new file mode 100644 index 0000000000..03b6ef8117 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_blend.c @@ -0,0 +1,41 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_blend_validate(struct nvfx_context *nvfx) +{ + so_ref(nvfx->blend->so, &nvfx->state.hw[NVFX_STATE_BLEND]); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_blend = { + .validate = nvfx_state_blend_validate, + .dirty = { + .pipe = NVFX_NEW_BLEND, + .hw = NVFX_STATE_BLEND + } +}; + +static boolean +nvfx_state_blend_colour_validate(struct nvfx_context *nvfx) +{ + struct nouveau_stateobj *so = so_new(1, 1, 0); + struct pipe_blend_color *bcol = &nvfx->blend_colour; + + so_method(so, nvfx->screen->eng3d, NV34TCL_BLEND_COLOR, 1); + so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | + (float_to_ubyte(bcol->color[0]) << 16) | + (float_to_ubyte(bcol->color[1]) << 8) | + (float_to_ubyte(bcol->color[2]) << 0))); + + so_ref(so, &nvfx->state.hw[NVFX_STATE_BCOL]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_blend_colour = { + .validate = nvfx_state_blend_colour_validate, + .dirty = { + .pipe = NVFX_NEW_BCOL, + .hw = NVFX_STATE_BCOL + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c new file mode 100644 index 0000000000..72537388ea --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c @@ -0,0 +1,179 @@ +#include "nvfx_context.h" +#include "nvfx_state.h" +#include "draw/draw_context.h" + +#define RENDER_STATES(name, vbo) \ +static struct nvfx_state_entry *name##render_states[] = { \ + &nvfx_state_framebuffer, \ + &nvfx_state_rasterizer, \ + &nvfx_state_scissor, \ + &nvfx_state_stipple, \ + &nvfx_state_fragprog, \ + &nvfx_state_fragtex, \ + &nvfx_state_vertprog, \ + &nvfx_state_blend, \ + &nvfx_state_blend_colour, \ + &nvfx_state_zsa, \ + &nvfx_state_sr, \ + &nvfx_state_viewport, \ + &nvfx_state_##vbo, \ + NULL \ +} + +RENDER_STATES(, vbo); +RENDER_STATES(swtnl_, vtxfmt); + +static void +nvfx_state_do_validate(struct nvfx_context *nvfx, + struct nvfx_state_entry **states) +{ + while (*states) { + struct nvfx_state_entry *e = *states; + + if (nvfx->dirty & e->dirty.pipe) { + if (e->validate(nvfx)) + nvfx->state.dirty |= (1ULL << e->dirty.hw); + } + + states++; + } + nvfx->dirty = 0; +} + +void +nvfx_state_emit(struct nvfx_context *nvfx) +{ + struct nvfx_state *state = &nvfx->state; + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + unsigned i; + uint64_t states; + + /* XXX: race conditions + */ + if (nvfx != screen->cur_ctx) { + for (i = 0; i < NVFX_STATE_MAX; i++) { + if (state->hw[i] && screen->state[i] != state->hw[i]) + state->dirty |= (1ULL << i); + } + + screen->cur_ctx = nvfx; + } + + for (i = 0, states = state->dirty; states; i++) { + if (!(states & (1ULL << i))) + continue; + so_ref (state->hw[i], &nvfx->screen->state[i]); + if (state->hw[i]) + so_emit(chan, nvfx->screen->state[i]); + states &= ~(1ULL << i); + } + + /* TODO: could nv30 need this or something similar too? */ + if(nvfx->is_nv4x) { + if (state->dirty & ((1ULL << NVFX_STATE_FRAGPROG) | + (1ULL << NVFX_STATE_FRAGTEX0))) { + BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1); + OUT_RING (chan, 2); + BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1); + OUT_RING (chan, 1); + } + } + state->dirty = 0; +} + +void +nvfx_state_flush_notify(struct nouveau_channel *chan) +{ + struct nvfx_context *nvfx = chan->user_private; + struct nvfx_state *state = &nvfx->state; + unsigned i, samplers; + + so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FB]); + for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { + if (!(samplers & (1 << i))) + continue; + so_emit_reloc_markers(chan, + state->hw[NVFX_STATE_FRAGTEX0+i]); + samplers &= ~(1ULL << i); + } + so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FRAGPROG]); + if (state->hw[NVFX_STATE_VTXBUF] && nvfx->render_mode == HW) + so_emit_reloc_markers(chan, state->hw[NVFX_STATE_VTXBUF]); +} + +boolean +nvfx_state_validate(struct nvfx_context *nvfx) +{ + boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE; + + if (nvfx->render_mode != HW) { + /* Don't even bother trying to go back to hw if none + * of the states that caused swtnl previously have changed. + */ + if ((nvfx->fallback_swtnl & nvfx->dirty) + != nvfx->fallback_swtnl) + return FALSE; + + /* Attempt to go to hwtnl again */ + nvfx->pipe.flush(&nvfx->pipe, 0, NULL); + nvfx->dirty |= (NVFX_NEW_VIEWPORT | + NVFX_NEW_VERTPROG | + NVFX_NEW_ARRAYS); + nvfx->render_mode = HW; + } + + nvfx_state_do_validate(nvfx, render_states); + + if (nvfx->fallback_swtnl || nvfx->fallback_swrast) + return FALSE; + + if (was_sw) + NOUVEAU_ERR("swtnl->hw\n"); + + return TRUE; +} + +boolean +nvfx_state_validate_swtnl(struct nvfx_context *nvfx) +{ + struct draw_context *draw = nvfx->draw; + + /* Setup for swtnl */ + if (nvfx->render_mode == HW) { + NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl); + nvfx->pipe.flush(&nvfx->pipe, 0, NULL); + nvfx->dirty |= (NVFX_NEW_VIEWPORT | + NVFX_NEW_VERTPROG | + NVFX_NEW_ARRAYS); + nvfx->render_mode = SWTNL; + } + + if (nvfx->draw_dirty & NVFX_NEW_VERTPROG) + draw_bind_vertex_shader(draw, nvfx->vertprog->draw); + + if (nvfx->draw_dirty & NVFX_NEW_RAST) + draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe); + + if (nvfx->draw_dirty & NVFX_NEW_UCP) + draw_set_clip_state(draw, &nvfx->clip); + + if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT) + draw_set_viewport_state(draw, &nvfx->viewport); + + if (nvfx->draw_dirty & NVFX_NEW_ARRAYS) { + draw_set_vertex_buffers(draw, nvfx->vtxbuf_nr, nvfx->vtxbuf); + draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe); + } + + nvfx_state_do_validate(nvfx, swtnl_render_states); + + if (nvfx->fallback_swrast) { + NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast); + return FALSE; + } + + nvfx->draw_dirty = 0; + return TRUE; +} diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c new file mode 100644 index 0000000000..665c0c36bb --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c @@ -0,0 +1,228 @@ +#include "nvfx_context.h" +#include "nvfx_resource.h" +#include "nouveau/nouveau_util.h" + + + +static boolean +nvfx_state_framebuffer_validate(struct nvfx_context *nvfx) +{ + struct pipe_framebuffer_state *fb = &nvfx->framebuffer; + struct nouveau_channel *chan = nvfx->screen->base.channel; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct nv04_surface *rt[4], *zeta = NULL; + uint32_t rt_enable = 0, rt_format = 0; + int i, colour_format = 0, zeta_format = 0; + int depth_only = 0; + struct nouveau_stateobj *so = so_new(18, 24, 10); + unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; + unsigned w = fb->width; + unsigned h = fb->height; + int colour_bits = 32, zeta_bits = 32; + + if(!nvfx->is_nv4x) + assert(fb->nr_cbufs <= 2); + else + assert(fb->nr_cbufs <= 4); + + for (i = 0; i < fb->nr_cbufs; i++) { + if (colour_format) { + assert(colour_format == fb->cbufs[i]->format); + } else { + colour_format = fb->cbufs[i]->format; + rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i); + rt[i] = (struct nv04_surface *)fb->cbufs[i]; + } + } + + if (rt_enable & (NV34TCL_RT_ENABLE_COLOR1 | + NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) + rt_enable |= NV34TCL_RT_ENABLE_MRT; + + if (fb->zsbuf) { + zeta_format = fb->zsbuf->format; + zeta = (struct nv04_surface *)fb->zsbuf; + } + + if (rt_enable & (NV34TCL_RT_ENABLE_COLOR0 | NV34TCL_RT_ENABLE_COLOR1 | + NV40TCL_RT_ENABLE_COLOR2 | NV40TCL_RT_ENABLE_COLOR3)) { + /* Render to at least a colour buffer */ + if (!(rt[0]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { + assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); + for (i = 1; i < fb->nr_cbufs; i++) + assert(!(rt[i]->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)); + + rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | + (log2i(rt[0]->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | + (log2i(rt[0]->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); + } + else + rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; + } else if (fb->zsbuf) { + depth_only = 1; + + /* Render to depth buffer only */ + if (!(zeta->base.texture->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { + assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); + + rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | + (log2i(zeta->base.width) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT) | + (log2i(zeta->base.height) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT); + } + else + rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR; + } else { + return FALSE; + } + + switch (colour_format) { + case PIPE_FORMAT_B8G8R8X8_UNORM: + rt_format |= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + case 0: + rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5; + colour_bits = 16; + break; + default: + assert(0); + } + + switch (zeta_format) { + case PIPE_FORMAT_Z16_UNORM: + rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16; + zeta_bits = 16; + break; + case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + case 0: + rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8; + break; + default: + assert(0); + } + + if ((!nvfx->is_nv4x) && colour_bits > zeta_bits) { + /* TODO: does this limitation really exist? + TODO: can it be worked around somehow? */ + return FALSE; + } + + if ((rt_enable & NV34TCL_RT_ENABLE_COLOR0) + || ((!nvfx->is_nv4x) && depth_only)) { + struct nv04_surface *rt0 = (depth_only ? zeta : rt[0]); + uint32_t pitch = rt0->pitch; + + if(!nvfx->is_nv4x) + { + if (zeta) { + pitch |= (zeta->pitch << 16); + } else { + pitch |= (pitch << 16); + } + } + + so_method(so, eng3d, NV34TCL_DMA_COLOR0, 1); + so_reloc (so, nvfx_surface_buffer(&rt0->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV34TCL_COLOR0_PITCH, 2); + so_data (so, pitch); + so_reloc (so, nvfx_surface_buffer(&rt[0]->base), + rt0->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + } + + if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { + so_method(so, eng3d, NV34TCL_DMA_COLOR1, 1); + so_reloc (so, nvfx_surface_buffer(&rt[1]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV34TCL_COLOR1_OFFSET, 2); + so_reloc (so, nvfx_surface_buffer(&rt[1]->base), + rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_data (so, rt[1]->pitch); + } + + if(nvfx->is_nv4x) + { + if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { + so_method(so, eng3d, NV40TCL_DMA_COLOR2, 1); + so_reloc (so, nvfx_surface_buffer(&rt[2]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV40TCL_COLOR2_OFFSET, 1); + so_reloc (so, nvfx_surface_buffer(&rt[2]->base), + rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, eng3d, NV40TCL_COLOR2_PITCH, 1); + so_data (so, rt[2]->pitch); + } + + if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { + so_method(so, eng3d, NV40TCL_DMA_COLOR3, 1); + so_reloc (so, nvfx_surface_buffer(&rt[3]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV40TCL_COLOR3_OFFSET, 1); + so_reloc (so, nvfx_surface_buffer(&rt[3]->base), + rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, eng3d, NV40TCL_COLOR3_PITCH, 1); + so_data (so, rt[3]->pitch); + } + } + + if (zeta_format) { + so_method(so, eng3d, NV34TCL_DMA_ZETA, 1); + so_reloc (so, nvfx_surface_buffer(&zeta->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, eng3d, NV34TCL_ZETA_OFFSET, 1); + /* TODO: reverse engineer LMA */ + so_reloc (so, nvfx_surface_buffer(&zeta->base), + zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); + if(nvfx->is_nv4x) { + so_method(so, eng3d, NV40TCL_ZETA_PITCH, 1); + so_data (so, zeta->pitch); + } + } + + so_method(so, eng3d, NV34TCL_RT_ENABLE, 1); + so_data (so, rt_enable); + so_method(so, eng3d, NV34TCL_RT_HORIZ, 3); + so_data (so, (w << 16) | 0); + so_data (so, (h << 16) | 0); + so_data (so, rt_format); + so_method(so, eng3d, NV34TCL_VIEWPORT_HORIZ, 2); + so_data (so, (w << 16) | 0); + so_data (so, (h << 16) | 0); + so_method(so, eng3d, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); + so_data (so, ((w - 1) << 16) | 0); + so_data (so, ((h - 1) << 16) | 0); + so_method(so, eng3d, 0x1d88, 1); + so_data (so, (1 << 12) | h); + + if(!nvfx->is_nv4x) { + /* Wonder why this is needed, context should all be set to zero on init */ + /* TODO: we can most likely remove this, after putting it in context init */ + so_method(so, eng3d, NV34TCL_VIEWPORT_TX_ORIGIN, 1); + so_data (so, 0); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_FB]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_framebuffer = { + .validate = nvfx_state_framebuffer_validate, + .dirty = { + .pipe = NVFX_NEW_FB, + .hw = NVFX_STATE_FB + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_rasterizer.c b/src/gallium/drivers/nvfx/nvfx_state_rasterizer.c new file mode 100644 index 0000000000..0d35ecbf20 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_rasterizer.c @@ -0,0 +1,17 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_rasterizer_validate(struct nvfx_context *nvfx) +{ + so_ref(nvfx->rasterizer->so, + &nvfx->state.hw[NVFX_STATE_RAST]); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_rasterizer = { + .validate = nvfx_state_rasterizer_validate, + .dirty = { + .pipe = NVFX_NEW_RAST, + .hw = NVFX_STATE_RAST + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_scissor.c b/src/gallium/drivers/nvfx/nvfx_state_scissor.c new file mode 100644 index 0000000000..940d8cb5c0 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_scissor.c @@ -0,0 +1,36 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_scissor_validate(struct nvfx_context *nvfx) +{ + struct pipe_rasterizer_state *rast = &nvfx->rasterizer->pipe; + struct pipe_scissor_state *s = &nvfx->scissor; + struct nouveau_stateobj *so; + + if (nvfx->state.hw[NVFX_STATE_SCISSOR] && + (rast->scissor == 0 && nvfx->state.scissor_enabled == 0)) + return FALSE; + nvfx->state.scissor_enabled = rast->scissor; + + so = so_new(1, 2, 0); + so_method(so, nvfx->screen->eng3d, NV34TCL_SCISSOR_HORIZ, 2); + if (nvfx->state.scissor_enabled) { + so_data (so, ((s->maxx - s->minx) << 16) | s->minx); + so_data (so, ((s->maxy - s->miny) << 16) | s->miny); + } else { + so_data (so, 4096 << 16); + so_data (so, 4096 << 16); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_SCISSOR]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_scissor = { + .validate = nvfx_state_scissor_validate, + .dirty = { + .pipe = NVFX_NEW_SCISSOR | NVFX_NEW_RAST, + .hw = NVFX_STATE_SCISSOR + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_stipple.c b/src/gallium/drivers/nvfx/nvfx_state_stipple.c new file mode 100644 index 0000000000..57cd3c936a --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_stipple.c @@ -0,0 +1,40 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_stipple_validate(struct nvfx_context *nvfx) +{ + struct pipe_rasterizer_state *rast = &nvfx->rasterizer->pipe; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct nouveau_stateobj *so; + + if (nvfx->state.hw[NVFX_STATE_STIPPLE] && + (rast->poly_stipple_enable == 0 && nvfx->state.stipple_enabled == 0)) + return FALSE; + + if (rast->poly_stipple_enable) { + unsigned i; + + so = so_new(2, 33, 0); + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); + so_data (so, 1); + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_PATTERN(0), 32); + for (i = 0; i < 32; i++) + so_data(so, nvfx->stipple[i]); + } else { + so = so_new(1, 1, 0); + so_method(so, eng3d, NV34TCL_POLYGON_STIPPLE_ENABLE, 1); + so_data (so, 0); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_STIPPLE]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_stipple = { + .validate = nvfx_state_stipple_validate, + .dirty = { + .pipe = NVFX_NEW_STIPPLE | NVFX_NEW_RAST, + .hw = NVFX_STATE_STIPPLE, + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_viewport.c b/src/gallium/drivers/nvfx/nvfx_state_viewport.c new file mode 100644 index 0000000000..82e0e9220b --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_viewport.c @@ -0,0 +1,51 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_viewport_validate(struct nvfx_context *nvfx) +{ + struct pipe_viewport_state *vpt = &nvfx->viewport; + struct nouveau_stateobj *so; + + if (nvfx->state.hw[NVFX_STATE_VIEWPORT] && + !(nvfx->dirty & NVFX_NEW_VIEWPORT)) + return FALSE; + + so = so_new(2, 9, 0); + so_method(so, nvfx->screen->eng3d, + NV34TCL_VIEWPORT_TRANSLATE_X, 8); + if(nvfx->render_mode == HW) { + so_data (so, fui(vpt->translate[0])); + so_data (so, fui(vpt->translate[1])); + so_data (so, fui(vpt->translate[2])); + so_data (so, fui(vpt->translate[3])); + so_data (so, fui(vpt->scale[0])); + so_data (so, fui(vpt->scale[1])); + so_data (so, fui(vpt->scale[2])); + so_data (so, fui(vpt->scale[3])); + so_method(so, nvfx->screen->eng3d, 0x1d78, 1); + so_data (so, 1); + } else { + so_data (so, fui(0.0f)); + so_data (so, fui(0.0f)); + so_data (so, fui(0.0f)); + so_data (so, fui(0.0f)); + so_data (so, fui(1.0f)); + so_data (so, fui(1.0f)); + so_data (so, fui(1.0f)); + so_data (so, fui(1.0f)); + so_method(so, nvfx->screen->eng3d, 0x1d78, 1); + so_data (so, nvfx->is_nv4x ? 0x110 : 1); + } + + so_ref(so, &nvfx->state.hw[NVFX_STATE_VIEWPORT]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_viewport = { + .validate = nvfx_state_viewport_validate, + .dirty = { + .pipe = NVFX_NEW_VIEWPORT, + .hw = NVFX_STATE_VIEWPORT + } +}; diff --git a/src/gallium/drivers/nvfx/nvfx_state_zsa.c b/src/gallium/drivers/nvfx/nvfx_state_zsa.c new file mode 100644 index 0000000000..c84fd041c1 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_state_zsa.c @@ -0,0 +1,41 @@ +#include "nvfx_context.h" + +static boolean +nvfx_state_zsa_validate(struct nvfx_context *nvfx) +{ + so_ref(nvfx->zsa->so, + &nvfx->state.hw[NVFX_STATE_ZSA]); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_zsa = { + .validate = nvfx_state_zsa_validate, + .dirty = { + .pipe = NVFX_NEW_ZSA, + .hw = NVFX_STATE_ZSA + } +}; + +static boolean +nvfx_state_sr_validate(struct nvfx_context *nvfx) +{ + struct nouveau_stateobj *so = so_new(2, 2, 0); + struct pipe_stencil_ref *sr = &nvfx->stencil_ref; + + so_method(so, nvfx->screen->eng3d, NV34TCL_STENCIL_FRONT_FUNC_REF, 1); + so_data (so, sr->ref_value[0]); + so_method(so, nvfx->screen->eng3d, NV34TCL_STENCIL_BACK_FUNC_REF, 1); + so_data (so, sr->ref_value[1]); + + so_ref(so, &nvfx->state.hw[NVFX_STATE_SR]); + so_ref(NULL, &so); + return TRUE; +} + +struct nvfx_state_entry nvfx_state_sr = { + .validate = nvfx_state_sr_validate, + .dirty = { + .pipe = NVFX_NEW_SR, + .hw = NVFX_STATE_SR + } +}; diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index bc18e577ee..8a05ad0a57 100644 --- a/src/gallium/drivers/nv30/nv30_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -1,9 +1,9 @@ /************************************************************************** - * + * * 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 @@ -11,11 +11,11 @@ * 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. @@ -23,40 +23,40 @@ * 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 "nv30_context.h" +#include "nvfx_context.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_tile.h" static void -nv30_surface_copy(struct pipe_context *pipe, +nvfx_surface_copy(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, struct pipe_surface *src, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv04_surface_2d *eng2d = nv30->screen->eng2d; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); } static void -nv30_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, +nvfx_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, unsigned width, unsigned height, unsigned value) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv04_surface_2d *eng2d = nv30->screen->eng2d; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; eng2d->fill(eng2d, dest, destx, desty, width, height, value); } void -nv30_init_surface_functions(struct nv30_context *nv30) +nvfx_init_surface_functions(struct nvfx_context *nvfx) { - nv30->pipe.surface_copy = nv30_surface_copy; - nv30->pipe.surface_fill = nv30_surface_fill; + nvfx->pipe.surface_copy = nvfx_surface_copy; + nvfx->pipe.surface_fill = nvfx_surface_fill; } diff --git a/src/gallium/drivers/nvfx/nvfx_tex.h b/src/gallium/drivers/nvfx/nvfx_tex.h new file mode 100644 index 0000000000..69187a79e7 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_tex.h @@ -0,0 +1,133 @@ +#ifndef NVFX_TEX_H_ +#define NVFX_TEX_H_ + +static inline unsigned +nvfx_tex_wrap_mode(unsigned wrap) { + unsigned ret; + + switch (wrap) { + case PIPE_TEX_WRAP_REPEAT: + ret = NV34TCL_TX_WRAP_S_REPEAT; + break; + case PIPE_TEX_WRAP_MIRROR_REPEAT: + ret = NV34TCL_TX_WRAP_S_MIRRORED_REPEAT; + break; + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: + ret = NV34TCL_TX_WRAP_S_CLAMP_TO_EDGE; + break; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: + ret = NV34TCL_TX_WRAP_S_CLAMP_TO_BORDER; + break; + case PIPE_TEX_WRAP_CLAMP: + ret = NV34TCL_TX_WRAP_S_CLAMP; + break; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_EDGE; + break; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP_TO_BORDER; + break; + case PIPE_TEX_WRAP_MIRROR_CLAMP: + ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP; + break; + default: + NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); + ret = NV34TCL_TX_WRAP_S_REPEAT; + break; + } + + return ret >> NV34TCL_TX_WRAP_S_SHIFT; +} + +static inline unsigned +nvfx_tex_wrap_compare_mode(const struct pipe_sampler_state* cso) +{ + if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { + switch (cso->compare_func) { + case PIPE_FUNC_NEVER: + return NV34TCL_TX_WRAP_RCOMP_NEVER; + case PIPE_FUNC_GREATER: + return NV34TCL_TX_WRAP_RCOMP_GREATER; + case PIPE_FUNC_EQUAL: + return NV34TCL_TX_WRAP_RCOMP_EQUAL; + case PIPE_FUNC_GEQUAL: + return NV34TCL_TX_WRAP_RCOMP_GEQUAL; + case PIPE_FUNC_LESS: + return NV34TCL_TX_WRAP_RCOMP_LESS; + case PIPE_FUNC_NOTEQUAL: + return NV34TCL_TX_WRAP_RCOMP_NOTEQUAL; + case PIPE_FUNC_LEQUAL: + return NV34TCL_TX_WRAP_RCOMP_LEQUAL; + case PIPE_FUNC_ALWAYS: + return NV34TCL_TX_WRAP_RCOMP_ALWAYS; + default: + break; + } + } + return 0; +} + +static inline unsigned nvfx_tex_filter(const struct pipe_sampler_state* cso) +{ + unsigned filter = 0; + switch (cso->mag_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + filter |= NV34TCL_TX_FILTER_MAGNIFY_LINEAR; + break; + case PIPE_TEX_FILTER_NEAREST: + default: + filter |= NV34TCL_TX_FILTER_MAGNIFY_NEAREST; + break; + } + + switch (cso->min_img_filter) { + case PIPE_TEX_FILTER_LINEAR: + switch (cso->min_mip_filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; + break; + case PIPE_TEX_MIPFILTER_LINEAR: + filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; + break; + case PIPE_TEX_MIPFILTER_NONE: + default: + filter |= NV34TCL_TX_FILTER_MINIFY_LINEAR; + break; + } + break; + case PIPE_TEX_FILTER_NEAREST: + default: + switch (cso->min_mip_filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; + break; + case PIPE_TEX_MIPFILTER_LINEAR: + filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; + break; + case PIPE_TEX_MIPFILTER_NONE: + default: + filter |= NV34TCL_TX_FILTER_MINIFY_NEAREST; + break; + } + break; + } + return filter; +} + +static inline unsigned nvfx_tex_border_color(const float* border_color) +{ + return ((float_to_ubyte(border_color[3]) << 24) | + (float_to_ubyte(border_color[0]) << 16) | + (float_to_ubyte(border_color[1]) << 8) | + (float_to_ubyte(border_color[2]) << 0)); +} + +struct nvfx_sampler_state { + uint32_t fmt; + uint32_t wrap; + uint32_t en; + uint32_t filt; + uint32_t bcol; +}; + +#endif /* NVFX_TEX_H_ */ diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c new file mode 100644 index 0000000000..4bcfe73696 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_transfer.c @@ -0,0 +1,189 @@ +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "nouveau/nouveau_winsys.h" +#include "nvfx_context.h" +#include "nvfx_screen.h" +#include "nvfx_state.h" +#include "nvfx_resource.h" +#include "nvfx_transfer.h" + +struct nvfx_transfer { + struct pipe_transfer base; + struct pipe_surface *surface; + boolean direct; +}; + +static void +nvfx_compatible_transfer_tex(struct pipe_resource *pt, unsigned width, unsigned height, + struct pipe_resource *template) +{ + memset(template, 0, sizeof(struct pipe_resource)); + template->target = pt->target; + template->format = pt->format; + template->width0 = width; + template->height0 = height; + template->depth0 = 1; + template->last_level = 0; + template->nr_samples = pt->nr_samples; + + template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | + NOUVEAU_TEXTURE_USAGE_LINEAR; +} + +struct pipe_transfer * +nvfx_miptree_transfer_new(struct pipe_context *pcontext, + struct pipe_resource *pt, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) +{ + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; + struct nvfx_transfer *tx; + struct pipe_resource tx_tex_template, *tx_tex; + static boolean firsttime = TRUE; + static boolean no_transfer = FALSE; + + if (firsttime) { + no_transfer = debug_get_bool_option("NOUVEAU_NO_TRANSFER", + TRUE/*XXX:FALSE*/); + firsttime = FALSE; + } + + tx = CALLOC_STRUCT(nvfx_transfer); + if (!tx) + return NULL; + + /* Don't handle 3D transfers yet. + */ + assert(box->depth == 1); + + pipe_resource_reference(&tx->base.resource, pt); + tx->base.sr = sr; + tx->base.usage = usage; + tx->base.box = *box; + tx->base.stride = mt->level[sr.level].pitch; + + /* Direct access to texture */ + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || no_transfer) && + pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) + { + tx->direct = true; + tx->surface = pscreen->get_tex_surface(pscreen, pt, + sr.face, sr.level, + box->z, + pipe_transfer_buffer_flags(&tx->base)); + return &tx->base; + } + + tx->direct = false; + + nvfx_compatible_transfer_tex(pt, box->width, box->height, &tx_tex_template); + + tx_tex = pscreen->resource_create(pscreen, &tx_tex_template); + if (!tx_tex) + { + FREE(tx); + return NULL; + } + + tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch; + + tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, + 0, 0, 0, + pipe_transfer_buffer_flags(&tx->base)); + + pipe_resource_reference(&tx_tex, NULL); + + if (!tx->surface) + { + pipe_surface_reference(&tx->surface, NULL); + FREE(tx); + return NULL; + } + + if (usage & PIPE_TRANSFER_READ) { + struct nvfx_screen *nvscreen = nvfx_screen(pscreen); + struct pipe_surface *src; + + src = pscreen->get_tex_surface(pscreen, pt, + sr.face, sr.level, box->z, + PIPE_BUFFER_USAGE_GPU_READ); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + /* TODO: Check if SIFM can un-swizzle */ + nvscreen->eng2d->copy(nvscreen->eng2d, + tx->surface, 0, 0, + src, + box->x, box->y, + box->width, box->height); + + pipe_surface_reference(&src, NULL); + } + + return &tx->base; +} + +void +nvfx_miptree_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx) +{ + struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; + + if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_screen *nvscreen = nvfx_screen(pscreen); + struct pipe_surface *dst; + + dst = pscreen->get_tex_surface(pscreen, + ptx->resource, + ptx->sr.face, + ptx->sr.level, + ptx->box.z, + PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER); + + /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ + nvscreen->eng2d->copy(nvscreen->eng2d, + dst, ptx->box.x, ptx->box.y, + tx->surface, 0, 0, + ptx->box.width, ptx->box.height); + + pipe_surface_reference(&dst, NULL); + } + + pipe_surface_reference(&tx->surface, NULL); + pipe_resource_reference(&ptx->resource, NULL); + FREE(ptx); +} + +void * +nvfx_miptree_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx) +{ + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; + struct nv04_surface *ns = (struct nv04_surface *)tx->surface; + struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture; + uint8_t *map = nouveau_screen_bo_map(pscreen, mt->base.bo, + pipe_transfer_buffer_flags(ptx)); + + if(!tx->direct) + return map + ns->base.offset; + else + return (map + ns->base.offset + + ptx->box.y * ns->pitch + + ptx->box.x * util_format_get_blocksize(ptx->resource->format)); +} + +void +nvfx_miptree_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx) +{ + struct pipe_screen *pscreen = pcontext->screen; + struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; + struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture; + + nouveau_screen_bo_unmap(pscreen, mt->base.bo); +} diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.h b/src/gallium/drivers/nvfx/nvfx_transfer.h new file mode 100644 index 0000000000..3e3317b2c7 --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_transfer.h @@ -0,0 +1,26 @@ + +#ifndef NVFX_TRANSFER_H +#define NVFX_TRANSFER_H + +#include "util/u_transfer.h" +#include "pipe/p_state.h" + + +struct pipe_transfer * +nvfx_miptree_transfer_new(struct pipe_context *pcontext, + struct pipe_resource *pt, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box); +void +nvfx_miptree_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void * +nvfx_miptree_transfer_map(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void +nvfx_miptree_transfer_unmap(struct pipe_context *pcontext, + struct pipe_transfer *ptx); + + +#endif diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c index f3856bb5a5..887aa1fa96 100644 --- a/src/gallium/drivers/nv30/nv30_vbo.c +++ b/src/gallium/drivers/nvfx/nvfx_vbo.c @@ -3,17 +3,25 @@ #include "util/u_inlines.h" #include "util/u_format.h" -#include "nv30_context.h" -#include "nv30_state.h" +#include "nvfx_context.h" +#include "nvfx_state.h" +#include "nvfx_resource.h" #include "nouveau/nouveau_channel.h" #include "nouveau/nouveau_pushbuf.h" #include "nouveau/nouveau_util.h" -#define FORCE_SWTNL 0 +static boolean +nvfx_force_swtnl(struct nvfx_context *nvfx) +{ + static int force_swtnl = -1; + if(force_swtnl < 0) + force_swtnl = debug_get_bool_option("NOUVEAU_SWTNL", 0); + return force_swtnl; +} static INLINE int -nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) +nvfx_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) { switch (pipe) { case PIPE_FORMAT_R32_FLOAT: @@ -69,15 +77,15 @@ nv30_vbo_format_to_hw(enum pipe_format pipe, unsigned *fmt, unsigned *ncomp) } static boolean -nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib, +nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_resource *ib, unsigned ib_size) { - struct pipe_screen *pscreen = &nv30->screen->base.base; + struct pipe_screen *pscreen = &nvfx->screen->base.base; unsigned type; if (!ib) { - nv30->idxbuf = NULL; - nv30->idxbuf_format = 0xdeadbeef; + nvfx->idxbuf = NULL; + nvfx->idxbuf_format = 0xdeadbeef; return FALSE; } @@ -95,96 +103,97 @@ nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib, return FALSE; } - if (ib != nv30->idxbuf || - type != nv30->idxbuf_format) { - nv30->dirty |= NV30_NEW_ARRAYS; - nv30->idxbuf = ib; - nv30->idxbuf_format = type; + if (ib != nvfx->idxbuf || + type != nvfx->idxbuf_format) { + nvfx->dirty |= NVFX_NEW_ARRAYS; + nvfx->idxbuf = ib; + nvfx->idxbuf_format = type; } return TRUE; } static boolean -nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, +nvfx_vbo_static_attrib(struct nvfx_context *nvfx, struct nouveau_stateobj *so, int attrib, struct pipe_vertex_element *ve, struct pipe_vertex_buffer *vb) { - struct pipe_screen *pscreen = nv30->pipe.screen; - struct nouveau_grobj *rankine = nv30->screen->rankine; + struct pipe_context *pipe = &nvfx->pipe; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct pipe_transfer *transfer; unsigned type, ncomp; - void *map; + uint8_t *map; - if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) + if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) return FALSE; - map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pipe, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ, &transfer); map += vb->buffer_offset + ve->src_offset; switch (type) { case NV34TCL_VTXFMT_TYPE_FLOAT: { - float *v = map; + float *v = (float *)map; switch (ncomp) { case 4: - so_method(so, rankine, NV34TCL_VTX_ATTR_4F_X(attrib), 4); + so_method(so, eng3d, NV34TCL_VTX_ATTR_4F_X(attrib), 4); so_data (so, fui(v[0])); so_data (so, fui(v[1])); so_data (so, fui(v[2])); so_data (so, fui(v[3])); break; case 3: - so_method(so, rankine, NV34TCL_VTX_ATTR_3F_X(attrib), 3); + so_method(so, eng3d, NV34TCL_VTX_ATTR_3F_X(attrib), 3); so_data (so, fui(v[0])); so_data (so, fui(v[1])); so_data (so, fui(v[2])); break; case 2: - so_method(so, rankine, NV34TCL_VTX_ATTR_2F_X(attrib), 2); + so_method(so, eng3d, NV34TCL_VTX_ATTR_2F_X(attrib), 2); so_data (so, fui(v[0])); so_data (so, fui(v[1])); break; case 1: - so_method(so, rankine, NV34TCL_VTX_ATTR_1F(attrib), 1); + so_method(so, eng3d, NV34TCL_VTX_ATTR_1F(attrib), 1); so_data (so, fui(v[0])); break; default: - pipe_buffer_unmap(pscreen, vb->buffer); + pipe_buffer_unmap(pipe, vb->buffer, transfer); return FALSE; } } break; default: - pipe_buffer_unmap(pscreen, vb->buffer); + pipe_buffer_unmap(pipe, vb->buffer, transfer); return FALSE; } - pipe_buffer_unmap(pscreen, vb->buffer); + pipe_buffer_unmap(pipe, vb->buffer, transfer); return TRUE; } void -nv30_draw_arrays(struct pipe_context *pipe, +nvfx_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; unsigned restart = 0; - nv30_vbo_set_idxbuf(nv30, NULL, 0); - if (FORCE_SWTNL || !nv30_state_validate(nv30)) { - /*return nv30_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count);*/ - return; + nvfx_vbo_set_idxbuf(nvfx, NULL, 0); + if (nvfx_force_swtnl(nvfx) || !nvfx_state_validate(nvfx)) { + nvfx_draw_elements_swtnl(pipe, NULL, 0, + mode, start, count); + return; } while (count) { unsigned vc, nr; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, mode, start, count, &restart); @@ -193,12 +202,12 @@ nv30_draw_arrays(struct pipe_context *pipe, continue; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { - BEGIN_RING(chan, rankine, NV34TCL_VB_VERTEX_BATCH, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, 1); OUT_RING (chan, ((nr - 1) << 24) | start); start += nr; } @@ -209,14 +218,14 @@ nv30_draw_arrays(struct pipe_context *pipe, nr -= push; - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_VERTEX_BATCH, push); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_VERTEX_BATCH, push); while (push--) { OUT_RING(chan, ((0x100 - 1) << 24) | start); start += 0x100; } } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); count -= vc; @@ -227,18 +236,18 @@ nv30_draw_arrays(struct pipe_context *pipe, } static INLINE void -nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, +nvfx_draw_elements_u08(struct nvfx_context *nvfx, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nv30_screen *screen = nv30->screen; + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; while (count) { uint8_t *elts = (uint8_t *)ib + start; unsigned vc, push, restart = 0; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, mode, start, count, &restart); @@ -248,11 +257,11 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, } count -= vc; - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); if (vc & 1) { - BEGIN_RING(chan, rankine, NV34TCL_VB_ELEMENT_U32, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, elts[0]); elts++; vc--; } @@ -262,7 +271,7 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, push = MIN2(vc, 2047 * 2); - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); for (i = 0; i < push; i+=2) OUT_RING(chan, (elts[i+1] << 16) | elts[i]); @@ -270,7 +279,7 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, elts += push; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); start = restart; @@ -278,18 +287,18 @@ nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, } static INLINE void -nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, +nvfx_draw_elements_u16(struct nvfx_context *nvfx, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nv30_screen *screen = nv30->screen; + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; while (count) { uint16_t *elts = (uint16_t *)ib + start; unsigned vc, push, restart = 0; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2, mode, start, count, &restart); @@ -299,11 +308,11 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, } count -= vc; - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); if (vc & 1) { - BEGIN_RING(chan, rankine, NV34TCL_VB_ELEMENT_U32, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_ELEMENT_U32, 1); OUT_RING (chan, elts[0]); elts++; vc--; } @@ -313,7 +322,7 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, push = MIN2(vc, 2047 * 2); - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U16, push >> 1); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U16, push >> 1); for (i = 0; i < push; i+=2) OUT_RING(chan, (elts[i+1] << 16) | elts[i]); @@ -321,7 +330,7 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, elts += push; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); start = restart; @@ -329,18 +338,18 @@ nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, } static INLINE void -nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, +nvfx_draw_elements_u32(struct nvfx_context *nvfx, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nv30_screen *screen = nv30->screen; + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; while (count) { uint32_t *elts = (uint32_t *)ib + start; unsigned vc, push, restart = 0; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1, mode, start, count, &restart); @@ -350,20 +359,20 @@ nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, } count -= vc; - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); while (vc) { push = MIN2(vc, 2047); - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_ELEMENT_U32, push); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_ELEMENT_U32, push); OUT_RINGp (chan, elts, push); vc -= push; elts += push; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); start = restart; @@ -371,15 +380,15 @@ nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, } static void -nv30_draw_elements_inline(struct pipe_context *pipe, - struct pipe_buffer *ib, unsigned ib_size, +nvfx_draw_elements_inline(struct pipe_context *pipe, + struct pipe_resource *ib, unsigned ib_size, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); - struct pipe_screen *pscreen = pipe->screen; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct pipe_transfer *transfer; void *map; - map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pipe, ib, PIPE_BUFFER_USAGE_CPU_READ, &transfer); if (!ib) { NOUVEAU_ERR("failed mapping ib\n"); return; @@ -387,36 +396,36 @@ nv30_draw_elements_inline(struct pipe_context *pipe, switch (ib_size) { case 1: - nv30_draw_elements_u08(nv30, map, mode, start, count); + nvfx_draw_elements_u08(nvfx, map, mode, start, count); break; case 2: - nv30_draw_elements_u16(nv30, map, mode, start, count); + nvfx_draw_elements_u16(nvfx, map, mode, start, count); break; case 4: - nv30_draw_elements_u32(nv30, map, mode, start, count); + nvfx_draw_elements_u32(nvfx, map, mode, start, count); break; default: NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size); break; } - pipe_buffer_unmap(pscreen, ib); + pipe_buffer_unmap(pipe, ib, transfer); } static void -nv30_draw_elements_vbo(struct pipe_context *pipe, +nvfx_draw_elements_vbo(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); - struct nv30_screen *screen = nv30->screen; + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_screen *screen = nvfx->screen; struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *rankine = screen->rankine; + struct nouveau_grobj *eng3d = screen->eng3d; unsigned restart = 0; while (count) { unsigned nr, vc; - nv30_state_emit(nv30); + nvfx_state_emit(nvfx); vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256, mode, start, count, &restart); @@ -425,12 +434,12 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, continue; } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); nr = (vc & 0xff); if (nr) { - BEGIN_RING(chan, rankine, NV34TCL_VB_INDEX_BATCH, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VB_INDEX_BATCH, 1); OUT_RING (chan, ((nr - 1) << 24) | start); start += nr; } @@ -441,14 +450,14 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, nr -= push; - BEGIN_RING_NI(chan, rankine, NV34TCL_VB_INDEX_BATCH, push); + BEGIN_RING_NI(chan, eng3d, NV34TCL_VB_INDEX_BATCH, push); while (push--) { OUT_RING(chan, ((0x100 - 1) << 24) | start); start += 0x100; } } - BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); + BEGIN_RING(chan, eng3d, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, 0); count -= vc; @@ -457,24 +466,24 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, } void -nv30_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, unsigned indexSize, +nvfx_draw_elements(struct pipe_context *pipe, + struct pipe_resource *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { - struct nv30_context *nv30 = nv30_context(pipe); + struct nvfx_context *nvfx = nvfx_context(pipe); boolean idxbuf; - idxbuf = nv30_vbo_set_idxbuf(nv30, indexBuffer, indexSize); - if (FORCE_SWTNL || !nv30_state_validate(nv30)) { - /*return nv30_draw_elements_swtnl(pipe, NULL, 0, - mode, start, count);*/ + idxbuf = nvfx_vbo_set_idxbuf(nvfx, indexBuffer, indexSize); + if (nvfx_force_swtnl(nvfx) || !nvfx_state_validate(nvfx)) { + nvfx_draw_elements_swtnl(pipe, indexBuffer, indexSize, + mode, start, count); return; } if (idxbuf) { - nv30_draw_elements_vbo(pipe, mode, start, count); + nvfx_draw_elements_vbo(pipe, mode, start, count); } else { - nv30_draw_elements_inline(pipe, indexBuffer, indexSize, + nvfx_draw_elements_inline(pipe, indexBuffer, indexSize, mode, start, count); } @@ -482,81 +491,82 @@ nv30_draw_elements(struct pipe_context *pipe, } static boolean -nv30_vbo_validate(struct nv30_context *nv30) +nvfx_vbo_validate(struct nvfx_context *nvfx) { struct nouveau_stateobj *vtxbuf, *vtxfmt, *sattr = NULL; - struct nouveau_grobj *rankine = nv30->screen->rankine; - struct pipe_buffer *ib = nv30->idxbuf; - unsigned ib_format = nv30->idxbuf_format; + struct nouveau_grobj *eng3d = nvfx->screen->eng3d; + struct pipe_resource *ib = nvfx->idxbuf; + unsigned ib_format = nvfx->idxbuf_format; unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; int hw; vtxbuf = so_new(3, 17, 18); - so_method(vtxbuf, rankine, NV34TCL_VTXBUF_ADDRESS(0), nv30->vtxelt->num_elements); + so_method(vtxbuf, eng3d, NV34TCL_VTXBUF_ADDRESS(0), nvfx->vtxelt->num_elements); vtxfmt = so_new(1, 16, 0); - so_method(vtxfmt, rankine, NV34TCL_VTXFMT(0), nv30->vtxelt->num_elements); + so_method(vtxfmt, eng3d, NV34TCL_VTXFMT(0), nvfx->vtxelt->num_elements); - for (hw = 0; hw < nv30->vtxelt->num_elements; hw++) { + for (hw = 0; hw < nvfx->vtxelt->num_elements; hw++) { struct pipe_vertex_element *ve; struct pipe_vertex_buffer *vb; unsigned type, ncomp; - ve = &nv30->vtxelt->pipe[hw]; - vb = &nv30->vtxbuf[ve->vertex_buffer_index]; + ve = &nvfx->vtxelt->pipe[hw]; + vb = &nvfx->vtxbuf[ve->vertex_buffer_index]; if (!vb->stride) { if (!sattr) sattr = so_new(16, 16 * 4, 0); - if (nv30_vbo_static_attrib(nv30, sattr, hw, ve, vb)) { + if (nvfx_vbo_static_attrib(nvfx, sattr, hw, ve, vb)) { so_data(vtxbuf, 0); so_data(vtxfmt, NV34TCL_VTXFMT_TYPE_FLOAT); continue; } } - if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { - /*nv30->fallback_swtnl |= NV30_NEW_ARRAYS;*/ + if (nvfx_vbo_format_to_hw(ve->src_format, &type, &ncomp)) { + nvfx->fallback_swtnl |= NVFX_NEW_ARRAYS; so_ref(NULL, &vtxbuf); so_ref(NULL, &vtxfmt); return FALSE; } - so_reloc(vtxbuf, nouveau_bo(vb->buffer), vb->buffer_offset + - ve->src_offset, vb_flags | NOUVEAU_BO_LOW | - NOUVEAU_BO_OR, 0, NV34TCL_VTXBUF_ADDRESS_DMA1); + so_reloc(vtxbuf, nvfx_resource(vb->buffer)->bo, + vb->buffer_offset + ve->src_offset, + vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, + 0, NV34TCL_VTXBUF_ADDRESS_DMA1); so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) | (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); } if (ib) { - struct nouveau_bo *bo = nouveau_bo(ib); + struct nouveau_bo *bo = nvfx_resource(ib)->bo; - so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2); + so_method(vtxbuf, eng3d, NV34TCL_IDXBUF_ADDRESS, 2); so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, 0, NV34TCL_IDXBUF_FORMAT_DMA1); } - so_method(vtxbuf, rankine, 0x1710, 1); + so_method(vtxbuf, eng3d, 0x1710, 1); so_data (vtxbuf, 0); - so_ref(vtxbuf, &nv30->state.hw[NV30_STATE_VTXBUF]); + so_ref(vtxbuf, &nvfx->state.hw[NVFX_STATE_VTXBUF]); so_ref(NULL, &vtxbuf); - nv30->state.dirty |= (1ULL << NV30_STATE_VTXBUF); - so_ref(vtxfmt, &nv30->state.hw[NV30_STATE_VTXFMT]); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXBUF); + so_ref(vtxfmt, &nvfx->state.hw[NVFX_STATE_VTXFMT]); so_ref(NULL, &vtxfmt); - nv30->state.dirty |= (1ULL << NV30_STATE_VTXFMT); - so_ref(sattr, &nv30->state.hw[NV30_STATE_VTXATTR]); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXFMT); + so_ref(sattr, &nvfx->state.hw[NVFX_STATE_VTXATTR]); so_ref(NULL, &sattr); - nv30->state.dirty |= (1ULL << NV30_STATE_VTXATTR); + nvfx->state.dirty |= (1ULL << NVFX_STATE_VTXATTR); return FALSE; } -struct nv30_state_entry nv30_state_vbo = { - .validate = nv30_vbo_validate, +struct nvfx_state_entry nvfx_state_vbo = { + .validate = nvfx_vbo_validate, .dirty = { - .pipe = NV30_NEW_ARRAYS, + .pipe = NVFX_NEW_ARRAYS, .hw = 0, } }; diff --git a/src/gallium/drivers/nvfx/nvfx_vertprog.c b/src/gallium/drivers/nvfx/nvfx_vertprog.c new file mode 100644 index 0000000000..c7bc08eb4e --- /dev/null +++ b/src/gallium/drivers/nvfx/nvfx_vertprog.c @@ -0,0 +1,1051 @@ +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "util/u_inlines.h" + +#include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_util.h" + +#include "nvfx_context.h" +#include "nvfx_state.h" + +/* TODO (at least...): + * 1. Indexed consts + ARL + * 3. NV_vp11, NV_vp2, NV_vp3 features + * - extra arith opcodes + * - branching + * - texture sampling + * - indexed attribs + * - indexed results + * 4. bugs + */ + +#include "nv30_vertprog.h" +#include "nv40_vertprog.h" + +#define NVFX_VP_INST_DEST_CLIP(n) ((~0 - 6) + (n)) + +struct nvfx_vpc { + struct nvfx_vertex_program *vp; + + struct nvfx_vertex_program_exec *vpi; + + unsigned r_temps; + unsigned r_temps_discard; + struct nvfx_sreg r_result[PIPE_MAX_SHADER_OUTPUTS]; + struct nvfx_sreg *r_address; + struct nvfx_sreg *r_temp; + + struct nvfx_sreg *imm; + unsigned nr_imm; + + unsigned hpos_idx; +}; + +static struct nvfx_sreg +temp(struct nvfx_vpc *vpc) +{ + int idx = ffs(~vpc->r_temps) - 1; + + if (idx < 0) { + NOUVEAU_ERR("out of temps!!\n"); + assert(0); + return nvfx_sr(NVFXSR_TEMP, 0); + } + + vpc->r_temps |= (1 << idx); + vpc->r_temps_discard |= (1 << idx); + return nvfx_sr(NVFXSR_TEMP, idx); +} + +static INLINE void +release_temps(struct nvfx_vpc *vpc) +{ + vpc->r_temps &= ~vpc->r_temps_discard; + vpc->r_temps_discard = 0; +} + +static struct nvfx_sreg +constant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w) +{ + struct nvfx_vertex_program *vp = vpc->vp; + struct nvfx_vertex_program_data *vpd; + int idx; + + if (pipe >= 0) { + for (idx = 0; idx < vp->nr_consts; idx++) { + if (vp->consts[idx].index == pipe) + return nvfx_sr(NVFXSR_CONST, idx); + } + } + + idx = vp->nr_consts++; + vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); + vpd = &vp->consts[idx]; + + vpd->index = pipe; + vpd->value[0] = x; + vpd->value[1] = y; + vpd->value[2] = z; + vpd->value[3] = w; + return nvfx_sr(NVFXSR_CONST, idx); +} + +#define arith(cc,s,o,d,m,s0,s1,s2) \ + nvfx_vp_arith(nvfx, (cc), NVFX_VP_INST_SLOT_##s, NVFX_VP_INST_##s##_OP_##o, (d), (m), (s0), (s1), (s2)) + +static void +emit_src(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int pos, struct nvfx_sreg src) +{ + struct nvfx_vertex_program *vp = vpc->vp; + uint32_t sr = 0; + + switch (src.type) { + case NVFXSR_TEMP: + sr |= (NVFX_VP(SRC_REG_TYPE_TEMP) << NVFX_VP(SRC_REG_TYPE_SHIFT)); + sr |= (src.index << NVFX_VP(SRC_TEMP_SRC_SHIFT)); + break; + case NVFXSR_INPUT: + sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) << + NVFX_VP(SRC_REG_TYPE_SHIFT)); + vp->ir |= (1 << src.index); + hw[1] |= (src.index << NVFX_VP(INST_INPUT_SRC_SHIFT)); + break; + case NVFXSR_CONST: + sr |= (NVFX_VP(SRC_REG_TYPE_CONST) << + NVFX_VP(SRC_REG_TYPE_SHIFT)); + assert(vpc->vpi->const_index == -1 || + vpc->vpi->const_index == src.index); + vpc->vpi->const_index = src.index; + break; + case NVFXSR_NONE: + sr |= (NVFX_VP(SRC_REG_TYPE_INPUT) << + NVFX_VP(SRC_REG_TYPE_SHIFT)); + break; + default: + assert(0); + } + + if (src.negate) + sr |= NVFX_VP(SRC_NEGATE); + + if (src.abs) + hw[0] |= (1 << (21 + pos)); + + sr |= ((src.swz[0] << NVFX_VP(SRC_SWZ_X_SHIFT)) | + (src.swz[1] << NVFX_VP(SRC_SWZ_Y_SHIFT)) | + (src.swz[2] << NVFX_VP(SRC_SWZ_Z_SHIFT)) | + (src.swz[3] << NVFX_VP(SRC_SWZ_W_SHIFT))); + + switch (pos) { + case 0: + hw[1] |= ((sr & NVFX_VP(SRC0_HIGH_MASK)) >> + NVFX_VP(SRC0_HIGH_SHIFT)) << NVFX_VP(INST_SRC0H_SHIFT); + hw[2] |= (sr & NVFX_VP(SRC0_LOW_MASK)) << + NVFX_VP(INST_SRC0L_SHIFT); + break; + case 1: + hw[2] |= sr << NVFX_VP(INST_SRC1_SHIFT); + break; + case 2: + hw[2] |= ((sr & NVFX_VP(SRC2_HIGH_MASK)) >> + NVFX_VP(SRC2_HIGH_SHIFT)) << NVFX_VP(INST_SRC2H_SHIFT); + hw[3] |= (sr & NVFX_VP(SRC2_LOW_MASK)) << + NVFX_VP(INST_SRC2L_SHIFT); + break; + default: + assert(0); + } +} + +static void +emit_dst(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, uint32_t *hw, int slot, struct nvfx_sreg dst) +{ + struct nvfx_vertex_program *vp = vpc->vp; + + switch (dst.type) { + case NVFXSR_TEMP: + if(!nvfx->is_nv4x) + hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT); + else { + hw[3] |= NV40_VP_INST_DEST_MASK; + if (slot == 0) { + hw[0] |= (dst.index << + NV40_VP_INST_VEC_DEST_TEMP_SHIFT); + } else { + hw[3] |= (dst.index << + NV40_VP_INST_SCA_DEST_TEMP_SHIFT); + } + } + break; + case NVFXSR_OUTPUT: + /* TODO: this may be wrong because on nv30 COL0 and BFC0 are swapped */ + switch (dst.index) { + case NVFX_VP_INST_DEST_CLIP(0): + vp->or |= (1 << 6); + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0; + dst.index = NVFX_VP(INST_DEST_FOGC); + break; + case NVFX_VP_INST_DEST_CLIP(1): + vp->or |= (1 << 7); + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1; + dst.index = NVFX_VP(INST_DEST_FOGC); + break; + case NVFX_VP_INST_DEST_CLIP(2): + vp->or |= (1 << 8); + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2; + dst.index = NVFX_VP(INST_DEST_FOGC); + break; + case NVFX_VP_INST_DEST_CLIP(3): + vp->or |= (1 << 9); + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3; + dst.index = NVFX_VP(INST_DEST_PSZ); + break; + case NVFX_VP_INST_DEST_CLIP(4): + vp->or |= (1 << 10); + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4; + dst.index = NVFX_VP(INST_DEST_PSZ); + break; + case NVFX_VP_INST_DEST_CLIP(5): + vp->or |= (1 << 11); + vp->clip_ctrl |= NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5; + dst.index = NVFX_VP(INST_DEST_PSZ); + break; + default: + if(!nvfx->is_nv4x) { + switch (dst.index) { + case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; + case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; + case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; + case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; + case NV30_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break; + case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; + case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; + case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; + case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; + case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; + case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; + case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; + case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; + case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; + } + } else { + switch (dst.index) { + case NV40_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; + case NV40_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; + case NV40_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; + case NV40_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; + case NV40_VP_INST_DEST_FOGC: vp->or |= (1 << 4); break; + case NV40_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; + case NV40_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; + case NV40_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; + case NV40_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; + case NV40_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; + case NV40_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; + case NV40_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; + case NV40_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; + case NV40_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; + } + } + break; + } + + if(!nvfx->is_nv4x) { + hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT); + hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + + /*XXX: no way this is entirely correct, someone needs to + * figure out what exactly it is. + */ + hw[3] |= 0x800; + } else { + hw[3] |= (dst.index << NV40_VP_INST_DEST_SHIFT); + if (slot == 0) { + hw[0] |= NV40_VP_INST_VEC_RESULT; + hw[0] |= NV40_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); + } else { + hw[3] |= NV40_VP_INST_SCA_RESULT; + hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; + } + } + break; + default: + assert(0); + } +} + +static void +nvfx_vp_arith(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, int slot, int op, + struct nvfx_sreg dst, int mask, + struct nvfx_sreg s0, struct nvfx_sreg s1, + struct nvfx_sreg s2) +{ + struct nvfx_vertex_program *vp = vpc->vp; + uint32_t *hw; + + vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); + vpc->vpi = &vp->insns[vp->nr_insns - 1]; + memset(vpc->vpi, 0, sizeof(*vpc->vpi)); + vpc->vpi->const_index = -1; + + hw = vpc->vpi->data; + + hw[0] |= (NVFX_COND_TR << NVFX_VP(INST_COND_SHIFT)); + hw[0] |= ((0 << NVFX_VP(INST_COND_SWZ_X_SHIFT)) | + (1 << NVFX_VP(INST_COND_SWZ_Y_SHIFT)) | + (2 << NVFX_VP(INST_COND_SWZ_Z_SHIFT)) | + (3 << NVFX_VP(INST_COND_SWZ_W_SHIFT))); + + if(!nvfx->is_nv4x) { + hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT); +// hw[3] |= NVFX_VP(INST_SCA_DEST_TEMP_MASK); +// hw[3] |= (mask << NVFX_VP(INST_VEC_WRITEMASK_SHIFT)); + + if (dst.type == NVFXSR_OUTPUT) { + if (slot) + hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT); + else + hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT); + } else { + if (slot) + hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT); + else + hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT); + } + } else { + if (slot == 0) { + hw[1] |= (op << NV40_VP_INST_VEC_OPCODE_SHIFT); + hw[3] |= NV40_VP_INST_SCA_DEST_TEMP_MASK; + hw[3] |= (mask << NV40_VP_INST_VEC_WRITEMASK_SHIFT); + } else { + hw[1] |= (op << NV40_VP_INST_SCA_OPCODE_SHIFT); + hw[0] |= (NV40_VP_INST_VEC_DEST_TEMP_MASK | (1 << 20)); + hw[3] |= (mask << NV40_VP_INST_SCA_WRITEMASK_SHIFT); + } + } + + emit_dst(nvfx, vpc, hw, slot, dst); + emit_src(nvfx, vpc, hw, 0, s0); + emit_src(nvfx, vpc, hw, 1, s1); + emit_src(nvfx, vpc, hw, 2, s2); +} + +static INLINE struct nvfx_sreg +tgsi_src(struct nvfx_vpc *vpc, const struct tgsi_full_src_register *fsrc) { + struct nvfx_sreg src; + + switch (fsrc->Register.File) { + case TGSI_FILE_INPUT: + src = nvfx_sr(NVFXSR_INPUT, fsrc->Register.Index); + break; + case TGSI_FILE_CONSTANT: + src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0); + break; + case TGSI_FILE_IMMEDIATE: + src = vpc->imm[fsrc->Register.Index]; + break; + case TGSI_FILE_TEMPORARY: + src = vpc->r_temp[fsrc->Register.Index]; + break; + default: + NOUVEAU_ERR("bad src file\n"); + break; + } + + src.abs = fsrc->Register.Absolute; + src.negate = fsrc->Register.Negate; + src.swz[0] = fsrc->Register.SwizzleX; + src.swz[1] = fsrc->Register.SwizzleY; + src.swz[2] = fsrc->Register.SwizzleZ; + src.swz[3] = fsrc->Register.SwizzleW; + return src; +} + +static INLINE struct nvfx_sreg +tgsi_dst(struct nvfx_vpc *vpc, const struct tgsi_full_dst_register *fdst) { + struct nvfx_sreg dst; + + switch (fdst->Register.File) { + case TGSI_FILE_OUTPUT: + dst = vpc->r_result[fdst->Register.Index]; + break; + case TGSI_FILE_TEMPORARY: + dst = vpc->r_temp[fdst->Register.Index]; + break; + case TGSI_FILE_ADDRESS: + dst = vpc->r_address[fdst->Register.Index]; + break; + default: + NOUVEAU_ERR("bad dst file\n"); + break; + } + + return dst; +} + +static INLINE int +tgsi_mask(uint tgsi) +{ + int mask = 0; + + if (tgsi & TGSI_WRITEMASK_X) mask |= NVFX_VP_MASK_X; + if (tgsi & TGSI_WRITEMASK_Y) mask |= NVFX_VP_MASK_Y; + if (tgsi & TGSI_WRITEMASK_Z) mask |= NVFX_VP_MASK_Z; + if (tgsi & TGSI_WRITEMASK_W) mask |= NVFX_VP_MASK_W; + return mask; +} + +static boolean +nvfx_vertprog_parse_instruction(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, + const struct tgsi_full_instruction *finst) +{ + struct nvfx_sreg src[3], dst, tmp; + struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0); + int mask; + int ai = -1, ci = -1, ii = -1; + int i; + + if (finst->Instruction.Opcode == TGSI_OPCODE_END) + return TRUE; + + for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { + const struct tgsi_full_src_register *fsrc; + + fsrc = &finst->Src[i]; + if (fsrc->Register.File == TGSI_FILE_TEMPORARY) { + src[i] = tgsi_src(vpc, fsrc); + } + } + + for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { + const struct tgsi_full_src_register *fsrc; + + fsrc = &finst->Src[i]; + + switch (fsrc->Register.File) { + case TGSI_FILE_INPUT: + if (ai == -1 || ai == fsrc->Register.Index) { + ai = fsrc->Register.Index; + src[i] = tgsi_src(vpc, fsrc); + } else { + src[i] = temp(vpc); + arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL, + tgsi_src(vpc, fsrc), none, none); + } + break; + case TGSI_FILE_CONSTANT: + if ((ci == -1 && ii == -1) || + ci == fsrc->Register.Index) { + ci = fsrc->Register.Index; + src[i] = tgsi_src(vpc, fsrc); + } else { + src[i] = temp(vpc); + arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL, + tgsi_src(vpc, fsrc), none, none); + } + break; + case TGSI_FILE_IMMEDIATE: + if ((ci == -1 && ii == -1) || + ii == fsrc->Register.Index) { + ii = fsrc->Register.Index; + src[i] = tgsi_src(vpc, fsrc); + } else { + src[i] = temp(vpc); + arith(vpc, VEC, MOV, src[i], NVFX_VP_MASK_ALL, + tgsi_src(vpc, fsrc), none, none); + } + break; + case TGSI_FILE_TEMPORARY: + /* handled above */ + break; + default: + NOUVEAU_ERR("bad src file\n"); + return FALSE; + } + } + + dst = tgsi_dst(vpc, &finst->Dst[0]); + mask = tgsi_mask(finst->Dst[0].Register.WriteMask); + + switch (finst->Instruction.Opcode) { + case TGSI_OPCODE_ABS: + arith(vpc, VEC, MOV, dst, mask, abs(src[0]), none, none); + break; + case TGSI_OPCODE_ADD: + arith(vpc, VEC, ADD, dst, mask, src[0], none, src[1]); + break; + case TGSI_OPCODE_ARL: + arith(vpc, VEC, ARL, dst, mask, src[0], none, none); + break; + case TGSI_OPCODE_DP3: + arith(vpc, VEC, DP3, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_DP4: + arith(vpc, VEC, DP4, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_DPH: + arith(vpc, VEC, DPH, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_DST: + arith(vpc, VEC, DST, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_EX2: + arith(vpc, SCA, EX2, dst, mask, none, none, src[0]); + break; + case TGSI_OPCODE_EXP: + arith(vpc, SCA, EXP, dst, mask, none, none, src[0]); + break; + case TGSI_OPCODE_FLR: + arith(vpc, VEC, FLR, dst, mask, src[0], none, none); + break; + case TGSI_OPCODE_FRC: + arith(vpc, VEC, FRC, dst, mask, src[0], none, none); + break; + case TGSI_OPCODE_LG2: + arith(vpc, SCA, LG2, dst, mask, none, none, src[0]); + break; + case TGSI_OPCODE_LIT: + arith(vpc, SCA, LIT, dst, mask, none, none, src[0]); + break; + case TGSI_OPCODE_LOG: + arith(vpc, SCA, LOG, dst, mask, none, none, src[0]); + break; + case TGSI_OPCODE_MAD: + arith(vpc, VEC, MAD, dst, mask, src[0], src[1], src[2]); + break; + case TGSI_OPCODE_MAX: + arith(vpc, VEC, MAX, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_MIN: + arith(vpc, VEC, MIN, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_MOV: + arith(vpc, VEC, MOV, dst, mask, src[0], none, none); + break; + case TGSI_OPCODE_MUL: + arith(vpc, VEC, MUL, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_POW: + tmp = temp(vpc); + arith(vpc, SCA, LG2, tmp, NVFX_VP_MASK_X, none, none, + swz(src[0], X, X, X, X)); + arith(vpc, VEC, MUL, tmp, NVFX_VP_MASK_X, swz(tmp, X, X, X, X), + swz(src[1], X, X, X, X), none); + arith(vpc, SCA, EX2, dst, mask, none, none, + swz(tmp, X, X, X, X)); + break; + case TGSI_OPCODE_RCP: + arith(vpc, SCA, RCP, dst, mask, none, none, src[0]); + break; + case TGSI_OPCODE_RET: + break; + case TGSI_OPCODE_RSQ: + arith(vpc, SCA, RSQ, dst, mask, none, none, abs(src[0])); + break; + case TGSI_OPCODE_SGE: + arith(vpc, VEC, SGE, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_SGT: + arith(vpc, VEC, SGT, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_SLT: + arith(vpc, VEC, SLT, dst, mask, src[0], src[1], none); + break; + case TGSI_OPCODE_SUB: + arith(vpc, VEC, ADD, dst, mask, src[0], none, neg(src[1])); + break; + case TGSI_OPCODE_XPD: + tmp = temp(vpc); + arith(vpc, VEC, MUL, tmp, mask, + swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); + arith(vpc, VEC, MAD, dst, (mask & ~NVFX_VP_MASK_W), + swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), + neg(tmp)); + break; + default: + NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); + return FALSE; + } + + release_temps(vpc); + return TRUE; +} + +static boolean +nvfx_vertprog_parse_decl_output(struct nvfx_context* nvfx, struct nvfx_vpc *vpc, + const struct tgsi_full_declaration *fdec) +{ + unsigned idx = fdec->Range.First; + int hw; + + switch (fdec->Semantic.Name) { + case TGSI_SEMANTIC_POSITION: + hw = NVFX_VP(INST_DEST_POS); + vpc->hpos_idx = idx; + break; + case TGSI_SEMANTIC_COLOR: + if (fdec->Semantic.Index == 0) { + hw = NVFX_VP(INST_DEST_COL0); + } else + if (fdec->Semantic.Index == 1) { + hw = NVFX_VP(INST_DEST_COL1); + } else { + NOUVEAU_ERR("bad colour semantic index\n"); + return FALSE; + } + break; + case TGSI_SEMANTIC_BCOLOR: + if (fdec->Semantic.Index == 0) { + hw = NVFX_VP(INST_DEST_BFC0); + } else + if (fdec->Semantic.Index == 1) { + hw = NVFX_VP(INST_DEST_BFC1); + } else { + NOUVEAU_ERR("bad bcolour semantic index\n"); + return FALSE; + } + break; + case TGSI_SEMANTIC_FOG: + hw = NVFX_VP(INST_DEST_FOGC); + break; + case TGSI_SEMANTIC_PSIZE: + hw = NVFX_VP(INST_DEST_PSZ); + break; + case TGSI_SEMANTIC_GENERIC: + if (fdec->Semantic.Index <= 7) { + hw = NVFX_VP(INST_DEST_TC(fdec->Semantic.Index)); + } else { + NOUVEAU_ERR("bad generic semantic index\n"); + return FALSE; + } + break; + case TGSI_SEMANTIC_EDGEFLAG: + /* not really an error just a fallback */ + NOUVEAU_ERR("cannot handle edgeflag output\n"); + return FALSE; + default: + NOUVEAU_ERR("bad output semantic\n"); + return FALSE; + } + + vpc->r_result[idx] = nvfx_sr(NVFXSR_OUTPUT, hw); + return TRUE; +} + +static boolean +nvfx_vertprog_prepare(struct nvfx_context* nvfx, struct nvfx_vpc *vpc) +{ + struct tgsi_parse_context p; + int high_temp = -1, high_addr = -1, nr_imm = 0, i; + + tgsi_parse_init(&p, vpc->vp->pipe.tokens); + while (!tgsi_parse_end_of_tokens(&p)) { + const union tgsi_full_token *tok = &p.FullToken; + + tgsi_parse_token(&p); + switch(tok->Token.Type) { + case TGSI_TOKEN_TYPE_IMMEDIATE: + nr_imm++; + break; + case TGSI_TOKEN_TYPE_DECLARATION: + { + const struct tgsi_full_declaration *fdec; + + fdec = &p.FullToken.FullDeclaration; + switch (fdec->Declaration.File) { + case TGSI_FILE_TEMPORARY: + if (fdec->Range.Last > high_temp) { + high_temp = + fdec->Range.Last; + } + break; +#if 0 /* this would be nice.. except gallium doesn't track it */ + case TGSI_FILE_ADDRESS: + if (fdec->Range.Last > high_addr) { + high_addr = + fdec->Range.Last; + } + break; +#endif + case TGSI_FILE_OUTPUT: + if (!nvfx_vertprog_parse_decl_output(nvfx, vpc, fdec)) + return FALSE; + break; + default: + break; + } + } + break; +#if 1 /* yay, parse instructions looking for address regs instead */ + case TGSI_TOKEN_TYPE_INSTRUCTION: + { + const struct tgsi_full_instruction *finst; + const struct tgsi_full_dst_register *fdst; + + finst = &p.FullToken.FullInstruction; + fdst = &finst->Dst[0]; + + if (fdst->Register.File == TGSI_FILE_ADDRESS) { + if (fdst->Register.Index > high_addr) + high_addr = fdst->Register.Index; + } + + } + break; +#endif + default: + break; + } + } + tgsi_parse_free(&p); + + if (nr_imm) { + vpc->imm = CALLOC(nr_imm, sizeof(struct nvfx_sreg)); + assert(vpc->imm); + } + + if (++high_temp) { + vpc->r_temp = CALLOC(high_temp, sizeof(struct nvfx_sreg)); + for (i = 0; i < high_temp; i++) + vpc->r_temp[i] = temp(vpc); + } + + if (++high_addr) { + vpc->r_address = CALLOC(high_addr, sizeof(struct nvfx_sreg)); + for (i = 0; i < high_addr; i++) + vpc->r_address[i] = temp(vpc); + } + + vpc->r_temps_discard = 0; + return TRUE; +} + +static void +nvfx_vertprog_translate(struct nvfx_context *nvfx, + struct nvfx_vertex_program *vp) +{ + struct tgsi_parse_context parse; + struct nvfx_vpc *vpc = NULL; + struct nvfx_sreg none = nvfx_sr(NVFXSR_NONE, 0); + int i; + + vpc = CALLOC(1, sizeof(struct nvfx_vpc)); + if (!vpc) + return; + vpc->vp = vp; + + if (!nvfx_vertprog_prepare(nvfx, vpc)) { + FREE(vpc); + return; + } + + /* Redirect post-transform vertex position to a temp if user clip + * planes are enabled. We need to append code to the vtxprog + * to handle clip planes later. + */ + if (vp->ucp.nr) { + vpc->r_result[vpc->hpos_idx] = temp(vpc); + vpc->r_temps_discard = 0; + } + + tgsi_parse_init(&parse, vp->pipe.tokens); + + while (!tgsi_parse_end_of_tokens(&parse)) { + tgsi_parse_token(&parse); + + switch (parse.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_IMMEDIATE: + { + const struct tgsi_full_immediate *imm; + + imm = &parse.FullToken.FullImmediate; + assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); + assert(imm->Immediate.NrTokens == 4 + 1); + vpc->imm[vpc->nr_imm++] = + constant(vpc, -1, + imm->u[0].Float, + imm->u[1].Float, + imm->u[2].Float, + imm->u[3].Float); + } + break; + case TGSI_TOKEN_TYPE_INSTRUCTION: + { + const struct tgsi_full_instruction *finst; + finst = &parse.FullToken.FullInstruction; + if (!nvfx_vertprog_parse_instruction(nvfx, vpc, finst)) + goto out_err; + } + break; + default: + break; + } + } + + /* Write out HPOS if it was redirected to a temp earlier */ + if (vpc->r_result[vpc->hpos_idx].type != NVFXSR_OUTPUT) { + struct nvfx_sreg hpos = nvfx_sr(NVFXSR_OUTPUT, + NVFX_VP(INST_DEST_POS)); + struct nvfx_sreg htmp = vpc->r_result[vpc->hpos_idx]; + + arith(vpc, VEC, MOV, hpos, NVFX_VP_MASK_ALL, htmp, none, none); + } + + /* Insert code to handle user clip planes */ + for (i = 0; i < vp->ucp.nr; i++) { + struct nvfx_sreg cdst = nvfx_sr(NVFXSR_OUTPUT, + NVFX_VP_INST_DEST_CLIP(i)); + struct nvfx_sreg ceqn = constant(vpc, -1, + nvfx->clip.ucp[i][0], + nvfx->clip.ucp[i][1], + nvfx->clip.ucp[i][2], + nvfx->clip.ucp[i][3]); + struct nvfx_sreg htmp = vpc->r_result[vpc->hpos_idx]; + unsigned mask; + + switch (i) { + case 0: case 3: mask = NVFX_VP_MASK_Y; break; + case 1: case 4: mask = NVFX_VP_MASK_Z; break; + case 2: case 5: mask = NVFX_VP_MASK_W; break; + default: + NOUVEAU_ERR("invalid clip dist #%d\n", i); + goto out_err; + } + + arith(vpc, VEC, DP4, cdst, mask, htmp, ceqn, none); + } + + vp->insns[vp->nr_insns - 1].data[3] |= NVFX_VP_INST_LAST; + vp->translated = TRUE; +out_err: + tgsi_parse_free(&parse); + if (vpc->r_temp) + FREE(vpc->r_temp); + if (vpc->r_address) + FREE(vpc->r_address); + if (vpc->imm) + FREE(vpc->imm); + FREE(vpc); +} + +static boolean +nvfx_vertprog_validate(struct nvfx_context *nvfx) +{ + struct pipe_context *pipe = &nvfx->pipe; + struct nvfx_screen *screen = nvfx->screen; + struct nouveau_channel *chan = screen->base.channel; + struct nouveau_grobj *eng3d = screen->eng3d; + struct nvfx_vertex_program *vp; + struct pipe_resource *constbuf; + struct pipe_transfer *transfer; + boolean upload_code = FALSE, upload_data = FALSE; + int i; + + if (nvfx->render_mode == HW) { + vp = nvfx->vertprog; + constbuf = nvfx->constbuf[PIPE_SHADER_VERTEX]; + + if ((nvfx->dirty & NVFX_NEW_UCP) || + memcmp(&nvfx->clip, &vp->ucp, sizeof(vp->ucp))) { + nvfx_vertprog_destroy(nvfx, vp); + memcpy(&vp->ucp, &nvfx->clip, sizeof(vp->ucp)); + } + } else { + vp = nvfx->swtnl.vertprog; + constbuf = NULL; + } + + /* Translate TGSI shader into hw bytecode */ + if (vp->translated) + goto check_gpu_resources; + + nvfx->fallback_swtnl &= ~NVFX_NEW_VERTPROG; + nvfx_vertprog_translate(nvfx, vp); + if (!vp->translated) { + nvfx->fallback_swtnl |= NVFX_NEW_VERTPROG; + return FALSE; + } + +check_gpu_resources: + /* Allocate hw vtxprog exec slots */ + if (!vp->exec) { + struct nouveau_resource *heap = nvfx->screen->vp_exec_heap; + struct nouveau_stateobj *so; + uint vplen = vp->nr_insns; + + if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) { + while (heap->next && heap->size < vplen) { + struct nvfx_vertex_program *evict; + + evict = heap->next->priv; + nouveau_resource_free(&evict->exec); + } + + if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) + assert(0); + } + + so = so_new(3, 4, 0); + so_method(so, eng3d, NV34TCL_VP_START_FROM_ID, 1); + so_data (so, vp->exec->start); + if(nvfx->is_nv4x) { + so_method(so, eng3d, NV40TCL_VP_ATTRIB_EN, 2); + so_data (so, vp->ir); + so_data (so, vp->or); + } + so_method(so, eng3d, NV34TCL_VP_CLIP_PLANES_ENABLE, 1); + so_data (so, vp->clip_ctrl); + so_ref(so, &vp->so); + so_ref(NULL, &so); + + upload_code = TRUE; + } + + /* Allocate hw vtxprog const slots */ + if (vp->nr_consts && !vp->data) { + struct nouveau_resource *heap = nvfx->screen->vp_data_heap; + + if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) { + while (heap->next && heap->size < vp->nr_consts) { + struct nvfx_vertex_program *evict; + + evict = heap->next->priv; + nouveau_resource_free(&evict->data); + } + + if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) + assert(0); + } + + /*XXX: handle this some day */ + assert(vp->data->start >= vp->data_start_min); + + upload_data = TRUE; + if (vp->data_start != vp->data->start) + upload_code = TRUE; + } + + /* If exec or data segments moved we need to patch the program to + * fixup offsets and register IDs. + */ + if (vp->exec_start != vp->exec->start) { + for (i = 0; i < vp->nr_insns; i++) { + struct nvfx_vertex_program_exec *vpi = &vp->insns[i]; + + if (vpi->has_branch_offset) { + assert(0); + } + } + + vp->exec_start = vp->exec->start; + } + + if (vp->nr_consts && vp->data_start != vp->data->start) { + for (i = 0; i < vp->nr_insns; i++) { + struct nvfx_vertex_program_exec *vpi = &vp->insns[i]; + + if (vpi->const_index >= 0) { + vpi->data[1] &= ~NVFX_VP(INST_CONST_SRC_MASK); + vpi->data[1] |= + (vpi->const_index + vp->data->start) << + NVFX_VP(INST_CONST_SRC_SHIFT); + + } + } + + vp->data_start = vp->data->start; + } + + /* Update + Upload constant values */ + if (vp->nr_consts) { + float *map = NULL; + + if (constbuf) { + map = pipe_buffer_map(pipe, constbuf, + PIPE_BUFFER_USAGE_CPU_READ, + &transfer); + } + + for (i = 0; i < vp->nr_consts; i++) { + struct nvfx_vertex_program_data *vpd = &vp->consts[i]; + + if (vpd->index >= 0) { + if (!upload_data && + !memcmp(vpd->value, &map[vpd->index * 4], + 4 * sizeof(float))) + continue; + memcpy(vpd->value, &map[vpd->index * 4], + 4 * sizeof(float)); + } + + BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_CONST_ID, 5); + OUT_RING (chan, i + vp->data->start); + OUT_RINGp (chan, (uint32_t *)vpd->value, 4); + } + + if (constbuf) + pipe_buffer_unmap(pipe, constbuf, transfer); + } + + /* Upload vtxprog */ + if (upload_code) { +#if 0 + for (i = 0; i < vp->nr_insns; i++) { + NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[0]); + NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[1]); + NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[2]); + NOUVEAU_MSG("VP %d: 0x%08x\n", i, vp->insns[i].data[3]); + } +#endif + BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_FROM_ID, 1); + OUT_RING (chan, vp->exec->start); + for (i = 0; i < vp->nr_insns; i++) { + BEGIN_RING(chan, eng3d, NV34TCL_VP_UPLOAD_INST(0), 4); + OUT_RINGp (chan, vp->insns[i].data, 4); + } + } + + if (vp->so != nvfx->state.hw[NVFX_STATE_VERTPROG]) { + so_ref(vp->so, &nvfx->state.hw[NVFX_STATE_VERTPROG]); + return TRUE; + } + + return FALSE; +} + +void +nvfx_vertprog_destroy(struct nvfx_context *nvfx, struct nvfx_vertex_program *vp) +{ + vp->translated = FALSE; + + if (vp->nr_insns) { + FREE(vp->insns); + vp->insns = NULL; + vp->nr_insns = 0; + } + + if (vp->nr_consts) { + FREE(vp->consts); + vp->consts = NULL; + vp->nr_consts = 0; + } + + nouveau_resource_free(&vp->exec); + vp->exec_start = 0; + nouveau_resource_free(&vp->data); + vp->data_start = 0; + vp->data_start_min = 0; + + vp->ir = vp->or = vp->clip_ctrl = 0; + so_ref(NULL, &vp->so); +} + +struct nvfx_state_entry nvfx_state_vertprog = { + .validate = nvfx_vertprog_validate, + .dirty = { + .pipe = NVFX_NEW_VERTPROG | NVFX_NEW_UCP, + .hw = NVFX_STATE_VERTPROG, + } +}; diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 61b54af4dd..5a8e00f15a 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -13,7 +13,9 @@ C_SOURCES = \ r300_fs.c \ r300_query.c \ r300_render.c \ + r300_resource.c \ r300_screen.c \ + r300_screen_buffer.c \ r300_state.c \ r300_state_derived.c \ r300_state_invariant.c \ diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index a60b12844d..bcdf950df9 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -114,8 +114,8 @@ static void r300_hw_copy(struct pipe_context* pipe, r300->blitter, state->sampler_count, (void**)state->sampler_states); util_blitter_save_fragment_sampler_views( - r300->blitter, r300->fragment_sampler_view_count, - r300->fragment_sampler_views); + r300->blitter, state->texture_count, + state->fragment_sampler_views); /* Do a copy */ util_blitter_copy(r300->blitter, @@ -149,6 +149,9 @@ void r300_surface_copy(struct pipe_context* pipe, case 4: new_format = PIPE_FORMAT_B8G8R8A8_UNORM; break; + case 8: + new_format = PIPE_FORMAT_R16G16B16A16_UNORM; + break; default: debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n" "r300: surface_copy: Software fallback doesn't work for tiled textures.\n", diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index ed24fb54ab..e805a84290 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -24,6 +24,7 @@ #include "util/u_memory.h" #include "util/u_simple_list.h" +#include "util/u_upload_mgr.h" #include "r300_blit.h" #include "r300_context.h" @@ -32,11 +33,11 @@ #include "r300_query.h" #include "r300_render.h" #include "r300_screen.h" +#include "r300_screen_buffer.h" #include "r300_state_invariant.h" #include "r300_texture.h" #include "r300_transfer.h" - -#include "radeon_winsys.h" +#include "r300_winsys.h" static void r300_destroy_context(struct pipe_context* context) { @@ -47,7 +48,7 @@ static void r300_destroy_context(struct pipe_context* context) draw_destroy(r300->draw); /* Free the OQ BO. */ - context->screen->buffer_destroy(r300->oqbo); + context->screen->resource_destroy(context->screen, r300->oqbo); /* If there are any queries pending or not destroyed, remove them now. */ foreach_s(query, temp, &r300->query_list) { @@ -55,6 +56,9 @@ static void r300_destroy_context(struct pipe_context* context) FREE(query); } + u_upload_destroy(r300->upload_vb); + u_upload_destroy(r300->upload_ib); + FREE(r300->blend_color_state.state); FREE(r300->clip_state.state); FREE(r300->fb_state.state); @@ -67,32 +71,6 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300); } -static unsigned int -r300_is_texture_referenced(struct pipe_context *pipe, - struct pipe_texture *texture, - unsigned face, unsigned level) -{ - return pipe->is_buffer_referenced(pipe, - ((struct r300_texture *)texture)->buffer); -} - -static unsigned int -r300_is_buffer_referenced(struct pipe_context *pipe, - struct pipe_buffer *buf) -{ - /* This only checks to see whether actual hardware buffers are - * referenced. Since we use managed BOs and transfers, it's actually not - * possible for pipe_buffers to ever reference the actual hardware, so - * buffers are never referenced. - */ - - /* XXX: that doesn't make sense given that - * r300_is_texture_referenced is implemented on top of this - * function and hardware can certainly refer to textures - * directly... - */ - return 0; -} static void r300_flush_cb(void *data) { @@ -157,14 +135,14 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, { struct r300_context* r300 = CALLOC_STRUCT(r300_context); struct r300_screen* r300screen = r300_screen(screen); - struct radeon_winsys* radeon_winsys = r300screen->radeon_winsys; + struct r300_winsys_screen *rws = r300screen->rws; if (!r300) return NULL; - r300->winsys = radeon_winsys; + r300->rws = rws; - r300->context.winsys = (struct pipe_winsys*)radeon_winsys; + r300->context.winsys = (struct pipe_winsys*)rws; r300->context.screen = screen; r300->context.priv = priv; @@ -194,30 +172,46 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, draw_set_viewport_state(r300->draw, &r300_viewport_identity); } - r300->context.is_texture_referenced = r300_is_texture_referenced; - r300->context.is_buffer_referenced = r300_is_buffer_referenced; - r300_setup_atoms(r300); + r300->sprite_coord_index = -1; + /* Open up the OQ BO. */ - r300->oqbo = screen->buffer_create(screen, 4096, - PIPE_BUFFER_USAGE_VERTEX, 4096); + r300->oqbo = pipe_buffer_create(screen, 4096, + PIPE_BUFFER_USAGE_PIXEL, 4096); make_empty_list(&r300->query_list); r300_init_flush_functions(r300); r300_init_query_functions(r300); - r300_init_transfer_functions(r300); - r300_init_state_functions(r300); r300->invariant_state.dirty = TRUE; - r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); + rws->set_flush_cb(r300->rws, r300_flush_cb, r300); r300->dirty_hw++; r300->blitter = util_blitter_create(&r300->context); + r300->upload_ib = u_upload_create(&r300->context, + 32 * 1024, 16, + PIPE_BUFFER_USAGE_INDEX); + + if (r300->upload_ib == NULL) + goto no_upload_ib; + + r300->upload_vb = u_upload_create(&r300->context, + 128 * 1024, 16, + PIPE_BUFFER_USAGE_VERTEX); + if (r300->upload_vb == NULL) + goto no_upload_vb; + return &r300->context; + + no_upload_ib: + u_upload_destroy(r300->upload_ib); + no_upload_vb: + FREE(r300); + return NULL; } diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 7b86669888..bcf87b3866 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -29,9 +29,12 @@ #include "pipe/p_context.h" #include "util/u_inlines.h" +#include "util/u_transfer.h" +#include "r300_defines.h" #include "r300_screen.h" +struct u_upload_mgr; struct r300_context; struct r300_fragment_shader; @@ -97,6 +100,16 @@ struct r300_rs_state { uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */ uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */ uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */ + + /* Specifies top of Raster pipe specific enable controls, + * i.e. texture coordinates stuffing for points, lines, triangles */ + uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */ + + /* Point sprites texture coordinates, 0: lower left, 1: upper right */ + float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */ + float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */ + float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */ + float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */ }; struct r300_rs_block { @@ -124,8 +137,6 @@ struct r300_texture_format_state { uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */ }; -#define R300_MAX_TEXTURE_LEVELS 13 - struct r300_texture_fb_state { /* Colorbuffer. */ uint32_t colorpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/ @@ -138,7 +149,7 @@ struct r300_texture_fb_state { struct r300_textures_state { /* Textures. */ - struct r300_texture *textures[8]; + struct pipe_sampler_view *fragment_sampler_views[8]; int texture_count; /* Sampler states. */ struct r300_sampler_state *sampler_states[8]; @@ -184,12 +195,6 @@ struct r300_ztop_state { uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */ }; -#define R300_NEW_FRAGMENT_SHADER 0x00000020 -#define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040 -#define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000 -#define R300_NEW_QUERY 0x40000000 -#define R300_NEW_KITCHEN_SINK 0x7fffffff - /* The next several objects are not pure Radeon state; they inherit from * various Gallium classes. */ @@ -227,15 +232,9 @@ struct r300_query { struct r300_query* next; }; -enum r300_buffer_tiling { - R300_BUFFER_LINEAR = 0, - R300_BUFFER_TILED, - R300_BUFFER_SQUARETILED -}; - struct r300_texture { /* Parent class */ - struct pipe_texture tex; + struct u_resource b; /* Offsets into the buffer. */ unsigned offset[R300_MAX_TEXTURE_LEVELS]; @@ -268,7 +267,7 @@ struct r300_texture { boolean is_npot; /* Pipe buffer backing this texture. */ - struct pipe_buffer* buffer; + struct r300_winsys_buffer *buffer; /* Registers carrying texture format data. */ struct r300_texture_format_state state; @@ -302,19 +301,19 @@ struct r300_context { struct pipe_context context; /* The interface to the windowing system, etc. */ - struct radeon_winsys* winsys; + struct r300_winsys_screen *rws; /* Draw module. Used mostly for SW TCL. */ struct draw_context* draw; /* Accelerated blit support. */ struct blitter_context* blitter; /* Vertex buffer for rendering. */ - struct pipe_buffer* vbo; + struct pipe_resource* vbo; /* Offset into the VBO. */ size_t vbo_offset; /* Occlusion query buffer. */ - struct pipe_buffer* oqbo; + struct pipe_resource* oqbo; /* Query list. */ struct r300_query *query_current; struct r300_query query_list; @@ -342,9 +341,8 @@ struct r300_context { struct r300_atom rs_block_state; /* Scissor state. */ struct r300_atom scissor_state; - /* Sampler view states. */ - struct pipe_sampler_view* fragment_sampler_views[8]; - int fragment_sampler_view_count; + /* Textures state. */ + struct r300_atom textures_state; /* Vertex stream formatting state. */ struct r300_atom vertex_stream_state; /* VAP (vertex shader) output mapping state. */ @@ -369,6 +367,7 @@ struct r300_context { int vertex_buffer_max_index; /* Vertex elements for Gallium. */ struct r300_vertex_element_state *velems; + bool any_user_vbs; /* Vertex info for Draw. */ struct vertex_info vertex_info; @@ -389,6 +388,12 @@ struct r300_context { uint32_t zbuffer_bpp; /* Whether scissor is enabled. */ boolean scissor_enabled; + /* Point sprites texcoord index, -1 = unused. */ + int sprite_coord_index; + + /* upload managers */ + struct u_upload_mgr *upload_vb; + struct u_upload_mgr *upload_ib; }; /* Convenience cast wrapper. */ @@ -404,8 +409,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, /* Context initialization. */ struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_state_functions(struct r300_context* r300); -void r300_init_surface_functions(struct r300_context* r300); -void r300_init_tex_functions( struct pipe_context *pipe ); +void r300_init_resource_functions(struct r300_context* r300); static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags) { @@ -427,4 +431,3 @@ static INLINE void CTX_DBG(struct r300_context * ctx, unsigned flags, #define DBG CTX_DBG #endif /* R300_CONTEXT_H */ - diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 151f72b0fe..456b2ec7b9 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -26,8 +26,7 @@ #include "util/u_math.h" #include "r300_reg.h" - -#include "radeon_winsys.h" +#include "r300_winsys.h" /* Yes, I know macros are ugly. However, they are much prettier than the code * that they neatly hide away, and don't have the cost of function setup,so @@ -51,7 +50,7 @@ #define CS_LOCALS(context) \ struct r300_context* const cs_context_copy = (context); \ - struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \ + struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \ int cs_count = 0; (void) cs_count; #define CHECK_CS(size) \ @@ -105,22 +104,34 @@ cs_count--; \ } while (0) -#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \ +#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \ DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, offset %d, " \ "domains (%d, %d, %d)\n", \ bo, offset, rd, wd, flags); \ assert(bo); \ cs_winsys->write_cs_dword(cs_winsys, offset); \ - cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ + r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ + cs_count -= 3; \ +} while (0) + + +#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \ + DBG(cs_context_copy, DBG_CS, "r300: writing relocation for texture %p, offset %d, " \ + "domains (%d, %d, %d)\n", \ + tex, offset, rd, wd, flags); \ + assert(tex); \ + cs_winsys->write_cs_dword(cs_winsys, offset); \ + r300_texture_write_reloc(cs_winsys, tex, rd, wd, flags); \ cs_count -= 3; \ } while (0) -#define OUT_CS_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ + +#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, " \ "domains (%d, %d, %d)\n", \ bo, rd, wd, flags); \ assert(bo); \ - cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ + r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ cs_count -= 2; \ } while (0) diff --git a/src/gallium/drivers/r300/r300_defines.h b/src/gallium/drivers/r300/r300_defines.h new file mode 100644 index 0000000000..2e04876de9 --- /dev/null +++ b/src/gallium/drivers/r300/r300_defines.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010 Marek Olšák <maraeo@gmail.com> + * + * 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 + * THE AUTHOR(S) AND/OR THEIR 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 R300_DEFINES_H +#define R300_DEFINES_H + +#include "pipe/p_defines.h" + +#define R300_MAX_TEXTURE_LEVELS 13 +#define R300_MAX_DRAW_VBO_SIZE (1024 * 1024) + +#define R300_TEXTURE_USAGE_TRANSFER PIPE_TEXTURE_USAGE_CUSTOM + +/* Non-atom dirty state flags. */ +#define R300_NEW_FRAGMENT_SHADER 0x00000020 +#define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040 +#define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000 +#define R300_NEW_QUERY 0x40000000 +#define R300_NEW_KITCHEN_SINK 0x7fffffff + +/* Tiling flags. */ +enum r300_buffer_tiling { + R300_BUFFER_LINEAR = 0, + R300_BUFFER_TILED, + R300_BUFFER_SQUARETILED +}; + +#endif diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 2f689e75bc..cf0d237058 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -32,6 +32,8 @@ #include "r300_emit.h" #include "r300_fs.h" #include "r300_screen.h" +#include "r300_screen_buffer.h" +#include "r300_state_inlines.h" #include "r300_vs.h" void r300_emit_blend_state(struct r300_context* r300, @@ -149,7 +151,7 @@ static const float * get_shader_constant( struct r300_textures_state* texstate = (struct r300_textures_state*)r300->textures_state.state; static float vec[4] = { 0.0, 0.0, 0.0, 1.0 }; - struct pipe_texture *tex; + struct pipe_resource *tex; switch(constant->Type) { case RC_CONSTANT_EXTERNAL: @@ -163,7 +165,7 @@ static const float * get_shader_constant( /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ case RC_STATE_R300_TEXRECT_FACTOR: - tex = r300->fragment_sampler_views[constant->u.State[1]]->texture; + tex = texstate->fragment_sampler_views[constant->u.State[1]]->texture; vec[0] = 1.0 / tex->width0; vec[1] = 1.0 / tex->height0; break; @@ -415,10 +417,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) assert(tex && tex->buffer && "cbuf is marked, but NULL!"); OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); - OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); - OUT_CS_RELOC(tex->buffer, tex->fb_state.colorpitch[surf->level], + OUT_CS_TEX_RELOC(tex, tex->fb_state.colorpitch[surf->level], 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), tex->fb_state.us_out_fmt); @@ -434,12 +436,12 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_TEX_RELOC(tex, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_ZB_FORMAT, tex->fb_state.zb_format); OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(tex->buffer, tex->fb_state.depthpitch[surf->level], + OUT_CS_TEX_RELOC(tex, tex->fb_state.depthpitch[surf->level], 0, RADEON_GEM_DOMAIN_VRAM, 0); } @@ -491,13 +493,13 @@ static void r300_emit_query_finish(struct r300_context *r300, /* pipe 3 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), 0, RADEON_GEM_DOMAIN_GTT, 0); case 3: /* pipe 2 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), 0, RADEON_GEM_DOMAIN_GTT, 0); case 2: /* pipe 1 only */ @@ -505,13 +507,13 @@ static void r300_emit_query_finish(struct r300_context *r300, OUT_CS_REG(R300_SU_REG_DEST, 1 << (caps->high_second_pipe ? 3 : 1)); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), 0, RADEON_GEM_DOMAIN_GTT, 0); case 1: /* pipe 0 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), 0, RADEON_GEM_DOMAIN_GTT, 0); break; default: @@ -533,7 +535,7 @@ static void rv530_emit_query_single(struct r300_context *r300, BEGIN_CS(8); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -546,10 +548,10 @@ static void rv530_emit_query_double(struct r300_context *r300, BEGIN_CS(14); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_BUF_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -614,6 +616,12 @@ void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config); OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value); OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode); + OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable); + OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); + OUT_CS_32F(rs->point_texcoord_left); + OUT_CS_32F(rs->point_texcoord_bottom); + OUT_CS_32F(rs->point_texcoord_right); + OUT_CS_32F(rs->point_texcoord_top); END_CS; } @@ -747,8 +755,9 @@ void r300_emit_textures_state(struct r300_context *r300, OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]); OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_CS_RELOC(allstate->textures[i]->buffer, texstate->tile_config, - RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); + OUT_CS_TEX_RELOC((struct r300_texture *)allstate->fragment_sampler_views[i]->texture, + texstate->tile_config, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); } } END_CS; @@ -788,8 +797,8 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) } for (i = 0; i < aos_count; i++) { - OUT_CS_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer, - RADEON_GEM_DOMAIN_GTT, 0, 0); + OUT_CS_BUF_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer, + RADEON_GEM_DOMAIN_GTT, 0, 0); } END_CS; } @@ -814,7 +823,7 @@ void r300_emit_vertex_buffer(struct r300_context* r300) OUT_CS(r300->vertex_info.size | (r300->vertex_info.size << 8)); OUT_CS(r300->vbo_offset); - OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); + OUT_CS_BUF_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); END_CS; } @@ -996,7 +1005,7 @@ void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, voi void r300_emit_buffer_validate(struct r300_context *r300, boolean do_validate_vertex_buffers, - struct pipe_buffer *index_buffer) + struct pipe_resource *index_buffer) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; @@ -1005,20 +1014,26 @@ void r300_emit_buffer_validate(struct r300_context *r300, struct r300_texture* tex; struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; - struct pipe_buffer *pbuf; + struct pipe_resource *pbuf; unsigned i; boolean invalid = FALSE; + /* upload buffers first */ + if (r300->any_user_vbs) { + r300_upload_user_buffers(r300); + r300->any_user_vbs = false; + } + /* Clean out BOs. */ - r300->winsys->reset_bos(r300->winsys); + r300->rws->reset_bos(r300->rws); validate: /* Color buffers... */ for (i = 0; i < fb->nr_cbufs; i++) { tex = (struct r300_texture*)fb->cbufs[i]->texture; assert(tex && tex->buffer && "cbuf is marked, but NULL!"); - if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM)) { + if (!r300_add_texture(r300->rws, tex, + 0, RADEON_GEM_DOMAIN_VRAM)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } @@ -1027,35 +1042,37 @@ validate: if (fb->zsbuf) { tex = (struct r300_texture*)fb->zsbuf->texture; assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); - if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM)) { + if (!r300_add_texture(r300->rws, tex, + 0, RADEON_GEM_DOMAIN_VRAM)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } /* ...textures... */ - for (i = 0; i < r300->fragment_sampler_view_count; i++) { - if (!r300->fragment_sampler_views[i]) + for (i = 0; i < texstate->count; i++) { + if (!(texstate->tx_enable & (1 << i))) { continue; - tex = (struct r300_texture *)r300->fragment_sampler_views[i]->texture; - if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, - RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { + } + + tex = (struct r300_texture*)texstate->fragment_sampler_views[i]->texture; + if (!r300_add_texture(r300->rws, tex, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } /* ...occlusion query buffer... */ if (r300->dirty_state & R300_NEW_QUERY) { - if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, - 0, RADEON_GEM_DOMAIN_GTT)) { + if (!r300_add_buffer(r300->rws, r300->oqbo, + 0, RADEON_GEM_DOMAIN_GTT)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } /* ...vertex buffer for SWTCL path... */ if (r300->vbo) { - if (!r300->winsys->add_buffer(r300->winsys, r300->vbo, - RADEON_GEM_DOMAIN_GTT, 0)) { + if (!r300_add_buffer(r300->rws, r300->vbo, + RADEON_GEM_DOMAIN_GTT, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } @@ -1065,23 +1082,22 @@ validate: for (i = 0; i < r300->velems->count; i++) { pbuf = vbuf[velem[i].vertex_buffer_index].buffer; - if (!r300->winsys->add_buffer(r300->winsys, pbuf, - RADEON_GEM_DOMAIN_GTT, 0)) { - r300->context.flush(&r300->context, 0, NULL); + if (!r300_add_buffer(r300->rws, pbuf, + RADEON_GEM_DOMAIN_GTT, 0)) { + r300->context.flush(&r300->context, 0, NULL); goto validate; } } } /* ...and index buffer for HWTCL path. */ if (index_buffer) { - if (!r300->winsys->add_buffer(r300->winsys, index_buffer, - RADEON_GEM_DOMAIN_GTT, 0)) { + if (!r300_add_buffer(r300->rws, index_buffer, + RADEON_GEM_DOMAIN_GTT, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } } - - if (!r300->winsys->validate(r300->winsys)) { + if (!r300->rws->validate(r300->rws)) { r300->context.flush(&r300->context, 0, NULL); if (invalid) { /* Well, hell. */ diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 7db2fc6a1a..27251a60ab 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -102,6 +102,6 @@ void r300_emit_dirty_state(struct r300_context* r300); void r300_emit_buffer_validate(struct r300_context *r300, boolean do_validate_vertex_buffers, - struct pipe_buffer *index_buffer); + struct pipe_resource *index_buffer); #endif /* R300_EMIT_H */ diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index ca00b043c5..40164b3ce8 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -76,17 +76,17 @@ static void r300_destroy_query(struct pipe_context* pipe, static void r300_begin_query(struct pipe_context* pipe, struct pipe_query* query) { - uint32_t* map; + uint32_t value = ~0U; struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; assert(r300->query_current == NULL); - map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, - PIPE_BUFFER_USAGE_CPU_WRITE); - map += q->offset / 4; - *map = ~0U; - pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); + pipe_buffer_write(pipe, + r300->oqbo, + q->offset, + sizeof value, + &value); q->flushed = FALSE; r300->query_current = q; @@ -110,6 +110,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_screen* r300screen = r300_screen(r300->context.screen); struct r300_query *q = (struct r300_query*)query; + struct pipe_transfer *transfer; unsigned flags = PIPE_BUFFER_USAGE_CPU_READ; uint32_t* map; uint32_t temp = 0; @@ -118,10 +119,10 @@ static boolean r300_get_query_result(struct pipe_context* pipe, if (q->flushed == FALSE) pipe->flush(pipe, 0, NULL); if (!wait) { - flags |= PIPE_BUFFER_USAGE_DONTBLOCK; + flags |= PIPE_TRANSFER_DONTBLOCK; } - map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags); + map = pipe_buffer_map(pipe, r300->oqbo, flags, &transfer); if (!map) return FALSE; map += q->offset / 4; @@ -144,7 +145,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe, temp += *map; map++; } - pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); + pipe_buffer_unmap(pipe, r300->oqbo, transfer); if (temp == ~0U) { /* Our results haven't been written yet... */ diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 971e7f3521..fa641ae8d0 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -30,18 +30,17 @@ #include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_upload_mgr.h" #include "util/u_prim.h" #include "r300_cs.h" #include "r300_context.h" +#include "r300_screen_buffer.h" #include "r300_emit.h" #include "r300_reg.h" #include "r300_render.h" #include "r300_state_derived.h" -/* r300_render: Vertex and index buffer primitive emission. */ -#define R300_MAX_VBO_SIZE (1024 * 1024) - /* XXX The DRM rejects VAP_ALT_NUM_VERTICES.. */ //#define ENABLE_ALT_NUM_VERTS @@ -123,7 +122,7 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, static boolean r300_reserve_cs_space(struct r300_context *r300, unsigned dwords) { - if (!r300->winsys->check_cs(r300->winsys, dwords)) { + if (!r300->rws->check_cs(r300->rws, dwords)) { r300->context.flush(&r300->context, 0, NULL); return TRUE; } @@ -139,7 +138,7 @@ static boolean immd_is_good_idea(struct r300_context *r300, unsigned vertex_element_count = r300->velems->count; unsigned i, vbi; - if (count > 4) { + if (count > 10) { return FALSE; } @@ -153,15 +152,15 @@ static boolean immd_is_good_idea(struct r300_context *r300, if (!checked[vbi]) { vbuf = &r300->vertex_buffer[vbi]; - if (r300->winsys->is_buffer_referenced(r300->winsys, - vbuf->buffer)) { + if (r300->context.is_resource_referenced(&r300->context, + vbuf->buffer, + 0, 0)) { /* It's a very bad idea to map it... */ return FALSE; } checked[vbi] = TRUE; } } - return TRUE; } @@ -190,6 +189,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Mapped vertex buffers. */ uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; + struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {NULL}; CS_LOCALS(r300); @@ -204,9 +204,10 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Map the buffer. */ if (!map[vbi]) { vbuf = &r300->vertex_buffer[vbi]; - map[vbi] = (uint32_t*)pipe_buffer_map(r300->context.screen, + map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, vbuf->buffer, - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_BUFFER_USAGE_CPU_READ, + &transfer[vbi]); map[vbi] += vbuf->buffer_offset / 4; stride[vbi] = vbuf->stride / 4; } @@ -249,7 +250,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, if (map[vbi]) { vbuf = &r300->vertex_buffer[vbi]; - pipe_buffer_unmap(r300->context.screen, vbuf->buffer); + pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]); map[vbi] = NULL; } } @@ -286,7 +287,7 @@ static void r300_emit_draw_arrays(struct r300_context *r300, } static void r300_emit_draw_elements(struct r300_context *r300, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, @@ -303,10 +304,9 @@ static void r300_emit_draw_elements(struct r300_context *r300, #endif CS_LOCALS(r300); - assert((start * indexSize) % 4 == 0); assert(count < (1 << 24)); - maxIndex = MIN3(maxIndex, r300->vertex_buffer_max_index, count - minIndex); + maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index); DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); @@ -345,30 +345,35 @@ static void r300_emit_draw_elements(struct r300_context *r300, OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | (0 << R300_INDX_BUFFER_SKIP_SHIFT)); OUT_CS(offset_dwords << 2); - OUT_CS_RELOC(indexBuffer, count_dwords, - RADEON_GEM_DOMAIN_GTT, 0, 0); + OUT_CS_BUF_RELOC(indexBuffer, count_dwords, + RADEON_GEM_DOMAIN_GTT, 0, 0); END_CS; } static void r300_shorten_ubyte_elts(struct r300_context* r300, - struct pipe_buffer** elts, + struct pipe_resource** elts, + unsigned start, unsigned count) { + struct pipe_context* context = &r300->context; struct pipe_screen* screen = r300->context.screen; - struct pipe_buffer* new_elts; + struct pipe_resource* new_elts; unsigned char *in_map; unsigned short *out_map; + struct pipe_transfer *src_transfer, *dst_transfer; unsigned i; - new_elts = screen->buffer_create(screen, 32, - PIPE_BUFFER_USAGE_INDEX | - PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_READ, - 2 * count); + new_elts = pipe_buffer_create(screen, 32, + PIPE_BUFFER_USAGE_INDEX | + PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_GPU_READ, + 2 * count); + + in_map = pipe_buffer_map(context, *elts, PIPE_BUFFER_USAGE_CPU_READ, &src_transfer); + out_map = pipe_buffer_map(context, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE, &dst_transfer); - in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); - out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); + in_map += start; for (i = 0; i < count; i++) { *out_map = (unsigned short)*in_map; @@ -376,15 +381,45 @@ static void r300_shorten_ubyte_elts(struct r300_context* r300, out_map++; } - pipe_buffer_unmap(screen, *elts); - pipe_buffer_unmap(screen, new_elts); + pipe_buffer_unmap(context, *elts, src_transfer); + pipe_buffer_unmap(context, new_elts, dst_transfer); + + *elts = new_elts; +} + +static void r300_align_ushort_elts(struct r300_context *r300, + struct pipe_resource **elts, + unsigned start, unsigned count) +{ + struct pipe_context* context = &r300->context; + struct pipe_transfer *in_transfer = NULL; + struct pipe_transfer *out_transfer = NULL; + struct pipe_resource* new_elts; + unsigned short *in_map; + unsigned short *out_map; + + new_elts = pipe_buffer_create(context->screen, 32, + PIPE_BUFFER_USAGE_INDEX | + PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_GPU_READ, + 2 * count); + + in_map = pipe_buffer_map(context, *elts, + PIPE_BUFFER_USAGE_CPU_READ, &in_transfer); + out_map = pipe_buffer_map(context, new_elts, + PIPE_BUFFER_USAGE_CPU_WRITE, &out_transfer); + + memcpy(out_map, in_map+start, 2 * count); + + pipe_buffer_unmap(context, *elts, in_transfer); + pipe_buffer_unmap(context, new_elts, out_transfer); *elts = new_elts; } /* This is the fast-path drawing & emission for HW TCL. */ void r300_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, @@ -393,7 +428,7 @@ void r300_draw_range_elements(struct pipe_context* pipe, unsigned count) { struct r300_context* r300 = r300_context(pipe); - struct pipe_buffer* orgIndexBuffer = indexBuffer; + struct pipe_resource* orgIndexBuffer = indexBuffer; #if defined(ENABLE_ALT_NUM_VERTS) boolean alt_num_verts = r300_screen(pipe->screen)->caps->is_r500 && count > 65536; @@ -407,18 +442,26 @@ void r300_draw_range_elements(struct pipe_context* pipe, } if (indexSize == 1) { - r300_shorten_ubyte_elts(r300, &indexBuffer, count); + r300_shorten_ubyte_elts(r300, &indexBuffer, start, count); indexSize = 2; + start = 0; + } else if (indexSize == 2 && start % 2 != 0) { + r300_align_ushort_elts(r300, &indexBuffer, start, count); + start = 0; } r300_update_derived_state(r300); + r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count); + /* 128 dwords for emit_aos and emit_draw_elements */ r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); r300_emit_buffer_validate(r300, TRUE, indexBuffer); r300_emit_dirty_state(r300); r300_emit_aos(r300, 0); + u_upload_flush(r300->upload_vb); + u_upload_flush(r300->upload_ib); if (alt_num_verts || count <= 65535) { r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); @@ -441,13 +484,13 @@ void r300_draw_range_elements(struct pipe_context* pipe, } if (indexBuffer != orgIndexBuffer) { - pipe->screen->buffer_destroy(indexBuffer); + pipe_resource_reference( &indexBuffer, NULL ); } } /* Simple helpers for context setup. Should probably be moved to util. */ void r300_draw_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { @@ -505,6 +548,7 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, } } while (count); } + u_upload_flush(r300->upload_vb); } } @@ -520,6 +564,7 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, unsigned count) { struct r300_context* r300 = r300_context(pipe); + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; int i; if (!u_trim_pipe_prim(mode, &count)) { @@ -527,9 +572,10 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, } for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe->screen, + void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_BUFFER_USAGE_CPU_READ, + &vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } @@ -545,14 +591,15 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, draw_arrays(r300->draw, mode, start, count); for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); + pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, + vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } } /* SW TCL elements, using Draw. */ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, @@ -561,6 +608,8 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, unsigned count) { struct r300_context* r300 = r300_context(pipe); + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; + struct pipe_transfer *ib_transfer; int i; void* indices; @@ -569,14 +618,15 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, } for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe->screen, + void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_TRANSFER_READ, + &vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } - indices = pipe_buffer_map(pipe->screen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + indices = pipe_buffer_map(pipe, indexBuffer, + PIPE_TRANSFER_READ, &ib_transfer); draw_set_mapped_element_buffer_range(r300->draw, indexSize, minIndex, maxIndex, indices); @@ -590,11 +640,13 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, draw_arrays(r300->draw, mode, start, count); for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); + pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, + vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } - pipe_buffer_unmap(pipe->screen, indexBuffer); + pipe_buffer_unmap(pipe, indexBuffer, + ib_transfer); draw_set_mapped_element_buffer_range(r300->draw, 0, start, start + count - 1, NULL); } @@ -613,11 +665,13 @@ struct r300_render { unsigned hwprim; /* VBO */ - struct pipe_buffer* vbo; + struct pipe_resource* vbo; size_t vbo_size; size_t vbo_offset; size_t vbo_max_used; void * vbo_ptr; + + struct pipe_transfer *vbo_transfer; }; static INLINE struct r300_render* @@ -648,13 +702,13 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, if (size + r300render->vbo_offset > r300render->vbo_size) { - pipe_buffer_reference(&r300->vbo, NULL); + pipe_resource_reference(&r300->vbo, NULL); r300render->vbo = pipe_buffer_create(screen, 64, PIPE_BUFFER_USAGE_VERTEX, - R300_MAX_VBO_SIZE); + R300_MAX_DRAW_VBO_SIZE); r300render->vbo_offset = 0; - r300render->vbo_size = R300_MAX_VBO_SIZE; + r300render->vbo_size = R300_MAX_DRAW_VBO_SIZE; } r300render->vertex_size = vertex_size; @@ -667,10 +721,11 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, static void* r300_render_map_vertices(struct vbuf_render* render) { struct r300_render* r300render = r300_render(render); - struct pipe_screen* screen = r300render->r300->context.screen; - r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo, - PIPE_BUFFER_USAGE_CPU_WRITE); + r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context, + r300render->vbo, + PIPE_BUFFER_USAGE_CPU_WRITE, + &r300render->vbo_transfer); return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset); } @@ -680,7 +735,7 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, ushort max) { struct r300_render* r300render = r300_render(render); - struct pipe_screen* screen = r300render->r300->context.screen; + struct pipe_context* context = &r300render->r300->context; CS_LOCALS(r300render->r300); BEGIN_CS(2); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); @@ -688,7 +743,7 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, r300render->vbo_max_used = MAX2(r300render->vbo_max_used, r300render->vertex_size * (max + 1)); - pipe_buffer_unmap(screen, r300render->vbo); + pipe_buffer_unmap(context, r300render->vbo, r300render->vbo_transfer); } static void r300_render_release_vertices(struct vbuf_render* render) diff --git a/src/gallium/drivers/r300/r300_render.h b/src/gallium/drivers/r300/r300_render.h index 27b5e6a963..f8fb6ec02f 100644 --- a/src/gallium/drivers/r300/r300_render.h +++ b/src/gallium/drivers/r300/r300_render.h @@ -26,7 +26,7 @@ uint32_t r300_translate_primitive(unsigned prim); void r300_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, @@ -35,7 +35,7 @@ void r300_draw_range_elements(struct pipe_context* pipe, unsigned count); void r300_draw_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count); @@ -48,7 +48,7 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, unsigned count); void r300_swtcl_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c new file mode 100644 index 0000000000..fe779ef515 --- /dev/null +++ b/src/gallium/drivers/r300/r300_resource.c @@ -0,0 +1,101 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * 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 + * THE AUTHOR(S) AND/OR THEIR 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: Dave Airlie + */ +#include <stdio.h> + +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_upload_mgr.h" +#include "util/u_math.h" + +#include "r300_context.h" +#include "r300_texture.h" +#include "r300_transfer.h" +#include "r300_screen.h" +#include "r300_state_inlines.h" +#include "r300_screen_buffer.h" + +#include "r300_winsys.h" + + + + + + + + + +static struct pipe_resource * +r300_resource_create(struct pipe_screen *screen, + const struct pipe_resource *template) +{ + if (template->target == PIPE_BUFFER) + return r300_buffer_create(screen, template); + else + return r300_resource_create(screen, template); + +} + +static struct pipe_resource * +r300_resource_from_handle(struct pipe_screen * screen, + const struct pipe_resource *template, + struct winsys_handle *whandle) +{ + if (template->target == PIPE_BUFFER) + return NULL; + else + return r300_texture_from_handle(screen, template, whandle); +} + + + +void +r300_init_resource_functions(struct r300_context *r300) +{ + r300->context.get_transfer = u_get_transfer_vtbl; + r300->context.transfer_map = u_transfer_map_vtbl; + r300->context.transfer_flush_region = u_transfer_flush_region_vtbl; + r300->context.transfer_unmap = u_transfer_unmap_vtbl; + r300->context.transfer_destroy = u_transfer_destroy_vtbl; + r300->context.transfer_inline_write = u_transfer_inline_write_vtbl; + r300->context.is_resource_referenced = u_is_resource_referenced_vtbl; +} + +void +r300_init_screen_resource_functions(struct r300_screen *r300screen) +{ + r300screen->screen.resource_create = r300_resource_create; + r300screen->screen.resource_from_handle = r300_resource_from_handle; + r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl; + r300screen->screen.resource_destroy = u_resource_destroy_vtbl; + r300screen->screen.user_buffer_create = r300_user_buffer_create; + + r300screen->screen.get_tex_surface = r300_get_tex_surface; + r300screen->screen.tex_surface_destroy = r300_tex_surface_destroy; + + r300screen->screen.video_surface_create = r300_video_surface_create; + r300screen->screen.video_surface_destroy = r300_video_surface_destroy; + +} diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 64d1909a38..c0620972f1 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -23,12 +23,10 @@ #include "util/u_format.h" #include "util/u_memory.h" -#include "util/u_simple_screen.h" #include "r300_context.h" #include "r300_texture.h" - -#include "radeon_winsys.h" +#include "r300_screen_buffer.h" #include "r300_winsys.h" /* Return the identifier behind whom the brave coders responsible for this @@ -254,15 +252,19 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, static void r300_destroy_screen(struct pipe_screen* pscreen) { struct r300_screen* r300screen = r300_screen(pscreen); + struct r300_winsys_screen *rws = r300_winsys_screen(pscreen); + + if (rws) + rws->destroy(rws); FREE(r300screen->caps); FREE(r300screen); } -struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) +struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws) { - struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen); - struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities); + struct r300_screen *r300screen = CALLOC_STRUCT(r300_screen); + struct r300_capabilities *caps = CALLOC_STRUCT(r300_capabilities); if (!r300screen || !caps) { FREE(r300screen); @@ -270,16 +272,16 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) return NULL; } - caps->pci_id = radeon_winsys->pci_id; - caps->num_frag_pipes = radeon_winsys->gb_pipes; - caps->num_z_pipes = radeon_winsys->z_pipes; + caps->pci_id = rws->get_value(rws, R300_VID_PCI_ID); + caps->num_frag_pipes = rws->get_value(rws, R300_VID_GB_PIPES); + caps->num_z_pipes = rws->get_value(rws, R300_VID_Z_PIPES); r300_init_debug(r300screen); r300_parse_chipset(caps); r300screen->caps = caps; - r300screen->radeon_winsys = radeon_winsys; - r300screen->screen.winsys = (struct pipe_winsys*)radeon_winsys; + r300screen->rws = rws; + r300screen->screen.winsys = (struct pipe_winsys*)rws; r300screen->screen.destroy = r300_destroy_screen; r300screen->screen.get_name = r300_get_name; r300screen->screen.get_vendor = r300_get_vendor; @@ -288,9 +290,13 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) r300screen->screen.is_format_supported = r300_is_format_supported; r300screen->screen.context_create = r300_create_context; - r300_init_screen_texture_functions(&r300screen->screen); - u_simple_screen_init(&r300screen->screen); + r300_init_screen_resource_functions(r300screen); return &r300screen->screen; } +struct r300_winsys_screen * +r300_winsys_screen(struct pipe_screen *screen) +{ + return r300_screen(screen)->rws; +} diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index abc1303e12..f49aae715a 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -28,15 +28,11 @@ #include "r300_chipset.h" -#define R300_TEXTURE_USAGE_TRANSFER PIPE_TEXTURE_USAGE_CUSTOM - -struct radeon_winsys; - struct r300_screen { /* Parent class */ struct pipe_screen screen; - struct radeon_winsys* radeon_winsys; + struct r300_winsys_screen *rws; /* Chipset capabilities */ struct r300_capabilities* caps; @@ -51,9 +47,6 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { return (struct r300_screen*)screen; } -/* Creates a new r300 screen. */ -struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); - /* Debug functionality. */ /** @@ -94,5 +87,7 @@ static INLINE void SCREEN_DBG(struct r300_screen * screen, unsigned flags, void r300_init_debug(struct r300_screen* ctx); +void r300_init_screen_resource_functions(struct r300_screen *r300screen); + #endif /* R300_SCREEN_H */ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c new file mode 100644 index 0000000000..1bb071d30a --- /dev/null +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -0,0 +1,369 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * 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 + * THE AUTHOR(S) AND/OR THEIR 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: Dave Airlie + */ +#include <stdio.h> + +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_upload_mgr.h" +#include "util/u_math.h" + +#include "r300_screen_buffer.h" + +#include "r300_winsys.h" + +static unsigned r300_buffer_is_referenced(struct pipe_context *context, + struct pipe_resource *buf, + unsigned face, unsigned level) +{ + struct r300_context *r300 = r300_context(context); + struct r300_buffer *rbuf = r300_buffer(buf); + + if (r300_buffer_is_user_buffer(buf)) + return PIPE_UNREFERENCED; + + if (r300->rws->is_resource_referenced(r300->rws, rbuf->buf)) + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + + return PIPE_UNREFERENCED; +} + +/* External helper, not required to implent u_resource_vtbl: + */ +int r300_upload_index_buffer(struct r300_context *r300, + struct pipe_resource **index_buffer, + unsigned index_size, + unsigned start, + unsigned count) +{ + struct pipe_resource *upload_buffer = NULL; + unsigned index_offset = start * index_size; + int ret = 0; + + if (r300_buffer_is_user_buffer(*index_buffer)) { + ret = u_upload_buffer(r300->upload_ib, + index_offset, + count * index_size, + *index_buffer, + &index_offset, + &upload_buffer); + if (ret) { + goto done; + } + *index_buffer = upload_buffer; + } + done: + // if (upload_buffer) + // pipe_resource_reference(&upload_buffer, NULL); + return ret; +} + +/* External helper, not required to implent u_resource_vtbl: + */ +int r300_upload_user_buffers(struct r300_context *r300) +{ + enum pipe_error ret = PIPE_OK; + int i, nr; + + nr = r300->vertex_buffer_count; + + for (i = 0; i < nr; i++) { + + if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) { + struct pipe_resource *upload_buffer = NULL; + unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/ + unsigned size = r300->vertex_buffer[i].buffer->width0; + unsigned upload_offset; + ret = u_upload_buffer(r300->upload_vb, + offset, size, + r300->vertex_buffer[i].buffer, + &upload_offset, &upload_buffer); + if (ret) + return ret; + + pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); + r300->vertex_buffer[i].buffer = upload_buffer; + r300->vertex_buffer[i].buffer_offset = upload_offset; + } + } + return ret; +} + +static struct r300_winsys_buffer * +r300_winsys_buffer_create(struct r300_screen *r300screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct r300_winsys_screen *rws = r300screen->rws; + struct r300_winsys_buffer *buf; + + buf = rws->buffer_create(rws, alignment, usage, size); + return buf; +} + +static void r300_winsys_buffer_destroy(struct r300_screen *r300screen, + struct r300_buffer *rbuf) +{ + struct r300_winsys_screen *rws = r300screen->rws; + + if (rbuf->buf) { + rws->buffer_reference(rws, &rbuf->buf, NULL); + rbuf->buf = NULL; + } +} + + +static void r300_buffer_destroy(struct pipe_screen *screen, + struct pipe_resource *buf) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_buffer *rbuf = r300_buffer(buf); + + r300_winsys_buffer_destroy(r300screen, rbuf); + FREE(rbuf); +} + +static void * +r300_buffer_map_range(struct pipe_screen *screen, + struct pipe_resource *buf, + unsigned offset, unsigned length, + unsigned usage ) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_winsys_screen *rws = r300screen->rws; + struct r300_buffer *rbuf = r300_buffer(buf); + void *map; + int flush = 0; + int i; + + if (rbuf->user_buffer) + return rbuf->user_buffer; + + if (rbuf->b.b.usage & PIPE_BUFFER_USAGE_CONSTANT) { + goto just_map; + } + + /* check if the mapping is to a range we already flushed */ + if (usage & PIPE_TRANSFER_DISCARD) { + for (i = 0; i < rbuf->num_ranges; i++) { + + if ((offset >= rbuf->ranges[i].start) && + (offset < rbuf->ranges[i].end)) + flush = 1; + + if (flush) { + /* unreference this hw buffer and allocate a new one */ + rws->buffer_reference(rws, &rbuf->buf, NULL); + + rbuf->num_ranges = 0; + rbuf->map = NULL; + rbuf->buf = r300_winsys_buffer_create(r300screen, + 16, + rbuf->b.b.usage, + rbuf->b.b.width0); + break; + } + } + } +just_map: + map = rws->buffer_map(rws, rbuf->buf, usage); + + return map; +} + +static void +r300_buffer_flush_mapped_range( struct pipe_screen *screen, + struct pipe_resource *buf, + unsigned offset, + unsigned length ) +{ + struct r300_buffer *rbuf = r300_buffer(buf); + int i; + + if (rbuf->user_buffer) + return; + + if (rbuf->b.b.usage & PIPE_BUFFER_USAGE_CONSTANT) + return; + + /* mark the range as used */ + for(i = 0; i < rbuf->num_ranges; ++i) { + if(offset <= rbuf->ranges[i].end && rbuf->ranges[i].start <= (offset+length)) { + rbuf->ranges[i].start = MIN2(rbuf->ranges[i].start, offset); + rbuf->ranges[i].end = MAX2(rbuf->ranges[i].end, (offset+length)); + return; + } + } + + rbuf->ranges[rbuf->num_ranges].start = offset; + rbuf->ranges[rbuf->num_ranges].end = offset+length; + rbuf->num_ranges++; +} + + +static void +r300_buffer_unmap(struct pipe_screen *screen, + struct pipe_resource *buf) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_winsys_screen *rws = r300screen->rws; + struct r300_buffer *rbuf = r300_buffer(buf); + + if (rbuf->buf) { + rws->buffer_unmap(rws, rbuf->buf); + } +} + + + + +/* As a first step, keep the original code intact, implement buffer + * transfers in terms of the old map/unmap functions. + * + * Utility functions for transfer create/destroy are hooked in and + * just record the arguments to those functions. + */ +static void * +r300_buffer_transfer_map( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + uint8_t *map = r300_buffer_map_range( pipe->screen, + transfer->resource, + transfer->box.x, + transfer->box.width, + transfer->usage ); + if (map == NULL) + return NULL; + + /* map_buffer() returned a pointer to the beginning of the buffer, + * but transfers are expected to return a pointer to just the + * region specified in the box. + */ + return map + transfer->box.x; +} + + + +static void r300_buffer_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + assert(box->x + box->width <= transfer->box.width); + + r300_buffer_flush_mapped_range(pipe->screen, + transfer->resource, + transfer->box.x + box->x, + box->width); +} + +static void r300_buffer_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + r300_buffer_unmap(pipe->screen, + transfer->resource); +} + + + + +struct u_resource_vtbl r300_buffer_vtbl = +{ + u_default_resource_get_handle, /* get_handle */ + r300_buffer_destroy, /* resource_destroy */ + r300_buffer_is_referenced, /* is_resource_referenced */ + u_default_get_transfer, /* get_transfer */ + u_default_transfer_destroy, /* transfer_destroy */ + r300_buffer_transfer_map, /* transfer_map */ + r300_buffer_transfer_flush_region, /* transfer_flush_region */ + r300_buffer_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + + +struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, + const struct pipe_resource *template) +{ + struct r300_screen *r300screen = r300_screen(screen); + struct r300_buffer *rbuf; + + rbuf = CALLOC_STRUCT(r300_buffer); + if (!rbuf) + goto error1; + + rbuf->magic = R300_BUFFER_MAGIC; + + rbuf->b.b = *template; + rbuf->b.vtbl = &r300_buffer_vtbl; + pipe_reference_init(&rbuf->b.b.reference, 1); + rbuf->b.b.screen = screen; + + rbuf->buf = r300_winsys_buffer_create(r300screen, + 16, + rbuf->b.b.usage, + rbuf->b.b.width0); + + if (!rbuf->buf) + goto error2; + + return &rbuf->b.b; +error2: + FREE(rbuf); +error1: + return NULL; +} + + +struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned usage) +{ + struct r300_buffer *rbuf; + + rbuf = CALLOC_STRUCT(r300_buffer); + if (!rbuf) + goto no_rbuf; + + rbuf->magic = R300_BUFFER_MAGIC; + + pipe_reference_init(&rbuf->b.b.reference, 1); + rbuf->b.vtbl = &r300_buffer_vtbl; + rbuf->b.b.screen = screen; + rbuf->b.b.format = PIPE_FORMAT_R8_UNORM; + rbuf->b.b.usage = usage; + rbuf->b.b.width0 = bytes; + rbuf->b.b.height0 = 1; + rbuf->b.b.depth0 = 1; + + rbuf->user_buffer = ptr; + return &rbuf->b.b; + +no_rbuf: + return NULL; +} + diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h new file mode 100644 index 0000000000..93009ea02f --- /dev/null +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -0,0 +1,106 @@ +#ifndef R300_SCREEN_BUFFER_H +#define R300_SCREEN_BUFFER_H +#include <stdio.h> +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" +#include "util/u_transfer.h" +#include "r300_screen.h" + +#include "r300_winsys.h" +#include "r300_context.h" + +#define R300_BUFFER_MAGIC 0xabcd1234 + +struct r300_buffer_range { + uint32_t start; + uint32_t end; +}; +#define R300_BUFFER_MAX_RANGES 32 + +struct r300_buffer +{ + struct u_resource b; + + uint32_t magic; + + struct r300_winsys_buffer *buf; + + void *user_buffer; + struct r300_buffer_range ranges[R300_BUFFER_MAX_RANGES]; + unsigned num_ranges; + + void *map; +}; + +static INLINE struct r300_buffer * +r300_buffer(struct pipe_resource *buffer) +{ + if (buffer) { + assert(((struct r300_buffer *)buffer)->magic == R300_BUFFER_MAGIC); + return (struct r300_buffer *)buffer; + } + return NULL; +} + +static INLINE boolean +r300_buffer_is_user_buffer(struct pipe_resource *buffer) +{ + return r300_buffer(buffer)->user_buffer ? true : false; +} + +static INLINE boolean r300_add_buffer(struct r300_winsys_screen *rws, + struct pipe_resource *buffer, + int rd, int wr) +{ + struct r300_buffer *buf = r300_buffer(buffer); + + if (!buf->buf) + return true; + + return rws->add_buffer(rws, buf->buf, rd, wr); +} + + +static INLINE boolean r300_add_texture(struct r300_winsys_screen *rws, + struct r300_texture *tex, + int rd, int wr) +{ + return rws->add_buffer(rws, tex->buffer, rd, wr); +} + + +static INLINE void r300_buffer_write_reloc(struct r300_winsys_screen *rws, + struct r300_buffer *buf, + uint32_t rd, uint32_t wd, uint32_t flags) +{ + if (!buf->buf) + return; + + rws->write_cs_reloc(rws, buf->buf, rd, wd, flags); +} + +static INLINE void r300_texture_write_reloc(struct r300_winsys_screen *rws, + struct r300_texture *texture, + uint32_t rd, uint32_t wd, uint32_t flags) +{ + rws->write_cs_reloc(rws, texture->buffer, rd, wd, flags); +} + +int r300_upload_user_buffers(struct r300_context *r300); + +int r300_upload_index_buffer(struct r300_context *r300, + struct pipe_resource **index_buffer, + unsigned index_size, + unsigned start, + unsigned count); + + +struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, + const struct pipe_resource *template); + +struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned usage); + +#endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index a732bc8d80..4759ccb5ec 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -34,11 +34,11 @@ #include "r300_context.h" #include "r300_reg.h" #include "r300_screen.h" +#include "r300_screen_buffer.h" #include "r300_state_inlines.h" #include "r300_fs.h" #include "r300_vs.h" - -#include "radeon_winsys.h" +#include "r300_winsys.h" /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ @@ -525,10 +525,10 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex = (struct r300_texture*)old_state->cbufs[i]->texture; if (tex) { - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[0], - tex->microtile != 0, - tex->macrotile != 0); + tex->microtile, + tex->macrotile); } } if (old_state->zsbuf && @@ -537,10 +537,10 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex = (struct r300_texture*)old_state->zsbuf->texture; if (tex) { - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[0], - tex->microtile != 0, - tex->macrotile != 0); + tex->microtile, + tex->macrotile); } } @@ -549,19 +549,19 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex = (struct r300_texture*)new_state->cbufs[i]->texture; level = new_state->cbufs[i]->level; - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[level], - tex->microtile != 0, - tex->mip_macrotile[level] != 0); + tex->microtile, + tex->mip_macrotile[level]); } if (new_state->zsbuf) { tex = (struct r300_texture*)new_state->zsbuf->texture; level = new_state->zsbuf->level; - r300->winsys->buffer_set_tiling(r300->winsys, tex->buffer, + r300->rws->buffer_set_tiling(r300->rws, tex->buffer, tex->pitch[level], - tex->microtile != 0, - tex->mip_macrotile[level] != 0); + tex->microtile, + tex->mip_macrotile[level]); } } @@ -714,6 +714,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, { struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state); + unsigned coord_index; /* Copy rasterizer state for Draw. */ rs->rs = *state; @@ -806,6 +807,32 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->color_control = R300_SHADE_MODEL_SMOOTH; } + /* Point sprites */ + if (state->sprite_coord_enable) { + coord_index = ffs(state->sprite_coord_enable)-1; + + SCREEN_DBG(r300screen, DBG_DRAW, + "r300: point sprite: shader coord=%d\n", coord_index); + + rs->stuffing_enable = + R300_GB_POINT_STUFF_ENABLE | + R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (coord_index*2)); + + rs->point_texcoord_left = 0.0f; + rs->point_texcoord_right = 1.0f; + + switch (state->sprite_coord_mode) { + case PIPE_SPRITE_COORD_UPPER_LEFT: + rs->point_texcoord_top = 0.0f; + rs->point_texcoord_bottom = 1.0f; + break; + case PIPE_SPRITE_COORD_LOWER_LEFT: + rs->point_texcoord_top = 1.0f; + rs->point_texcoord_bottom = 0.0f; + break; + } + } + return (void*)rs; } @@ -815,6 +842,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; boolean scissor_was_enabled = r300->scissor_enabled; + int last_sprite_coord_index = r300->sprite_coord_index; if (r300->draw) { draw_flush(r300->draw); @@ -824,17 +852,22 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; r300->scissor_enabled = rs->rs.scissor; + r300->sprite_coord_index = ffs(rs->rs.sprite_coord_enable)-1; } else { r300->polygon_offset_enabled = FALSE; r300->scissor_enabled = FALSE; + r300->sprite_coord_index = -1; } UPDATE_STATE(state, r300->rs_state); - r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0); + r300->rs_state.size = 24 + (r300->polygon_offset_enabled ? 5 : 0); if (scissor_was_enabled != r300->scissor_enabled) { r300->scissor_state.dirty = TRUE; } + if (last_sprite_coord_index != r300->sprite_coord_index) { + r300->rs_block_state.dirty = TRUE; + } } /* Free rasterizer state. */ @@ -937,6 +970,9 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, struct pipe_sampler_view** views) { struct r300_context* r300 = r300_context(pipe); + struct r300_textures_state* state = + (struct r300_textures_state*)r300->textures_state.state; + struct r300_texture *texture; unsigned i; boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; boolean dirty_tex = FALSE; @@ -947,16 +983,19 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, } for (i = 0; i < count; i++) { - if (r300->fragment_sampler_views[i] != views[i]) { - struct r300_texture *texture; + if (state->fragment_sampler_views[i] != views[i]) { + pipe_sampler_view_reference(&state->fragment_sampler_views[i], + views[i]); - pipe_sampler_view_reference(&r300->fragment_sampler_views[i], - views[i]); + if (!views[i]) { + continue; + } + + /* A new sampler view (= texture)... */ dirty_tex = TRUE; + /* R300-specific - set the texrect factor in the fragment shader */ texture = (struct r300_texture *)views[i]->texture; - - /* R300-specific - set the texrect factor in a fragment shader */ if (!is_r500 && texture->is_npot) { /* XXX It would be nice to re-emit just 1 constant, * XXX not all of them */ @@ -966,13 +1005,13 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, } for (i = count; i < 8; i++) { - if (r300->fragment_sampler_views[i]) { - pipe_sampler_view_reference(&r300->fragment_sampler_views[i], - NULL); + if (state->fragment_sampler_views[i]) { + pipe_sampler_view_reference(&state->fragment_sampler_views[i], + NULL); } } - r300->fragment_sampler_view_count = count; + state->texture_count = count; r300->textures_state.dirty = TRUE; @@ -983,29 +1022,27 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, static struct pipe_sampler_view * r300_create_sampler_view(struct pipe_context *pipe, - struct pipe_texture *texture, + struct pipe_resource *texture, const struct pipe_sampler_view *templ) { - struct r300_context *r300 = r300_context(pipe); struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); if (view) { *view = *templ; view->reference.count = 1; view->texture = NULL; - pipe_texture_reference(&view->texture, texture); + pipe_resource_reference(&view->texture, texture); view->context = pipe; } return view; } - static void r300_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { - pipe_texture_reference(&view->texture, NULL); + pipe_resource_reference(&view->texture, NULL); FREE(view); } @@ -1070,17 +1107,66 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); + struct pipe_vertex_buffer *vbo; unsigned i, max_index = (1 << 24) - 1; + boolean any_user_buffer = FALSE; - memcpy(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count); + if (count == r300->vertex_buffer_count && + memcmp(r300->vertex_buffer, buffers, + sizeof(struct pipe_vertex_buffer) * count) == 0) { + return; + } + + /* Check if the stride is aligned to the size of DWORD. */ + for (i = 0; i < count; i++) { + if (buffers[i].buffer) { + if (buffers[i].stride % 4 != 0) { + // XXX Shouldn't we align the buffer? + fprintf(stderr, "r300_set_vertex_buffers: " + "Unaligned buffer stride %i isn't supported.\n", + buffers[i].stride); + assert(0); + abort(); + } + } + } for (i = 0; i < count; i++) { - max_index = MIN2(buffers[i].max_index, max_index); + /* Why, yes, I AM casting away constness. How did you know? */ + vbo = (struct pipe_vertex_buffer*)&buffers[i]; + + /* Reference our buffer. */ + pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); + + /* Skip NULL buffers */ + if (!buffers[i].buffer) { + continue; + } + + if (r300_buffer_is_user_buffer(vbo->buffer)) { + any_user_buffer = TRUE; + } + + if (vbo->max_index == ~0) { + /* Bogus value from broken state tracker; hax it. */ + vbo->max_index = + (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; + } + + max_index = MIN2(vbo->max_index, max_index); + } + + for (; i < r300->vertex_buffer_count; i++) { + /* Dereference any old buffers. */ + pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); } + memcpy(r300->vertex_buffer, buffers, + sizeof(struct pipe_vertex_buffer) * count); + r300->vertex_buffer_count = count; r300->vertex_buffer_max_index = max_index; + r300->any_user_vbs = any_user_buffer; if (r300->draw) { draw_flush(r300->draw); @@ -1088,22 +1174,6 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, } } -static boolean r300_validate_aos(struct r300_context *r300) -{ - struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->velems->velem; - int i; - - /* Check if formats and strides are aligned to the size of DWORD. */ - for (i = 0; i < r300->velems->count; i++) { - if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || - util_format_get_blocksize(velem[i].src_format) % 4 != 0) { - return FALSE; - } - } - return TRUE; -} - static void r300_draw_emit_attrib(struct r300_context* r300, enum attrib_emit emit, enum interp_mode interp, @@ -1273,6 +1343,7 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, struct r300_context *r300 = r300_context(pipe); struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_vertex_element_state *velems; + unsigned i, size; assert(count <= PIPE_MAX_ATTRIBS); velems = CALLOC_STRUCT(r300_vertex_element_state); @@ -1281,6 +1352,20 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); if (r300screen->caps->has_tcl) { + /* Check if the format is aligned to the size of DWORD. */ + for (i = 0; i < count; i++) { + size = util_format_get_blocksize(attribs[i].src_format); + + if (size % 4 != 0) { + /* XXX Shouldn't we align the format? */ + fprintf(stderr, "r300_create_vertex_elements_state: " + "Unaligned format %s:%i isn't supported\n", + util_format_name(attribs[i].src_format), size); + assert(0); + abort(); + } + } + r300_vertex_psc(velems); } else { memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); @@ -1309,12 +1394,6 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, draw_set_vertex_elements(r300->draw, velems->count, velems->velem); } - if (!r300_validate_aos(r300)) { - /* XXX We should fallback using draw. */ - assert(0); - abort(); - } - UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2; } @@ -1398,21 +1477,22 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) static void r300_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_resource *buf) { struct r300_context* r300 = r300_context(pipe); struct r300_screen *r300screen = r300_screen(pipe->screen); + struct pipe_transfer *tr; void *mapped; int max_size = 0; - if (buf == NULL || buf->size == 0 || - (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL) + if (buf == NULL || buf->width0 == 0 || + (mapped = pipe_buffer_map(pipe, buf, PIPE_BUFFER_USAGE_CPU_READ, &tr)) == NULL) { r300->shader_constants[shader].count = 0; return; } - assert((buf->size % 4 * sizeof(float)) == 0); + assert((buf->width0 % 4 * sizeof(float)) == 0); /* Check the size of the constant buffer. */ switch (shader) { @@ -1434,15 +1514,15 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, } /* XXX Subtract immediates and RC_STATE_* variables. */ - if (buf->size > (sizeof(float) * 4 * max_size)) { + if (buf->width0 > (sizeof(float) * 4 * max_size)) { debug_printf("r300: Max size of the constant buffer is " "%i*4 floats.\n", max_size); abort(); } - memcpy(r300->shader_constants[shader].constants, mapped, buf->size); - r300->shader_constants[shader].count = buf->size / (4 * sizeof(float)); - pipe_buffer_unmap(pipe->screen, buf); + memcpy(r300->shader_constants[shader].constants, mapped, buf->width0); + r300->shader_constants[shader].count = buf->width0 / (4 * sizeof(float)); + pipe_buffer_unmap(pipe, buf, tr); if (shader == PIPE_SHADER_VERTEX) { if (r300screen->caps->has_tcl) { diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 6b9f61acd7..b979a4c269 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -178,7 +178,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize texture coordinates. */ for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { + if (vs_outputs->generic[i] != ATTR_UNUSED || + r300->sprite_coord_index == i) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ rX00_rs_tex(&rs, tex_count, tex_count, FALSE); @@ -186,6 +187,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->generic[i] != ATTR_UNUSED) { rX00_rs_tex_write(&rs, tex_count, fp_offset); + if (r300->sprite_coord_index == i) + debug_printf("r300: SpriteCoord (generic index %i) is being written to reg %i\n", i, fp_offset); fp_offset++; } tex_count++; @@ -332,20 +335,25 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) (struct r300_textures_state*)r300->textures_state.state; struct r300_texture_sampler_state *texstate; struct r300_sampler_state *sampler; + struct pipe_sampler_view *view; struct r300_texture *tex; unsigned min_level, max_level, i, size; unsigned count = MIN2(state->texture_count, state->sampler_count); state->tx_enable = 0; + state->count = 0; size = 2; for (i = 0; i < count; i++) { - if (state->textures[i] && state->sampler_states[i]) { + if (state->fragment_sampler_views[i] && state->sampler_states[i]) { state->tx_enable |= 1 << i; - tex = state->textures[i]; + view = state->fragment_sampler_views[i]; + tex = (struct r300_texture *)view->texture; sampler = state->sampler_states[i]; + assert(view->format == tex->b.b.format); + texstate = &state->regs[i]; memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3); texstate->filter[0] = sampler->filter0; @@ -355,7 +363,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) R300_TXO_MICRO_TILE(tex->microtile); /* to emulate 1D textures through 2D ones correctly */ - if (tex->tex.target == PIPE_TEXTURE_1D) { + if (tex->b.b.target == PIPE_TEXTURE_1D) { texstate->filter[0] &= ~R300_TX_WRAP_T_MASK; texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } @@ -367,8 +375,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } else { /* determine min/max levels */ /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN2(sampler->max_lod, tex->tex.last_level); - min_level = MIN2(sampler->min_lod, max_level); + max_level = MIN3(sampler->max_lod + view->first_level, + tex->b.b.last_level, view->last_level); + min_level = MIN2(sampler->min_lod + view->first_level, + max_level); texstate->format[0] |= R300_TX_NUM_LEVELS(max_level); texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level); } diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index 4a2c68269b..2d9a63d29a 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -44,13 +44,9 @@ void r300_emit_invariant_state(struct r300_context* r300, struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(14 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(12 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ - /* Various GB enables */ - OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | - R300_GB_LINE_STUFF_ENABLE | - R300_GB_TRIANGLE_STUFF_ENABLE); /* Subpixel multisampling for AA * These are commented out because glisse's CS checker doesn't like them. * I presume these will be re-enabled later. @@ -78,7 +74,7 @@ void r300_emit_invariant_state(struct r300_context* r300, END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + + BEGIN_CS(40 + (caps->has_tcl ? 7 : 0) + (caps->family >= CHIP_FAMILY_RV350 ? 4 : 0)); if (caps->has_tcl) { @@ -90,11 +86,6 @@ void r300_emit_invariant_state(struct r300_context* r300, OUT_CS_32F(1.0); OUT_CS_32F(1.0); } - /* XXX point tex stuffing */ - OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1); - OUT_CS_32F(0.0); - OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1); - OUT_CS_32F(1.0); /* XXX line tex stuffing */ OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1); OUT_CS_32F(0.0); diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 04124afd4d..f4040b2431 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -29,10 +29,10 @@ #include "r300_context.h" #include "r300_texture.h" +#include "r300_transfer.h" #include "r300_screen.h" #include "r300_state_inlines.h" - -#include "radeon_winsys.h" +#include "r300_winsys.h" #define TILE_WIDTH 0 #define TILE_HEIGHT 1 @@ -46,6 +46,18 @@ static const unsigned microblock_table[5][3][2] = { {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ }; +/* Return true for non-compressed and non-YUV formats. */ +static boolean r300_format_is_plain(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + if (!format) { + return FALSE; + } + + return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN; +} + /* Translate a pipe_format into a useful texture format for sampling. * * Some special formats are translated directly using R300_EASY_TX_FORMAT, @@ -302,7 +314,6 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return R300_COLOR_FORMAT_I8; @@ -311,24 +322,19 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_B5G6R5_UNORM: return R300_COLOR_FORMAT_RGB565; case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B5G5R5X1_UNORM: return R300_COLOR_FORMAT_ARGB1555; case PIPE_FORMAT_B4G4R4A4_UNORM: return R300_COLOR_FORMAT_ARGB4444; /* 32-bit buffers. */ case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8A8_SRGB: case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_B8G8R8X8_SRGB: case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_A8R8G8B8_SRGB: case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_SRGB: case PIPE_FORMAT_A8B8G8R8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: - case PIPE_FORMAT_A8B8G8R8_SRGB: case PIPE_FORMAT_X8B8G8R8_UNORM: - case PIPE_FORMAT_X8B8G8R8_SRGB: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: return R300_COLOR_FORMAT_ARGB8888; case PIPE_FORMAT_R10G10B10A2_UNORM: @@ -393,12 +399,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) desc = util_format_description(format); /* Specifies how the shader output is written to the fog unit. */ - if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { - /* The gamma correction causes precision loss so we need - * higher precision to maintain reasonable quality. - * It has nothing to do with the colorbuffer format. */ - modifier |= R300_US_OUT_FMT_C4_10_GAMMA; - } else if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { + if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { if (desc->channel[0].size == 32) { modifier |= R300_US_OUT_FMT_C4_32_FP; } else { @@ -428,46 +429,39 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) return modifier | R300_C2_SEL_A; case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return modifier | R300_C2_SEL_R; - /* ARGB 32-bit outputs. */ + /* BGRA outputs. */ case PIPE_FORMAT_B5G6R5_UNORM: case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B4G4R4A4_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8A8_SRGB: case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_B8G8R8X8_SRGB: return modifier | R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A; - /* BGRA 32-bit outputs. */ + /* ARGB outputs. */ case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_A8R8G8B8_SRGB: case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_SRGB: return modifier | R300_C0_SEL_A | R300_C1_SEL_R | R300_C2_SEL_G | R300_C3_SEL_B; - /* RGBA 32-bit outputs. */ + /* ABGR outputs. */ case PIPE_FORMAT_A8B8G8R8_UNORM: - case PIPE_FORMAT_R8G8B8A8_SNORM: - case PIPE_FORMAT_A8B8G8R8_SRGB: case PIPE_FORMAT_X8B8G8R8_UNORM: - case PIPE_FORMAT_X8B8G8R8_SRGB: return modifier | R300_C0_SEL_A | R300_C1_SEL_B | R300_C2_SEL_G | R300_C3_SEL_R; - /* ABGR 32-bit outputs. */ + /* RGBA outputs. */ + case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: case PIPE_FORMAT_R10G10B10A2_UNORM: - /* RGBA high precision outputs (same swizzles as ABGR low precision) */ case PIPE_FORMAT_R16G16B16A16_UNORM: case PIPE_FORMAT_R16G16B16A16_SNORM: //case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */ @@ -500,7 +494,7 @@ boolean r300_is_sampler_format_supported(enum pipe_format format) static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) { struct r300_texture_format_state* state = &tex->state; - struct pipe_texture *pt = &tex->tex; + struct pipe_resource *pt = &tex->b.b; unsigned i; boolean is_r500 = screen->caps->is_r500; @@ -540,28 +534,28 @@ static void r300_setup_texture_state(struct r300_screen* screen, struct r300_tex pt->width0, pt->height0, pt->last_level); /* Set framebuffer state. */ - if (util_format_is_depth_or_stencil(tex->tex.format)) { - for (i = 0; i <= tex->tex.last_level; i++) { + if (util_format_is_depth_or_stencil(tex->b.b.format)) { + for (i = 0; i <= tex->b.b.last_level; i++) { tex->fb_state.depthpitch[i] = tex->pitch[i] | R300_DEPTHMACROTILE(tex->mip_macrotile[i]) | R300_DEPTHMICROTILE(tex->microtile); } - tex->fb_state.zb_format = r300_translate_zsformat(tex->tex.format); + tex->fb_state.zb_format = r300_translate_zsformat(tex->b.b.format); } else { - for (i = 0; i <= tex->tex.last_level; i++) { + for (i = 0; i <= tex->b.b.last_level; i++) { tex->fb_state.colorpitch[i] = tex->pitch[i] | - r300_translate_colorformat(tex->tex.format) | + r300_translate_colorformat(tex->b.b.format) | R300_COLOR_TILE(tex->mip_macrotile[i]) | R300_COLOR_MICROTILE(tex->microtile); } - tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->tex.format); + tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->b.b.format); } } void r300_texture_reinterpret_format(struct pipe_screen *screen, - struct pipe_texture *tex, + struct pipe_resource *tex, enum pipe_format new_format) { struct r300_screen *r300screen = r300_screen(screen); @@ -579,7 +573,7 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, { unsigned offset = tex->offset[level]; - switch (tex->tex.target) { + switch (tex->b.b.target) { case PIPE_TEXTURE_3D: assert(face == 0); return offset + zslice * tex->layer_size[level]; @@ -603,7 +597,7 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex, { unsigned pixsize, tile_size; - pixsize = util_format_get_blocksize(tex->tex.format); + pixsize = util_format_get_blocksize(tex->b.b.format); tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim]; if (macrotile) { @@ -624,9 +618,9 @@ static boolean r300_texture_macro_switch(struct r300_texture *tex, tile = r300_texture_get_tile_size(tex, dim, TRUE); if (dim == TILE_WIDTH) { - texdim = u_minify(tex->tex.width0, level); + texdim = u_minify(tex->b.b.width0, level); } else { - texdim = u_minify(tex->tex.height0, level); + texdim = u_minify(tex->b.b.height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ @@ -650,22 +644,22 @@ unsigned r300_texture_get_stride(struct r300_screen* screen, return tex->stride_override; /* Check the level. */ - if (level > tex->tex.last_level) { + if (level > tex->b.b.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", - __FUNCTION__, level, tex->tex.last_level); + __FUNCTION__, level, tex->b.b.last_level); return 0; } - width = u_minify(tex->tex.width0, level); + width = u_minify(tex->b.b.width0, level); - if (!util_format_is_compressed(tex->tex.format)) { + if (r300_format_is_plain(tex->b.b.format)) { tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, tex->mip_macrotile[level]); width = align(width, tile_width); - return util_format_get_stride(tex->tex.format, width); + return util_format_get_stride(tex->b.b.format, width); } else { - return align(util_format_get_stride(tex->tex.format, width), 32); + return align(util_format_get_stride(tex->b.b.format, width), 32); } } @@ -674,21 +668,21 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, { unsigned height, tile_height; - height = u_minify(tex->tex.height0, level); + height = u_minify(tex->b.b.height0, level); - if (!util_format_is_compressed(tex->tex.format)) { + if (r300_format_is_plain(tex->b.b.format)) { tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT, tex->mip_macrotile[level]); height = align(height, tile_height); } - return util_format_get_nblocksy(tex->tex.format, height); + return util_format_get_nblocksy(tex->b.b.format, height); } static void r300_setup_miptree(struct r300_screen* screen, struct r300_texture* tex) { - struct pipe_texture* base = &tex->tex; + struct pipe_resource* base = &tex->b.b; unsigned stride, size, layer_size, nblocksy, i; boolean rv350_mode = screen->caps->family >= CHIP_FAMILY_RV350; @@ -726,22 +720,23 @@ static void r300_setup_miptree(struct r300_screen* screen, static void r300_setup_flags(struct r300_texture* tex) { - tex->is_npot = !util_is_power_of_two(tex->tex.width0) || - !util_is_power_of_two(tex->tex.height0); + tex->is_npot = !util_is_power_of_two(tex->b.b.width0) || + !util_is_power_of_two(tex->b.b.height0); } static void r300_setup_tiling(struct pipe_screen *screen, struct r300_texture *tex) { - enum pipe_format format = tex->tex.format; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; + enum pipe_format format = tex->b.b.format; boolean rv350_mode = r300_screen(screen)->caps->family >= CHIP_FAMILY_RV350; - if (util_format_is_compressed(format)) { + if (!r300_format_is_plain(format)) { return; } - if (tex->tex.width0 == 1 || - tex->tex.height0 == 1) { + if (tex->b.b.width0 == 1 || + tex->b.b.height0 == 1) { return; } @@ -752,12 +747,12 @@ static void r300_setup_tiling(struct pipe_screen *screen, tex->microtile = R300_BUFFER_TILED; break; - /* XXX Square-tiling doesn't work with kernel older than 2.6.34, - * XXX need to check the DRM version */ - /*case 2: + case 2: case 8: - tex->microtile = R300_BUFFER_SQUARETILED; - break;*/ + if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { + tex->microtile = R300_BUFFER_SQUARETILED; + } + break; } /* Set macrotiling. */ @@ -767,21 +762,86 @@ static void r300_setup_tiling(struct pipe_screen *screen, } } + +static unsigned r300_texture_is_referenced(struct pipe_context *context, + struct pipe_resource *texture, + unsigned face, unsigned level) +{ + struct r300_context *r300 = r300_context(context); + struct r300_texture *rtex = (struct r300_texture *)texture; + + if (r300->rws->is_resource_referenced(r300->rws, rtex->buffer)) + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + + return PIPE_UNREFERENCED; +} + +static void r300_texture_destroy(struct pipe_screen *screen, + struct pipe_resource* texture) +{ + struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; + + rws->buffer_reference(rws, &tex->buffer, NULL); + FREE(tex); +} + + + + +static boolean + r300_texture_get_handle(struct pipe_screen* screen, + struct pipe_resource *texture, + struct winsys_handle *whandle) +{ + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; + struct r300_texture* tex = (struct r300_texture*)texture; + unsigned stride; + + if (!tex) { + return FALSE; + } + + stride = r300_texture_get_stride(r300_screen(screen), tex, 0); + + rws->buffer_get_handle(rws, tex->buffer, stride, whandle); + + return TRUE; +} + + + +struct u_resource_vtbl r300_texture_vtbl = +{ + r300_texture_get_handle, /* get_handle */ + r300_texture_destroy, /* resource_destroy */ + r300_texture_is_referenced, /* is_resource_referenced */ + r300_texture_get_transfer, /* get_transfer */ + r300_texture_transfer_destroy, /* transfer_destroy */ + r300_texture_transfer_map, /* transfer_map */ + u_default_transfer_flush_region, /* transfer_flush_region */ + r300_texture_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + /* Create a new texture. */ -static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, - const struct pipe_texture* template) +struct pipe_resource* r300_texture_create(struct pipe_screen* screen, + const struct pipe_resource* template) { struct r300_texture* tex = CALLOC_STRUCT(r300_texture); struct r300_screen* rscreen = r300_screen(screen); - struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; if (!tex) { return NULL; } - tex->tex = *template; - pipe_reference_init(&tex->tex.reference, 1); - tex->tex.screen = screen; + tex->b.b = *template; + tex->b.vtbl = &r300_texture_vtbl; + pipe_reference_init(&tex->b.b.reference, 1); + tex->b.b.screen = screen; r300_setup_flags(tex); if (!(template->tex_usage & R300_TEXTURE_USAGE_TRANSFER)) { @@ -790,37 +850,32 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, r300_setup_miptree(rscreen, tex); r300_setup_texture_state(rscreen, tex); - tex->buffer = screen->buffer_create(screen, 2048, - PIPE_BUFFER_USAGE_PIXEL, - tex->size); - winsys->buffer_set_tiling(winsys, tex->buffer, - tex->pitch[0], - tex->microtile != R300_BUFFER_LINEAR, - tex->macrotile != R300_BUFFER_LINEAR); + tex->buffer = rws->buffer_create(rws, 2048, + PIPE_BUFFER_USAGE_PIXEL, + tex->size); + rws->buffer_set_tiling(rws, tex->buffer, + tex->pitch[0], + tex->microtile, + tex->macrotile); if (!tex->buffer) { FREE(tex); return NULL; } - return (struct pipe_texture*)tex; + return (struct pipe_resource*)tex; } -static void r300_texture_destroy(struct pipe_texture* texture) -{ - struct r300_texture* tex = (struct r300_texture*)texture; - pipe_buffer_reference(&tex->buffer, NULL); - FREE(tex); -} - -static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, - struct pipe_texture* texture, - unsigned face, - unsigned level, - unsigned zslice, - unsigned flags) +/* Not required to implement u_resource_vtbl, consider moving to another file: + */ +struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, + struct pipe_resource* texture, + unsigned face, + unsigned level, + unsigned zslice, + unsigned flags) { struct r300_texture* tex = (struct r300_texture*)texture; struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface); @@ -830,7 +885,7 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, if (surface) { pipe_reference_init(&surface->reference, 1); - pipe_texture_reference(&surface->texture, texture); + pipe_resource_reference(&surface->texture, texture); surface->format = texture->format; surface->width = u_minify(texture->width0, level); surface->height = u_minify(texture->height0, level); @@ -845,21 +900,22 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, return surface; } -static void r300_tex_surface_destroy(struct pipe_surface* s) +/* Not required to implement u_resource_vtbl, consider moving to another file: + */ +void r300_tex_surface_destroy(struct pipe_surface* s) { - pipe_texture_reference(&s->texture, NULL); + pipe_resource_reference(&s->texture, NULL); FREE(s); } - -static struct pipe_texture* - r300_texture_from_handle(struct pipe_screen* screen, - const struct pipe_texture* base, - struct winsys_handle *whandle) +struct pipe_resource* +r300_texture_from_handle(struct pipe_screen* screen, + const struct pipe_resource* base, + struct winsys_handle *whandle) { - struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; + struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; struct r300_screen* rscreen = r300_screen(screen); - struct pipe_buffer *buffer; + struct r300_winsys_buffer *buffer; struct r300_texture* tex; unsigned stride; @@ -870,7 +926,7 @@ static struct pipe_texture* return NULL; } - buffer = winsys->buffer_from_handle(winsys, screen, whandle, &stride); + buffer = rws->buffer_from_handle(rws, screen, whandle, &stride); if (!buffer) { return NULL; } @@ -880,9 +936,9 @@ static struct pipe_texture* return NULL; } - tex->tex = *base; - pipe_reference_init(&tex->tex.reference, 1); - tex->tex.screen = screen; + tex->b.b = *base; + pipe_reference_init(&tex->b.b.reference, 1); + tex->b.b.screen = screen; tex->stride_override = stride; tex->pitch[0] = stride / util_format_get_blocksize(base->format); @@ -893,36 +949,19 @@ static struct pipe_texture* /* one ref already taken */ tex->buffer = buffer; - return (struct pipe_texture*)tex; + return (struct pipe_resource*)tex; } -static boolean - r300_texture_get_handle(struct pipe_screen* screen, - struct pipe_texture *texture, - struct winsys_handle *whandle) -{ - struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; - struct r300_texture* tex = (struct r300_texture*)texture; - unsigned stride; - if (!tex) { - return FALSE; - } - stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - - winsys->buffer_get_handle(winsys, tex->buffer, stride, whandle); - - return TRUE; -} -static struct pipe_video_surface * +struct pipe_video_surface * r300_video_surface_create(struct pipe_screen *screen, enum pipe_video_chroma_format chroma_format, unsigned width, unsigned height) { struct r300_video_surface *r300_vsfc; - struct pipe_texture template; + struct pipe_resource template; assert(screen); assert(width && height); @@ -937,7 +976,7 @@ r300_video_surface_create(struct pipe_screen *screen, r300_vsfc->base.width = width; r300_vsfc->base.height = height; - memset(&template, 0, sizeof(struct pipe_texture)); + memset(&template, 0, sizeof template); template.target = PIPE_TEXTURE_2D; template.format = PIPE_FORMAT_B8G8R8X8_UNORM; template.last_level = 0; @@ -947,7 +986,7 @@ r300_video_surface_create(struct pipe_screen *screen, template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET; - r300_vsfc->tex = screen->texture_create(screen, &template); + r300_vsfc->tex = screen->resource_create(screen, &template); if (!r300_vsfc->tex) { FREE(r300_vsfc); @@ -957,23 +996,9 @@ r300_video_surface_create(struct pipe_screen *screen, return &r300_vsfc->base; } -static void r300_video_surface_destroy(struct pipe_video_surface *vsfc) +void r300_video_surface_destroy(struct pipe_video_surface *vsfc) { struct r300_video_surface *r300_vsfc = r300_video_surface(vsfc); - pipe_texture_reference(&r300_vsfc->tex, NULL); + pipe_resource_reference(&r300_vsfc->tex, NULL); FREE(r300_vsfc); } - -void r300_init_screen_texture_functions(struct pipe_screen* screen) -{ - screen->texture_create = r300_texture_create; - screen->texture_from_handle = r300_texture_from_handle; - screen->texture_get_handle = r300_texture_get_handle; - screen->texture_destroy = r300_texture_destroy; - screen->get_tex_surface = r300_get_tex_surface; - screen->tex_surface_destroy = r300_tex_surface_destroy; - - screen->video_surface_create = r300_video_surface_create; - screen->video_surface_destroy= r300_video_surface_destroy; -} - diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 138b62784e..e33b1c29ec 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -30,8 +30,6 @@ struct r300_texture; -void r300_init_screen_texture_functions(struct pipe_screen* screen); - unsigned r300_texture_get_stride(struct r300_screen* screen, struct r300_texture* tex, unsigned level); @@ -39,7 +37,7 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, unsigned zslice, unsigned face); void r300_texture_reinterpret_format(struct pipe_screen *screen, - struct pipe_texture *tex, + struct pipe_resource *tex, enum pipe_format new_format); boolean r300_is_colorbuffer_format_supported(enum pipe_format format); @@ -51,7 +49,7 @@ boolean r300_is_sampler_format_supported(enum pipe_format format); struct r300_video_surface { struct pipe_video_surface base; - struct pipe_texture *tex; + struct pipe_resource *tex; }; static INLINE struct r300_video_surface * @@ -60,11 +58,32 @@ r300_video_surface(struct pipe_video_surface *pvs) return (struct r300_video_surface *)pvs; } -/* Used internally for texture_is_referenced() - */ -boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture* texture, - struct pipe_buffer** buffer, - unsigned* stride); + + +struct pipe_resource* +r300_texture_from_handle(struct pipe_screen* screen, + const struct pipe_resource* base, + struct winsys_handle *whandle); + +struct pipe_resource* +r300_texture_create(struct pipe_screen* screen, + const struct pipe_resource* template); + +struct pipe_video_surface * +r300_video_surface_create(struct pipe_screen *screen, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height); + +void r300_video_surface_destroy(struct pipe_video_surface *vsfc); + + +struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, + struct pipe_resource* texture, + unsigned face, + unsigned level, + unsigned zslice, + unsigned flags); + +void r300_tex_surface_destroy(struct pipe_surface* s); #endif /* R300_TEXTURE_H */ diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 2b1a40bd8d..e3b6f04a09 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -26,6 +26,8 @@ #include "r300_texture.h" #include "r300_screen.h" +#include "r300_winsys.h" + #include "util/u_memory.h" #include "util/u_format.h" @@ -36,9 +38,6 @@ struct r300_transfer { /* Pipe context. */ struct pipe_context *ctx; - /* Parameters of get_transfer. */ - unsigned x, y, level, zslice, face; - /* Offset from start of buffer. */ unsigned offset; @@ -46,7 +45,7 @@ struct r300_transfer { struct r300_texture *detiled_texture; /* Transfer and format flags. */ - unsigned buffer_usage, render_target_usage; + unsigned render_target_usage; }; /* Convenience cast wrapper. */ @@ -62,22 +61,24 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, { struct pipe_screen *screen = ctx->screen; struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; - struct pipe_texture *tex = transfer->texture; + struct pipe_resource *tex = transfer->resource; struct pipe_surface *src, *dst; - src = screen->get_tex_surface(screen, tex, r300transfer->face, - r300transfer->level, r300transfer->zslice, + src = screen->get_tex_surface(screen, tex, + transfer->sr.face, + transfer->sr.level, + transfer->box.z, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_PIXEL); - dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE | - PIPE_BUFFER_USAGE_PIXEL | - r300transfer->buffer_usage); + PIPE_BUFFER_USAGE_PIXEL); - ctx->surface_copy(ctx, dst, 0, 0, src, r300transfer->x, r300transfer->y, - transfer->width, transfer->height); + ctx->surface_copy(ctx, dst, 0, 0, src, + transfer->box.x, transfer->box.y, + transfer->box.width, transfer->box.height); pipe_surface_reference(&src, NULL); pipe_surface_reference(&dst, NULL); @@ -89,16 +90,18 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, { struct pipe_screen *screen = ctx->screen; struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; - struct pipe_texture *tex = transfer->texture; + struct pipe_resource *tex = transfer->resource; struct pipe_surface *src, *dst; - src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_PIXEL); - dst = screen->get_tex_surface(screen, tex, r300transfer->face, - r300transfer->level, r300transfer->zslice, + dst = screen->get_tex_surface(screen, tex, + transfer->sr.face, + transfer->sr.level, + transfer->box.z, PIPE_BUFFER_USAGE_GPU_WRITE | PIPE_BUFFER_USAGE_PIXEL); @@ -107,8 +110,10 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, * Reproducible with perf/copytex. */ ctx->flush(ctx, 0, NULL); - ctx->surface_copy(ctx, dst, r300transfer->x, r300transfer->y, src, 0, 0, - transfer->width, transfer->height); + ctx->surface_copy(ctx, dst, + transfer->box.x, transfer->box.y, + src, 0, 0, + transfer->box.width, transfer->box.height); /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */ ctx->flush(ctx, 0, NULL); @@ -117,36 +122,30 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, pipe_surface_reference(&dst, NULL); } -static struct pipe_transfer* -r300_get_transfer(struct pipe_context *ctx, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, unsigned x, unsigned y, - unsigned w, unsigned h) +struct pipe_transfer* +r300_texture_get_transfer(struct pipe_context *ctx, + struct pipe_resource *texture, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) { struct r300_texture *tex = (struct r300_texture *)texture; struct r300_screen *r300screen = r300_screen(ctx->screen); struct r300_transfer *trans; - struct pipe_texture template; + struct pipe_resource template; trans = CALLOC_STRUCT(r300_transfer); if (trans) { /* Initialize the transfer object. */ - pipe_texture_reference(&trans->transfer.texture, texture); + pipe_resource_reference(&trans->transfer.resource, texture); + trans->transfer.sr = sr; trans->transfer.usage = usage; - trans->transfer.width = w; - trans->transfer.height = h; + trans->transfer.box = *box; trans->ctx = ctx; - trans->x = x; - trans->y = y; - trans->level = level; - trans->zslice = zslice; - trans->face = face; /* If the texture is tiled, we must create a temporary detiled texture * for this transfer. */ if (tex->microtile || tex->macrotile) { - trans->buffer_usage = pipe_transfer_buffer_flags(&trans->transfer); trans->render_target_usage = util_format_is_depth_or_stencil(texture->format) ? PIPE_TEXTURE_USAGE_DEPTH_STENCIL : @@ -154,8 +153,8 @@ r300_get_transfer(struct pipe_context *ctx, template.target = PIPE_TEXTURE_2D; template.format = texture->format; - template.width0 = w; - template.height0 = h; + template.width0 = box->width; + template.height0 = box->height; template.depth0 = 0; template.last_level = 0; template.nr_samples = 0; @@ -175,14 +174,19 @@ r300_get_transfer(struct pipe_context *ctx, /* Create the temporary texture. */ trans->detiled_texture = (struct r300_texture*) - ctx->screen->texture_create(ctx->screen, + ctx->screen->resource_create(ctx->screen, &template); assert(!trans->detiled_texture->microtile && !trans->detiled_texture->macrotile); /* Set the stride. - * Parameters x, y, level, zslice, and face remain zero. */ + * + * Even though we are using an internal texture for this, + * the transfer sr, box and usage parameters still reflect + * the arguments received to get_transfer. We just do the + * right thing internally. + */ trans->transfer.stride = r300_texture_get_stride(r300screen, trans->detiled_texture, 0); @@ -192,21 +196,16 @@ r300_get_transfer(struct pipe_context *ctx, r300_copy_from_tiled_texture(ctx, trans); } } else { - trans->transfer.x = x; - trans->transfer.y = y; trans->transfer.stride = - r300_texture_get_stride(r300screen, tex, level); - trans->transfer.level = level; - trans->transfer.zslice = zslice; - trans->transfer.face = face; - trans->offset = r300_texture_get_offset(tex, level, zslice, face); + r300_texture_get_stride(r300screen, tex, sr.level); + trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face); } } return &trans->transfer; } -static void r300_transfer_destroy(struct pipe_context *ctx, - struct pipe_transfer *trans) +void r300_texture_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *trans) { struct r300_transfer *r300transfer = r300_transfer(trans); @@ -215,62 +214,54 @@ static void r300_transfer_destroy(struct pipe_context *ctx, r300_copy_into_tiled_texture(r300transfer->ctx, r300transfer); } - pipe_texture_reference( - (struct pipe_texture**)&r300transfer->detiled_texture, NULL); + pipe_resource_reference( + (struct pipe_resource**)&r300transfer->detiled_texture, NULL); } - pipe_texture_reference(&trans->texture, NULL); + pipe_resource_reference(&trans->resource, NULL); FREE(trans); } -static void* r300_transfer_map(struct pipe_context *ctx, - struct pipe_transfer *transfer) +void* r300_texture_transfer_map(struct pipe_context *ctx, + struct pipe_transfer *transfer) { + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = (struct r300_texture*)transfer->texture; + struct r300_texture *tex = (struct r300_texture*)transfer->resource; char *map; - enum pipe_format format = tex->tex.format; + enum pipe_format format = tex->b.b.format; if (r300transfer->detiled_texture) { /* The detiled texture is of the same size as the region being mapped * (no offset needed). */ - return pipe_buffer_map(ctx->screen, + return rws->buffer_map(rws, r300transfer->detiled_texture->buffer, - pipe_transfer_buffer_flags(transfer)); + transfer->usage); } else { /* Tiling is disabled. */ - map = pipe_buffer_map(ctx->screen, tex->buffer, - pipe_transfer_buffer_flags(transfer)); + map = rws->buffer_map(rws, tex->buffer, + transfer->usage); if (!map) { return NULL; } return map + r300_transfer(transfer)->offset + - transfer->y / util_format_get_blockheight(format) * transfer->stride + - transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + transfer->box.y / util_format_get_blockheight(format) * transfer->stride + + transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } } -static void r300_transfer_unmap(struct pipe_context *ctx, - struct pipe_transfer *transfer) +void r300_texture_transfer_unmap(struct pipe_context *ctx, + struct pipe_transfer *transfer) { + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = (struct r300_texture*)transfer->texture; + struct r300_texture *tex = (struct r300_texture*)transfer->resource; if (r300transfer->detiled_texture) { - pipe_buffer_unmap(ctx->screen, r300transfer->detiled_texture->buffer); + rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer); } else { - pipe_buffer_unmap(ctx->screen, tex->buffer); + rws->buffer_unmap(rws, tex->buffer); } } - -void r300_init_transfer_functions( struct r300_context *r300ctx ) -{ - struct pipe_context *ctx = &r300ctx->context; - - ctx->get_transfer = r300_get_transfer; - ctx->transfer_destroy = r300_transfer_destroy; - ctx->transfer_map = r300_transfer_map; - ctx->transfer_unmap = r300_transfer_unmap; -} diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h index 79baf6d048..d72e54e5ed 100644 --- a/src/gallium/drivers/r300/r300_transfer.h +++ b/src/gallium/drivers/r300/r300_transfer.h @@ -28,6 +28,24 @@ struct r300_context; -void r300_init_transfer_functions(struct r300_context *r300ctx); +struct pipe_transfer* +r300_texture_get_transfer(struct pipe_context *ctx, + struct pipe_resource *texture, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box); + +void +r300_texture_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *trans); + +void* +r300_texture_transfer_map(struct pipe_context *ctx, + struct pipe_transfer *transfer); + +void +r300_texture_transfer_unmap(struct pipe_context *ctx, + struct pipe_transfer *transfer); + #endif diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 379939ac75..bd6b95dccb 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -34,8 +34,6 @@ #include "radeon_compiler.h" -#include "util/u_math.h" - /* Convert info about VS output semantics into r300_shader_semantics. */ static void r300_shader_read_vs_outputs( struct tgsi_shader_info* info, diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index ddf2b79003..61ec49c619 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -23,10 +23,6 @@ #ifndef R300_WINSYS_H #define R300_WINSYS_H -#ifdef __cplusplus -extern "C" { -#endif - /* The public interface header for the r300 pipe driver. * Any winsys hosting this pipe needs to implement r300_winsys and then * call r300_create_screen to start things. */ @@ -34,14 +30,142 @@ extern "C" { #include "pipe/p_defines.h" #include "pipe/p_state.h" -struct radeon_winsys; +#include "r300_defines.h" + +struct r300_winsys_screen; /* Creates a new r300 screen. */ -struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); +struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws); + +struct r300_winsys_buffer; + + +enum r300_value_id { + R300_VID_PCI_ID, + R300_VID_GB_PIPES, + R300_VID_Z_PIPES, + R300_VID_SQUARE_TILING_SUPPORT +}; + +struct r300_winsys_screen { + void (*destroy)(struct r300_winsys_screen *ws); + + /** + * Buffer management. Buffer attributes are mostly fixed over its lifetime. + * + * Remember that gallium gets to choose the interface it needs, and the + * window systems must then implement that interface (rather than the + * other way around...). + * + * usage is a bitmask of R300_WINSYS_BUFFER_USAGE_PIXEL/VERTEX/INDEX/CONSTANT. This + * usage argument is only an optimization hint, not a guarantee, therefore + * proper behavior must be observed in all circumstances. + * + * alignment indicates the client's alignment requirements, eg for + * SSE instructions. + */ + struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws, + unsigned alignment, + unsigned usage, + unsigned size); + + /** + * Map the entire data store of a buffer object into the client's address. + * flags is bitmask of R300_WINSYS_BUFFER_USAGE_CPU_READ/WRITE flags. + */ + void *(*buffer_map)( struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf, + unsigned usage); + + void (*buffer_unmap)( struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf ); + + void (*buffer_destroy)( struct r300_winsys_buffer *buf ); + + + void (*buffer_reference)(struct r300_winsys_screen *rws, + struct r300_winsys_buffer **pdst, + struct r300_winsys_buffer *src); + + boolean (*buffer_references)(struct r300_winsys_buffer *a, + struct r300_winsys_buffer *b); + + void (*buffer_flush_range)(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, + unsigned offset, + unsigned length); + + /* Add a pipe_resource to the list of buffer objects to validate. */ + boolean (*add_buffer)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buf, + uint32_t rd, + uint32_t wd); + + + /* Revalidate all currently setup pipe_buffers. + * Returns TRUE if a flush is required. */ + boolean (*validate)(struct r300_winsys_screen* winsys); + + /* Check to see if there's room for commands. */ + boolean (*check_cs)(struct r300_winsys_screen* winsys, int size); + + /* Start a command emit. */ + void (*begin_cs)(struct r300_winsys_screen* winsys, + int size, + const char* file, + const char* function, + int line); + + /* Write a dword to the command buffer. */ + void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword); + + /* Write a relocated dword to the command buffer. */ + void (*write_cs_reloc)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buf, + uint32_t rd, + uint32_t wd, + uint32_t flags); + + /* Finish a command emit. */ + void (*end_cs)(struct r300_winsys_screen* winsys, + const char* file, + const char* function, + int line); + + /* Flush the CS. */ + void (*flush_cs)(struct r300_winsys_screen* winsys); + + /* winsys flush - callback from winsys when flush required */ + void (*set_flush_cb)(struct r300_winsys_screen *winsys, + void (*flush_cb)(void *), void *data); + + void (*reset_bos)(struct r300_winsys_screen *winsys); + + void (*buffer_set_tiling)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buffer, + uint32_t pitch, + enum r300_buffer_tiling microtiled, + enum r300_buffer_tiling macrotiled); + + uint32_t (*get_value)(struct r300_winsys_screen *winsys, + enum r300_value_id vid); + + struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys, + struct pipe_screen *screen, + struct winsys_handle *whandle, + unsigned *stride); + boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buffer, + unsigned stride, + struct winsys_handle *whandle); + + boolean (*is_resource_referenced)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buffer); + +}; -#ifdef __cplusplus -} -#endif +struct r300_winsys_screen * +r300_winsys_screen(struct pipe_screen *screen); #endif /* R300_WINSYS_H */ diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index 9949a53adf..6bd7e07e6c 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -7,7 +7,6 @@ softpipe = env.ConvenienceLibrary( source = [ 'sp_fs_exec.c', 'sp_fs_sse.c', - 'sp_buffer.c', 'sp_clear.c', 'sp_context.c', 'sp_draw_arrays.c', diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 6548ba2cfd..32e6ccc5bf 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -172,8 +172,10 @@ softpipe_is_format_supported( struct pipe_screen *screen, break; } - if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { - if(!winsys->is_displaytarget_format_supported(winsys, format)) + if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { + if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) return FALSE; } diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index a2250ccf8b..b91e04df5e 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -92,6 +92,7 @@ softpipe_displaytarget_layout(struct pipe_screen *screen, /* Round up the surface size to a multiple of the tile size? */ spt->dt = winsys->displaytarget_create(winsys, + spt->base.tex_usage, spt->base.format, spt->base.width0, spt->base.height0, @@ -142,8 +143,6 @@ softpipe_resource_create(struct pipe_screen *screen, } - - static void softpipe_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt) @@ -165,6 +164,55 @@ softpipe_resource_destroy(struct pipe_screen *pscreen, } +static struct pipe_resource * +softpipe_resource_from_handle(struct pipe_screen *screen, + const struct pipe_resource *template, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + struct softpipe_resource *spt = CALLOC_STRUCT(softpipe_resource); + if (!spt) + return NULL; + + spt->base = *template; + pipe_reference_init(&spt->base.reference, 1); + spt->base.screen = screen; + + spt->pot = (util_is_power_of_two(template->width0) && + util_is_power_of_two(template->height0) && + util_is_power_of_two(template->depth0)); + + spt->dt = winsys->displaytarget_from_handle(winsys, + template, + whandle, + &spt->stride[0]); + if (!spt->dt) + goto fail; + + return &spt->base; + + fail: + FREE(spt); + return NULL; +} + + +static boolean +softpipe_resource_get_handle(struct pipe_screen *screen, + struct pipe_resource *pt, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + struct softpipe_resource *spt = softpipe_resource(pt); + + assert(spt->dt); + if (!spt->dt) + return FALSE; + + return winsys->displaytarget_get_handle(winsys, spt->dt, whandle); +} + + /** * Get a pipe_surface "view" into a texture. */ @@ -242,7 +290,7 @@ static struct pipe_transfer * softpipe_get_transfer(struct pipe_context *pipe, struct pipe_resource *resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box) { struct softpipe_resource *sptex = softpipe_resource(resource); @@ -263,11 +311,10 @@ softpipe_get_transfer(struct pipe_context *pipe, int nblocksy = util_format_get_nblocksy(resource->format, u_minify(resource->height0, sr.level)); pipe_resource_reference(&pt->resource, resource); + pt->sr = sr; + pt->usage = usage; pt->box = *box; pt->stride = sptex->stride[sr.level]; - pt->usage = usage; - //pt->face = face; - //pt->level = level; spt->offset = sptex->level_offset[sr.level]; @@ -408,6 +455,8 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen) { screen->resource_create = softpipe_resource_create; screen->resource_destroy = softpipe_resource_destroy; + screen->resource_from_handle = softpipe_resource_from_handle; + screen->resource_get_handle = softpipe_resource_get_handle; screen->user_buffer_create = softpipe_user_buffer_create; screen->get_tex_surface = softpipe_get_tex_surface; diff --git a/src/gallium/drivers/svga/SConscript b/src/gallium/drivers/svga/SConscript index 737b791ceb..ba1b81dbd9 100644 --- a/src/gallium/drivers/svga/SConscript +++ b/src/gallium/drivers/svga/SConscript @@ -39,9 +39,7 @@ sources = [ 'svga_pipe_vertex.c', 'svga_pipe_vs.c', 'svga_screen.c', - 'svga_screen_buffer.c', 'svga_screen_cache.c', - 'svga_screen_texture.c', 'svga_state.c', 'svga_state_constants.c', 'svga_state_framebuffer.c', diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 5fc8875257..cb432fb890 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -341,7 +341,7 @@ static struct pipe_transfer * svga_texture_get_transfer(struct pipe_context *pipe, struct pipe_resource *texture, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box) { struct svga_screen *ss = svga_screen(pipe->screen); diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 09ee5a7d04..dd0fd8ed98 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -1305,7 +1305,7 @@ static struct pipe_transfer * trace_context_get_transfer(struct pipe_context *_context, struct pipe_resource *_resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box) { struct trace_context *tr_context = trace_context(_context); @@ -1457,7 +1457,7 @@ static void trace_context_transfer_inline_write(struct pipe_context *_context, struct pipe_resource *_resource, struct pipe_subresource sr, - enum pipe_transfer_usage usage, + unsigned usage, const struct pipe_box *box, const void *data, unsigned stride, diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c index 56961e921a..eaa47df406 100644 --- a/src/gallium/drivers/trace/tr_drm.c +++ b/src/gallium/drivers/trace/tr_drm.c @@ -30,8 +30,6 @@ #include "util/u_memory.h" #include "tr_drm.h" #include "tr_screen.h" -#include "tr_context.h" -#include "tr_texture.h" #include "tr_public.h" struct trace_drm_api diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 60fa6b32bc..2444683f41 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -315,7 +315,7 @@ struct pipe_context { struct pipe_transfer *(*get_transfer)(struct pipe_context *, struct pipe_resource *resource, struct pipe_subresource, - enum pipe_transfer_usage, + unsigned usage, /* a combination of PIPE_TRANSFER_x */ const struct pipe_box *); void (*transfer_destroy)(struct pipe_context *, @@ -342,7 +342,7 @@ struct pipe_context { void (*transfer_inline_write)( struct pipe_context *, struct pipe_resource *, struct pipe_subresource, - enum pipe_transfer_usage, + unsigned usage, /* a combination of PIPE_TRANSFER_x */ const struct pipe_box *, const void *data, unsigned stride, diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h index cbf3273ec8..ba2985f449 100644 --- a/src/gallium/include/pipe/p_format.h +++ b/src/gallium/include/pipe/p_format.h @@ -157,6 +157,7 @@ enum pipe_format { PIPE_FORMAT_DXT5_SRGBA = 109, PIPE_FORMAT_A8B8G8R8_UNORM = 110, + PIPE_FORMAT_B5G5R5X1_UNORM = 111, PIPE_FORMAT_COUNT }; diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h index cc9cebca6e..8fa648e187 100644 --- a/src/gallium/include/pipe/p_screen.h +++ b/src/gallium/include/pipe/p_screen.h @@ -107,7 +107,7 @@ struct pipe_screen { * Create a new texture object, using the given template info. */ struct pipe_resource * (*resource_create)(struct pipe_screen *, - const struct pipe_resource *template); + const struct pipe_resource *templat); /** * Create a texture from a winsys_handle. The handle is often created in @@ -115,7 +115,7 @@ struct pipe_screen { * texture_get_handle. */ struct pipe_resource * (*resource_from_handle)(struct pipe_screen *, - const struct pipe_resource *template, + const struct pipe_resource *templat, struct winsys_handle *handle); /** diff --git a/src/gallium/include/state_tracker/dri1_api.h b/src/gallium/include/state_tracker/dri1_api.h index b173ba3683..777bb9590e 100644 --- a/src/gallium/include/state_tracker/dri1_api.h +++ b/src/gallium/include/state_tracker/dri1_api.h @@ -7,13 +7,13 @@ #include "state_tracker/drm_api.h" -#include <drm.h> +struct drm_clip_rect; struct pipe_screen; struct pipe_winsys; struct pipe_buffer; struct pipe_context; -struct pipe_texture; +struct pipe_resource; struct dri1_api_version { diff --git a/src/gallium/include/state_tracker/drm_api.h b/src/gallium/include/state_tracker/drm_api.h index fe7ef253ef..3d8fdd86fc 100644 --- a/src/gallium/include/state_tracker/drm_api.h +++ b/src/gallium/include/state_tracker/drm_api.h @@ -8,7 +8,7 @@ struct pipe_screen; struct pipe_winsys; struct pipe_buffer; struct pipe_context; -struct pipe_texture; +struct pipe_resource; enum drm_create_screen_mode { DRM_CREATE_NORMAL = 0, diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h new file mode 100644 index 0000000000..8897ff7c25 --- /dev/null +++ b/src/gallium/include/state_tracker/st_api.h @@ -0,0 +1,407 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 _ST_API_H_ +#define _ST_API_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +/** + * \file API for communication between state trackers and state tracker + * managers. + * + * While both are state tackers, we use the term state tracker for rendering + * APIs such as OpenGL or OpenVG, and state tracker manager for window system + * APIs such as EGL or GLX in this file. + * + * This file defines an API to be implemented by both state trackers and state + * tracker managers. + */ + +/** + * The entry points of the state trackers. + */ +#define ST_MODULE_OPENGL_SYMBOL "st_module_OpenGL" +#define ST_MODULE_OPENGL_ES1_SYMBOL "st_module_OpenGL_ES1" +#define ST_MODULE_OPENGL_ES2_SYMBOL "st_module_OpenGL_ES2" +#define ST_MODULE_OPENVG_SYMBOL "st_module_OpenVG" + +/** + * The supported rendering API of a state tracker. + */ +enum st_api_type { + ST_API_OPENGL, + ST_API_OPENGL_ES1, + ST_API_OPENGL_ES2, + ST_API_OPENVG, + + ST_API_COUNT +}; + +/** + * Used in st_context_iface->teximage. + */ +enum st_texture_type { + ST_TEXTURE_1D, + ST_TEXTURE_2D, + ST_TEXTURE_3D, + ST_TEXTURE_RECT, +}; + +/** + * Available attachments of framebuffer. + */ +enum st_attachment_type { + ST_ATTACHMENT_FRONT_LEFT, + ST_ATTACHMENT_BACK_LEFT, + ST_ATTACHMENT_FRONT_RIGHT, + ST_ATTACHMENT_BACK_RIGHT, + ST_ATTACHMENT_DEPTH_STENCIL, + ST_ATTACHMENT_ACCUM, + ST_ATTACHMENT_SAMPLE, + + ST_ATTACHMENT_COUNT, + ST_ATTACHMENT_INVALID = -1 +}; + +/* for buffer_mask in st_visual */ +#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT) +#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT) +#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT) +#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT) +#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL) +#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM) +#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE) + +/** + * Enumerations of state tracker context resources. + */ +enum st_context_resource_type { + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z, + ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER, + ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE, +}; + +/** + * The return type of st_api->get_proc_address. + */ +typedef void (*st_proc_t)(void); + +struct pipe_context; +struct pipe_resource; +struct pipe_fence_handle; + +/** + * Used in st_context_iface->get_resource_for_egl_image. + */ +struct st_context_resource +{ + /* these fields are filled by the caller */ + enum st_context_resource_type type; + void *resource; + + /* this is owned by the caller */ + struct pipe_resource *texture; +}; + +/** + * Used in st_manager_iface->get_egl_image. + */ +struct st_egl_image +{ + /* these fields are filled by the caller */ + struct st_context_iface *stctxi; + void *egl_image; + + /* this is owned by the caller */ + struct pipe_resource *texture; + + unsigned face; + unsigned level; + unsigned zslice; +}; + +/** + * Represent the visual of a framebuffer. + */ +struct st_visual +{ + /** + * Available buffers. Tested with ST_FRAMEBUFFER_*_MASK. + */ + unsigned buffer_mask; + + /** + * Buffer formats. The formats are always set even when the buffer is + * not available. + */ + enum pipe_format color_format; + enum pipe_format depth_stencil_format; + enum pipe_format accum_format; + int samples; + + /** + * Desired render buffer. + */ + enum st_attachment_type render_buffer; +}; + +/** + * Represent a windowing system drawable. + * + * The framebuffer is implemented by the state tracker manager and + * used by the state trackers. + * + * Instead of the winsys pokeing into the API context to figure + * out what buffers that might be needed in the future by the API + * context, it calls into the framebuffer to get the textures. + * + * This structure along with the notify_invalid_framebuffer + * allows framebuffers to be shared between different threads + * but at the same make the API context free from thread + * syncronisation primitves, with the exception of a small + * atomic flag used for notification of framebuffer dirty status. + * + * The thread syncronisation is put inside the framebuffer + * and only called once the framebuffer has become dirty. + */ +struct st_framebuffer_iface +{ + /** + * Available for the state tracker manager to use. + */ + void *st_manager_private; + + /** + * The visual of a framebuffer. + */ + const struct st_visual *visual; + + /** + * Flush the front buffer. + * + * On some window systems, changes to the front buffers are not immediately + * visible. They need to be flushed. + * + * @att is one of the front buffer attachments. + */ + boolean (*flush_front)(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt); + + /** + * The state tracker asks for the textures it needs. + * + * It should try to only ask for attachments that it currently renders + * to, thus allowing the winsys to delay the allocation of textures not + * needed. For example front buffer attachments are not needed if you + * only do back buffer rendering. + * + * The implementor of this function needs to also ensure + * thread safty as this call might be done from multiple threads. + * + * The returned textures are owned by the caller. They should be + * unreferenced when no longer used. If this function is called multiple + * times with different sets of attachments, those buffers not included in + * the last call might be destroyed. This behavior might change in the + * future. + */ + boolean (*validate)(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out); +}; + +/** + * Represent a rendering context. + * + * This entity is created from st_api and used by the state tracker manager. + */ +struct st_context_iface +{ + /** + * Available for the state tracker and the manager to use. + */ + void *st_context_private; + void *st_manager_private; + + /** + * Destroy the context. + */ + void (*destroy)(struct st_context_iface *stctxi); + + /** + * Invalidate the current textures that was taken from a framebuffer. + * + * The state tracker manager calls this function to let the rendering + * context know that it should update the textures it got from + * st_framebuffer_iface::validate. It should do so at the latest time possible. + * Possible right before sending triangles to the pipe context. + * + * For certain platforms this function might be called from a thread other + * than the thread that the context is currently bound in, and must + * therefore be thread safe. But it is the state tracker manager's + * responsibility to make sure that the framebuffer is bound to the context + * and the API context is current for the duration of this call. + * + * Thus reducing the sync primitive needed to a single atomic flag. + */ + void (*notify_invalid_framebuffer)(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi); + + /** + * Flush all drawing from context to the pipe also flushes the pipe. + */ + void (*flush)(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence); + + /** + * Replace the texture image of a texture object at the specified level. + * + * This function is optional. + */ + boolean (*teximage)(struct st_context_iface *stctxi, enum st_texture_type target, + int level, enum pipe_format internal_format, + struct pipe_resource *tex, boolean mipmap); + + /** + * Used to implement glXCopyContext. + */ + void (*copy)(struct st_context_iface *stctxi, + struct st_context_iface *stsrci, unsigned mask); + + /** + * Look up and return the info of a resource for EGLImage. + * + * This function is optional. + */ + boolean (*get_resource_for_egl_image)(struct st_context_iface *stctxi, + struct st_context_resource *stres); +}; + + +/** + * Represent a state tracker manager. + * + * This interface is implemented by the state tracker manager. It corresponds + * to a "display" in the window system. + */ +struct st_manager +{ + struct pipe_screen *screen; + + /** + * Look up and return the info of an EGLImage. + * + * This function is optional. + */ + boolean (*get_egl_image)(struct st_manager *smapi, + struct st_egl_image *stimg); +}; + +/** + * Represent a rendering API such as OpenGL or OpenVG. + * + * Implemented by the state tracker and used by the state tracker manager. + */ +struct st_api +{ + /** + * Destroy the API. + */ + void (*destroy)(struct st_api *stapi); + + /** + * Return an API entry point. + * + * For GL this is the same as _glapi_get_proc_address. + */ + st_proc_t (*get_proc_address)(struct st_api *stapi, const char *procname); + + /** + * Return true if the visual is supported by the state tracker. + */ + boolean (*is_visual_supported)(struct st_api *stapi, + const struct st_visual *visual); + + /** + * Create a rendering context. + */ + struct st_context_iface *(*create_context)(struct st_api *stapi, + struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *stsharei); + + /** + * Bind the context to the calling thread with draw and read as drawables. + * + * The framebuffers might have different visuals than the context does. + */ + boolean (*make_current)(struct st_api *stapi, + struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi); + + /** + * Get the currently bound context in the calling thread. + */ + struct st_context_iface *(*get_current)(struct st_api *stapi); +}; + +/** + * Represent a state tracker. + * + * This is the entry point of a state tracker. + */ +struct st_module +{ + enum st_api_type api; + struct st_api *(*create_api)(void); +}; + +/** + * Return true if the visual has the specified buffers. + */ +static INLINE boolean +st_visual_have_buffers(const struct st_visual *visual, unsigned mask) +{ + return ((visual->buffer_mask & mask) == mask); +} + +/* these symbols may need to be dynamically lookup up */ +extern PUBLIC const struct st_module st_module_OpenGL; +extern PUBLIC const struct st_module st_module_OpenGL_ES1; +extern PUBLIC const struct st_module st_module_OpenGL_ES2; +extern PUBLIC const struct st_module st_module_OpenVG; + +#endif /* _ST_API_H_ */ diff --git a/src/gallium/include/state_tracker/sw_winsys.h b/src/gallium/include/state_tracker/sw_winsys.h index 0de98bbc1c..12f58c617e 100644 --- a/src/gallium/include/state_tracker/sw_winsys.h +++ b/src/gallium/include/state_tracker/sw_winsys.h @@ -44,8 +44,10 @@ extern "C" { #endif +struct winsys_handle; struct pipe_screen; struct pipe_context; +struct pipe_resource; /** @@ -68,6 +70,7 @@ struct sw_winsys boolean (*is_displaytarget_format_supported)( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format ); /** @@ -83,12 +86,30 @@ struct sw_winsys */ struct sw_displaytarget * (*displaytarget_create)( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, unsigned *stride ); /** + * Used to implement texture_from_handle. + */ + struct sw_displaytarget * + (*displaytarget_from_handle)( struct sw_winsys *ws, + const struct pipe_resource *template, + struct winsys_handle *whandle, + unsigned *stride ); + + /** + * Used to implement texture_get_handle. + */ + boolean + (*displaytarget_get_handle)( struct sw_winsys *ws, + struct sw_displaytarget *dt, + struct winsys_handle *whandle ); + + /** * \param flags bitmask of PIPE_BUFFER_USAGE_x flags */ void * diff --git a/src/gallium/state_trackers/dri/Makefile b/src/gallium/state_trackers/dri/Makefile index ef8f19709a..f5af8aa3a6 100644 --- a/src/gallium/state_trackers/dri/Makefile +++ b/src/gallium/state_trackers/dri/Makefile @@ -15,7 +15,9 @@ C_SOURCES = \ dri_context.c \ dri_screen.c \ dri_drawable.c \ - dri_extensions.c + dri_extensions.c \ + dri_st_api.c \ + dri1.c # $(TOP)/src/mesa/drivers/dri/common/utils.c \ $(TOP)/src/mesa/drivers/dri/common/vblank.c \ diff --git a/src/gallium/state_trackers/dri/SConscript b/src/gallium/state_trackers/dri/SConscript index ce2c273597..7c67ceecd8 100644 --- a/src/gallium/state_trackers/dri/SConscript +++ b/src/gallium/state_trackers/dri/SConscript @@ -18,6 +18,8 @@ if env['dri']: 'dri_drawable.c', 'dri_extensions.c', 'dri_screen.c', + 'dri_st_api.c', + 'dri1.c', ] ) Export('st_dri') diff --git a/src/gallium/state_trackers/dri/dri1.c b/src/gallium/state_trackers/dri/dri1.c new file mode 100644 index 0000000000..64a4842654 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri1.c @@ -0,0 +1,583 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * 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 VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <keithw@vmware.com> + * Author: Jakob Bornecrantz <wallbraker@gmail.com> + */ + +/* XXX DRI1 is untested after the switch to st_api.h */ + +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" +#include "pipe/p_context.h" +#include "state_tracker/dri1_api.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" + +static INLINE void +dri1_lock(struct dri_context *ctx) +{ + drm_context_t hw_context = ctx->cPriv->hHWContext; + char ret = 0; + + DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret); + if (ret) { + drmGetLock(ctx->sPriv->fd, hw_context, 0); + ctx->stLostLock = TRUE; + ctx->wsLostLock = TRUE; + } + ctx->isLocked = TRUE; +} + +static INLINE void +dri1_unlock(struct dri_context *ctx) +{ + ctx->isLocked = FALSE; + DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext); +} + +static struct pipe_fence_handle * +dri_swap_fences_pop_front(struct dri_drawable *draw) +{ + struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; + struct pipe_fence_handle *fence = NULL; + + if (draw->cur_fences >= draw->desired_fences) { + screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); + screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); + --draw->cur_fences; + draw->tail &= DRI_SWAP_FENCES_MASK; + } + return fence; +} + +static void +dri_swap_fences_push_back(struct dri_drawable *draw, + struct pipe_fence_handle *fence) +{ + struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; + + if (!fence) + return; + + if (draw->cur_fences < DRI_SWAP_FENCES_MAX) { + draw->cur_fences++; + screen->fence_reference(screen, &draw->swap_fences[draw->head++], + fence); + draw->head &= DRI_SWAP_FENCES_MASK; + } +} + +void +dri1_swap_fences_clear(struct dri_drawable *drawable) +{ + struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen; + struct pipe_fence_handle *fence; + + while (drawable->cur_fences) { + fence = dri_swap_fences_pop_front(drawable); + screen->fence_reference(screen, &fence, NULL); + } +} + +static void +dri1_update_drawables_locked(struct dri_context *ctx, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv) +{ + if (ctx->stLostLock) { + ctx->stLostLock = FALSE; + if (driDrawPriv == driReadPriv) + DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv); + else + DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv, + driReadPriv); + } +} + +/** + * This ensures all contexts which bind to a drawable pick up the + * drawable change and signal new buffer state. + */ +static void +dri1_propagate_drawable_change(struct dri_context *ctx) +{ + __DRIdrawable *dPriv = ctx->dPriv; + __DRIdrawable *rPriv = ctx->rPriv; + struct dri_drawable *draw = dri_drawable(dPriv); + struct dri_drawable *read = dri_drawable(rPriv); + boolean flushed = FALSE; + + if (dPriv && draw->texture_stamp != dPriv->lastStamp) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + flushed = TRUE; + ctx->st->notify_invalid_framebuffer(ctx->st, draw->stfb); + } + + if (rPriv && dPriv != rPriv && read->texture_stamp != rPriv->lastStamp) { + if (!flushed) + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + ctx->st->notify_invalid_framebuffer(ctx->st, read->stfb); + } +} + +static INLINE boolean +dri1_intersect_src_bbox(struct drm_clip_rect *dst, + int dst_x, + int dst_y, + const struct drm_clip_rect *src, + const struct drm_clip_rect *bbox) +{ + int xy1; + int xy2; + + xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : + (int)bbox->x1 + dst_x; + xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : + (int)bbox->x2 + dst_x; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->x1 = xy1; + dst->x2 = xy2; + + xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : + (int)bbox->y1 + dst_y; + xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : + (int)bbox->y2 + dst_y; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->y1 = xy1; + dst->y2 = xy2; + return TRUE; +} + +static void +dri1_swap_copy(struct pipe_context *pipe, + struct pipe_surface *dst, + struct pipe_surface *src, + __DRIdrawable * dPriv, const struct drm_clip_rect *bbox) +{ + struct drm_clip_rect clip; + struct drm_clip_rect *cur; + int i; + + cur = dPriv->pClipRects; + + for (i = 0; i < dPriv->numClipRects; ++i) { + if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) { + if (pipe->surface_copy) { + pipe->surface_copy(pipe, dst, clip.x1, clip.y1, + src, + (int)clip.x1 - dPriv->x, + (int)clip.y1 - dPriv->y, + clip.x2 - clip.x1, clip.y2 - clip.y1); + } else { + util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1, + src, + (int)clip.x1 - dPriv->x, + (int)clip.y1 - dPriv->y, + clip.x2 - clip.x1, clip.y2 - clip.y1); + } + } + } +} + +static struct pipe_surface * +dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_resource *ptex) +{ + struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->pipe_screen; + struct pipe_surface *psurf = drawable->dri1_surface; + + if (!psurf || psurf->texture != ptex) { + pipe_surface_reference(&drawable->dri1_surface, NULL); + + drawable->dri1_surface = pipe_screen->get_tex_surface(pipe_screen, + ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + + psurf = drawable->dri1_surface; + } + + return psurf; +} + +static struct pipe_context * +dri1_get_pipe_context(struct dri_drawable *drawable) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_context *pipe = screen->dri1_pipe; + + if (!pipe) { + screen->dri1_pipe = + screen->pipe_screen->context_create(screen->pipe_screen, NULL); + pipe = screen->dri1_pipe; + } + + return pipe; +} + +static void +dri1_present_texture_locked(__DRIdrawable * dPriv, + struct pipe_resource *ptex, + const struct drm_clip_rect *sub_box, + struct pipe_fence_handle **fence) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_context *pipe; + struct pipe_surface *psurf; + struct drm_clip_rect bbox; + boolean visible = TRUE; + + *fence = NULL; + + bbox.x1 = 0; + bbox.x2 = ptex->width0; + bbox.y1 = 0; + bbox.y2 = ptex->height0; + + if (sub_box) + visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box); + if (!visible) + return; + + pipe = dri1_get_pipe_context(drawable); + psurf = dri1_get_pipe_surface(drawable, ptex); + if (!pipe || !psurf) + return; + + if (__dri1_api_hooks->present_locked) { + __dri1_api_hooks->present_locked(pipe, psurf, + dPriv->pClipRects, dPriv->numClipRects, + dPriv->x, dPriv->y, &bbox, fence); + } else if (__dri1_api_hooks->front_srf_locked) { + struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe); + + if (front) + dri1_swap_copy(pipe, front, psurf, dPriv, &bbox); + + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, fence); + } +} + +static void +dri1_copy_to_front(struct dri_context *ctx, + struct pipe_resource *ptex, + __DRIdrawable * dPriv, + const struct drm_clip_rect *sub_box, + struct pipe_fence_handle **fence) +{ + boolean save_lost_lock; + + dri1_lock(ctx); + save_lost_lock = ctx->stLostLock; + dri1_update_drawables_locked(ctx, dPriv, dPriv); + + dri1_present_texture_locked(dPriv, ptex, sub_box, fence); + + ctx->stLostLock = save_lost_lock; + + /** + * FIXME: Revisit this: Update drawables on copy_sub_buffer ? + */ + + if (!sub_box) + dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv); + + dri1_unlock(ctx); + dri1_propagate_drawable_change(ctx); +} + +void +dri1_flush_frontbuffer(struct dri_drawable *drawable, + struct pipe_resource *ptex) +{ + struct st_api *stapi = dri_get_st_api(); + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct dri_context *ctx; + struct pipe_fence_handle *dummy_fence; + struct st_context_iface *st = stapi->get_current(stapi); + + if (!st) + return; + + ctx = (struct dri_context *) st->st_manager_private; + + dri1_copy_to_front(ctx, ptex, ctx->dPriv, NULL, &dummy_fence); + pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL); + + /** + * FIXME: Do we need swap throttling here? + */ +} + +void +dri1_swap_buffers(__DRIdrawable * dPriv) +{ + struct dri_context *ctx = dri_get_current(); + struct dri_drawable *draw = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(draw->sPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct pipe_fence_handle *fence; + struct pipe_resource *ptex; + + assert(__dri1_api_hooks != NULL); + + if (!ctx) + return; /* For now */ + + ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT]; + if (ptex) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + fence = dri_swap_fences_pop_front(draw); + if (fence) { + (void)pipe_screen->fence_finish(pipe_screen, fence, 0); + pipe_screen->fence_reference(pipe_screen, &fence, NULL); + } + dri1_copy_to_front(ctx, ptex, dPriv, NULL, &fence); + dri_swap_fences_push_back(draw, fence); + pipe_screen->fence_reference(pipe_screen, &fence, NULL); + } +} + +void +dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h) +{ + struct dri_context *ctx = dri_get_current(); + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct drm_clip_rect sub_bbox; + struct dri_drawable *draw = dri_drawable(dPriv); + struct pipe_fence_handle *dummy_fence; + struct pipe_resource *ptex; + + assert(__dri1_api_hooks != NULL); + + if (!ctx) + return; + + sub_bbox.x1 = x; + sub_bbox.x2 = x + w; + sub_bbox.y1 = y; + sub_bbox.y2 = y + h; + + ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT]; + if (ptex) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + dri1_copy_to_front(ctx, ptex, dPriv, &sub_bbox, &dummy_fence); + pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL); + } +} + +void +dri1_allocate_textures(struct dri_drawable *drawable, + unsigned width, unsigned height, + unsigned mask) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_resource templ; + int i; + + /* remove outdated textures */ + if (drawable->old_w != width || drawable->old_h != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned tex_usage; + + /* the texture already exists or not requested */ + if (drawable->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (drawable->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = drawable->stvis.color_format; + tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = drawable->stvis.depth_stencil_format; + tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.tex_usage = tex_usage; + + drawable->textures[i] = + screen->pipe_screen->resource_create(screen->pipe_screen, &templ); + } + } + + drawable->old_w = width; + drawable->old_h = height; + drawable->texture_mask = mask; +} + +static void +st_dri_lock(struct pipe_context *pipe) +{ + dri1_lock((struct dri_context *)pipe->priv); +} + +static void +st_dri_unlock(struct pipe_context *pipe) +{ + dri1_unlock((struct dri_context *)pipe->priv); +} + +static boolean +st_dri_is_locked(struct pipe_context *pipe) +{ + return ((struct dri_context *)pipe->priv)->isLocked; +} + +static boolean +st_dri_lost_lock(struct pipe_context *pipe) +{ + return ((struct dri_context *)pipe->priv)->wsLostLock; +} + +static void +st_dri_clear_lost_lock(struct pipe_context *pipe) +{ + ((struct dri_context *)pipe->priv)->wsLostLock = FALSE; +} + +static struct dri1_api_lock_funcs dri1_lf = { + .lock = st_dri_lock, + .unlock = st_dri_unlock, + .is_locked = st_dri_is_locked, + .is_lock_lost = st_dri_lost_lock, + .clear_lost_lock = st_dri_clear_lost_lock +}; + +static const __DRIextension *dri1_screen_extensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + NULL +}; + +struct dri1_api *__dri1_api_hooks = NULL; + +static INLINE void +dri1_copy_version(struct dri1_api_version *dst, + const struct __DRIversionRec *src) +{ + dst->major = src->major; + dst->minor = src->minor; + dst->patch_level = src->patch; +} + +const __DRIconfig ** +dri1_init_screen(__DRIscreen * sPriv) +{ + struct dri_screen *screen; + const __DRIconfig **configs; + struct dri1_create_screen_arg arg; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->api = drm_api_create(); + screen->sPriv = sPriv; + screen->fd = sPriv->fd; + screen->drmLock = (drmLock *) & sPriv->pSAREA->lock; + + sPriv->private = (void *)screen; + sPriv->extensions = dri1_screen_extensions; + + arg.base.mode = DRM_CREATE_DRI1; + arg.lf = &dri1_lf; + arg.ddx_info = sPriv->pDevPriv; + arg.ddx_info_size = sPriv->devPrivSize; + arg.sarea = sPriv->pSAREA; + dri1_copy_version(&arg.ddx_version, &sPriv->ddx_version); + dri1_copy_version(&arg.dri_version, &sPriv->dri_version); + dri1_copy_version(&arg.drm_version, &sPriv->drm_version); + arg.api = NULL; + + screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base); + + if (!screen->pipe_screen || !arg.api) { + debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__); + goto out_no_screen; + } + + __dri1_api_hooks = arg.api; + + driParseOptionInfo(&screen->optionCache, + __driConfigOptions, __driNConfigOptions); + + /** + * FIXME: If the driver supports format conversion swapbuffer blits, we might + * want to support other color bit depths than the server is currently + * using. + */ + + configs = dri_fill_in_modes(screen, sPriv->fbBPP); + if (!configs) + goto out_no_configs; + + return configs; + out_no_configs: + screen->pipe_screen->destroy(screen->pipe_screen); + out_no_screen: + FREE(screen); + return NULL; +} diff --git a/src/gallium/drivers/cell/ppu/cell_buffer.h b/src/gallium/state_trackers/dri/dri1.h index ef0a8a70e5..2ac1ed76d9 100644 --- a/src/gallium/drivers/cell/ppu/cell_buffer.h +++ b/src/gallium/state_trackers/dri/dri1.h @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2009 VMware, Inc. + * Copyright 2009, VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -24,32 +24,40 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ +/* + * Author: Keith Whitwell <keithw@vmware.com> + * Author: Jakob Bornecrantz <wallbraker@gmail.com> + */ -#ifndef SP_BUFFER_H -#define SP_BUFFER_H +#ifndef DRI1_H +#define DRI1_H -#include "pipe/p_compiler.h" -#include "pipe/p_state.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "state_tracker/st_api.h" +#include "dri_util.h" -struct cell_buffer -{ - struct pipe_buffer base; - boolean userBuffer; /** Is this a user-space buffer? */ - void *data; -}; +extern struct dri1_api *__dri1_api_hooks; +const __DRIconfig ** +dri1_init_screen(__DRIscreen * sPriv); -/** Cast wrapper */ -static INLINE struct cell_buffer * -cell_buffer( struct pipe_buffer *buf ) -{ - return (struct cell_buffer *)buf; -} +void +dri1_flush_frontbuffer(struct dri_drawable *drawable, + struct pipe_resource *ptex); + +void +dri1_allocate_textures(struct dri_drawable *drawable, + unsigned width, unsigned height, + unsigned mask); +void dri1_swap_buffers(__DRIdrawable * dPriv); void -cell_init_screen_buffer_funcs(struct pipe_screen *screen); +dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h); +void +dri1_swap_fences_clear(struct dri_drawable *drawable); -#endif /* SP_BUFFER_H */ +#endif /* DRI1_H */ diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index 2f991c39e3..54568a8b22 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -30,26 +30,24 @@ */ #include "dri_screen.h" - #include "dri_drawable.h" -#include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" -#include "pipe/p_context.h" - #include "dri_context.h" +#include "dri_st_api.h" +#include "dri1.h" +#include "pipe/p_context.h" #include "util/u_memory.h" GLboolean dri_create_context(const __GLcontextModes * visual, __DRIcontext * cPriv, void *sharedContextPrivate) { + struct st_api *stapi = dri_get_st_api(); __DRIscreen *sPriv = cPriv->driScreenPriv; struct dri_screen *screen = dri_screen(sPriv); struct dri_context *ctx = NULL; - struct st_context *st_share = NULL; + struct st_context_iface *st_share = NULL; + struct st_visual stvis; if (sharedContextPrivate) { st_share = ((struct dri_context *)sharedContextPrivate)->st; @@ -63,21 +61,15 @@ dri_create_context(const __GLcontextModes * visual, ctx->cPriv = cPriv; ctx->sPriv = sPriv; ctx->lock = screen->drmLock; - ctx->d_stamp = -1; - ctx->r_stamp = -1; driParseConfigFiles(&ctx->optionCache, &screen->optionCache, sPriv->myNum, "dri"); - ctx->pipe = screen->pipe_screen->context_create( screen->pipe_screen, - ctx ); - - if (ctx->pipe == NULL) - goto fail; - - ctx->st = st_create_context(ctx->pipe, visual, st_share); + dri_fill_st_visual(&stvis, screen, visual); + ctx->st = stapi->create_context(stapi, screen->smapi, &stvis, st_share); if (ctx->st == NULL) goto fail; + ctx->st->st_manager_private = (void *) ctx; dri_init_extensions(ctx); @@ -85,10 +77,7 @@ dri_create_context(const __GLcontextModes * visual, fail: if (ctx && ctx->st) - st_destroy_context(ctx->st); - - if (ctx && ctx->pipe) - ctx->pipe->destroy(ctx->pipe); + ctx->st->destroy(ctx->st); FREE(ctx); return FALSE; @@ -110,11 +99,8 @@ dri_destroy_context(__DRIcontext * cPriv) * to avoid having to add code elsewhere to cope with flushing a * partially destroyed context. */ - st_flush(ctx->st, 0, NULL); - - /* Also frees ctx->pipe? - */ - st_destroy_context(ctx->st); + ctx->st->flush(ctx->st, 0, NULL); + ctx->st->destroy(ctx->st); FREE(ctx); } @@ -122,14 +108,16 @@ dri_destroy_context(__DRIcontext * cPriv) GLboolean dri_unbind_context(__DRIcontext * cPriv) { + struct st_api *stapi = dri_get_st_api(); + if (cPriv) { struct dri_context *ctx = dri_context(cPriv); if (--ctx->bind_count == 0) { - if (ctx->st && ctx->st == st_get_current()) { - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - st_make_current(NULL, NULL, NULL, NULL); - } + if (ctx->st == stapi->get_current(stapi)) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + stapi->make_current(stapi, NULL, NULL, NULL); + } } } @@ -141,83 +129,47 @@ dri_make_current(__DRIcontext * cPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { + struct st_api *stapi = dri_get_st_api(); + if (cPriv) { struct dri_context *ctx = dri_context(cPriv); struct dri_drawable *draw = dri_drawable(driDrawPriv); struct dri_drawable *read = dri_drawable(driReadPriv); - struct st_context *old_st = st_get_current(); + struct st_context_iface *old_st; + old_st = stapi->get_current(stapi); if (old_st && old_st != ctx->st) - st_flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL); + ctx->st->flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL); ++ctx->bind_count; if (ctx->dPriv != driDrawPriv) { ctx->dPriv = driDrawPriv; - ctx->d_stamp = driDrawPriv->lastStamp - 1; + draw->texture_stamp = driDrawPriv->lastStamp - 1; } if (ctx->rPriv != driReadPriv) { ctx->rPriv = driReadPriv; - ctx->r_stamp = driReadPriv->lastStamp - 1; + read->texture_stamp = driReadPriv->lastStamp - 1; } - /* DRI co-state tracker currently overrides flush_frontbuffer. - * When this is fixed, will need to pass the drawable in the - * fourth parameter here so that when Mesa calls - * flush_frontbuffer directly (in front-buffer rendering), it - * will have access to the drawable argument: - */ - st_make_current(ctx->st, draw->stfb, read->stfb, NULL); - - if (__dri1_api_hooks) { - dri1_update_drawables(ctx, draw, read); - } else { - dri_update_buffer(ctx->pipe->screen, - ctx->pipe->priv); - } - } else { - st_make_current(NULL, NULL, NULL, NULL); + stapi->make_current(stapi, ctx->st, draw->stfb, read->stfb); + } + else { + stapi->make_current(stapi, NULL, NULL, NULL); } return GL_TRUE; } -static void -st_dri_lock(struct pipe_context *pipe) -{ - dri_lock((struct dri_context *)pipe->priv); -} - -static void -st_dri_unlock(struct pipe_context *pipe) -{ - dri_unlock((struct dri_context *)pipe->priv); -} - -static boolean -st_dri_is_locked(struct pipe_context *pipe) +struct dri_context * +dri_get_current(void) { - return ((struct dri_context *)pipe->priv)->isLocked; -} + struct st_api *stapi = dri_get_st_api(); + struct st_context_iface *st; -static boolean -st_dri_lost_lock(struct pipe_context *pipe) -{ - return ((struct dri_context *)pipe->priv)->wsLostLock; -} + st = stapi->get_current(stapi); -static void -st_dri_clear_lost_lock(struct pipe_context *pipe) -{ - ((struct dri_context *)pipe->priv)->wsLostLock = FALSE; + return (struct dri_context *) (st) ? st->st_manager_private : NULL; } -struct dri1_api_lock_funcs dri1_lf = { - .lock = st_dri_lock, - .unlock = st_dri_unlock, - .is_locked = st_dri_is_locked, - .is_lock_lost = st_dri_lost_lock, - .clear_lost_lock = st_dri_clear_lost_lock -}; - /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/dri_context.h index 13f497462f..845b420cf8 100644 --- a/src/gallium/state_trackers/dri/dri_context.h +++ b/src/gallium/state_trackers/dri/dri_context.h @@ -51,9 +51,6 @@ struct dri_context driOptionCache optionCache; - unsigned int d_stamp; - unsigned int r_stamp; - drmLock *lock; boolean isLocked; boolean stLostLock; @@ -62,8 +59,7 @@ struct dri_context unsigned int bind_count; /* gallium */ - struct st_context *st; - struct pipe_context *pipe; + struct st_context_iface *st; }; static INLINE struct dri_context * @@ -72,33 +68,9 @@ dri_context(__DRIcontext * driContextPriv) return (struct dri_context *)driContextPriv->driverPrivate; } -static INLINE void -dri_lock(struct dri_context *ctx) -{ - drm_context_t hw_context = ctx->cPriv->hHWContext; - char ret = 0; - - DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret); - if (ret) { - drmGetLock(ctx->sPriv->fd, hw_context, 0); - ctx->stLostLock = TRUE; - ctx->wsLostLock = TRUE; - } - ctx->isLocked = TRUE; -} - -static INLINE void -dri_unlock(struct dri_context *ctx) -{ - ctx->isLocked = FALSE; - DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext); -} - /*********************************************************************** * dri_context.c */ -extern struct dri1_api_lock_funcs dri1_lf; - void dri_destroy_context(__DRIcontext * driContextPriv); boolean dri_unbind_context(__DRIcontext * driContextPriv); @@ -108,6 +80,9 @@ dri_make_current(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv); +struct dri_context * +dri_get_current(void); + boolean dri_create_context(const __GLcontextModes * visual, __DRIcontext * driContextPriv, diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 458473853c..7437d756f7 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -32,251 +32,30 @@ #include "dri_screen.h" #include "dri_context.h" #include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" -#include "pipe/p_context.h" #include "pipe/p_screen.h" -#include "main/mtypes.h" -#include "main/renderbuffer.h" -#include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_cb_fbo.h" - #include "util/u_format.h" #include "util/u_memory.h" -#include "util/u_rect.h" #include "util/u_inlines.h" -static struct pipe_surface * -dri_surface_from_handle(struct drm_api *api, - struct pipe_screen *screen, - unsigned handle, - enum pipe_format format, - unsigned width, unsigned height, unsigned pitch) -{ - struct pipe_surface *surface = NULL; - struct pipe_texture *texture = NULL; - struct pipe_texture templat; - struct winsys_handle whandle; - - memset(&templat, 0, sizeof(templat)); - templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - templat.target = PIPE_TEXTURE_2D; - templat.last_level = 0; - templat.depth0 = 1; - templat.format = format; - templat.width0 = width; - templat.height0 = height; - - memset(&whandle, 0, sizeof(whandle)); - whandle.handle = handle; - whandle.stride = pitch; - - texture = screen->texture_from_handle(screen, &templat, &whandle); - - if (!texture) { - debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__); - return NULL; - } - - surface = screen->get_tex_surface(screen, texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - - /* we don't need the texture from this point on */ - pipe_texture_reference(&texture, NULL); - return surface; -} - -/** - * Pixmaps have will have the same name of fake front and front. - */ -static boolean -dri2_check_if_pixmap(__DRIbuffer *buffers, int count) -{ - boolean found = FALSE; - boolean is_pixmap = FALSE; - unsigned name; - int i; - - for (i = 0; i < count; i++) { - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - if (found) { - is_pixmap = buffers[i].name == name; - } else { - name = buffers[i].name; - found = TRUE; - } - default: - continue; - } - } - - return is_pixmap; -} - -/** - * This will be called a drawable is known to have been resized. - */ -void -dri_get_buffers(__DRIdrawable * dPriv) -{ - - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_surface *surface = NULL; - struct dri_screen *st_screen = dri_screen(drawable->sPriv); - struct pipe_screen *screen = st_screen->pipe_screen; - __DRIbuffer *buffers = NULL; - __DRIscreen *dri_screen = drawable->sPriv; - __DRIdrawable *dri_drawable = drawable->dPriv; - struct drm_api *api = st_screen->api; - boolean have_depth = FALSE; - int i, count; - - if ((dri_screen->dri2.loader - && (dri_screen->dri2.loader->base.version > 2) - && (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) { - buffers = (*dri_screen->dri2.loader->getBuffersWithFormat) - (dri_drawable, &dri_drawable->w, &dri_drawable->h, - drawable->attachments, drawable->num_attachments, - &count, dri_drawable->loaderPrivate); - } else { - assert(dri_screen->dri2.loader); - buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable, - &dri_drawable->w, - &dri_drawable->h, - drawable->attachments, - drawable-> - num_attachments, &count, - dri_drawable-> - loaderPrivate); - } - - if (buffers == NULL) { - return; - } - - /* set one cliprect to cover the whole dri_drawable */ - dri_drawable->x = 0; - dri_drawable->y = 0; - dri_drawable->backX = 0; - dri_drawable->backY = 0; - dri_drawable->numClipRects = 1; - dri_drawable->pClipRects[0].x1 = 0; - dri_drawable->pClipRects[0].y1 = 0; - dri_drawable->pClipRects[0].x2 = dri_drawable->w; - dri_drawable->pClipRects[0].y2 = dri_drawable->h; - dri_drawable->numBackClipRects = 1; - dri_drawable->pBackClipRects[0].x1 = 0; - dri_drawable->pBackClipRects[0].y1 = 0; - dri_drawable->pBackClipRects[0].x2 = dri_drawable->w; - dri_drawable->pBackClipRects[0].y2 = dri_drawable->h; - - if (drawable->old_num == count && - drawable->old_w == dri_drawable->w && - drawable->old_h == dri_drawable->h && - memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) { - return; - } else { - drawable->old_num = count; - drawable->old_w = dri_drawable->w; - drawable->old_h = dri_drawable->h; - memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); - } - - drawable->is_pixmap = dri2_check_if_pixmap(buffers, count); - - for (i = 0; i < count; i++) { - enum pipe_format format = 0; - int index = 0; - - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - if (!st_screen->auto_fake_front) - continue; - /* fallthrough */ - case __DRI_BUFFER_FAKE_FRONT_LEFT: - index = ST_SURFACE_FRONT_LEFT; - format = drawable->color_format; - break; - case __DRI_BUFFER_BACK_LEFT: - index = ST_SURFACE_BACK_LEFT; - format = drawable->color_format; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - index = ST_SURFACE_DEPTH; - format = drawable->depth_stencil_format; - break; - case __DRI_BUFFER_ACCUM: - default: - assert(0); - } - - if (index == ST_SURFACE_DEPTH) { - if (have_depth) - continue; - else - have_depth = TRUE; - } - - surface = dri_surface_from_handle(api, - screen, - buffers[i].name, - format, - dri_drawable->w, - dri_drawable->h, buffers[i].pitch); - - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - case __DRI_BUFFER_BACK_LEFT: - drawable->color_format = surface->format; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - drawable->depth_stencil_format = surface->format; - break; - case __DRI_BUFFER_ACCUM: - default: - assert(0); - } - - st_set_framebuffer_surface(drawable->stfb, index, surface); - pipe_surface_reference(&surface, NULL); - } - /* this needed, or else the state tracker fails to pick the new buffers */ - st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h); -} - /** * These are used for GLX_EXT_texture_from_pixmap */ void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, GLint format, __DRIdrawable *dPriv) { + struct dri_context *ctx = dri_context(pDRICtx); struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_surface *ps; + struct pipe_resource *pt = + dri_get_st_framebuffer_texture(drawable->stfb, ST_ATTACHMENT_FRONT_LEFT); - if (!drawable->stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer) { - struct gl_renderbuffer *rb = - st_new_renderbuffer_fb(drawable->color_format, 0 /*XXX*/, FALSE); - _mesa_add_renderbuffer(&drawable->stfb->Base, BUFFER_FRONT_LEFT, rb); + if (pt) { + ctx->st->teximage(ctx->st, + (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, + 0, drawable->stvis.color_format, pt, FALSE); } - - dri_get_buffers(drawable->dPriv); - st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps); - - if (!ps) - return; - - st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D : - ST_TEXTURE_RECT, 0, drawable->color_format); } void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, @@ -285,53 +64,6 @@ void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); } -void -dri_update_buffer(struct pipe_screen *screen, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - - if (ctx->d_stamp == *ctx->dPriv->pStamp && - ctx->r_stamp == *ctx->rPriv->pStamp) - return; - - ctx->d_stamp = *ctx->dPriv->pStamp; - ctx->r_stamp = *ctx->rPriv->pStamp; - - /* Ask the X server for new renderbuffers. */ - dri_get_buffers(ctx->dPriv); - if (ctx->dPriv != ctx->rPriv) - dri_get_buffers(ctx->rPriv); - -} - -void -dri_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - struct dri_drawable *drawable = dri_drawable(ctx->dPriv); - __DRIdrawable *dri_drawable = ctx->dPriv; - __DRIscreen *dri_screen = ctx->sPriv; - - /* XXX Does this function get called with DRI1? */ - - if (ctx->dPriv == NULL) { - debug_printf("%s: no drawable bound to context\n", __func__); - return; - } - -#if 0 - /* TODO if rendering to pixmaps is slow enable this code. */ - if (drawable->is_pixmap) - return; -#else - (void)drawable; -#endif - - (*dri_screen->dri2.loader->flushFrontBuffer)(dri_drawable, - dri_drawable->loaderPrivate); -} - /** * This is called when we need to set up GL rendering to a new X window. */ @@ -342,7 +74,6 @@ dri_create_buffer(__DRIscreen * sPriv, { struct dri_screen *screen = sPriv->private; struct dri_drawable *drawable = NULL; - int i; if (isPixmap) goto fail; /* not implemented */ @@ -351,45 +82,8 @@ dri_create_buffer(__DRIscreen * sPriv, if (drawable == NULL) goto fail; - if (visual->redBits == 8) { - if (visual->alphaBits == 8) - drawable->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; - else - drawable->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; - } else { - drawable->color_format = PIPE_FORMAT_B5G6R5_UNORM; - } - - switch(visual->depthBits) { - default: - case 0: - drawable->depth_stencil_format = PIPE_FORMAT_NONE; - break; - case 16: - drawable->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; - break; - case 24: - if (visual->stencilBits == 0) { - drawable->depth_stencil_format = (screen->d_depth_bits_last) ? - PIPE_FORMAT_Z24X8_UNORM: - PIPE_FORMAT_X8Z24_UNORM; - } else { - drawable->depth_stencil_format = (screen->sd_depth_bits_last) ? - PIPE_FORMAT_Z24S8_UNORM: - PIPE_FORMAT_S8Z24_UNORM; - } - break; - case 32: - drawable->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; - break; - } - - drawable->stfb = st_create_framebuffer(visual, - drawable->color_format, - drawable->depth_stencil_format, - drawable->depth_stencil_format, - dPriv->w, - dPriv->h, (void *)drawable); + dri_fill_st_visual(&drawable->stvis, screen, visual); + drawable->stfb = dri_create_st_framebuffer(drawable); if (drawable->stfb == NULL) goto fail; @@ -397,48 +91,6 @@ dri_create_buffer(__DRIscreen * sPriv, drawable->dPriv = dPriv; dPriv->driverPrivate = (void *)drawable; - /* setup dri2 buffers information */ - /* TODO incase of double buffer visual, delay fake creation */ - i = 0; - if (sPriv->dri2.loader - && (sPriv->dri2.loader->base.version > 2) - && (sPriv->dri2.loader->getBuffersWithFormat != NULL)) { - drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - drawable->attachments[i++] = visual->rgbBits; - if (!screen->auto_fake_front) { - drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; - drawable->attachments[i++] = visual->rgbBits; - } - if (visual->doubleBufferMode) { - drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; - drawable->attachments[i++] = visual->rgbBits; - } - if (visual->depthBits && visual->stencilBits) { - drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; - drawable->attachments[i++] = visual->depthBits + visual->stencilBits; - } else if (visual->depthBits) { - drawable->attachments[i++] = __DRI_BUFFER_DEPTH; - drawable->attachments[i++] = visual->depthBits; - } else if (visual->stencilBits) { - drawable->attachments[i++] = __DRI_BUFFER_STENCIL; - drawable->attachments[i++] = visual->stencilBits; - } - drawable->num_attachments = i / 2; - } else { - drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - if (!screen->auto_fake_front) - drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; - if (visual->doubleBufferMode) - drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; - if (visual->depthBits && visual->stencilBits) - drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; - else if (visual->depthBits) - drawable->attachments[i++] = __DRI_BUFFER_DEPTH; - else if (visual->stencilBits) - drawable->attachments[i++] = __DRI_BUFFER_STENCIL; - drawable->num_attachments = i; - } - drawable->desired_fences = 2; return GL_TRUE; @@ -447,319 +99,23 @@ fail: return GL_FALSE; } -static struct pipe_fence_handle * -dri_swap_fences_pop_front(struct dri_drawable *draw) -{ - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - struct pipe_fence_handle *fence = NULL; - - if (draw->cur_fences >= draw->desired_fences) { - screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); - screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); - --draw->cur_fences; - draw->tail &= DRI_SWAP_FENCES_MASK; - } - return fence; -} - -static void -dri_swap_fences_push_back(struct dri_drawable *draw, - struct pipe_fence_handle *fence) -{ - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - - if (!fence) - return; - - if (draw->cur_fences < DRI_SWAP_FENCES_MAX) { - draw->cur_fences++; - screen->fence_reference(screen, &draw->swap_fences[draw->head++], - fence); - draw->head &= DRI_SWAP_FENCES_MASK; - } -} - void dri_destroy_buffer(__DRIdrawable * dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_fence_handle *fence; - struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen; - - st_unreference_framebuffer(drawable->stfb); - drawable->desired_fences = 0; - while (drawable->cur_fences) { - fence = dri_swap_fences_pop_front(drawable); - screen->fence_reference(screen, &fence, NULL); - } - - FREE(drawable); -} - -static void -dri1_update_drawables_locked(struct dri_context *ctx, - __DRIdrawable * driDrawPriv, - __DRIdrawable * driReadPriv) -{ - if (ctx->stLostLock) { - ctx->stLostLock = FALSE; - if (driDrawPriv == driReadPriv) - DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv); - else - DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv, - driReadPriv); - } -} - -/** - * This ensures all contexts which bind to a drawable pick up the - * drawable change and signal new buffer state. - * Calling st_resize_framebuffer for each context may seem like overkill, - * but no new buffers will actually be allocated if the dimensions don't - * change. - */ - -static void -dri1_propagate_drawable_change(struct dri_context *ctx) -{ - __DRIdrawable *dPriv = ctx->dPriv; - __DRIdrawable *rPriv = ctx->rPriv; - boolean flushed = FALSE; - - if (dPriv && ctx->d_stamp != dPriv->lastStamp) { - - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - flushed = TRUE; - ctx->d_stamp = dPriv->lastStamp; - st_resize_framebuffer(dri_drawable(dPriv)->stfb, dPriv->w, dPriv->h); - - } - - if (rPriv && dPriv != rPriv && ctx->r_stamp != rPriv->lastStamp) { - - if (!flushed) - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - ctx->r_stamp = rPriv->lastStamp; - st_resize_framebuffer(dri_drawable(rPriv)->stfb, rPriv->w, rPriv->h); - - } else if (rPriv && dPriv == rPriv) { - - ctx->r_stamp = ctx->d_stamp; - - } -} - -void -dri1_update_drawables(struct dri_context *ctx, - struct dri_drawable *draw, struct dri_drawable *read) -{ - dri_lock(ctx); - dri1_update_drawables_locked(ctx, draw->dPriv, read->dPriv); - dri_unlock(ctx); - - dri1_propagate_drawable_change(ctx); -} - -static INLINE boolean -dri1_intersect_src_bbox(struct drm_clip_rect *dst, - int dst_x, - int dst_y, - const struct drm_clip_rect *src, - const struct drm_clip_rect *bbox) -{ - int xy1; - int xy2; - - xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : - (int)bbox->x1 + dst_x; - xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : - (int)bbox->x2 + dst_x; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->x1 = xy1; - dst->x2 = xy2; - - xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : - (int)bbox->y1 + dst_y; - xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : - (int)bbox->y2 + dst_y; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->y1 = xy1; - dst->y2 = xy2; - return TRUE; -} - -static void -dri1_swap_copy(struct dri_context *ctx, - struct pipe_surface *dst, - struct pipe_surface *src, - __DRIdrawable * dPriv, const struct drm_clip_rect *bbox) -{ - struct pipe_context *pipe = ctx->pipe; - struct drm_clip_rect clip; - struct drm_clip_rect *cur; int i; - cur = dPriv->pClipRects; - - for (i = 0; i < dPriv->numClipRects; ++i) { - if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) { - if (pipe->surface_copy) { - pipe->surface_copy(pipe, dst, clip.x1, clip.y1, - src, - (int)clip.x1 - dPriv->x, - (int)clip.y1 - dPriv->y, - clip.x2 - clip.x1, clip.y2 - clip.y1); - } else { - util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1, - src, - (int)clip.x1 - dPriv->x, - (int)clip.y1 - dPriv->y, - clip.x2 - clip.x1, clip.y2 - clip.y1); - } - } - } -} - -static void -dri1_copy_to_front(struct dri_context *ctx, - struct pipe_surface *surf, - __DRIdrawable * dPriv, - const struct drm_clip_rect *sub_box, - struct pipe_fence_handle **fence) -{ - struct pipe_context *pipe = ctx->pipe; - boolean save_lost_lock; - uint cur_w; - uint cur_h; - struct drm_clip_rect bbox; - boolean visible = TRUE; - - *fence = NULL; - - dri_lock(ctx); - save_lost_lock = ctx->stLostLock; - dri1_update_drawables_locked(ctx, dPriv, dPriv); - st_get_framebuffer_dimensions(dri_drawable(dPriv)->stfb, &cur_w, &cur_h); - - bbox.x1 = 0; - bbox.x2 = cur_w; - bbox.y1 = 0; - bbox.y2 = cur_h; - - if (sub_box) - visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box); - - if (visible && __dri1_api_hooks->present_locked) { - - __dri1_api_hooks->present_locked(pipe, - surf, - dPriv->pClipRects, - dPriv->numClipRects, - dPriv->x, dPriv->y, &bbox, fence); - - } else if (visible && __dri1_api_hooks->front_srf_locked) { - - struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe); + dri1_swap_fences_clear(drawable); - if (front) - dri1_swap_copy(ctx, front, surf, dPriv, &bbox); - - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence); - } - - ctx->stLostLock = save_lost_lock; - - /** - * FIXME: Revisit this: Update drawables on copy_sub_buffer ? - */ - - if (!sub_box) - dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv); - - dri_unlock(ctx); - dri1_propagate_drawable_change(ctx); -} - -void -dri1_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - struct pipe_fence_handle *dummy_fence; + pipe_surface_reference(&drawable->dri1_surface, NULL); + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); - dri1_copy_to_front(ctx, surf, ctx->dPriv, NULL, &dummy_fence); - screen->fence_reference(screen, &dummy_fence, NULL); + dri_destroy_st_framebuffer(drawable->stfb); - /** - * FIXME: Do we need swap throttling here? - */ -} - -void -dri_swap_buffers(__DRIdrawable * dPriv) -{ - struct dri_context *ctx; - struct pipe_surface *back_surf; - struct dri_drawable *draw = dri_drawable(dPriv); - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - struct pipe_fence_handle *fence; - struct st_context *st = st_get_current(); - - assert(__dri1_api_hooks != NULL); - - if (!st) - return; /* For now */ - - ctx = (struct dri_context *)st->pipe->priv; - - st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf); - if (back_surf) { - st_notify_swapbuffers(draw->stfb); - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - fence = dri_swap_fences_pop_front(draw); - if (fence) { - (void)screen->fence_finish(screen, fence, 0); - screen->fence_reference(screen, &fence, NULL); - } - dri1_copy_to_front(ctx, back_surf, dPriv, NULL, &fence); - dri_swap_fences_push_back(draw, fence); - screen->fence_reference(screen, &fence, NULL); - } -} - -void -dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h) -{ - struct pipe_screen *screen = dri_screen(dPriv->driScreenPriv)->pipe_screen; - struct drm_clip_rect sub_bbox; - struct dri_context *ctx; - struct pipe_surface *back_surf; - struct dri_drawable *draw = dri_drawable(dPriv); - struct pipe_fence_handle *dummy_fence; - struct st_context *st = st_get_current(); - - assert(__dri1_api_hooks != NULL); - - if (!st) - return; - - ctx = (struct dri_context *)st->pipe->priv; - - sub_bbox.x1 = x; - sub_bbox.x2 = x + w; - sub_bbox.y1 = y; - sub_bbox.y2 = y + h; + drawable->desired_fences = 0; - st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf); - if (back_surf) { - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - dri1_copy_to_front(ctx, back_surf, dPriv, &sub_bbox, &dummy_fence); - screen->fence_reference(screen, &dummy_fence, NULL); - } + FREE(drawable); } /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h index 8bc59cb4c3..6aa424a4f5 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.h +++ b/src/gallium/state_trackers/dri/dri_drawable.h @@ -29,6 +29,8 @@ #define DRI_DRAWABLE_H #include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "state_tracker/st_api.h" struct pipe_surface; struct pipe_fence_handle; @@ -44,26 +46,26 @@ struct dri_drawable __DRIdrawable *dPriv; __DRIscreen *sPriv; - unsigned attachments[8]; - unsigned num_attachments; - - boolean is_pixmap; + /* gallium */ + struct st_framebuffer_iface *stfb; + struct st_visual stvis; __DRIbuffer old[8]; unsigned old_num; unsigned old_w; unsigned old_h; - /* gallium */ - struct st_framebuffer *stfb; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + unsigned int texture_mask, texture_stamp; + struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; unsigned int head; unsigned int tail; unsigned int desired_fences; unsigned int cur_fences; - enum pipe_format color_format; - enum pipe_format depth_stencil_format; + /* used only by DRI1 */ + struct pipe_surface *dri1_surface; }; static INLINE struct dri_drawable * @@ -80,20 +82,6 @@ dri_create_buffer(__DRIscreen * sPriv, __DRIdrawable * dPriv, const __GLcontextModes * visual, boolean isPixmap); -void -dri_update_buffer(struct pipe_screen *screen, void *context_private); - -void -dri_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private); - -void dri_swap_buffers(__DRIdrawable * dPriv); - -void -dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h); - -void dri_get_buffers(__DRIdrawable * dPriv); - void dri_destroy_buffer(__DRIdrawable * dPriv); void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, @@ -102,13 +90,6 @@ void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv); -void -dri1_update_drawables(struct dri_context *ctx, - struct dri_drawable *draw, struct dri_drawable *read); - -void -dri1_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private); #endif /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c index 800677a2d1..df458e1eb0 100644 --- a/src/gallium/state_trackers/dri/dri_extensions.c +++ b/src/gallium/state_trackers/dri/dri_extensions.c @@ -38,9 +38,11 @@ void dri_init_extensions(struct dri_context *ctx) { + struct st_context *st = (struct st_context *) ctx->st; + /* New extensions should be added in mesa/state_tracker/st_extensions.c * and not in this file. */ - driInitExtensions(ctx->st->ctx, NULL, GL_FALSE); + driInitExtensions(st->ctx, NULL, GL_FALSE); } /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c index 7ccad8f5dd..17b9f1c5fa 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -36,11 +36,13 @@ #include "dri_screen.h" #include "dri_context.h" #include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" +#include "util/u_inlines.h" #include "pipe/p_screen.h" #include "pipe/p_format.h" #include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" #include "util/u_debug.h" @@ -53,7 +55,7 @@ PUBLIC const char __driConfigOptions[] = DRI_CONF_ALLOW_LARGE_TEXTURES(1) DRI_CONF_SECTION_END DRI_CONF_END; - const uint __driNConfigOptions = 3; +const uint __driNConfigOptions = 3; static const __DRItexBufferExtension dri2TexBufferExtension = { { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, @@ -66,10 +68,23 @@ dri2_flush_drawable(__DRIdrawable *draw) { } +static void +dri2_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_context *ctx = dri_context(dPriv->driContextPriv); + + dri2InvalidateDrawable(dPriv); + drawable->dPriv->lastStamp = *drawable->dPriv->pStamp; + + if (ctx) + ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb); +} + static const __DRI2flushExtension dri2FlushExtension = { { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, dri2_flush_drawable, - dri2InvalidateDrawable, + dri2_invalidate_drawable, }; static const __DRIextension *dri_screen_extensions[] = { @@ -83,9 +98,7 @@ static const __DRI2flushExtension dri2FlushExtension = { NULL }; -struct dri1_api *__dri1_api_hooks = NULL; - -static const __DRIconfig ** +const __DRIconfig ** dri_fill_in_modes(struct dri_screen *screen, unsigned pixel_bits) { @@ -229,6 +242,68 @@ dri_fill_in_modes(struct dri_screen *screen, } /** + * Roughly the converse of dri_fill_in_modes. + */ +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const __GLcontextModes *mode) +{ + memset(stvis, 0, sizeof(*stvis)); + + stvis->samples = mode->samples; + stvis->render_buffer = ST_ATTACHMENT_INVALID; + + if (mode->redBits == 8) { + if (mode->alphaBits == 8) + stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; + else + stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; + } else { + stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; + } + + switch (mode->depthBits) { + default: + case 0: + stvis->depth_stencil_format = PIPE_FORMAT_NONE; + break; + case 16: + stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; + break; + case 24: + if (mode->stencilBits == 0) { + stvis->depth_stencil_format = (screen->d_depth_bits_last) ? + PIPE_FORMAT_Z24X8_UNORM: + PIPE_FORMAT_X8Z24_UNORM; + } else { + stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? + PIPE_FORMAT_Z24S8_UNORM: + PIPE_FORMAT_S8Z24_UNORM; + } + break; + case 32: + stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; + break; + } + + stvis->accum_format = (mode->haveAccumBuffer) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (mode->stereoMode) { + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + if (mode->haveDepthBuffer || mode->haveStencilBuffer) + stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; + /* let the state tracker allocate the accum buffer */ +} + +/** * Get information about previous buffer swaps. */ static int @@ -240,73 +315,31 @@ dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo) return 0; } -static INLINE void -dri_copy_version(struct dri1_api_version *dst, - const struct __DRIversionRec *src) -{ - dst->major = src->major; - dst->minor = src->minor; - dst->patch_level = src->patch; -} - -static const __DRIconfig ** -dri_init_screen(__DRIscreen * sPriv) +static void +dri_destroy_screen(__DRIscreen * sPriv) { - struct dri_screen *screen; - const __DRIconfig **configs; - struct dri1_create_screen_arg arg; + struct dri_screen *screen = dri_screen(sPriv); + int i; - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; + if (screen->dri1_pipe) + screen->dri1_pipe->destroy(screen->dri1_pipe); - screen->api = drm_api_create(); - screen->sPriv = sPriv; - screen->fd = sPriv->fd; - screen->drmLock = (drmLock *) & sPriv->pSAREA->lock; + if (screen->smapi) + dri_destroy_st_manager(screen->smapi); + if (screen->pipe_screen) + screen->pipe_screen->destroy(screen->pipe_screen); - sPriv->private = (void *)screen; - sPriv->extensions = dri_screen_extensions; - - arg.base.mode = DRM_CREATE_DRI1; - arg.lf = &dri1_lf; - arg.ddx_info = sPriv->pDevPriv; - arg.ddx_info_size = sPriv->devPrivSize; - arg.sarea = sPriv->pSAREA; - dri_copy_version(&arg.ddx_version, &sPriv->ddx_version); - dri_copy_version(&arg.dri_version, &sPriv->dri_version); - dri_copy_version(&arg.drm_version, &sPriv->drm_version); - arg.api = NULL; - - screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base); - - if (!screen->pipe_screen || !arg.api) { - debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__); - goto out_no_screen; + for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { + FREE(screen->optionCache.info[i].name); + FREE(screen->optionCache.info[i].ranges); } - __dri1_api_hooks = arg.api; - - screen->pipe_screen->flush_frontbuffer = dri1_flush_frontbuffer; - driParseOptionInfo(&screen->optionCache, - __driConfigOptions, __driNConfigOptions); - - /** - * FIXME: If the driver supports format conversion swapbuffer blits, we might - * want to support other color bit depths than the server is currently - * using. - */ - - configs = dri_fill_in_modes(screen, sPriv->fbBPP); - if (!configs) - goto out_no_configs; + FREE(screen->optionCache.info); + FREE(screen->optionCache.values); - return configs; - out_no_configs: - screen->pipe_screen->destroy(screen->pipe_screen); - out_no_screen: FREE(screen); - return NULL; + sPriv->private = NULL; + sPriv->extensions = NULL; } /** @@ -324,7 +357,7 @@ dri_init_screen2(__DRIscreen * sPriv) screen = CALLOC_STRUCT(dri_screen); if (!screen) - goto fail; + return NULL; screen->api = drm_api_create(); screen->sPriv = sPriv; @@ -339,9 +372,9 @@ dri_init_screen2(__DRIscreen * sPriv) goto fail; } - /* We need to hook in here */ - screen->pipe_screen->update_buffer = dri_update_buffer; - screen->pipe_screen->flush_frontbuffer = dri_flush_frontbuffer; + screen->smapi = dri_create_st_manager(screen); + if (!screen->smapi) + goto fail; driParseOptionInfo(&screen->optionCache, __driConfigOptions, __driNConfigOptions); @@ -350,46 +383,27 @@ dri_init_screen2(__DRIscreen * sPriv) dri2_ext->getBuffersWithFormat != NULL; return dri_fill_in_modes(screen, 32); - fail: +fail: + dri_destroy_screen(sPriv); return NULL; } -static void -dri_destroy_screen(__DRIscreen * sPriv) -{ - struct dri_screen *screen = dri_screen(sPriv); - int i; - - screen->pipe_screen->destroy(screen->pipe_screen); - - for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { - FREE(screen->optionCache.info[i].name); - FREE(screen->optionCache.info[i].ranges); - } - - FREE(screen->optionCache.info); - FREE(screen->optionCache.values); - - FREE(screen); - sPriv->private = NULL; -} - -PUBLIC const struct __DriverAPIRec driDriverAPI = { - .InitScreen = dri_init_screen, +const struct __DriverAPIRec driDriverAPI = { .DestroyScreen = dri_destroy_screen, .CreateContext = dri_create_context, .DestroyContext = dri_destroy_context, .CreateBuffer = dri_create_buffer, .DestroyBuffer = dri_destroy_buffer, - .SwapBuffers = dri_swap_buffers, .MakeCurrent = dri_make_current, .UnbindContext = dri_unbind_context, .GetSwapInfo = dri_get_swap_info, .GetDrawableMSC = driDrawableGetMSC32, .WaitForMSC = driWaitForMSC32, - .CopySubBuffer = dri_copy_sub_buffer, - .InitScreen = dri_init_screen, .InitScreen2 = dri_init_screen2, + + .InitScreen = dri1_init_screen, + .SwapBuffers = dri1_swap_buffers, + .CopySubBuffer = dri1_copy_sub_buffer, }; /* This is the table of extensions that the loader will dlsym() for. */ diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h index 75a0ee4250..e9944e0f63 100644 --- a/src/gallium/state_trackers/dri/dri_screen.h +++ b/src/gallium/state_trackers/dri/dri_screen.h @@ -36,8 +36,9 @@ #include "xmlconfig.h" #include "pipe/p_compiler.h" - -#include "state_tracker/dri1_api.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "state_tracker/st_api.h" struct dri_screen { @@ -60,6 +61,11 @@ struct dri_screen boolean d_depth_bits_last; boolean sd_depth_bits_last; boolean auto_fake_front; + + struct st_manager *smapi; + + /* used only by DRI1 */ + struct pipe_context *dri1_pipe; }; /** cast wrapper */ @@ -69,11 +75,14 @@ dri_screen(__DRIscreen * sPriv) return (struct dri_screen *)sPriv->private; } -/*********************************************************************** - * dri_screen.c - */ +extern const uint __driNConfigOptions; + +const __DRIconfig ** +dri_fill_in_modes(struct dri_screen *screen, unsigned pixel_bits); -extern struct dri1_api *__dri1_api_hooks; +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const __GLcontextModes *mode); #endif diff --git a/src/gallium/state_trackers/dri/dri_st_api.c b/src/gallium/state_trackers/dri/dri_st_api.c new file mode 100644 index 0000000000..7533cc4b1e --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_st_api.c @@ -0,0 +1,445 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_debug.h" +#include "state_tracker/drm_api.h" +#include "state_tracker/st_manager.h" /* for st_manager_create_api */ + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" + +static struct { + int32_t refcnt; + struct st_api *stapi; +} dri_st_api; + +/** + * Get the format of an attachment. + */ +static INLINE enum pipe_format +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + enum pipe_format format; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = drawable->stvis.color_format; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = drawable->stvis.depth_stencil_format; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + return format; +} + +/** + * Process __DRIbuffer and convert them into pipe_textures. + */ +static void +dri_drawable_process_buffers(struct dri_drawable *drawable, + __DRIbuffer *buffers, unsigned count) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + __DRIdrawable *dri_drawable = drawable->dPriv; + struct pipe_resource templ; + struct winsys_handle whandle; + boolean have_depth = FALSE; + unsigned i; + + if (drawable->old_num == count && + drawable->old_w == dri_drawable->w && + drawable->old_h == dri_drawable->h && + memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) + return; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + + memset(&templ, 0, sizeof(templ)); + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = dri_drawable->w; + templ.height0 = dri_drawable->h; + templ.depth0 = 1; + + memset(&whandle, 0, sizeof(whandle)); + + for (i = 0; i < count; i++) { + __DRIbuffer *buf = &buffers[i]; + enum st_attachment_type statt; + enum pipe_format format; + + switch (buf->attachment) { + case __DRI_BUFFER_FRONT_LEFT: + if (!screen->auto_fake_front) { + statt = ST_ATTACHMENT_INVALID; + break; + } + /* fallthrough */ + case __DRI_BUFFER_FAKE_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case __DRI_BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_STENCIL: + statt = ST_ATTACHMENT_DEPTH_STENCIL; + /* use only the first depth/stencil buffer */ + if (have_depth) + statt = ST_ATTACHMENT_INVALID; + else + have_depth = TRUE; + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + format = dri_drawable_get_format(drawable, statt); + if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + whandle.handle = buf->name; + whandle.stride = buf->pitch; + + drawable->textures[statt] = + screen->pipe_screen->resource_from_handle(screen->pipe_screen, + &templ, &whandle); + } + + drawable->old_num = count; + drawable->old_w = dri_drawable->w; + drawable->old_h = dri_drawable->h; + memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); +} + +/** + * Retrieve __DRIbuffer from the DRI loader. + */ +static __DRIbuffer * +dri_drawable_get_buffers(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned *count) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; + boolean with_format; + __DRIbuffer *buffers; + int num_buffers; + unsigned attachments[8]; + unsigned num_attachments, i; + + assert(loader); + with_format = (loader->base.version > 2 && loader->getBuffersWithFormat); + + num_attachments = 0; + for (i = 0; i < *count; i++) { + enum pipe_format format; + int att; + + format = dri_drawable_get_format(drawable, statts[i]); + if (format == PIPE_FORMAT_NONE) + continue; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + att = __DRI_BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + att = __DRI_BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + att = __DRI_BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + att = __DRI_BUFFER_BACK_RIGHT; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + att = __DRI_BUFFER_DEPTH_STENCIL; + break; + default: + att = -1; + break; + } + + if (att >= 0) { + attachments[num_attachments++] = att; + if (with_format) { + attachments[num_attachments++] = + util_format_get_blocksizebits(format); + } + } + } + + if (with_format) { + num_attachments /= 2; + buffers = loader->getBuffersWithFormat(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + else { + buffers = loader->getBuffers(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + + if (buffers) { + /* set one cliprect to cover the whole dri_drawable */ + dri_drawable->x = 0; + dri_drawable->y = 0; + dri_drawable->backX = 0; + dri_drawable->backY = 0; + dri_drawable->numClipRects = 1; + dri_drawable->pClipRects[0].x1 = 0; + dri_drawable->pClipRects[0].y1 = 0; + dri_drawable->pClipRects[0].x2 = dri_drawable->w; + dri_drawable->pClipRects[0].y2 = dri_drawable->h; + dri_drawable->numBackClipRects = 1; + dri_drawable->pBackClipRects[0].x1 = 0; + dri_drawable->pBackClipRects[0].y1 = 0; + dri_drawable->pBackClipRects[0].x2 = dri_drawable->w; + dri_drawable->pBackClipRects[0].y2 = dri_drawable->h; + + *count = num_buffers; + } + + return buffers; +} + +static boolean +dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + unsigned statt_mask, i; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= (1 << statts[i]); + + /* + * dPriv->pStamp is the server stamp. It should be accessed with a lock, at + * least for DRI1. dPriv->lastStamp is the client stamp. It has the value + * of the server stamp when last checked. + * + * This function updates the textures and records the stamp of the textures. + */ + if (drawable->texture_stamp != drawable->dPriv->lastStamp || + (statt_mask & ~drawable->texture_mask)) { + if (__dri1_api_hooks) { + dri1_allocate_textures(drawable, + drawable->dPriv->w, drawable->dPriv->h, statt_mask); + } + else { + __DRIbuffer *buffers; + unsigned num_buffers = count; + + buffers = dri_drawable_get_buffers(drawable, statts, &num_buffers); + dri_drawable_process_buffers(drawable, buffers, num_buffers); + } + + drawable->texture_stamp = drawable->dPriv->lastStamp; + drawable->texture_mask = statt_mask; + } + + if (!out) + return TRUE; + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_resource_reference(&out[i], drawable->textures[statts[i]]); + } + + return TRUE; +} + +static boolean +dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + struct __DRIdri2LoaderExtensionRec *loader = + drawable->sPriv->dri2.loader; + + if (__dri1_api_hooks) { + struct pipe_resource *ptex = drawable->textures[statt]; + if (ptex) + dri1_flush_frontbuffer(drawable, ptex); + return TRUE; + } + + if (statt == ST_ATTACHMENT_FRONT_LEFT && loader->flushFrontBuffer) { + loader->flushFrontBuffer(drawable->dPriv, + drawable->dPriv->loaderPrivate); + } + + return TRUE; +} + +/** + * Create a framebuffer from the given drawable. + */ +struct st_framebuffer_iface * +dri_create_st_framebuffer(struct dri_drawable *drawable) +{ + struct st_framebuffer_iface *stfbi; + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + if (stfbi) { + stfbi->visual = &drawable->stvis; + stfbi->flush_front = dri_st_framebuffer_flush_front; + stfbi->validate = dri_st_framebuffer_validate; + stfbi->st_manager_private = (void *) drawable; + } + + return stfbi; +} + +/** + * Destroy a framebuffer. + */ +void +dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + FREE(stfbi); +} + +/** + * Return the texture at an attachment. Allocate the texture if it does not + * exist. + */ +struct pipe_resource * +dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + + if (!(drawable->texture_mask & (1 << statt))) { + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned i, count = 0; + + /* make sure DRI2 does not destroy existing buffers */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (drawable->texture_mask & (1 << i)) { + statts[count++] = i; + } + } + statts[count++] = statt; + + drawable->texture_stamp = drawable->dPriv->lastStamp - 1; + dri_st_framebuffer_validate(stfbi, statts, count, NULL); + } + + return drawable->textures[statt]; +} + +/** + * Add a reference to the st_api of the state tracker. + */ +static void +_dri_get_st_api(void) +{ + p_atomic_inc(&dri_st_api.refcnt); + if (p_atomic_read(&dri_st_api.refcnt) == 1) + dri_st_api.stapi = st_manager_create_api(); +} + +/** + * Remove a reference to the st_api of the state tracker. + */ +static void +_dri_put_st_api(void) +{ + struct st_api *stapi = dri_st_api.stapi; + + if (p_atomic_dec_zero(&dri_st_api.refcnt)) { + stapi->destroy(dri_st_api.stapi); + dri_st_api.stapi = NULL; + } +} + +/** + * Create a state tracker manager from the given screen. + */ +struct st_manager * +dri_create_st_manager(struct dri_screen *screen) +{ + struct st_manager *smapi; + + smapi = CALLOC_STRUCT(st_manager); + if (smapi) { + smapi->screen = screen->pipe_screen; + _dri_get_st_api(); + } + + return smapi; +} + +/** + * Destroy a state tracker manager. + */ +void +dri_destroy_st_manager(struct st_manager *smapi) +{ + _dri_put_st_api(); + FREE(smapi); +} + +/** + * Return the st_api of OpenGL state tracker. + */ +struct st_api * +dri_get_st_api(void) +{ + assert(dri_st_api.stapi); + return dri_st_api.stapi; +} diff --git a/src/gallium/state_trackers/dri/dri_st_api.h b/src/gallium/state_trackers/dri/dri_st_api.h new file mode 100644 index 0000000000..0869c620a4 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_st_api.h @@ -0,0 +1,55 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _DRI_ST_API_H_ +#define _DRI_ST_API_H_ + +#include "state_tracker/st_api.h" + +struct dri_screen; +struct dri_drawable; + +struct st_api * +dri_get_st_api(void); + +struct st_manager * +dri_create_st_manager(struct dri_screen *screen); + +void +dri_destroy_st_manager(struct st_manager *smapi); + +struct st_framebuffer_iface * +dri_create_st_framebuffer(struct dri_drawable *drawable); + +void +dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +struct pipe_resource * +dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt); + +#endif /* _DRI_ST_API_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index e4972d493d..4d70fb987a 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -36,234 +36,27 @@ #include "native.h" #include "egl_g3d.h" +#include "egl_g3d_st.h" #include "egl_g3d_image.h" -#include "egl_st.h" - -/** - * Validate the draw/read surfaces of the context. - */ -static void -egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct pipe_screen *screen = gdpy->native->screen; - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { - ST_SURFACE_FRONT_LEFT, - ST_SURFACE_BACK_LEFT, - ST_SURFACE_FRONT_RIGHT, - ST_SURFACE_BACK_RIGHT, - }; - EGLint num_surfaces, s; - - /* validate draw and/or read buffers */ - num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; - for (s = 0; s < num_surfaces; s++) { - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - EGLint att; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - if (!gctx->force_validate) { - unsigned int seq_num; - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &seq_num, NULL, NULL, NULL); - /* skip validation */ - if (gsurf->sequence_number == seq_num) - continue; - } - - pipe_surface_reference(&gsurf->render_surface, NULL); - memset(textures, 0, sizeof(textures)); - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &gsurf->sequence_number, textures, - &gsurf->base.Width, &gsurf->base.Height); - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - struct pipe_texture *pt = textures[att]; - struct pipe_surface *ps; - - if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) { - ps = screen->get_tex_surface(screen, pt, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb, - st_att_map[att], ps); - - if (gsurf->render_att == att) - pipe_surface_reference(&gsurf->render_surface, ps); - - pipe_surface_reference(&ps, NULL); - pipe_texture_reference(&pt, NULL); - } - } - - gctx->stapi->st_resize_framebuffer(gbuf->st_fb, - gsurf->base.Width, gsurf->base.Height); - } - - gctx->force_validate = EGL_FALSE; - -} - -/** - * Create a st_framebuffer. - */ -static struct st_framebuffer * -create_framebuffer(_EGLContext *ctx, _EGLSurface *surf) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); - - return gctx->stapi->st_create_framebuffer(&gconf->native->mode, - gconf->native->color_format, gconf->native->depth_format, - gconf->native->stencil_format, - gsurf->base.Width, gsurf->base.Height, &gsurf->base); -} - -/** - * Update the attachments of draw/read surfaces. - */ -static void -egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - EGLint s; - - /* route draw and read buffers' attachments */ - for (s = 0; s < 2; s++) { - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - gbuf->attachment_mask = (1 << gsurf->render_att); - - /* FIXME OpenGL defaults to draw the front or back buffer when the - * context is single-buffered or double-buffered respectively. In EGL, - * however, the buffer to be drawn is determined by the surface, instead - * of the context. As a result, rendering to a pixmap surface with a - * double-buffered context does not work as expected. - * - * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt == - * NATIVE_ATTACHMENT_FRONT_LEFT); - */ - - /* - * FIXME If the back buffer is asked for here, and the front buffer is - * later needed by the client API (e.g. glDrawBuffer is called to draw - * the front buffer), it will create a new pipe texture and draw there. - * One fix is to ask for both buffers here, but it would be a waste if - * the front buffer is never used. A better fix is to add a callback to - * the pipe screen with context private (just like flush_frontbuffer). - */ - } -} - -/** - * Reallocate the context's framebuffers after draw/read surfaces change. - */ -static EGLBoolean -egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface); - struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface); - - /* unreference the old framebuffers */ - if (gctx->draw.st_fb) { - EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb); - void *priv; - - priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb); - if (!gdraw || priv != (void *) &gdraw->base) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - - if (is_equal) { - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - else { - priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb); - if (!gread || priv != (void *) &gread->base) { - gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb); - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - } - } - - if (!gdraw) - return EGL_TRUE; - - /* create the draw fb */ - if (!gctx->draw.st_fb) { - gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base); - if (!gctx->draw.st_fb) - return EGL_FALSE; - } - - /* create the read fb */ - if (!gctx->read.st_fb) { - if (gread != gdraw) { - gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base); - if (!gctx->read.st_fb) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - return EGL_FALSE; - } - } - else { - /* there is no st_reference_framebuffer... */ - gctx->read.st_fb = gctx->draw.st_fb; - } - } - - egl_g3d_route_context(dpy, &gctx->base); - gctx->force_validate = EGL_TRUE; - - return EGL_TRUE; -} /** * Return the state tracker for the given context. */ -static const struct egl_g3d_st * +static struct st_api * egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - const struct egl_g3d_st *stapi; + struct st_api *stapi; EGLint idx = -1; switch (ctx->ClientAPI) { case EGL_OPENGL_ES_API: switch (ctx->ClientVersion) { case 1: - idx = EGL_G3D_ST_OPENGL_ES; + idx = ST_API_OPENGL_ES1; break; case 2: - idx = EGL_G3D_ST_OPENGL_ES2; + idx = ST_API_OPENGL_ES2; break; default: _eglLog(_EGL_WARNING, "unknown client version %d", @@ -272,10 +65,10 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) } break; case EGL_OPENVG_API: - idx = EGL_G3D_ST_OPENVG; + idx = ST_API_OPENVG; break; case EGL_OPENGL_API: - idx = EGL_G3D_ST_OPENGL; + idx = ST_API_OPENGL; break; default: _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); @@ -299,10 +92,10 @@ egl_g3d_init_st(_EGLDriver *drv) if (gdrv->api_mask) return; - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - gdrv->stapis[i] = egl_g3d_get_st(i); + for (i = 0; i < ST_API_COUNT; i++) { + gdrv->stapis[i] = egl_g3d_create_st_api(i); if (gdrv->stapis[i]) - gdrv->api_mask |= gdrv->stapis[i]->api_bit; + gdrv->api_mask |= egl_g3d_st_api_bit(i); } if (gdrv->api_mask) @@ -351,35 +144,6 @@ egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy) } } -/** - * Return an API mask that consists of the state trackers that supports the - * given mode. - * - * FIXME add st_is_mode_supported()? - */ -static EGLint -get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask) -{ - EGLint check; - - /* OpenGL ES 1.x and 2.x are checked together */ - check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; - if (api_mask & check) { - /* this is required by EGL, not by OpenGL ES */ - if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode) - api_mask &= ~check; - } - - check = EGL_OPENVG_BIT; - if (api_mask & check) { - /* vega st needs the depth/stencil rb */ - if (!mode->depthBits && !mode->stencilBits) - api_mask &= ~check; - } - - return api_mask; -} - #ifdef EGL_MESA_screen_surface static void @@ -444,18 +208,88 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) #endif /* EGL_MESA_screen_surface */ /** + * Initialize an EGL config from the native config. + */ +static EGLBoolean +egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const struct native_config *nconf) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + const __GLcontextModes *mode = &nconf->mode; + EGLint buffer_mask, api_mask; + EGLBoolean valid; + EGLint i; + + buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (mode->doubleBufferMode) + buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (mode->stereoMode) { + buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (mode->doubleBufferMode) + buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + gconf->stvis.buffer_mask = buffer_mask; + gconf->stvis.color_format = nconf->color_format; + gconf->stvis.depth_stencil_format = nconf->depth_format; + gconf->stvis.accum_format = PIPE_FORMAT_NONE; + gconf->stvis.samples = 0; + + gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT) ? + ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; + + api_mask = 0; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; + if (stapi) { + if (stapi->is_visual_supported(stapi, &gconf->stvis)) + api_mask |= egl_g3d_st_api_bit(i); + } + } + /* this is required by EGL, not by OpenGL ES */ + if ((mode->drawableType & GLX_WINDOW_BIT) && !mode->doubleBufferMode) + api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); + + if (!api_mask) { + _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", + mode->visualID); + } + + valid = _eglConfigFromContextModesRec(&gconf->base, + mode, api_mask, api_mask); + if (valid) { +#ifdef EGL_MESA_screen_surface + /* check if scanout surface bit is set */ + if (nconf->scanout_bit) { + EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE); + val |= EGL_SCREEN_BIT_MESA; + SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val); + } +#endif + valid = _eglValidateConfig(&gconf->base, EGL_FALSE); + } + if (!valid) { + _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", mode->visualID); + return EGL_FALSE; + } + + gconf->native = nconf; + + return EGL_TRUE; +} + +/** * Add configs to display and return the next config ID. */ static EGLint egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) { - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct egl_g3d_display *gdpy = egl_g3d_display(dpy); const struct native_config **native_configs; int num_configs, i; - native_configs = gdpy->native->get_configs(gdpy->native, - &num_configs); + native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); if (!num_configs) { if (native_configs) free(native_configs); @@ -463,61 +297,25 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) } for (i = 0; i < num_configs; i++) { - EGLint api_mask; struct egl_g3d_config *gconf; - EGLBoolean valid; gconf = CALLOC_STRUCT(egl_g3d_config); - if (!gconf) - continue; - - _eglInitConfig(&gconf->base, dpy, id); - - api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask); - if (!api_mask) { - _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", - native_configs[i]->mode.visualID); - } - - valid = _eglConfigFromContextModesRec(&gconf->base, - &native_configs[i]->mode, api_mask, api_mask); - if (valid) { -#ifdef EGL_MESA_screen_surface - /* check if scanout surface bit is set */ - if (native_configs[i]->scanout_bit) { - EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE); - val |= EGL_SCREEN_BIT_MESA; - SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val); + if (gconf) { + _eglInitConfig(&gconf->base, dpy, id); + if (!egl_g3d_init_config(drv, dpy, &gconf->base, native_configs[i])) { + free(gconf); + continue; } -#endif - valid = _eglValidateConfig(&gconf->base, EGL_FALSE); - } - if (!valid) { - _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", - native_configs[i]->mode.visualID); - free(gconf); - continue; - } - gconf->native = native_configs[i]; - _eglAddConfig(dpy, &gconf->base); - id++; + _eglAddConfig(dpy, &gconf->base); + id++; + } } free(native_configs); return id; } -/** - * Re-validate the context. - */ -static void -egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) -{ - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); -} - static void egl_g3d_invalid_surface(struct native_display *ndpy, struct native_surface *nsurf, @@ -525,11 +323,15 @@ egl_g3d_invalid_surface(struct native_display *ndpy, { /* XXX not thread safe? */ struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); - struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext); - - /* set force_validate to skip an unnecessary check */ + struct egl_g3d_context *gctx; + + /* + * Some functions such as egl_g3d_copy_buffers create a temporary native + * surface. There is no gsurf associated with it. + */ + gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; if (gctx) - gctx->force_validate = TRUE; + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); } static struct native_event_handler egl_g3d_native_event_handler = { @@ -545,6 +347,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) _eglReleaseDisplayResources(drv, dpy); _eglCleanupDisplay(dpy); + if (gdpy->pipe) + gdpy->pipe->destroy(gdpy->pipe); + if (dpy->Screens) { for (i = 0; i < dpy->NumScreens; i++) { struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]); @@ -554,6 +359,9 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) free(dpy->Screens); } + if (gdpy->smapi) + egl_g3d_destroy_st_manager(gdpy->smapi); + if (gdpy->native) gdpy->native->destroy(gdpy->native); @@ -588,11 +396,17 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } gdpy->native->user_data = (void *) dpy; - gdpy->native->screen->update_buffer = egl_g3d_update_buffer; egl_g3d_init_st(&gdrv->base); dpy->ClientAPIsMask = gdrv->api_mask; + gdpy->smapi = egl_g3d_create_st_manager(dpy); + if (!gdpy->smapi) { + _eglError(EGL_NOT_INITIALIZED, + "eglInitialize(failed to create st manager)"); + goto fail; + } + #ifdef EGL_MESA_screen_surface /* enable MESA_screen_surface before adding (and validating) configs */ if (gdpy->native->modeset) { @@ -629,7 +443,6 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, struct egl_g3d_context *gshare = egl_g3d_context(share); struct egl_g3d_config *gconf = egl_g3d_config(conf); struct egl_g3d_context *gctx; - const __GLcontextModes *mode; gctx = CALLOC_STRUCT(egl_g3d_context); if (!gctx) { @@ -648,24 +461,14 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, return NULL; } - mode = &gconf->native->mode; - - gctx->pipe = gdpy->native->screen->context_create( - gdpy->native->screen, - (void *) &gctx->base); - - if (!gctx->pipe) { + gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, + &gconf->stvis, (gshare) ? gshare->stctxi : NULL); + if (!gctx->stctxi) { free(gctx); return NULL; } - gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode, - (gshare) ? gshare->st_ctx : NULL); - if (!gctx->st_ctx) { - gctx->pipe->destroy(gctx->pipe); - free(gctx); - return NULL; - } + gctx->stctxi->st_manager_private = (void *) &gctx->base; return &gctx->base; } @@ -682,9 +485,7 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) if (!dpy->Initialized) _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); - egl_g3d_realloc_context(dpy, &gctx->base); - /* it will destroy the associated pipe context */ - gctx->stapi->st_destroy_context(gctx->st_ctx); + gctx->stctxi->destroy(gctx->stctxi); free(gctx); } @@ -786,14 +587,20 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, return NULL; } + gsurf->stvis = gconf->stvis; + if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) + gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT; + + gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); + if (!gsurf->stfbi) { + gsurf->native->destroy(gsurf->native); + free(gsurf); + return NULL; + } + nsurf->user_data = &gsurf->base; gsurf->native = nsurf; - gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; - if (!gconf->native->mode.doubleBufferMode) - gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; - return &gsurf->base; } @@ -849,7 +656,8 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) if (!dpy->Initialized) _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); - pipe_surface_reference(&gsurf->render_surface, NULL); + pipe_resource_reference(&gsurf->render_texture, NULL); + egl_g3d_destroy_st_framebuffer(gsurf->stfbi); gsurf->native->destroy(gsurf->native); free(gsurf); } @@ -868,6 +676,7 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, { struct egl_g3d_context *gctx = egl_g3d_context(ctx); struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); + struct egl_g3d_surface *gread = egl_g3d_surface(read); struct egl_g3d_context *old_gctx; EGLBoolean ok = EGL_TRUE; @@ -878,39 +687,29 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, if (old_gctx) { /* flush old context */ - old_gctx->stapi->st_flush(old_gctx->st_ctx, + old_gctx->stctxi->flush(old_gctx->stctxi, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - - /* - * The old context is no longer current, and egl_g3d_realloc_context() - * should be called to destroy the framebuffers. However, it is possible - * that it will be made current again with the same draw/read surfaces. - * It might be better to keep it around. - */ } if (gctx) { - ok = egl_g3d_realloc_context(dpy, &gctx->base); + ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi, + (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL); if (ok) { - /* XXX: need to pass the winsys argument for - * flush_frontbuffer in the fourth parameter here: - */ - ok = gctx->stapi->st_make_current(gctx->st_ctx, - gctx->draw.st_fb, - gctx->read.st_fb, - NULL); - if (ok) { - egl_g3d_validate_context(dpy, &gctx->base); - if (gdraw->base.Type == EGL_WINDOW_BIT) { - gctx->base.WindowRenderBuffer = - (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ? - EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; - } + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi); + if (gread != gdraw) { + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, + gread->stfbi); + } + + if (gdraw->base.Type == EGL_WINDOW_BIT) { + gctx->base.WindowRenderBuffer = + (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ? + EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; } } } else if (old_gctx) { - ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL, NULL); + ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL); old_gctx->base.WindowRenderBuffer = EGL_NONE; } @@ -937,15 +736,17 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) return EGL_TRUE; /* or when the surface is single-buffered */ - if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) + if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) return EGL_TRUE; if (ctx && ctx->DrawSurface == surf) gctx = egl_g3d_context(ctx); /* flush if the surface is current */ - if (gctx) - gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); + if (gctx) { + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } return gsurf->native->swap_buffers(gsurf->native); } @@ -976,7 +777,7 @@ static struct pipe_surface * get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, enum native_attachment natt) { - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; struct pipe_surface *psurf; textures[natt] = NULL; @@ -985,8 +786,8 @@ get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, return NULL; psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], - 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE); - pipe_texture_reference(&textures[natt], NULL); + 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); + pipe_resource_reference(&textures[natt], NULL); return psurf; } @@ -1003,7 +804,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, struct pipe_screen *screen = gdpy->native->screen; struct pipe_surface *psurf; - if (!gsurf->render_surface) + if (!gsurf->render_texture) return EGL_TRUE; gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); @@ -1018,26 +819,33 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, /* flush if the surface is current */ if (ctx && ctx->DrawSurface == &gsurf->base) { struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_flush(gctx->st_ctx, + gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); } + /* create a pipe context to copy surfaces */ + if (!gdpy->pipe) { + gdpy->pipe = + gdpy->native->screen->context_create(gdpy->native->screen, NULL); + if (!gdpy->pipe) + return EGL_FALSE; + } + psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); if (psurf) { - struct pipe_context pipe; + struct pipe_surface *psrc; - /** - * XXX This is hacky. If we might allow the EGLDisplay to create a pipe - * context of its own and use the blitter context for this. - */ - memset(&pipe, 0, sizeof(pipe)); - pipe.screen = screen; + psrc = screen->get_tex_surface(screen, gsurf->render_texture, + 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + if (psrc) { + gdpy->pipe->surface_copy(gdpy->pipe, psurf, 0, 0, + psrc, 0, 0, psurf->width, psurf->height); + pipe_surface_reference(&psrc, NULL); - util_surface_copy(&pipe, FALSE, psurf, 0, 0, - gsurf->render_surface, 0, 0, psurf->width, psurf->height); + nsurf->flush_frontbuffer(nsurf); + } pipe_surface_reference(&psurf, NULL); - nsurf->flush_frontbuffer(nsurf); } nsurf->destroy(nsurf); @@ -1048,8 +856,16 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, static EGLBoolean egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_finish(gctx->st_ctx); + struct pipe_screen *screen = gdpy->native->screen; + struct pipe_fence_handle *fence = NULL; + + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + screen->fence_finish(screen, fence, 0); + screen->fence_reference(screen, &fence, NULL); + return EGL_TRUE; } @@ -1079,10 +895,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) /* in case this is called before a display is initialized */ egl_g3d_init_st(&gdrv->base); - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - const struct egl_g3d_st *stapi = gdrv->stapis[i]; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; if (stapi) { - proc = (_EGLProc) stapi->st_get_proc_address(procname); + proc = (_EGLProc) stapi->get_proc_address(stapi, procname); if (proc) return proc; } @@ -1098,8 +914,8 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); struct egl_g3d_context *gctx; - enum pipe_format target_format; - int target; + enum pipe_format internal_format; + enum st_texture_type target; if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); @@ -1110,10 +926,10 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, switch (gsurf->base.TextureFormat) { case EGL_TEXTURE_RGB: - target_format = PIPE_FORMAT_R8G8B8_UNORM; + internal_format = PIPE_FORMAT_R8G8B8_UNORM; break; case EGL_TEXTURE_RGBA: - target_format = PIPE_FORMAT_B8G8R8A8_UNORM; + internal_format = PIPE_FORMAT_B8G8R8A8_UNORM; break; default: return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); @@ -1129,21 +945,24 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, if (!es1) return EGL_TRUE; - if (!gsurf->render_surface) + if (!gsurf->render_texture) return EGL_FALSE; /* flush properly if the surface is bound */ if (gsurf->base.CurrentContext) { gctx = egl_g3d_context(gsurf->base.CurrentContext); - gctx->stapi->st_flush(gctx->st_ctx, + gctx->stctxi->flush(gctx->stctxi, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); } gctx = egl_g3d_context(es1); - gctx->stapi->st_bind_texture_surface(gsurf->render_surface, - target, gsurf->base.MipmapLevel, target_format); - - gsurf->base.BoundToTexture = EGL_TRUE; + if (gctx->stctxi->teximage) { + if (!gctx->stctxi->teximage(gctx->stctxi, target, + gsurf->base.MipmapLevel, internal_format, + gsurf->render_texture, gsurf->base.MipmapTexture)) + return EGL_FALSE; + gsurf->base.BoundToTexture = EGL_TRUE; + } return EGL_TRUE; } @@ -1160,14 +979,15 @@ egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, if (buffer != EGL_BACK_BUFFER) return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); - if (gsurf->render_surface) { + if (gsurf->render_texture) { _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); struct egl_g3d_context *gctx = egl_g3d_context(ctx); /* what if the context the surface binds to is no longer current? */ - if (gctx) - gctx->stapi->st_unbind_texture_surface(gsurf->render_surface, - ST_TEXTURE_2D, gsurf->base.MipmapLevel); + if (gctx) { + gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D, + gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE); + } } gsurf->base.BoundToTexture = EGL_FALSE; @@ -1279,6 +1099,12 @@ static void egl_g3d_unload(_EGLDriver *drv) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + EGLint i; + + for (i = 0; i < ST_API_COUNT; i++) { + if (gdrv->stapis[i]) + gdrv->stapis[i]->destroy(gdrv->stapis[i]); + } egl_g3d_destroy_probe(drv, NULL); free(gdrv); diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index e3e55e46d3..a2e0912efc 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -39,11 +39,11 @@ #include "eglmode.h" #include "native.h" -#include "egl_st.h" +#include "egl_g3d_st.h" struct egl_g3d_driver { _EGLDriver base; - const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS]; + struct st_api *stapis[ST_API_COUNT]; EGLint api_mask; EGLint probe_key; @@ -51,40 +51,39 @@ struct egl_g3d_driver { struct egl_g3d_display { struct native_display *native; -}; -struct egl_g3d_buffer { - struct st_framebuffer *st_fb; - uint attachment_mask; + struct st_manager *smapi; + struct pipe_context *pipe; }; struct egl_g3d_context { _EGLContext base; - const struct egl_g3d_st *stapi; - struct pipe_context *pipe; + struct st_api *stapi; - struct st_context *st_ctx; - EGLBoolean force_validate; - struct egl_g3d_buffer draw, read; + struct st_context_iface *stctxi; }; struct egl_g3d_surface { _EGLSurface base; + + struct st_visual stvis; + struct st_framebuffer_iface *stfbi; + struct native_surface *native; - enum native_attachment render_att; - struct pipe_surface *render_surface; + struct pipe_resource *render_texture; unsigned int sequence_number; }; struct egl_g3d_config { _EGLConfig base; const struct native_config *native; + struct st_visual stvis; }; struct egl_g3d_image { _EGLImage base; - struct pipe_texture *texture; + struct pipe_resource *texture; unsigned face; unsigned level; unsigned zslice; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c index d701f9c9a8..e49bcdedf1 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -40,13 +40,13 @@ /** * Reference and return the front left buffer of the native pixmap. */ -static struct pipe_texture * +static struct pipe_resource * egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_config *gconf; struct native_surface *nsurf; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; enum native_attachment natt; gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, pix)); @@ -72,7 +72,7 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attribs) { - struct pipe_texture *ptex; + struct pipe_resource *ptex; struct egl_g3d_image *gimg; unsigned face = 0, level = 0, zslice = 0; @@ -104,13 +104,13 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, if (level > ptex->last_level) { _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR"); - pipe_texture_reference(&gimg->texture, NULL); + pipe_resource_reference(&gimg->texture, NULL); free(gimg); return NULL; } if (zslice > ptex->depth0) { _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); - pipe_texture_reference(&gimg->texture, NULL); + pipe_resource_reference(&gimg->texture, NULL); free(gimg); return NULL; } @@ -129,7 +129,7 @@ egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img) { struct egl_g3d_image *gimg = egl_g3d_image(img); - pipe_texture_reference(&gimg->texture, NULL); + pipe_resource_reference(&gimg->texture, NULL); free(gimg); return EGL_TRUE; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c new file mode 100644 index 0000000000..5690312400 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -0,0 +1,227 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_dl.h" +#include "eglimage.h" +#include "eglmutex.h" + +#include "egl_g3d.h" +#include "egl_g3d_st.h" + +struct egl_g3d_st_manager { + struct st_manager base; + _EGLDisplay *display; +}; + +static INLINE struct egl_g3d_st_manager * +egl_g3d_st_manager(struct st_manager *smapi) +{ + return (struct egl_g3d_st_manager *) smapi; +} + +struct st_api * +egl_g3d_create_st_api(enum st_api_type api) +{ + const char *stmod_name; + struct util_dl_library *lib; + const struct st_module *mod; + + switch (api) { + case ST_API_OPENGL: + stmod_name = ST_MODULE_OPENGL_SYMBOL; + break; + case ST_API_OPENGL_ES1: + stmod_name = ST_MODULE_OPENGL_ES1_SYMBOL; + break; + case ST_API_OPENGL_ES2: + stmod_name = ST_MODULE_OPENGL_ES2_SYMBOL; + break; + case ST_API_OPENVG: + stmod_name = ST_MODULE_OPENVG_SYMBOL; + break; + default: + stmod_name = NULL; + break; + } + if (!stmod_name) + return NULL; + + mod = NULL; + lib = util_dl_open(NULL); + if (lib) { + mod = (const struct st_module *) + util_dl_get_proc_address(lib, stmod_name); + util_dl_close(lib); + } + if (!mod || mod->api != api) + return NULL; + + return mod->create_api(); +} + +struct st_manager * +egl_g3d_create_st_manager(_EGLDisplay *dpy) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_st_manager *gsmapi; + + gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); + if (gsmapi) { + gsmapi->display = dpy; + + gsmapi->base.screen = gdpy->native->screen; + } + + return &gsmapi->base;; +} + +void +egl_g3d_destroy_st_manager(struct st_manager *smapi) +{ + struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); + free(gsmapi); +} + +static boolean +egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + return gsurf->native->flush_frontbuffer(gsurf->native); +} + +static boolean +egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; + uint attachment_mask = 0; + unsigned i; + + for (i = 0; i < count; i++) { + int natt; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + natt = NATIVE_ATTACHMENT_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + natt = NATIVE_ATTACHMENT_BACK_RIGHT; + default: + natt = -1; + break; + } + + if (natt >= 0) + attachment_mask |= 1 << natt; + } + + if (!gsurf->native->validate(gsurf->native, attachment_mask, + &gsurf->sequence_number, textures, &gsurf->base.Width, + &gsurf->base.Height)) + return FALSE; + + for (i = 0; i < count; i++) { + struct pipe_resource *tex; + int natt; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + natt = NATIVE_ATTACHMENT_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + natt = NATIVE_ATTACHMENT_BACK_RIGHT; + break; + default: + natt = -1; + break; + } + + if (natt >= 0) { + tex = textures[natt]; + + if (statts[i] == stfbi->visual->render_buffer) + pipe_resource_reference(&gsurf->render_texture, tex); + + if (attachment_mask & (1 << natt)) { + /* transfer the ownership to the caller */ + out[i] = tex; + attachment_mask &= ~(1 << natt); + } + else { + /* the attachment is listed more than once */ + pipe_resource_reference(&out[i], tex); + } + } + } + + return TRUE; +} + +struct st_framebuffer_iface * +egl_g3d_create_st_framebuffer(_EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct st_framebuffer_iface *stfbi; + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + if (!stfbi) + return NULL; + + stfbi->visual = &gsurf->stvis; + stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; + stfbi->validate = egl_g3d_st_framebuffer_validate; + stfbi->st_manager_private = (void *) &gsurf->base; + + return stfbi; +} + +void +egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + free(stfbi); +} diff --git a/src/gallium/state_trackers/egl/common/egl_st.h b/src/gallium/state_trackers/egl/common/egl_g3d_st.h index 8fb464bd3d..ea8b4068cd 100644 --- a/src/gallium/state_trackers/egl/common/egl_st.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 7.8 + * Version: 7.9 * - * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> + * Copyright (C) 2010 LunarG Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,54 +20,60 @@ * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> */ -#ifndef _EGL_ST_H_ -#define _EGL_ST_H_ - -#include "GL/gl.h" /* for GL types */ -#include "GL/internal/glcore.h" /* for __GLcontextModes */ +#ifndef _EGL_G3D_ST_H_ +#define _EGL_G3D_ST_H_ #include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" +#include "state_tracker/st_api.h" +#include "egltypedefs.h" -/* avoid calling st functions directly */ -#if 1 +struct st_api * +egl_g3d_create_st_api(enum st_api_type api); -#define ST_SURFACE_FRONT_LEFT 0 -#define ST_SURFACE_BACK_LEFT 1 -#define ST_SURFACE_FRONT_RIGHT 2 -#define ST_SURFACE_BACK_RIGHT 3 +struct st_manager * +egl_g3d_create_st_manager(_EGLDisplay *dpy); -#define ST_TEXTURE_2D 0x2 +void +egl_g3d_destroy_st_manager(struct st_manager *smapi); -struct st_context; -struct st_framebuffer; -typedef void (*st_proc)(); +struct st_framebuffer_iface * +egl_g3d_create_st_framebuffer(_EGLSurface *surf); -#else -#include "state_tracker/st_public.h" -#endif +void +egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); -/* remember to update egl_g3d_get_st() when update the enums */ -enum egl_g3d_st_api { - EGL_G3D_ST_OPENGL_ES = 0, - EGL_G3D_ST_OPENVG, - EGL_G3D_ST_OPENGL_ES2, - EGL_G3D_ST_OPENGL, - - NUM_EGL_G3D_STS -}; +/** + * Return the EGL_<api>_BIT of the st api. + */ +static INLINE int +egl_g3d_st_api_bit(enum st_api_type api) +{ + int bit; -struct egl_g3d_st { -#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__); -#include "st_public_tmp.h" - /* fields must be added here */ - EGLint api_bit; -}; + switch (api) { + case ST_API_OPENGL: + bit = EGL_OPENGL_BIT; + break; + case ST_API_OPENGL_ES1: + bit = EGL_OPENGL_ES_BIT; + break; + case ST_API_OPENGL_ES2: + bit = EGL_OPENGL_ES2_BIT; + break; + case ST_API_OPENVG: + bit = EGL_OPENVG_BIT; + break; + default: + bit = 0; + break; + } -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api); + return bit; +} -#endif /* _EGL_ST_H_ */ +#endif /* _EGL_G3D_ST_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_st.c b/src/gallium/state_trackers/egl/common/egl_st.c deleted file mode 100644 index a88ff911cd..0000000000 --- a/src/gallium/state_trackers/egl/common/egl_st.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 7.8 - * - * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL 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 <dlfcn.h> -#include "pipe/p_compiler.h" -#include "util/u_memory.h" -#include "egllog.h" -#include "EGL/egl.h" /* for EGL_api_BIT */ - -#include "egl_st.h" - -#ifndef HAVE_DLADDR -#define HAVE_DLADDR 1 -#endif - -#if HAVE_DLADDR - -static const char * -egl_g3d_st_names[] = { -#define ST_PUBLIC(name, ...) #name, -#include "st_public_tmp.h" - NULL -}; - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ - st_proc *procs = (st_proc *) stapi; - void *handle; - Dl_info info; - const char **name; - - if (!dladdr(sym, &info)) - return FALSE; - handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); - if (!handle) - return FALSE; - - for (name = egl_g3d_st_names; *name; name++) { - st_proc proc = (st_proc) dlsym(handle, *name); - if (!proc) { - _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname); - memset(stapi, 0, sizeof(*stapi)); - dlclose(handle); - return FALSE; - } - *procs++ = proc; - } - - dlclose(handle); - return TRUE; -} - -#else /* HAVE_DLADDR */ - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ -#define ST_PUBLIC(name, ...) stapi->name = name; -#include "st_public_tmp.h" - return TRUE; -} - -#endif /* HAVE_DLADDR */ - -static boolean -egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api) -{ - void *handle, *sym; - boolean res = FALSE; - - /* already initialized */ - if (stapi->st_notify_swapbuffers != NULL) - return TRUE; - - handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); - if (!handle) - return FALSE; - - sym = dlsym(handle, api); - if (sym && egl_g3d_fill_st(stapi, sym)) - res = TRUE; - - dlclose(handle); - return res; -} - -static struct { - const char *symbol; - EGLint api_bit; -} egl_g3d_st_info[NUM_EGL_G3D_STS] = { - { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT }, - { "st_api_OpenVG", EGL_OPENVG_BIT }, - { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT }, - { "st_api_OpenGL", EGL_OPENGL_BIT }, -}; - -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api) -{ - static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS]; - - if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) { - all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit; - return &all_trackers[api]; - } - else { - return NULL; - } -} diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 93c81b26e1..a709ae3e80 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -112,7 +112,7 @@ struct native_surface { * behavior might change in the future. */ boolean (*validate)(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height); /** diff --git a/src/gallium/state_trackers/egl/common/st_public_tmp.h b/src/gallium/state_trackers/egl/common/st_public_tmp.h deleted file mode 100644 index 562dd68c15..0000000000 --- a/src/gallium/state_trackers/egl/common/st_public_tmp.h +++ /dev/null @@ -1,20 +0,0 @@ -ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share) -ST_PUBLIC(st_destroy_context, void, struct st_context *st) -ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask) -ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData) -ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height) -ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf) -ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height) -ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface) -ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture) -ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb) -ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read, void *winsys_drawable_handle) -ST_PUBLIC(st_get_current, struct st_context *, void) -ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence) -ST_PUBLIC(st_finish, void, struct st_context *st) -ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format) -ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level) -ST_PUBLIC(st_get_proc_address, st_proc, const char *procname) -#undef ST_PUBLIC diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c index 7322240856..435edda9e9 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.c +++ b/src/gallium/state_trackers/egl/kms/native_kms.c @@ -36,13 +36,13 @@ static boolean kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) { struct kms_surface *ksurf = kms_surface(nsurf); struct kms_display *kdpy = ksurf->kdpy; struct pipe_screen *screen = kdpy->base.screen; - struct pipe_texture templ, *ptex; + struct pipe_resource templ, *ptex; int att; if (attachment_mask) { @@ -66,13 +66,13 @@ kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, ptex = ksurf->textures[att]; if (!ptex) { - ptex = screen->texture_create(screen, &templ); + ptex = screen->resource_create(screen, &templ); ksurf->textures[att] = ptex; } if (textures) { textures[att] = NULL; - pipe_texture_reference(&textures[att], ptex); + pipe_resource_reference(&textures[att], ptex); } } @@ -118,7 +118,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) if (!ksurf->textures[natt]) return FALSE; - pipe_texture_reference(&fb->texture, ksurf->textures[natt]); + pipe_resource_reference(&fb->texture, ksurf->textures[natt]); } /* already initialized */ @@ -131,7 +131,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; - if (!kdpy->base.screen->texture_get_handle(kdpy->base.screen, + if (!kdpy->base.screen->resource_get_handle(kdpy->base.screen, fb->texture, &whandle)) return FALSE; @@ -173,7 +173,7 @@ kms_surface_swap_buffers(struct native_surface *nsurf) struct kms_crtc *kcrtc = &ksurf->current_crtc; struct kms_display *kdpy = ksurf->kdpy; struct kms_framebuffer tmp_fb; - struct pipe_texture *tmp_texture; + struct pipe_resource *tmp_texture; int err; /* pbuffer is private */ @@ -228,15 +228,15 @@ kms_surface_destroy(struct native_surface *nsurf) if (ksurf->front_fb.buffer_id) drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id); - pipe_texture_reference(&ksurf->front_fb.texture, NULL); + pipe_resource_reference(&ksurf->front_fb.texture, NULL); if (ksurf->back_fb.buffer_id) drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id); - pipe_texture_reference(&ksurf->back_fb.texture, NULL); + pipe_resource_reference(&ksurf->back_fb.texture, NULL); for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct pipe_texture *ptex = ksurf->textures[i]; - pipe_texture_reference(&ptex, NULL); + struct pipe_resource *ptex = ksurf->textures[i]; + pipe_resource_reference(&ptex, NULL); } free(ksurf); diff --git a/src/gallium/state_trackers/egl/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h index f9cbcb158b..1850cd8790 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.h +++ b/src/gallium/state_trackers/egl/kms/native_kms.h @@ -69,7 +69,7 @@ struct kms_display { }; struct kms_framebuffer { - struct pipe_texture *texture; + struct pipe_resource *texture; boolean is_passive; uint32_t buffer_id; @@ -82,7 +82,7 @@ struct kms_surface { struct kms_display *kdpy; int width, height; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; unsigned int sequence_number; struct kms_framebuffer front_fb, back_fb; diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 9839979231..7e350d3299 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -72,7 +72,7 @@ struct dri2_surface { unsigned int server_stamp; unsigned int client_stamp; int width, height; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; boolean have_back, have_fake; @@ -113,14 +113,14 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - struct pipe_texture templ; + struct pipe_resource templ; struct winsys_handle whandle; uint valid_mask; int i; /* free the old textures */ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) - pipe_texture_reference(&dri2surf->textures[i], NULL); + pipe_resource_reference(&dri2surf->textures[i], NULL); dri2surf->valid_mask = 0x0; dri2surf->have_back = FALSE; @@ -175,7 +175,7 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, memset(&whandle, 0, sizeof(whandle)); whandle.stride = xbuf->pitch; whandle.handle = xbuf->name; - dri2surf->textures[natt] = dri2dpy->base.screen->texture_from_handle( + dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle( dri2dpy->base.screen, &templ, &whandle); if (dri2surf->textures[natt]) valid_mask |= 1 << natt; @@ -262,7 +262,7 @@ dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) /* create textures for pbuffer */ if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) { struct pipe_screen *screen = dri2dpy->base.screen; - struct pipe_texture templ; + struct pipe_resource templ; uint new_valid = 0x0; int att; @@ -283,7 +283,7 @@ dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) if (native_attachment_mask_test(buffer_mask, att)) { assert(!dri2surf->textures[att]); - dri2surf->textures[att] = screen->texture_create(screen, &templ); + dri2surf->textures[att] = screen->resource_create(screen, &templ); if (!dri2surf->textures[att]) break; @@ -372,7 +372,7 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) static boolean dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) { struct dri2_surface *dri2surf = dri2_surface(nsurf); @@ -390,10 +390,10 @@ dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, int att; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(attachment_mask, att)) { - struct pipe_texture *ptex = dri2surf->textures[att]; + struct pipe_resource *ptex = dri2surf->textures[att]; textures[att] = NULL; - pipe_texture_reference(&textures[att], ptex); + pipe_resource_reference(&textures[att], ptex); } } } @@ -429,8 +429,8 @@ dri2_surface_destroy(struct native_surface *nsurf) free(dri2surf->last_xbufs); for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct pipe_texture *ptex = dri2surf->textures[i]; - pipe_texture_reference(&ptex, NULL); + struct pipe_resource *ptex = dri2surf->textures[i]; + pipe_resource_reference(&ptex, NULL); } if (dri2surf->drawable) { diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index c6b16354f9..a51d10f310 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -65,7 +65,7 @@ struct ximage_display { }; struct ximage_buffer { - struct pipe_texture *texture; + struct pipe_resource *texture; struct xlib_drawable xdraw; }; @@ -116,7 +116,7 @@ ximage_surface_free_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; - pipe_texture_reference(&xbuf->texture, NULL); + pipe_resource_reference(&xbuf->texture, NULL); } static boolean @@ -126,7 +126,7 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; - struct pipe_texture templ; + struct pipe_resource templ; /* free old data */ if (xbuf->texture) @@ -154,7 +154,7 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, break; } } - xbuf->texture = screen->texture_create(screen, &templ); + xbuf->texture = screen->resource_create(screen, &templ); if (xbuf->texture) { xbuf->xdraw.visual = xsurf->visual.visual; xbuf->xdraw.depth = xsurf->visual.depth; @@ -329,7 +329,7 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) static boolean ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) { struct ximage_surface *xsurf = ximage_surface(nsurf); @@ -350,7 +350,7 @@ ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, struct ximage_buffer *xbuf = &xsurf->buffers[att]; textures[att] = NULL; - pipe_texture_reference(&textures[att], xbuf->texture); + pipe_resource_reference(&textures[att], xbuf->texture); } } } diff --git a/src/gallium/state_trackers/es/Makefile b/src/gallium/state_trackers/es/Makefile index b036551271..089d441167 100644 --- a/src/gallium/state_trackers/es/Makefile +++ b/src/gallium/state_trackers/es/Makefile @@ -38,6 +38,8 @@ SYS_LIBS = -lm -pthread INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ -I$(TOP)/src/gallium/include .c.o: diff --git a/src/gallium/state_trackers/es/st_es1.c b/src/gallium/state_trackers/es/st_es1.c index 25bc53b21e..4e89e06b34 100644 --- a/src/gallium/state_trackers/es/st_es1.c +++ b/src/gallium/state_trackers/es/st_es1.c @@ -1,3 +1,8 @@ -#include "pipe/p_compiler.h" +#include "state_tracker/st_manager.h" PUBLIC const int st_api_OpenGL_ES1 = 1; + +PUBLIC const struct st_module st_module_OpenGL_ES1 = { + .api = ST_API_OPENGL_ES1, + .create_api = st_manager_create_api +}; diff --git a/src/gallium/state_trackers/es/st_es2.c b/src/gallium/state_trackers/es/st_es2.c index 171ea62b97..82e88b176a 100644 --- a/src/gallium/state_trackers/es/st_es2.c +++ b/src/gallium/state_trackers/es/st_es2.c @@ -1,3 +1,8 @@ -#include "pipe/p_compiler.h" +#include "state_tracker/st_manager.h" PUBLIC const int st_api_OpenGL_ES2 = 1; + +PUBLIC const struct st_module st_module_OpenGL_ES2 = { + .api = ST_API_OPENGL_ES2, + .create_api = st_manager_create_api +}; diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile index 8c7cc524df..582e72bb46 100644 --- a/src/gallium/state_trackers/glx/xlib/Makefile +++ b/src/gallium/state_trackers/glx/xlib/Makefile @@ -12,6 +12,7 @@ C_SOURCES = \ glx_api.c \ glx_getproc.c \ glx_usefont.c \ - xm_api.c + xm_api.c \ + xm_st.c include ../../../Makefile.template diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript index bb20235150..d6c16ad2f5 100644 --- a/src/gallium/state_trackers/glx/xlib/SConscript +++ b/src/gallium/state_trackers/glx/xlib/SConscript @@ -20,6 +20,7 @@ if env['platform'] == 'linux' \ 'glx_getproc.c', 'glx_usefont.c', 'xm_api.c', + 'xm_st.c', ] ) Export('st_xlib') diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 2454585850..4930cd6cd5 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_api.c +++ b/src/gallium/state_trackers/glx/xlib/glx_api.c @@ -35,12 +35,9 @@ #include "xm_api.h" #include "main/context.h" -#include "main/config.h" #include "main/macros.h" #include "main/imports.h" #include "main/version.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" /* This indicates the client-side GLX API and GLX encoder version. */ @@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, if (MakeCurrent_PrevContext == src) { _mesa_Flush(); } - st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask ); + XMesaCopyContext(xm_src, xm_dst, mask); } diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index f4d7133d2f..62a2bfcfa0 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -54,11 +54,9 @@ #endif #include "xm_api.h" -#include "main/context.h" -#include "main/framebuffer.h" +#include "xm_st.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" +#include "main/context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" @@ -72,19 +70,56 @@ * global. */ static struct xm_driver driver; +static struct st_api *stapi; void xmesa_set_driver( const struct xm_driver *templ ) { driver = *templ; + stapi = driver.create_st_api(); } -/** - * Global X driver lock - */ -pipe_mutex _xmesa_lock; +static XMesaDisplay +xmesa_init_display( Display *display ) +{ + pipe_static_mutex(init_mutex); + static struct xmesa_display xm_display; + XMesaDisplay xmdpy; + + pipe_mutex_lock(init_mutex); + + /* TODO support for multiple displays */ + xmdpy = &xm_display; + + if (!xmdpy->display && display) { + xmdpy->display = display; + xmdpy->screen = driver.create_pipe_screen(display); + xmdpy->smapi = CALLOC_STRUCT(st_manager); + if (xmdpy->smapi) + xmdpy->smapi->screen = xmdpy->screen; + + if (xmdpy->screen && xmdpy->smapi) { + pipe_mutex_init(xmdpy->mutex); + } + else { + if (xmdpy->screen) { + xmdpy->screen->destroy(xmdpy->screen); + xmdpy->screen = NULL; + } + if (xmdpy->smapi) { + FREE(xmdpy->smapi); + xmdpy->smapi = NULL; + } -static struct pipe_screen *screen = NULL; + xmdpy->display = NULL; + } + } + if (!xmdpy->display || xmdpy->display != display) + xmdpy = NULL; + pipe_mutex_unlock(init_mutex); + + return xmdpy; +} /**********************************************************************/ /***** X Utility Functions *****/ @@ -194,12 +229,13 @@ void xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height) { + XMesaDisplay xmdpy = xmesa_init_display(dpy); Status stat; - pipe_mutex_lock(_xmesa_lock); + pipe_mutex_lock(xmdpy->mutex); XSync(b->xm_visual->display, 0); /* added for Chromium */ stat = get_drawable_size(dpy, b->ws.drawable, width, height); - pipe_mutex_unlock(_xmesa_lock); + pipe_mutex_unlock(xmdpy->mutex); if (!stat) { /* probably querying a window that's recently been destroyed */ @@ -273,49 +309,43 @@ choose_pixel_format(XMesaVisual v) return 0; } - - /** - * Query the default gallium screen for a Z/Stencil format that - * at least matches the given depthBits and stencilBits. + * Choose a depth/stencil format that is "better" than the given depth and + * stencil sizes. */ -static void -xmesa_choose_z_stencil_format(int depthBits, int stencilBits, - enum pipe_format *depthFormat, - enum pipe_format *stencilFormat) +static enum pipe_format +choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil) { const enum pipe_texture_target target = PIPE_TEXTURE_2D; const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE | PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO); - static enum pipe_format formats[] = { - PIPE_FORMAT_S8Z24_UNORM, - PIPE_FORMAT_Z24S8_UNORM, - PIPE_FORMAT_Z16_UNORM, - PIPE_FORMAT_Z32_UNORM - }; - int i; + enum pipe_format formats[8], fmt; + int count, i; - assert(screen); + count = 0; + if (depth <= 24 && stencil <= 8) { + formats[count++] = PIPE_FORMAT_S8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24S8_UNORM; + } - *depthFormat = *stencilFormat = PIPE_FORMAT_NONE; + if (!stencil) { + if (depth <= 16) + formats[count++] = PIPE_FORMAT_Z16_UNORM; + if (depth <= 32) + formats[count++] = PIPE_FORMAT_Z32_UNORM; + } - /* search for supported format */ - for (i = 0; i < Elements(formats); i++) { - if (screen->is_format_supported(screen, formats[i], + fmt = PIPE_FORMAT_NONE; + for (i = 0; i < count; i++) { + if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], target, tex_usage, geom_flags)) { - *depthFormat = formats[i]; + fmt = formats[i]; break; } } - if (stencilBits) { - *stencilFormat = *depthFormat; - } - - /* XXX we should check that he chosen format has at least as many bits - * as what was requested. - */ + return fmt; } @@ -324,7 +354,7 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits, /***** Linked list of XMesaBuffers *****/ /**********************************************************************/ -XMesaBuffer XMesaBufferList = NULL; +static XMesaBuffer XMesaBufferList = NULL; /** @@ -342,13 +372,15 @@ static XMesaBuffer create_xmesa_buffer(Drawable d, BufferType type, XMesaVisual vis, Colormap cmap) { + XMesaDisplay xmdpy = xmesa_init_display(vis->display); XMesaBuffer b; - GLframebuffer *fb; - enum pipe_format colorFormat, depthFormat, stencilFormat; uint width, height; ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); + if (!xmdpy) + return NULL; + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); if (!b) return NULL; @@ -361,24 +393,12 @@ create_xmesa_buffer(Drawable d, BufferType type, b->type = type; b->cmap = cmap; - /* determine PIPE_FORMATs for buffers */ - colorFormat = choose_pixel_format(vis); - - xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits, - vis->mesa_visual.stencilBits, - &depthFormat, &stencilFormat); - - get_drawable_size(vis->display, d, &width, &height); /* * Create framebuffer, but we'll plug in our own renderbuffers below. */ - b->stfb = st_create_framebuffer(&vis->mesa_visual, - colorFormat, depthFormat, stencilFormat, - width, height, - (void *) b); - fb = &b->stfb->Base; + b->stfb = xmesa_create_st_framebuffer(xmdpy, b); /* GLX_EXT_texture_from_pixmap */ b->TextureTarget = 0; @@ -422,24 +442,21 @@ xmesa_free_buffer(XMesaBuffer buffer) for (b = XMesaBufferList; b; b = b->Next) { if (b == buffer) { - struct gl_framebuffer *fb = &buffer->stfb->Base; - /* unlink buffer from list */ if (prev) prev->Next = buffer->Next; else XMesaBufferList = buffer->Next; - /* mark as delete pending */ - fb->DeletePending = GL_TRUE; - /* Since the X window for the XMesaBuffer is going away, we don't * want to dereference this pointer in the future. */ b->ws.drawable = 0; - /* Unreference. If count = zero we'll really delete the buffer */ - _mesa_reference_framebuffer(&fb, NULL); + /* XXX we should move the buffer to a delete-pending list and destroy + * the buffer until it is no longer current. + */ + xmesa_destroy_st_framebuffer(buffer->stfb); free(buffer); @@ -596,10 +613,12 @@ XMesaVisual XMesaCreateVisual( Display *display, GLint level, GLint visualCaveat ) { + XMesaDisplay xmdpy = xmesa_init_display(display); XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; - xmesa_init( display ); + if (!xmdpy) + return NULL; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { @@ -681,6 +700,26 @@ XMesaVisual XMesaCreateVisual( Display *display, accum_blue_size, accum_alpha_size, 0 ); + v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (stereo_flag) { + v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + v->stvis.color_format = choose_pixel_format(v); + v->stvis.depth_stencil_format = + choose_depth_stencil_format(xmdpy, depth_size, stencil_size); + + v->stvis.accum_format = (accum_red_size + + accum_green_size + accum_blue_size + accum_alpha_size) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + v->stvis.samples = num_samples; + v->stvis.render_buffer = ST_ATTACHMENT_INVALID; + /* XXX minor hack */ v->mesa_visual.level = level; return v; @@ -696,17 +735,12 @@ void XMesaDestroyVisual( XMesaVisual v ) /** - * Do one-time initializations. + * Do per-display initializations. */ void xmesa_init( Display *display ) { - static GLboolean firstTime = GL_TRUE; - if (firstTime) { - pipe_mutex_init(_xmesa_lock); - screen = driver.create_pipe_screen( display ); - firstTime = GL_FALSE; - } + xmesa_init_display(display); } @@ -720,51 +754,33 @@ xmesa_init( Display *display ) PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { - struct pipe_context *pipe = NULL; + XMesaDisplay xmdpy = xmesa_init_display(v->display); XMesaContext c; - GLcontext *mesaCtx; - uint pf; - xmesa_init( v->display ); + if (!xmdpy) + return NULL; /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ c = (XMesaContext) CALLOC_STRUCT(xmesa_context); if (!c) return NULL; - pf = choose_pixel_format(v); - assert(pf); - c->xm_visual = v; c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ c->xm_read_buffer = NULL; - if (screen == NULL) - goto fail; - - /* Trace screen knows how to properly wrap context creation in the - * wrapped screen, so nothing special to do here: - */ - pipe = screen->context_create(screen, (void *) c); - if (pipe == NULL) - goto fail; - - c->st = st_create_context(pipe, - &v->mesa_visual, - share_list ? share_list->st : NULL); + c->st = stapi->create_context(stapi, xmdpy->smapi, + &v->stvis, (share_list) ? share_list->st : NULL); if (c->st == NULL) goto fail; - mesaCtx = c->st->ctx; - c->st->ctx->DriverCtx = c; + c->st->st_manager_private = (void *) c; return c; fail: if (c->st) - st_destroy_context(c->st); - else if (pipe) - pipe->destroy(pipe); + c->st->destroy(c->st); free(c); return NULL; @@ -775,7 +791,7 @@ fail: PUBLIC void XMesaDestroyContext( XMesaContext c ) { - st_destroy_context(c->st); + c->st->destroy(c->st); /* FIXME: We should destroy the screen here, but if we do so, surfaces may * outlive it, causing segfaults @@ -881,7 +897,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, { GET_CURRENT_CONTEXT(ctx); XMesaBuffer b; - GLuint width, height; assert(v); @@ -889,19 +904,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, if (!b) return NULL; - /* get pixmap size, update framebuffer/renderbuffer dims */ - xmesa_get_window_size(v->display, b, &width, &height); - _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height); + /* get pixmap size */ + xmesa_get_window_size(v->display, b, &b->width, &b->height); if (target == 0) { /* examine dims */ if (ctx->Extensions.ARB_texture_non_power_of_two) { target = GLX_TEXTURE_2D_EXT; } - else if ( _mesa_bitcount(width) == 1 - && _mesa_bitcount(height) == 1) { + else if ( _mesa_bitcount(b->width) == 1 + && _mesa_bitcount(b->height) == 1) { /* power of two size */ - if (height == 1) { + if (b->height == 1) { target = GLX_TEXTURE_1D_EXT; } else { @@ -974,23 +988,20 @@ XMesaDestroyBuffer(XMesaBuffer b) /** - * Query the current window size and update the corresponding GLframebuffer - * and all attached renderbuffers. - * Called when: - * 1. the first time a buffer is bound to a context. - * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too... - * Note: it's possible (and legal) for xmctx to be NULL. That can happen - * when resizing a buffer when no rendering context is bound. + * Query the current drawable size and notify the binding context. */ void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) +xmesa_check_buffer_size(XMesaBuffer b) { - GLuint width, height; - xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height); - st_resize_framebuffer(drawBuffer->stfb, width, height); -} + XMesaContext xmctx = XMesaGetCurrentContext(); + if (b->type == PBUFFER) + return; + xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); + if (xmctx && xmctx->xm_buffer == b) + xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb); +} /* @@ -1017,22 +1028,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, c->xm_read_buffer == readBuffer) return GL_TRUE; + xmesa_check_buffer_size(drawBuffer); + if (readBuffer != drawBuffer) + xmesa_check_buffer_size(readBuffer); + c->xm_buffer = drawBuffer; c->xm_read_buffer = readBuffer; - st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb, - &drawBuffer->ws); - - xmesa_check_and_update_buffer_size(c, drawBuffer); - if (readBuffer != drawBuffer) - xmesa_check_and_update_buffer_size(c, readBuffer); + stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb); /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ drawBuffer->wasCurrent = GL_TRUE; } else { /* Detach */ - st_make_current( NULL, NULL, NULL, NULL ); + stapi->make_current(stapi, NULL, NULL, NULL); } return GL_TRUE; @@ -1051,14 +1061,8 @@ GLboolean XMesaUnbindContext( XMesaContext c ) XMesaContext XMesaGetCurrentContext( void ) { - GET_CURRENT_CONTEXT(ctx); - if (ctx) { - XMesaContext xmesa = xmesa_context(ctx); - return xmesa; - } - else { - return 0; - } + struct st_context_iface *st = stapi->get_current(stapi); + return (XMesaContext) (st) ? st->st_manager_private : NULL; } @@ -1070,17 +1074,17 @@ XMesaContext XMesaGetCurrentContext( void ) PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { - struct pipe_surface *frontLeftSurf; - - st_swapbuffers(b->stfb, &frontLeftSurf, NULL); - - if (frontLeftSurf) { - screen->flush_frontbuffer( screen, - frontLeftSurf, - &b->ws ); + XMesaContext xmctx = XMesaGetCurrentContext(); + + if (xmctx && xmctx->xm_buffer == b) { + xmctx->st->flush( xmctx->st, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL); } - xmesa_check_and_update_buffer_size(NULL, b); + xmesa_swap_st_framebuffer(b->stfb); } @@ -1090,21 +1094,9 @@ void XMesaSwapBuffers( XMesaBuffer b ) */ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) { - struct pipe_surface *surf_front; - struct pipe_surface *surf_back; - struct pipe_context *pipe = NULL; /* XXX fix */ - - st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front); - st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back); - - if (!surf_front || !surf_back) - return; - - assert(pipe); - pipe->surface_copy(pipe, - surf_front, x, y, /* dest */ - surf_back, x, y, /* src */ - width, height); + xmesa_copy_st_framebuffer(b->stfb, + ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT, + x, y, width, height); } @@ -1112,7 +1104,14 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) void XMesaFlush( XMesaContext c ) { if (c && c->xm_visual->display) { - st_finish(c->st); + XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display); + struct pipe_fence_handle *fence = NULL; + + c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + if (fence) { + xmdpy->screen->fence_finish(xmdpy->screen, fence, 0); + xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); + } XSync( c->xm_visual->display, False ); } } @@ -1186,3 +1185,10 @@ XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) { } + +void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask) +{ + if (dst->st->copy) + dst->st->copy(dst->st, src->st, mask); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index de47064b41..4f2c8a6e6a 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -58,8 +58,7 @@ and create a window, you must do the following to use the X/Mesa interface: #include "main/mtypes.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" +#include "state_tracker/st_api.h" #include "os/os_thread.h" #include "state_tracker/xlib_sw_winsys.h" @@ -68,11 +67,22 @@ and create a window, you must do the following to use the X/Mesa interface: # include <X11/Xlibint.h> # include <X11/Xutil.h> +typedef struct xmesa_display *XMesaDisplay; typedef struct xmesa_buffer *XMesaBuffer; typedef struct xmesa_context *XMesaContext; typedef struct xmesa_visual *XMesaVisual; +struct xmesa_display { + pipe_mutex mutex; + + Display *display; + struct pipe_screen *screen; + struct st_manager *smapi; + + struct pipe_context *pipe; +}; + /* * Create a new X/Mesa visual. @@ -258,16 +268,13 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, int format, int target, int mipmap); +extern void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask); /*********************************************************************** */ -extern pipe_mutex _xmesa_lock; - -extern struct xmesa_buffer *XMesaBufferList; - - /** * Visual inforation, derived from GLvisual. * Basically corresponds to an XVisualInfo. @@ -280,6 +287,8 @@ struct xmesa_visual { GLint BitsPerPixel; /* True bits per pixel for XImages */ GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ + + struct st_visual stvis; }; @@ -288,7 +297,7 @@ struct xmesa_visual { * Basically corresponds to a GLXContext. */ struct xmesa_context { - struct st_context *st; + struct st_context_iface *st; XMesaVisual xm_visual; /** pixel format info */ XMesaBuffer xm_buffer; /** current drawbuffer */ XMesaBuffer xm_read_buffer; /** current readbuffer */ @@ -311,7 +320,7 @@ typedef enum { * Basically corresponds to a GLXDrawable. */ struct xmesa_buffer { - struct st_framebuffer *stfb; + struct st_framebuffer_iface *stfb; struct xlib_drawable ws; GLboolean wasCurrent; /* was ever the current buffer? */ @@ -335,33 +344,15 @@ struct xmesa_buffer { GLint TextureMipmap; /** 0 or 1 */ struct xmesa_buffer *Next; /* Linked list pointer: */ -}; - - - -/** cast wrapper */ -static INLINE XMesaContext -xmesa_context(GLcontext *ctx) -{ - return (XMesaContext) ctx->DriverCtx; -} + unsigned width, height; +}; -/** cast wrapper */ -static INLINE XMesaBuffer -xmesa_buffer(GLframebuffer *fb) -{ - struct st_framebuffer *stfb = (struct st_framebuffer *) fb; - return (XMesaBuffer) st_framebuffer_private(stfb); -} extern void xmesa_init(Display *dpy); -extern void -xmesa_delete_framebuffer(struct gl_framebuffer *fb); - extern XMesaBuffer xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis); @@ -370,7 +361,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height); extern void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer); +xmesa_check_buffer_size(XMesaBuffer b); extern void xmesa_destroy_buffers_on_display(Display *dpy); @@ -378,13 +369,13 @@ xmesa_destroy_buffers_on_display(Display *dpy); static INLINE GLuint xmesa_buffer_width(XMesaBuffer b) { - return b->stfb->Base.Width; + return b->width; } static INLINE GLuint xmesa_buffer_height(XMesaBuffer b) { - return b->stfb->Base.Height; + return b->height; } diff --git a/src/gallium/state_trackers/glx/xlib/xm_public.h b/src/gallium/state_trackers/glx/xlib/xm_public.h index ac6a8ffb27..950eb21521 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_public.h +++ b/src/gallium/state_trackers/glx/xlib/xm_public.h @@ -26,19 +26,23 @@ * **************************************************************************/ -#ifndef XM_WINSYS_H -#define XM_WINSYS_H +#ifndef XM_PUBLIC_H +#define XM_PUBLIC_H -struct xm_driver; +#include <X11/Xlib.h> + +struct pipe_screen; +struct st_api; /* This is the driver interface required by the glx/xlib state tracker. */ struct xm_driver { struct pipe_screen *(*create_pipe_screen)( Display *display ); + struct st_api *(*create_st_api)( void ); }; extern void xmesa_set_driver( const struct xm_driver *driver ); -#endif +#endif /* XM_PUBLIC_H */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c new file mode 100644 index 0000000000..60009c4cb0 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -0,0 +1,332 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "xm_api.h" +#include "xm_st.h" + +struct xmesa_st_framebuffer { + XMesaDisplay display; + XMesaBuffer buffer; + struct pipe_screen *screen; + + struct st_visual stvis; + + unsigned texture_width, texture_height, texture_mask; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + + struct pipe_surface *display_surface; +}; + +static INLINE struct xmesa_st_framebuffer * +xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; +} + +/** + * Display an attachment to the xlib_drawable of the framebuffer. + */ +static boolean +xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource *ptex = xstfb->textures[statt]; + struct pipe_surface *psurf; + + if (!ptex) + return TRUE; + + psurf = xstfb->display_surface; + /* (re)allocate the surface for the texture to be displayed */ + if (!psurf || psurf->texture != ptex) { + pipe_surface_reference(&xstfb->display_surface, NULL); + + psurf = xstfb->screen->get_tex_surface(xstfb->screen, + ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ); + if (!psurf) + return FALSE; + + xstfb->display_surface = psurf; + } + + xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws); + + return TRUE; +} + +/** + * Copy the contents between the attachments. + */ +static void +xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src_statt, + enum st_attachment_type dst_statt, + unsigned x, unsigned y, + unsigned width, unsigned height) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource *src_ptex = xstfb->textures[src_statt]; + struct pipe_resource *dst_ptex = xstfb->textures[dst_statt]; + struct pipe_surface *src, *dst; + struct pipe_context *pipe; + + if (!src_ptex || !dst_ptex) + return; + + pipe = xstfb->display->pipe; + if (!pipe) { + pipe = xstfb->screen->context_create(xstfb->screen, NULL); + if (!pipe) + return; + xstfb->display->pipe = pipe; + } + + src = xstfb->screen->get_tex_surface(xstfb->screen, + src_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + dst = xstfb->screen->get_tex_surface(xstfb->screen, + dst_ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); + + if (src && dst) + pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +/** + * Remove outdated textures and create the requested ones. + */ +static void +xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + unsigned width, unsigned height, + unsigned mask) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource templ; + unsigned i; + + /* remove outdated textures */ + if (xstfb->texture_width != width || xstfb->texture_height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&xstfb->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned tex_usage; + + /* the texture already exists or not requested */ + if (xstfb->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (xstfb->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = xstfb->stvis.color_format; + tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = xstfb->stvis.depth_stencil_format; + tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.tex_usage = tex_usage; + + xstfb->textures[i] = + xstfb->screen->resource_create(xstfb->screen, &templ); + } + } + + xstfb->texture_width = width; + xstfb->texture_height = height; + xstfb->texture_mask = mask; +} + +static boolean +xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + unsigned statt_mask, new_mask, i; + boolean resized; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; + /* record newly allocated textures */ + new_mask = statt_mask & ~xstfb->texture_mask; + + resized = (xstfb->buffer->width != xstfb->texture_width || + xstfb->buffer->height != xstfb->texture_height); + + /* revalidate textures */ + if (resized || new_mask) { + xmesa_st_framebuffer_validate_textures(stfbi, + xstfb->buffer->width, xstfb->buffer->height, statt_mask); + + if (!resized) { + enum st_attachment_type back, front; + + back = ST_ATTACHMENT_BACK_LEFT; + front = ST_ATTACHMENT_FRONT_LEFT; + /* copy the contents if front is newly allocated and back is not */ + if ((statt_mask & (1 << back)) && + (new_mask & (1 << front)) && + !(new_mask & (1 << back))) { + xmesa_st_framebuffer_copy_textures(stfbi, back, front, + 0, 0, xstfb->texture_width, xstfb->texture_height); + } + } + } + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_resource_reference(&out[i], xstfb->textures[statts[i]]); + } + + return TRUE; +} + +static boolean +xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, statt); + if (ret) + xmesa_check_buffer_size(xstfb->buffer); + + return ret; +} + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b) +{ + struct st_framebuffer_iface *stfbi; + struct xmesa_st_framebuffer *xstfb; + + assert(xmdpy->display == b->xm_visual->display); + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); + if (!stfbi || !xstfb) { + if (stfbi) + FREE(stfbi); + if (xstfb) + FREE(xstfb); + return NULL; + } + + xstfb->display = xmdpy; + xstfb->buffer = b; + xstfb->screen = xmdpy->screen; + xstfb->stvis = b->xm_visual->stvis; + + stfbi->visual = &xstfb->stvis; + stfbi->flush_front = xmesa_st_framebuffer_flush_front; + stfbi->validate = xmesa_st_framebuffer_validate; + stfbi->st_manager_private = (void *) xstfb; + + return stfbi; +} + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + int i; + + pipe_surface_reference(&xstfb->display_surface, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&xstfb->textures[i], NULL); + + FREE(xstfb); + FREE(stfbi); +} + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); + if (ret) { + struct pipe_resource **front, **back, *tmp; + + front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; + back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; + /* swap textures only if the front texture has been allocated */ + if (*front) { + tmp = *front; + *front = *back; + *back = tmp; + } + + xmesa_check_buffer_size(xstfb->buffer); + } +} + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h) +{ + xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h); + if (dst == ST_ATTACHMENT_FRONT_LEFT) + xmesa_st_framebuffer_display(stfbi, dst); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h new file mode 100644 index 0000000000..396495c189 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.h @@ -0,0 +1,51 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _XM_ST_H_ +#define _XM_ST_H_ + +#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" + +#include "xm_api.h" + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h); + +#endif /* _XM_ST_H_ */ diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c index c09452f777..3a8a72c33e 100644 --- a/src/gallium/state_trackers/python/st_device.c +++ b/src/gallium/state_trackers/python/st_device.c @@ -128,7 +128,7 @@ st_context_destroy(struct st_context *st_ctx) pipe_sampler_view_reference(&st_ctx->fragment_sampler_views[i], NULL); for(i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) pipe_sampler_view_reference(&st_ctx->vertex_sampler_views[i], NULL); - pipe_texture_reference(&st_ctx->default_texture, NULL); + pipe_resource_reference(&st_ctx->default_texture, NULL); FREE(st_ctx); @@ -229,8 +229,7 @@ st_context_create(struct st_device *st_dev) /* default textures */ { struct pipe_screen *screen = st_dev->screen; - struct pipe_texture templat; - struct pipe_transfer *transfer; + struct pipe_resource templat; struct pipe_sampler_view view_templ; struct pipe_sampler_view *view; unsigned i; @@ -243,26 +242,23 @@ st_context_create(struct st_device *st_dev) templat.depth0 = 1; templat.last_level = 0; - st_ctx->default_texture = screen->texture_create( screen, &templat ); + st_ctx->default_texture = screen->resource_create( screen, &templat ); if(st_ctx->default_texture) { - transfer = screen->get_transfer(screen, - st_ctx->default_texture, - 0, 0, 0, - PIPE_TRANSFER_WRITE, - 0, 0, - st_ctx->default_texture->width0, - st_ctx->default_texture->height0); - if (transfer) { - uint32_t *map; - map = (uint32_t *) screen->transfer_map(screen, transfer); - if(map) { - *map = 0x00000000; - screen->transfer_unmap(screen, transfer); - } - screen->tex_transfer_destroy(transfer); - } + struct pipe_box box; + uint32_t zero = 0; + + u_box_wh( 1, 1, &box ); + + st_ctx->pipe->transfer_inline_write(st_ctx->pipe, + st_ctx->default_texture, + u_subresource(0,0), + PIPE_TRANSFER_WRITE, + &box, + &zero, + sizeof zero, + 0); } - + u_sampler_view_default_template(&view_templ, st_ctx->default_texture, st_ctx->default_texture->format); diff --git a/src/gallium/state_trackers/python/st_device.h b/src/gallium/state_trackers/python/st_device.h index dcd0dc6e27..2dca7a1974 100644 --- a/src/gallium/state_trackers/python/st_device.h +++ b/src/gallium/state_trackers/python/st_device.h @@ -40,7 +40,7 @@ struct st_winsys; struct st_surface { - struct pipe_texture *texture; + struct pipe_resource *texture; unsigned face; unsigned level; unsigned zslice; @@ -59,7 +59,7 @@ struct st_context void *fs; void *gs; - struct pipe_texture *default_texture; + struct pipe_resource *default_texture; struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; @@ -85,7 +85,7 @@ struct st_device static INLINE struct pipe_surface * st_pipe_surface(struct st_surface *surface, unsigned usage) { - struct pipe_texture *texture = surface->texture; + struct pipe_resource *texture = surface->texture; struct pipe_screen *screen = texture->screen; return screen->get_tex_surface(screen, texture, surface->face, surface->level, surface->zslice, usage); } diff --git a/src/gallium/state_trackers/python/st_sample.c b/src/gallium/state_trackers/python/st_sample.c index ea27275325..52904fa22c 100644 --- a/src/gallium/state_trackers/python/st_sample.c +++ b/src/gallium/state_trackers/python/st_sample.c @@ -525,7 +525,7 @@ st_sample_pixel_block(enum pipe_format format, void st_sample_surface(struct st_surface *surface, float *rgba) { - struct pipe_texture *texture = surface->texture; + struct pipe_resource *texture = surface->texture; struct pipe_screen *screen = texture->screen; unsigned width = u_minify(texture->width0, surface->level); unsigned height = u_minify(texture->height0, surface->level); @@ -570,5 +570,5 @@ st_sample_surface(struct st_surface *surface, float *rgba) screen->transfer_unmap(screen, transfer); } - screen->tex_transfer_destroy(transfer); + screen->transfer_destroy(transfer); } diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile index 7f04b2aa83..7c315de827 100644 --- a/src/gallium/state_trackers/vega/Makefile +++ b/src/gallium/state_trackers/vega/Makefile @@ -25,6 +25,7 @@ VG_SOURCES = \ api_transform.c \ vgu.c \ vg_context.c \ + vg_manager.c \ vg_state.c \ vg_tracker.c \ vg_translate.c \ diff --git a/src/gallium/state_trackers/vega/api_context.c b/src/gallium/state_trackers/vega/api_context.c index 47db102dd2..eb2fbe26e7 100644 --- a/src/gallium/state_trackers/vega/api_context.c +++ b/src/gallium/state_trackers/vega/api_context.c @@ -26,6 +26,7 @@ #include "VG/openvg.h" +#include "vg_manager.h" #include "vg_context.h" #include "pipe/p_context.h" @@ -55,6 +56,8 @@ void vgFlush(void) pipe = ctx->pipe; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + + vg_manager_flush_frontbuffer(ctx); } void vgFinish(void) diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c index 6400f1f3c6..d7a7aea2ba 100644 --- a/src/gallium/state_trackers/vega/api_filters.c +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -40,6 +40,7 @@ #include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "asm_filters.h" @@ -53,7 +54,7 @@ struct filter_info { const void *const_buffer; VGint const_buffer_len; VGTilingMode tiling_mode; - struct pipe_resource *extra_texture; + struct pipe_sampler_view *extra_texture_view; }; static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx, @@ -91,13 +92,35 @@ static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx, return tex; } +static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context *ctx, + const VGuint *color_data, + const VGint color_data_len) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_resource *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_texture_1d(ctx, color_data, color_data_len); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&texture, NULL); + + return view; +} + static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst) { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; struct pipe_framebuffer_state fb; struct pipe_surface *dst_surf = pipe->screen->get_tex_surface( - pipe->screen, dst->texture, 0, 0, 0, + pipe->screen, dst->sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_RENDER_TARGET); /* drawing dest */ @@ -168,7 +191,7 @@ static void setup_constant_buffer(struct vg_context *ctx, const void *buffer, static void setup_samplers(struct vg_context *ctx, struct filter_info *info) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state sampler[3]; int num_samplers = 0; int num_textures = 0; @@ -177,10 +200,10 @@ static void setup_samplers(struct vg_context *ctx, struct filter_info *info) samplers[1] = NULL; samplers[2] = NULL; samplers[3] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; - textures[3] = NULL; + sampler_views[0] = NULL; + sampler_views[1] = NULL; + sampler_views[2] = NULL; + sampler_views[3] = NULL; memset(&sampler[0], 0, sizeof(struct pipe_sampler_state)); sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -215,21 +238,21 @@ static void setup_samplers(struct vg_context *ctx, struct filter_info *info) } samplers[0] = &sampler[0]; - textures[0] = info->src->texture; + sampler_views[0] = info->src->sampler_view; ++num_samplers; ++num_textures; - if (info->extra_texture) { + if (info->extra_texture_view) { memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state)); samplers[1] = &sampler[1]; - textures[1] = info->extra_texture; + sampler_views[1] = info->extra_texture_view; ++num_samplers; ++num_textures; } cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, num_textures, textures); + cso_set_fragment_sampler_views(ctx->cso_context, num_textures, sampler_views); } static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data) @@ -308,7 +331,7 @@ static void execute_filter(struct vg_context *ctx, cso_save_viewport(ctx->cso_context); cso_save_blend(ctx->cso_context); cso_save_samplers(ctx->cso_context); - cso_save_sampler_textures(ctx->cso_context); + cso_save_fragment_sampler_views(ctx->cso_context); dst_surf = setup_framebuffer(info->dst); setup_viewport(info->dst); @@ -318,7 +341,7 @@ static void execute_filter(struct vg_context *ctx, setup_samplers(ctx, info); renderer_draw_texture(ctx->renderer, - info->src->texture, + info->src->sampler_view->texture, info->dst->x, info->dst->y, info->dst->x + info->dst->width, info->dst->y + info->dst->height, @@ -331,7 +354,7 @@ static void execute_filter(struct vg_context *ctx, cso_restore_viewport(ctx->cso_context); cso_restore_blend(ctx->cso_context); cso_restore_samplers(ctx->cso_context); - cso_restore_sampler_textures(ctx->cso_context); + cso_restore_fragment_sampler_views(ctx->cso_context); vg_shader_destroy(ctx, shader); @@ -369,7 +392,7 @@ void vgColorMatrix(VGImage dst, VGImage src, info.const_buffer = matrix; info.const_buffer_len = 20 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); } @@ -479,7 +502,7 @@ void vgConvolve(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = buffer_len * sizeof(VGfloat); info.tiling_mode = tilingMode; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); free(buffer); @@ -669,7 +692,7 @@ void vgGaussianBlur(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = buffer_len * sizeof(VGfloat); info.tiling_mode = tilingMode; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); free(buffer); @@ -688,7 +711,7 @@ void vgLookup(VGImage dst, VGImage src, struct vg_image *d, *s; VGuint color_data[256]; VGint i; - struct pipe_resource *lut_texture; + struct pipe_sampler_view *lut_texture_view; VGfloat buffer[4]; struct filter_info info; @@ -714,7 +737,7 @@ void vgLookup(VGImage dst, VGImage src, color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 | redLUT[i] << 8 | alphaLUT[i]; } - lut_texture = create_texture_1d(ctx, color_data, 255); + lut_texture_view = create_texture_1d_view(ctx, color_data, 255); buffer[0] = 0.f; buffer[1] = 0.f; @@ -728,11 +751,11 @@ void vgLookup(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = 4 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = lut_texture; + info.extra_texture_view = lut_texture_view; execute_filter(ctx, &info); - pipe_resource_reference(&lut_texture, NULL); + pipe_sampler_view_reference(&lut_texture_view, NULL); } void vgLookupSingle(VGImage dst, VGImage src, @@ -743,7 +766,7 @@ void vgLookupSingle(VGImage dst, VGImage src, { struct vg_context *ctx = vg_current_context(); struct vg_image *d, *s; - struct pipe_resource *lut_texture; + struct pipe_sampler_view *lut_texture_view; VGfloat buffer[4]; struct filter_info info; VGuint color_data[256]; @@ -783,7 +806,7 @@ void vgLookupSingle(VGImage dst, VGImage src, color_data[i] = blue << 24 | green << 16 | red << 8 | alpha; } - lut_texture = create_texture_1d(ctx, color_data, 256); + lut_texture_view = create_texture_1d_view(ctx, color_data, 256); buffer[0] = 0.f; buffer[1] = 0.f; @@ -797,9 +820,9 @@ void vgLookupSingle(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = 4 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = lut_texture; + info.extra_texture_view = lut_texture_view; execute_filter(ctx, &info); - pipe_resource_reference(&lut_texture, NULL); + pipe_sampler_view_reference(&lut_texture_view, NULL); } diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c index 9796bcaf86..eecae090a5 100644 --- a/src/gallium/state_trackers/vega/api_masks.c +++ b/src/gallium/state_trackers/vega/api_masks.c @@ -118,10 +118,6 @@ clear_with_quad(struct vg_context *st, float x0, float y0, x1, y1); */ - if (st->pipe->screen && st->pipe->screen->update_buffer) - st->pipe->screen->update_buffer( st->pipe->screen, - st->pipe->priv ); - cso_save_blend(st->cso_context); cso_save_rasterizer(st->cso_context); cso_save_fragment_shader(st->cso_context); diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c index ba3397fd66..e666bee170 100644 --- a/src/gallium/state_trackers/vega/image.c +++ b/src/gallium/state_trackers/vega/image.c @@ -43,6 +43,7 @@ #include "util/u_tile.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_sampler.h" static enum pipe_format vg_format_to_pipe(VGImageFormat format) { @@ -81,7 +82,7 @@ static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc) static void vg_copy_texture(struct vg_context *ctx, struct pipe_resource *dst, VGint dx, VGint dy, - struct pipe_resource *src, VGint sx, VGint sy, + struct pipe_sampler_view *src, VGint sx, VGint sy, VGint width, VGint height) { VGfloat dst_loc[4], src_loc[4]; @@ -103,8 +104,8 @@ static void vg_copy_texture(struct vg_context *ctx, src_loc[3] = height; src_bounds[0] = 0.f; src_bounds[1] = 0.f; - src_bounds[2] = src->width0; - src_bounds[3] = src->height0; + src_bounds[2] = src->texture->width0; + src_bounds[3] = src->texture->height0; vg_bound_rect(src_loc, src_bounds, src_shift); vg_bound_rect(dst_loc, dst_bounds, dst_shift); @@ -218,7 +219,7 @@ void vg_copy_surface(struct vg_context *ctx, static struct pipe_resource *image_texture(struct vg_image *img) { - struct pipe_resource *tex = img->texture; + struct pipe_resource *tex = img->sampler_view->texture; return tex; } @@ -247,9 +248,12 @@ struct vg_image * image_create(VGImageFormat format, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; struct vg_image *image = CALLOC_STRUCT(vg_image); enum pipe_format pformat = vg_format_to_pipe(format); struct pipe_resource pt, *newtex; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; struct pipe_screen *screen = ctx->pipe->screen; vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE); @@ -281,7 +285,12 @@ struct vg_image * image_create(VGImageFormat format, debug_assert(newtex); - image->texture = newtex; + u_sampler_view_default_template(&view_templ, newtex, newtex->format); + view = pipe->create_sampler_view(pipe, newtex, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&newtex, NULL); + + image->sampler_view = view; vg_context_add_object(ctx, VG_OBJECT_IMAGE, image); @@ -345,7 +354,7 @@ void image_destroy(struct vg_image *img) array_destroy(img->children_array); } - pipe_resource_reference(&img->texture, NULL); + pipe_sampler_view_reference(&img->sampler_view, NULL); free(img); } @@ -444,7 +453,7 @@ void image_get_sub_data(struct vg_image * image, { struct pipe_transfer *transfer = pipe_get_transfer(pipe, - image->texture, 0, 0, 0, + image->sampler_view->texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, image->x + image->width, @@ -478,9 +487,9 @@ struct vg_image * image_child_image(struct vg_image *parent, image->width = width; image->height = height; image->parent = parent; - image->texture = 0; - pipe_resource_reference(&image->texture, - parent->texture); + image->sampler_view = NULL; + pipe_sampler_view_reference(&image->sampler_view, + parent->sampler_view); image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -514,8 +523,8 @@ void image_copy(struct vg_image *dst, VGint dx, VGint dy, } /* make sure rendering has completed */ ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy, - src->texture, src->x + sx, src->y + sy, width, height); + vg_copy_texture(ctx, dst->sampler_view->texture, dst->x + dx, dst->y + dy, + src->sampler_view, src->x + sx, src->y + sy, width, height); } void image_draw(struct vg_image *img) @@ -624,12 +633,12 @@ VGboolean vg_image_overlaps(struct vg_image *dst, } VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { img->sampler.min_img_filter = image_sampler_filter(img->base.ctx); img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx); samplers[3] = &img->sampler; - textures[3] = img->texture; + sampler_views[3] = img->sampler_view; return 1; } diff --git a/src/gallium/state_trackers/vega/image.h b/src/gallium/state_trackers/vega/image.h index 8dcaf131b6..a990c9c587 100644 --- a/src/gallium/state_trackers/vega/image.h +++ b/src/gallium/state_trackers/vega/image.h @@ -43,7 +43,7 @@ struct vg_image { struct vg_image *parent; - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; struct pipe_sampler_state sampler; struct array *children_array; @@ -89,7 +89,7 @@ void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy, VGint width, VGint height); VGint image_bind_samplers(struct vg_image *dst, struct pipe_sampler_state **samplers, - struct pipe_resource **textures); + struct pipe_sampler_view **sampler_views); VGboolean vg_image_overlaps(struct vg_image *dst, struct vg_image *src); diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c index 5f097e7107..509a68582b 100644 --- a/src/gallium/state_trackers/vega/mask.c +++ b/src/gallium/state_trackers/vega/mask.c @@ -45,7 +45,7 @@ struct vg_mask_layer { VGint width; VGint height; - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; }; static INLINE struct pipe_surface * @@ -54,7 +54,7 @@ alpha_mask_surface(struct vg_context *ctx, int usage) struct pipe_screen *screen = ctx->pipe->screen; struct st_framebuffer *stfb = ctx->draw_buffer; return screen->get_tex_surface(screen, - stfb->alpha_mask, + stfb->alpha_mask_view->texture, 0, 0, 0, usage); } @@ -284,35 +284,33 @@ static void setup_mask_operation(VGMaskOperation operation) cso_set_fragment_shader_handle(ctx->cso_context, shader); } -static void setup_mask_samplers(struct pipe_resource *umask) +static void setup_mask_samplers(struct pipe_sampler_view *umask) { struct vg_context *ctx = vg_current_context(); struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct st_framebuffer *fb_buffers = ctx->draw_buffer; - struct pipe_resource *uprev = NULL; + struct pipe_sampler_view *uprev = NULL; struct pipe_sampler_state sampler; - uprev = fb_buffers->blend_texture; + uprev = fb_buffers->blend_texture_view; sampler = ctx->mask.sampler; sampler.normalized_coords = 1; samplers[0] = NULL; samplers[1] = NULL; - samplers[2] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; + sampler_views[0] = NULL; + sampler_views[1] = NULL; samplers[0] = &sampler; samplers[1] = &ctx->mask.sampler; - textures[0] = umask; - textures[1] = uprev; + sampler_views[0] = umask; + sampler_views[1] = uprev; cso_set_samplers(ctx->cso_context, 2, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, 2, textures); + cso_set_fragment_sampler_views(ctx->cso_context, 2, sampler_views); } @@ -411,12 +409,13 @@ static void surface_fill(struct pipe_surface *surf, } -static void mask_using_texture(struct pipe_resource *texture, +static void mask_using_texture(struct pipe_sampler_view *sampler_view, VGMaskOperation operation, VGint x, VGint y, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); + struct pipe_resource *texture = sampler_view->texture; struct pipe_surface *surface = alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_RENDER_TARGET); VGint offsets[4], loc[4]; @@ -439,13 +438,13 @@ static void mask_using_texture(struct pipe_resource *texture, vg_prepare_blend_surface_from_mask(ctx); cso_save_samplers(ctx->cso_context); - cso_save_sampler_textures(ctx->cso_context); + cso_save_fragment_sampler_views(ctx->cso_context); cso_save_framebuffer(ctx->cso_context); cso_save_blend(ctx->cso_context); cso_save_fragment_shader(ctx->cso_context); cso_save_viewport(ctx->cso_context); - setup_mask_samplers(texture); + setup_mask_samplers(sampler_view); setup_mask_blend(); setup_mask_operation(operation); setup_mask_framebuffer(surface, surface->width, surface->height); @@ -463,7 +462,7 @@ static void mask_using_texture(struct pipe_resource *texture, cso_restore_framebuffer(ctx->cso_context); cso_restore_fragment_shader(ctx->cso_context); cso_restore_samplers(ctx->cso_context); - cso_restore_sampler_textures(ctx->cso_context); + cso_restore_fragment_sampler_views(ctx->cso_context); cso_restore_viewport(ctx->cso_context); pipe_surface_reference(&surface, NULL); @@ -484,7 +483,11 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height) { struct pipe_resource pt; + struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view = NULL; + struct pipe_resource *texture; memset(&pt, 0, sizeof(pt)); pt.target = PIPE_TEXTURE_2D; @@ -496,7 +499,14 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height) pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; pt.compressed = 0; - mask->texture = screen->resource_create(screen, &pt); + texture = screen->resource_create(screen, &pt); + + if (texture) { + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + } + pipe_resource_reference(&texture, NULL); + mask->sampler_view = view; } vg_context_add_object(ctx, VG_OBJECT_MASK, mask); @@ -525,7 +535,7 @@ void mask_layer_fill(struct vg_mask_layer *layer, alpha_color[3] = value; surface = ctx->pipe->screen->get_tex_surface( - ctx->pipe->screen, layer->texture, + ctx->pipe->screen, layer->sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); @@ -545,10 +555,10 @@ void mask_copy(struct vg_mask_layer *layer, struct st_framebuffer *fb_buffers = ctx->draw_buffer; renderer_copy_texture(ctx->renderer, - layer->texture, + layer->sampler_view, sx, sy, sx + width, sy + height, - fb_buffers->alpha_mask, + fb_buffers->alpha_mask_view->texture, dx, dy, dx + width, dy + height); } @@ -562,7 +572,7 @@ static void mask_layer_render_to(struct vg_mask_layer *layer, struct pipe_screen *screen = ctx->pipe->screen; struct pipe_surface *surface; - surface = screen->get_tex_surface(screen, layer->texture, 0, 0, 0, + surface = screen->get_tex_surface(screen, layer->sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); cso_save_framebuffer(ctx->cso_context); @@ -604,8 +614,8 @@ void mask_render_to(struct path *path, struct vg_mask_layer *temp_layer; VGint width, height; - width = fb_buffers->alpha_mask->width0; - height = fb_buffers->alpha_mask->width0; + width = fb_buffers->alpha_mask_view->texture->width0; + height = fb_buffers->alpha_mask_view->texture->width0; temp_layer = mask_layer_create(width, height); @@ -622,7 +632,7 @@ void mask_using_layer(struct vg_mask_layer *layer, VGint x, VGint y, VGint width, VGint height) { - mask_using_texture(layer->texture, operation, + mask_using_texture(layer->sampler_view, operation, x, y, width, height); } @@ -644,7 +654,7 @@ void mask_using_image(struct vg_image *image, VGint x, VGint y, VGint width, VGint height) { - mask_using_texture(image->texture, operation, + mask_using_texture(image->sampler_view, operation, x, y, width, height); } @@ -672,7 +682,7 @@ void mask_fill(VGint x, VGint y, VGint width, VGint height, } VGint mask_bind_samplers(struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { struct vg_context *ctx = vg_current_context(); @@ -680,7 +690,7 @@ VGint mask_bind_samplers(struct pipe_sampler_state **samplers, struct st_framebuffer *fb_buffers = ctx->draw_buffer; samplers[1] = &ctx->mask.sampler; - textures[1] = fb_buffers->alpha_mask; + sampler_views[1] = fb_buffers->alpha_mask_view; return 1; } else return 0; diff --git a/src/gallium/state_trackers/vega/mask.h b/src/gallium/state_trackers/vega/mask.h index 1489257193..c626402c86 100644 --- a/src/gallium/state_trackers/vega/mask.h +++ b/src/gallium/state_trackers/vega/mask.h @@ -63,6 +63,6 @@ void mask_fill(VGint x, VGint y, VGfloat value); VGint mask_bind_samplers(struct pipe_sampler_state **samplers, - struct pipe_resource **textures); + struct pipe_sampler_view **sampler_views); #endif diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c index 5c1482cb07..a481ed2307 100644 --- a/src/gallium/state_trackers/vega/paint.c +++ b/src/gallium/state_trackers/vega/paint.c @@ -37,6 +37,7 @@ #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" @@ -61,7 +62,7 @@ struct vg_paint { VGfloat vals[5]; VGint valsi[5]; } radial; - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; struct pipe_sampler_state sampler; VGfloat *ramp_stops; @@ -72,7 +73,7 @@ struct vg_paint { } gradient; struct { - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; VGTilingMode tiling_mode; struct pipe_sampler_state sampler; } pattern; @@ -173,6 +174,26 @@ static INLINE struct pipe_resource *create_gradient_texture(struct vg_paint *p) return tex; } +static INLINE struct pipe_sampler_view *create_gradient_sampler_view(struct vg_paint *p) +{ + struct pipe_context *pipe = p->base.ctx->pipe; + struct pipe_resource *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_gradient_texture(p); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&texture, NULL); + + return view; +} + struct vg_paint * paint_create(struct vg_context *ctx) { struct vg_paint *paint = CALLOC_STRUCT(vg_paint); @@ -207,8 +228,9 @@ struct vg_paint * paint_create(struct vg_context *ctx) void paint_destroy(struct vg_paint *paint) { struct vg_context *ctx = paint->base.ctx; - if (paint->pattern.texture) - pipe_resource_reference(&paint->pattern.texture, NULL); + pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL); + if (paint->pattern.sampler_view) + pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL); if (ctx) vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint); @@ -329,8 +351,8 @@ static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer) map[4] = 0.f; map[5] = 1.f; - map[6] = paint->pattern.texture->width0; - map[7] = paint->pattern.texture->height0; + map[6] = paint->pattern.sampler_view->texture->width0; + map[7] = paint->pattern.sampler_view->texture->height0; { struct matrix mat; memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix, @@ -394,12 +416,12 @@ void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops, create_gradient_data(stops, num / 5, paint->gradient.color_data, 1024); - if (paint->gradient.texture) { - pipe_resource_reference(&paint->gradient.texture, NULL); - paint->gradient.texture = 0; + if (paint->gradient.sampler_view) { + pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL); + paint->gradient.sampler_view = NULL; } - paint->gradient.texture = create_gradient_texture(paint); + paint->gradient.sampler_view = create_gradient_sampler_view(paint); } void paint_set_colori(struct vg_paint *p, @@ -459,12 +481,12 @@ void paint_set_radial_gradient(struct vg_paint *paint, void paint_set_pattern(struct vg_paint *paint, struct vg_image *img) { - if (paint->pattern.texture) - pipe_resource_reference(&paint->pattern.texture, NULL); + if (paint->pattern.sampler_view) + pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL); - paint->pattern.texture = 0; - pipe_resource_reference(&paint->pattern.texture, - img->texture); + paint->pattern.sampler_view = NULL; + pipe_sampler_view_reference(&paint->pattern.sampler_view, + img->sampler_view); } void paint_set_pattern_tiling(struct vg_paint *paint, @@ -611,18 +633,18 @@ VGTilingMode paint_pattern_tiling(struct vg_paint *paint) } VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { struct vg_context *ctx = vg_current_context(); switch(paint->type) { case VG_PAINT_TYPE_LINEAR_GRADIENT: case VG_PAINT_TYPE_RADIAL_GRADIENT: { - if (paint->gradient.texture) { + if (paint->gradient.sampler_view) { paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx); paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx); samplers[0] = &paint->gradient.sampler; - textures[0] = paint->gradient.texture; + sampler_views[0] = paint->gradient.sampler_view; return 1; } } @@ -634,7 +656,7 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx); paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx); samplers[0] = &paint->pattern.sampler; - textures[0] = paint->pattern.texture; + sampler_views[0] = paint->pattern.sampler_view; return 1; } break; @@ -647,7 +669,7 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa void paint_resolve_type(struct vg_paint *paint) { if (paint->type == VG_PAINT_TYPE_PATTERN && - !paint->pattern.texture) { + !paint->pattern.sampler_view) { paint->type = VG_PAINT_TYPE_COLOR; } } diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h index cf9a701c35..012cd3e561 100644 --- a/src/gallium/state_trackers/vega/paint.h +++ b/src/gallium/state_trackers/vega/paint.h @@ -108,7 +108,7 @@ VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint); VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, - struct pipe_resource **textures); + struct pipe_sampler_view **sampler_views); VGint paint_constant_buffer_size(struct vg_paint *paint); void paint_fill_constant_buffer(struct vg_paint *paint, diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 05897c05d9..d5e4e0ba9d 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -39,6 +39,7 @@ #include "util/u_simple_shaders.h" #include "util/u_memory.h" #include "util/u_rect.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" @@ -266,7 +267,7 @@ void renderer_draw_texture(struct renderer *r, } void renderer_copy_texture(struct renderer *ctx, - struct pipe_resource *src, + struct pipe_sampler_view *src, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, struct pipe_resource *dst, @@ -275,6 +276,7 @@ void renderer_copy_texture(struct renderer *ctx, { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; + struct pipe_resource *tex = src->texture; struct pipe_resource *buf; struct pipe_surface *dst_surf = screen->get_tex_surface( screen, dst, 0, 0, 0, @@ -282,8 +284,8 @@ void renderer_copy_texture(struct renderer *ctx, struct pipe_framebuffer_state fb; float s0, t0, s1, t1; - assert(src->width0 != 0); - assert(src->height0 != 0); + assert(tex->width0 != 0); + assert(tex->height0 != 0); assert(dst->width0 != 0); assert(dst->height0 != 0); @@ -293,10 +295,10 @@ void renderer_copy_texture(struct renderer *ctx, #endif #if 1 - s0 = sx1 / src->width0; - s1 = sx2 / src->width0; - t0 = sy1 / src->height0; - t1 = sy2 / src->height0; + s0 = sx1 / tex->width0; + s1 = sx2 / tex->width0; + t0 = sy1 / tex->height0; + t1 = sy2 / tex->height0; #else s0 = 0; s1 = 1; @@ -310,7 +312,7 @@ void renderer_copy_texture(struct renderer *ctx, /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -348,7 +350,7 @@ void renderer_copy_texture(struct renderer *ctx, vg_set_viewport(ctx->owner, VEGA_Y0_TOP); /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &src); + cso_set_fragment_sampler_views(ctx->cso, 1, &src); /* shaders */ cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); @@ -388,7 +390,7 @@ void renderer_copy_texture(struct renderer *ctx, /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_fragment_shader(ctx->cso); @@ -409,6 +411,8 @@ void renderer_copy_surface(struct renderer *ctx, struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_resource *buf; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; struct pipe_resource texTemp, *tex; struct pipe_surface *texSurf; struct pipe_framebuffer_state fb; @@ -460,6 +464,12 @@ void renderer_copy_surface(struct renderer *ctx, if (!tex) return; + u_sampler_view_default_template(&view_templ, tex, tex->format); + view = pipe->create_sampler_view(pipe, tex, &view_templ); + + if (!view) + return; + texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, PIPE_BUFFER_USAGE_RENDER_TARGET); @@ -482,7 +492,7 @@ void renderer_copy_surface(struct renderer *ctx, /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -518,7 +528,7 @@ void renderer_copy_surface(struct renderer *ctx, } /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &tex); + cso_set_fragment_sampler_views(ctx->cso, 1, &view); /* shaders */ cso_set_fragment_shader_handle(ctx->cso, ctx->fs); @@ -555,13 +565,14 @@ void renderer_copy_surface(struct renderer *ctx, /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_viewport(ctx->cso); pipe_resource_reference(&tex, NULL); + pipe_sampler_view_reference(&view, NULL); } void renderer_texture_quad(struct renderer *r, diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h index 6afb3097f3..b1a9fb58be 100644 --- a/src/gallium/state_trackers/vega/renderer.h +++ b/src/gallium/state_trackers/vega/renderer.h @@ -33,6 +33,7 @@ struct renderer; struct vg_context; struct pipe_resource; +struct pipe_sampler_view; struct pipe_surface; struct renderer *renderer_create(struct vg_context *owner); @@ -57,7 +58,7 @@ void renderer_texture_quad(struct renderer *, VGfloat x3, VGfloat y3, VGfloat x4, VGfloat y4); void renderer_copy_texture(struct renderer *r, - struct pipe_resource *src, + struct pipe_sampler_view *src, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, struct pipe_resource *dst, diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index e1a3676612..288515d9ad 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -120,7 +120,7 @@ static void setup_constant_buffer(struct shader *shader) static VGint blend_bind_samplers(struct vg_context *ctx, struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { VGBlendMode bmode = ctx->state.vg.blend_mode; @@ -133,15 +133,15 @@ static VGint blend_bind_samplers(struct vg_context *ctx, vg_prepare_blend_surface(ctx); samplers[2] = &ctx->blend_sampler; - textures[2] = stfb->blend_texture; + sampler_views[2] = stfb->blend_texture_view; - if (!samplers[0] || !textures[0]) { + if (!samplers[0] || !sampler_views[0]) { samplers[0] = samplers[2]; - textures[0] = textures[2]; + sampler_views[0] = sampler_views[2]; } - if (!samplers[1] || !textures[1]) { + if (!samplers[1] || !sampler_views[1]) { samplers[1] = samplers[0]; - textures[1] = textures[0]; + sampler_views[1] = sampler_views[0]; } return 1; @@ -152,7 +152,7 @@ static VGint blend_bind_samplers(struct vg_context *ctx, static void setup_samplers(struct shader *shader) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct vg_context *ctx = shader->context; /* a little wonky: we use the num as a boolean that just says * whether any sampler/textures have been set. the actual numbering @@ -168,20 +168,20 @@ static void setup_samplers(struct shader *shader) samplers[1] = NULL; samplers[2] = NULL; samplers[3] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; - textures[3] = NULL; - - num += paint_bind_samplers(shader->paint, samplers, textures); - num += mask_bind_samplers(samplers, textures); - num += blend_bind_samplers(ctx, samplers, textures); + sampler_views[0] = NULL; + sampler_views[1] = NULL; + sampler_views[2] = NULL; + sampler_views[3] = NULL; + + num += paint_bind_samplers(shader->paint, samplers, sampler_views); + num += mask_bind_samplers(samplers, sampler_views); + num += blend_bind_samplers(ctx, samplers, sampler_views); if (shader->drawing_image && shader->image) - num += image_bind_samplers(shader->image, samplers, textures); + num += image_bind_samplers(shader->image, samplers, sampler_views); if (num) { cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, 4, textures); + cso_set_fragment_sampler_views(ctx->cso_context, 4, sampler_views); } } diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index 887fd356ef..948b8400cb 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -32,6 +32,7 @@ #include "shader.h" #include "asm_util.h" #include "st_inlines.h" +#include "vg_manager.h" #include "pipe/p_context.h" #include "util/u_inlines.h" @@ -42,6 +43,7 @@ #include "util/u_simple_shaders.h" #include "util/u_memory.h" #include "util/u_blit.h" +#include "util/u_sampler.h" struct vg_context *_vg_context = 0; @@ -305,6 +307,8 @@ static void update_clip_state(struct vg_context *ctx) void vg_validate_state(struct vg_context *ctx) { + vg_manager_validate_framebuffer(ctx); + if ((ctx->state.dirty & BLEND_DIRTY)) { struct pipe_blend_state *blend = &ctx->state.g3d.blend; memset(blend, 0, sizeof(struct pipe_blend_state)); @@ -433,20 +437,25 @@ void vg_prepare_blend_surface(struct vg_context *ctx) { struct pipe_surface *dest_surface = NULL; struct pipe_context *pipe = ctx->pipe; + struct pipe_sampler_view *view; + struct pipe_sampler_view view_templ; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; /* first finish all pending rendering */ vgFinish(); + u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format); + view = pipe->create_sampler_view(pipe, strb->texture, &view_templ); + dest_surface = pipe->screen->get_tex_surface(pipe->screen, - stfb->blend_texture, + stfb->blend_texture_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_BLIT_DESTINATION | PIPE_BUFFER_USAGE_RENDER_TARGET); /* flip it, because we want to use it as a sampler */ util_blit_pixels_tex(ctx->blit, - strb->texture, + view, 0, strb->height, strb->width, 0, dest_surface, @@ -459,6 +468,8 @@ void vg_prepare_blend_surface(struct vg_context *ctx) /* make sure it's complete */ vgFinish(); + + pipe_sampler_view_reference(&view, NULL); } @@ -475,14 +486,14 @@ void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) vgFinish(); dest_surface = pipe->screen->get_tex_surface(pipe->screen, - stfb->blend_texture, + stfb->blend_texture_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_BLIT_DESTINATION | PIPE_BUFFER_USAGE_RENDER_TARGET); /* flip it, because we want to use it as a sampler */ util_blit_pixels_tex(ctx->blit, - stfb->alpha_mask, + stfb->alpha_mask_view, 0, strb->height, strb->width, 0, dest_surface, diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h index 361c962c67..dac67192a5 100644 --- a/src/gallium/state_trackers/vega/vg_context.h +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -33,6 +33,7 @@ #include "pipe/p_state.h" #include "util/u_pointer.h" #include "util/u_math.h" +#include "state_tracker/st_api.h" #include "cso_cache/cso_hash.h" #include "cso_cache/cso_context.h" @@ -54,9 +55,13 @@ struct st_framebuffer { struct st_renderbuffer *strb; struct st_renderbuffer *dsrb; - struct pipe_resource *alpha_mask; + struct pipe_sampler_view *alpha_mask_view; - struct pipe_resource *blend_texture; + struct pipe_sampler_view *blend_texture_view; + + + struct st_framebuffer_iface *iface; + enum st_attachment_type strb_att; void *privateData; }; @@ -84,6 +89,8 @@ enum dirty_state { struct vg_context { + struct st_context_iface iface; + struct pipe_context *pipe; struct { @@ -101,6 +108,7 @@ struct vg_context VGErrorCode _error; struct st_framebuffer *draw_buffer; + int32_t draw_buffer_invalid; struct cso_hash *owned_objects[VG_OBJECT_LAST]; diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c new file mode 100644 index 0000000000..773494151f --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_manager.c @@ -0,0 +1,373 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "state_tracker/st_api.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "vg_manager.h" +#include "vg_context.h" +#include "vg_tracker.h" /* for st_resize_framebuffer */ +#include "image.h" + +/** + * Flush the front buffer if the current context renders to the front buffer. + */ +void +vg_manager_flush_frontbuffer(struct vg_context *ctx) +{ + struct st_framebuffer *stfb = ctx->draw_buffer; + + if (!stfb) + return; + + /* st_public.h is used */ + if (!stfb->iface) { + struct pipe_screen *screen = ctx->pipe->screen; + if (screen->flush_frontbuffer) { + screen->flush_frontbuffer(screen, + stfb->strb->surface, ctx->pipe->priv); + } + return; + } + + switch (stfb->strb_att) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + stfb->iface->flush_front(stfb->iface, stfb->strb_att); + break; + default: + break; + } +} + +/** + * Re-validate the framebuffer. + */ +void +vg_manager_validate_framebuffer(struct vg_context *ctx) +{ + struct pipe_screen *screen = ctx->pipe->screen; + struct st_framebuffer *stfb = ctx->draw_buffer; + struct st_renderbuffer *rb; + struct pipe_resource *pt; + + /* no binding surface */ + if (!stfb) + return; + + /* st_public.h is used */ + if (!stfb->iface) { + struct pipe_screen *screen = ctx->pipe->screen; + if (screen->update_buffer) + screen->update_buffer(screen, ctx->pipe->priv); + return; + } + + if (!p_atomic_read(&ctx->draw_buffer_invalid)) + return; + + /* validate the fb */ + if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt) + return; + + rb = stfb->strb; + if (rb->texture == pt) { + pipe_resource_reference(&pt, NULL); + return; + } + + /* unreference existing ones */ + pipe_surface_reference(&rb->surface, NULL); + pipe_resource_reference(&rb->texture, NULL); + + rb->texture = pt; + rb->surface = screen->get_tex_surface(screen, rb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); + + rb->width = rb->surface->width; + rb->height = rb->surface->height; + + st_resize_framebuffer(stfb, rb->width, rb->height); + + p_atomic_set(&ctx->draw_buffer_invalid, FALSE); +} + + +static void +vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + p_atomic_set(&ctx->draw_buffer_invalid, TRUE); +} + +static void +vg_context_flush(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + ctx->pipe->flush(ctx->pipe, flags, fence); + if (flags & PIPE_FLUSH_RENDER_CACHE) + vg_manager_flush_frontbuffer(ctx); +} + +static void +vg_context_destroy(struct st_context_iface *stctxi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + vg_destroy_context(ctx); +} + +static struct st_context_iface * +vg_api_create_context(struct st_api *stapi, struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *shared_stctxi) +{ + struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi; + struct vg_context *ctx; + struct pipe_context *pipe; + + pipe = smapi->screen->context_create(smapi->screen, NULL); + if (!pipe) + return NULL; + ctx = vg_create_context(pipe, NULL, shared_ctx); + if (!ctx) { + pipe->destroy(pipe); + return NULL; + } + + ctx->iface.destroy = vg_context_destroy; + + ctx->iface.notify_invalid_framebuffer = + vg_context_notify_invalid_framebuffer; + ctx->iface.flush = vg_context_flush; + + ctx->iface.teximage = NULL; + ctx->iface.copy = NULL; + + ctx->iface.st_context_private = (void *) smapi; + + return &ctx->iface; +} + +static struct st_renderbuffer * +create_renderbuffer(enum pipe_format format) +{ + struct st_renderbuffer *strb; + + strb = CALLOC_STRUCT(st_renderbuffer); + if (strb) + strb->format = format; + + return strb; +} + +static void +destroy_renderbuffer(struct st_renderbuffer *strb) +{ + pipe_surface_reference(&strb->surface, NULL); + pipe_resource_reference(&strb->texture, NULL); + free(strb); +} + +/** + * Decide the buffer to render to. + */ +static enum st_attachment_type +choose_attachment(struct st_framebuffer_iface *stfbi) +{ + enum st_attachment_type statt; + + statt = stfbi->visual->render_buffer; + if (statt != ST_ATTACHMENT_INVALID) { + /* use the buffer given by the visual, unless it is unavailable */ + if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) { + switch (statt) { + case ST_ATTACHMENT_BACK_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + statt = ST_ATTACHMENT_FRONT_RIGHT; + break; + default: + break; + } + + if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) + statt = ST_ATTACHMENT_INVALID; + } + } + + return statt; +} + +/** + * Bind the context to the given framebuffers. + */ +static boolean +vg_context_bind_framebuffers(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + struct st_framebuffer *stfb; + enum st_attachment_type strb_att; + + /* the draw and read framebuffers must be the same */ + if (stdrawi != streadi) + return FALSE; + + p_atomic_set(&ctx->draw_buffer_invalid, TRUE); + + strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID; + + if (ctx->draw_buffer) { + stfb = ctx->draw_buffer; + + /* free the existing fb */ + if (!stdrawi || + stfb->strb_att != strb_att || + stfb->strb->format != stdrawi->visual->color_format || + stfb->dsrb->format != stdrawi->visual->depth_stencil_format) { + destroy_renderbuffer(stfb->strb); + destroy_renderbuffer(stfb->dsrb); + free(stfb); + + ctx->draw_buffer = NULL; + } + } + + if (!stdrawi) + return TRUE; + + if (strb_att == ST_ATTACHMENT_INVALID) + return FALSE; + + /* create a new fb */ + if (!ctx->draw_buffer) { + stfb = CALLOC_STRUCT(st_framebuffer); + if (!stfb) + return FALSE; + + stfb->strb = create_renderbuffer(stdrawi->visual->color_format); + if (!stfb->strb) { + free(stfb); + return FALSE; + } + + stfb->dsrb = create_renderbuffer(stdrawi->visual->depth_stencil_format); + if (!stfb->dsrb) { + free(stfb->strb); + free(stfb); + return FALSE; + } + + stfb->width = 0; + stfb->height = 0; + stfb->strb_att = strb_att; + + ctx->draw_buffer = stfb; + } + + ctx->draw_buffer->iface = stdrawi; + + return TRUE; +} + +static boolean +vg_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + + if (stctxi) + vg_context_bind_framebuffers(stctxi, stdrawi, streadi); + vg_set_current_context(ctx); + + return TRUE; +} + +static struct st_context_iface * +vg_api_get_current(struct st_api *stapi) +{ + struct vg_context *ctx = vg_current_context(); + + return (ctx) ? &ctx->iface : NULL; +} + +static boolean +vg_api_is_visual_supported(struct st_api *stapi, + const struct st_visual *visual) +{ + /* the impl requires a depth/stencil buffer */ + if (visual->depth_stencil_format == PIPE_FORMAT_NONE) + return FALSE; + + return TRUE; +} + +static st_proc_t +vg_api_get_proc_address(struct st_api *stapi, const char *procname) +{ + /* TODO */ + return (st_proc_t) NULL; +} + +static void +vg_api_destroy(struct st_api *stapi) +{ + free(stapi); +} + +static struct st_api * +vg_module_create_api(void) +{ + struct st_api *stapi; + + stapi = CALLOC_STRUCT(st_api); + if (stapi) { + stapi->destroy = vg_api_destroy; + stapi->get_proc_address = vg_api_get_proc_address; + stapi->is_visual_supported = vg_api_is_visual_supported; + + stapi->create_context = vg_api_create_context; + stapi->make_current = vg_api_make_current; + stapi->get_current = vg_api_get_current; + } + + return stapi; +} + +PUBLIC const struct st_module st_module_OpenVG = { + .api = ST_API_OPENVG, + .create_api = vg_module_create_api, +}; diff --git a/src/gallium/state_trackers/vega/vg_manager.h b/src/gallium/state_trackers/vega/vg_manager.h new file mode 100644 index 0000000000..1a276c0f35 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_manager.h @@ -0,0 +1,40 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef VG_MANAGER_H +#define VG_MANAGER_H + +#include "state_tracker/st_api.h" +#include "vg_context.h" + +void +vg_manager_flush_frontbuffer(struct vg_context *ctx); + +void +vg_manager_validate_framebuffer(struct vg_context *ctx); + +#endif /* VG_MANAGER_H */ diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c index 658ef03046..a21542fd2e 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.c +++ b/src/gallium/state_trackers/vega/vg_tracker.c @@ -32,6 +32,7 @@ #include "util/u_inlines.h" #include "pipe/p_screen.h" #include "util/u_format.h" +#include "util/u_sampler.h" #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_rect.h" @@ -41,7 +42,7 @@ PUBLIC const int st_api_OpenVG = 1; static struct pipe_resource * create_texture(struct pipe_context *pipe, enum pipe_format format, - VGint width, VGint height) + VGint width, VGint height) { struct pipe_resource templ; @@ -71,6 +72,27 @@ create_texture(struct pipe_context *pipe, enum pipe_format format, return pipe->screen->resource_create(pipe->screen, &templ); } +static struct pipe_sampler_view * +create_tex_and_view(struct pipe_context *pipe, enum pipe_format format, + VGint width, VGint height) +{ + struct pipe_resource *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_texture(pipe, format, width, height); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&texture, NULL); + + return view; +} + /** * Allocate a renderbuffer for a an on-screen window (not a user-created * renderbuffer). The window system code determines the format. @@ -116,8 +138,8 @@ st_renderbuffer_alloc_storage(struct vg_context * ctx, PIPE_BUFFER_USAGE_BLIT_SOURCE | PIPE_BUFFER_USAGE_BLIT_DESTINATION); - strb->texture = create_texture(pipe, strb->format, - width, height); + strb->texture = create_texture(pipe, strb->format, width, height); + if (!strb->texture) return FALSE; @@ -192,7 +214,7 @@ struct st_framebuffer * st_create_framebuffer(const void *visual, /*### currently we always allocate it but it's possible it's not necessary if EGL_ALPHA_MASK_SIZE was 0 */ - stfb->alpha_mask = 0; + stfb->alpha_mask_view = NULL; stfb->width = width; stfb->height = height; @@ -207,19 +229,19 @@ static void setup_new_alpha_mask(struct vg_context *ctx, uint width, uint height) { struct pipe_context *pipe = ctx->pipe; - struct pipe_resource *old_texture = stfb->alpha_mask; + struct pipe_sampler_view *old_sampler_view = stfb->alpha_mask_view; /* we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to this texture and use it as a sampler, so while this wastes some space it makes both of those a lot simpler */ - stfb->alpha_mask = - create_texture(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height); + stfb->alpha_mask_view = + create_tex_and_view(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height); - if (!stfb->alpha_mask) { - if (old_texture) - pipe_resource_reference(&old_texture, NULL); + if (!stfb->alpha_mask_view) { + if (old_sampler_view) + pipe_sampler_view_reference(&old_sampler_view, NULL); return; } @@ -229,16 +251,16 @@ static void setup_new_alpha_mask(struct vg_context *ctx, mask_fill(0, 0, width, height, 1.f); /* if we had an old surface copy it over */ - if (old_texture) { + if (old_sampler_view) { struct pipe_surface *surface = pipe->screen->get_tex_surface( pipe->screen, - stfb->alpha_mask, + stfb->alpha_mask_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_RENDER_TARGET | PIPE_BUFFER_USAGE_BLIT_DESTINATION); struct pipe_surface *old_surface = pipe->screen->get_tex_surface( pipe->screen, - old_texture, + old_sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_BLIT_SOURCE); if (pipe->surface_copy) { @@ -266,8 +288,8 @@ static void setup_new_alpha_mask(struct vg_context *ctx, /* Free the old texture */ - if (old_texture) - pipe_resource_reference(&old_texture, NULL); + if (old_sampler_view) + pipe_sampler_view_reference(&old_sampler_view, NULL); } void st_resize_framebuffer(struct st_framebuffer *stfb, @@ -328,9 +350,9 @@ void st_resize_framebuffer(struct st_framebuffer *stfb, setup_new_alpha_mask(ctx, stfb, width, height); - pipe_resource_reference( &stfb->blend_texture, NULL ); - stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM, - width, height); + pipe_sampler_view_reference( &stfb->blend_texture_view, NULL ); + stfb->blend_texture_view = create_tex_and_view(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM, + width, height); } void st_set_framebuffer_surface(struct st_framebuffer *stfb, diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index 715a5e7b94..4ff48026e5 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -4,6 +4,7 @@ #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" +#include "util/u_sampler.h" /*XXX also in Xrender.h but the including it here breaks compilition */ @@ -356,6 +357,9 @@ bind_samplers(struct exa_context *exa, int op, { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state src_sampler, mask_sampler; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; + struct pipe_context *pipe = exa->pipe; exa->num_bound_samplers = 0; @@ -366,7 +370,7 @@ bind_samplers(struct exa_context *exa, int op, if (exa->has_solid_color) { debug_assert(!"solid color with textures"); samplers[0] = NULL; - exa->bound_textures[0] = NULL; + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); } else { unsigned src_wrap = render_repeat_to_gallium( pSrcPicture->repeatType); @@ -381,8 +385,13 @@ bind_samplers(struct exa_context *exa, int op, src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; src_sampler.normalized_coords = 1; samplers[0] = &src_sampler; - exa->bound_textures[0] = pSrc->tex; exa->num_bound_samplers = 1; + u_sampler_view_default_template(&view_templ, + pSrc->tex, + pSrc->tex->format); + src_view = pipe->create_sampler_view(pipe, pSrc->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); + exa->bound_sampler_views[0] = src_view; } } @@ -400,14 +409,19 @@ bind_samplers(struct exa_context *exa, int op, src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; mask_sampler.normalized_coords = 1; samplers[1] = &mask_sampler; - exa->bound_textures[1] = pMask->tex; exa->num_bound_samplers = 2; + u_sampler_view_default_template(&view_templ, + pMask->tex, + pMask->tex->format); + src_view = pipe->create_sampler_view(pipe, pMask->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); + exa->bound_sampler_views[1] = src_view; } cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers, - exa->bound_textures); + cso_set_fragment_sampler_views(exa->renderer->cso, exa->num_bound_samplers, + exa->bound_sampler_views); } @@ -476,7 +490,6 @@ boolean xorg_composite_bind_state(struct exa_context *exa, renderer_begin_solid(exa->renderer); } else { renderer_begin_textures(exa->renderer, - exa->bound_textures, exa->num_bound_samplers); } @@ -506,7 +519,7 @@ void xorg_composite(struct exa_context *exa, renderer_texture(exa->renderer, pos, width, height, - exa->bound_textures, + exa->bound_sampler_views, exa->num_bound_samplers, src_matrix, mask_matrix); } @@ -538,7 +551,7 @@ boolean xorg_solid_bind_state(struct exa_context *exa, pixmap->width, pixmap->height); bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL); cso_set_samplers(exa->renderer->cso, 0, NULL); - cso_set_sampler_textures(exa->renderer->cso, 0, NULL); + cso_set_fragment_sampler_views(exa->renderer->cso, 0, NULL); shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index a811c829fc..4aa1d6cb2b 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -62,7 +62,7 @@ struct crtc_private drmModeCrtcPtr drm_crtc; /* hwcursor */ - struct pipe_texture *cursor_tex; + struct pipe_resource *cursor_tex; struct kms_bo *cursor_bo; unsigned cursor_handle; @@ -197,7 +197,7 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) struct pipe_transfer *transfer; if (!crtcp->cursor_tex) { - struct pipe_texture templat; + struct pipe_resource templat; struct winsys_handle whandle; memset(&templat, 0, sizeof(templat)); @@ -213,14 +213,14 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; - crtcp->cursor_tex = ms->screen->texture_create(ms->screen, + crtcp->cursor_tex = ms->screen->resource_create(ms->screen, &templat); - ms->screen->texture_get_handle(ms->screen, crtcp->cursor_tex, &whandle); + ms->screen->resource_get_handle(ms->screen, crtcp->cursor_tex, &whandle); crtcp->cursor_handle = whandle.handle; } - transfer = ms->ctx->get_transfer(ms->ctx, crtcp->cursor_tex, + transfer = pipe_get_transfer(ms->ctx, crtcp->cursor_tex, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, 64, 64); @@ -229,7 +229,7 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) transfer->stride, 0, 0, 64, 64, (void*)image, 64 * 4, 0, 0); ms->ctx->transfer_unmap(ms->ctx, transfer); - ms->ctx->tex_transfer_destroy(ms->ctx, transfer); + ms->ctx->transfer_destroy(ms->ctx, transfer); } #if HAVE_LIBKMS @@ -329,7 +329,7 @@ xorg_crtc_cursor_destroy(xf86CrtcPtr crtc) struct crtc_private *crtcp = crtc->driver_private; if (crtcp->cursor_tex) - pipe_texture_reference(&crtcp->cursor_tex, NULL); + pipe_resource_reference(&crtcp->cursor_tex, NULL); #ifdef HAVE_LIBKMS if (crtcp->cursor_bo) kms_bo_destroy(&crtcp->cursor_bo); diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index f23e4c6cc7..092d573806 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -53,14 +53,14 @@ static Bool set_format_in_do_create_buffer; typedef struct { PixmapPtr pPixmap; - struct pipe_texture *tex; + struct pipe_resource *tex; struct pipe_fence_handle *fence; } *BufferPrivatePtr; static Bool dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int format) { - struct pipe_texture *tex = NULL; + struct pipe_resource *tex = NULL; ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); @@ -101,9 +101,9 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form /* Fall through */ case DRI2BufferDepth: if (exa_priv->depth_stencil_tex) - pipe_texture_reference(&tex, exa_priv->depth_stencil_tex); + pipe_resource_reference(&tex, exa_priv->depth_stencil_tex); else { - struct pipe_texture template; + struct pipe_resource template; unsigned depthBits = (format != 0) ? format : pDraw->depth; memset(&template, 0, sizeof(template)); template.target = PIPE_TEXTURE_2D; @@ -130,8 +130,8 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form template.last_level = 0; template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL | PIPE_TEXTURE_USAGE_SHARED; - tex = ms->screen->texture_create(ms->screen, &template); - pipe_texture_reference(&exa_priv->depth_stencil_tex, tex); + tex = ms->screen->resource_create(ms->screen, &template); + pipe_resource_reference(&exa_priv->depth_stencil_tex, tex); } break; } @@ -157,7 +157,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_SHARED; - ms->screen->texture_get_handle(ms->screen, tex, &whandle); + ms->screen->resource_get_handle(ms->screen, tex, &whandle); buffer->name = whandle.handle; buffer->pitch = whandle.stride; @@ -185,9 +185,9 @@ dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer) BufferPrivatePtr private = buffer->driverPrivate; struct exa_pixmap_priv *exa_priv = exaGetPixmapDriverPrivate(private->pPixmap); - pipe_texture_reference(&private->tex, NULL); + pipe_resource_reference(&private->tex, NULL); ms->screen->fence_reference(ms->screen, &private->fence, NULL); - pipe_texture_reference(&exa_priv->depth_stencil_tex, NULL); + pipe_resource_reference(&exa_priv->depth_stencil_tex, NULL); (*pScreen->DestroyPixmap)(private->pPixmap); } diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index 8ac5179545..c97fc821fa 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -986,7 +986,7 @@ drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn) ms->fb_id = -1; } - pipe_texture_reference(&ms->root_texture, NULL); + pipe_resource_reference(&ms->root_texture, NULL); return TRUE; } @@ -994,7 +994,7 @@ static Bool drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); - struct pipe_texture *tex; + struct pipe_resource *tex; struct winsys_handle whandle; unsigned fb_id; int ret; @@ -1010,7 +1010,7 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; - if (!ms->screen->texture_get_handle(ms->screen, tex, &whandle)) + if (!ms->screen->resource_get_handle(ms->screen, tex, &whandle)) goto err_destroy; ret = drmModeAddFB(ms->fd, @@ -1034,14 +1034,14 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) pScrn->frameY0 = 0; drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - pipe_texture_reference(&ms->root_texture, tex); - pipe_texture_reference(&tex, NULL); + pipe_resource_reference(&ms->root_texture, tex); + pipe_resource_reference(&tex, NULL); ms->fb_id = fb_id; return TRUE; err_destroy: - pipe_texture_reference(&tex, NULL); + pipe_resource_reference(&tex, NULL); return FALSE; } @@ -1051,7 +1051,7 @@ drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn) modesettingPtr ms = modesettingPTR(pScrn); ScreenPtr pScreen = pScrn->pScreen; PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); - struct pipe_texture *check; + struct pipe_resource *check; xorg_exa_set_displayed_usage(rootPixmap); xorg_exa_set_shared_usage(rootPixmap); @@ -1063,7 +1063,7 @@ drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn) if (ms->root_texture != check) FatalError("Created new root texture\n"); - pipe_texture_reference(&check, NULL); + pipe_resource_reference(&check, NULL); return TRUE; } diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index bcf6cfcbfc..25f87699f8 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -188,7 +188,7 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, if (!priv || !priv->tex) return FALSE; - transfer = exa->pipe->get_transfer(exa->pipe, priv->tex, 0, 0, 0, + transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0, PIPE_TRANSFER_READ, x, y, w, h); if (!transfer) return FALSE; @@ -203,7 +203,7 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, transfer->stride, 0, 0); exa->pipe->transfer_unmap(exa->pipe, transfer); - exa->pipe->tex_transfer_destroy(exa->pipe, transfer); + exa->pipe->transfer_destroy(exa->pipe, transfer); return TRUE; } @@ -222,7 +222,7 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, if (!priv || !priv->tex) return FALSE; - transfer = exa->pipe->get_transfer(exa->pipe, priv->tex, 0, 0, 0, + transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0, PIPE_TRANSFER_WRITE, x, y, w, h); if (!transfer) return FALSE; @@ -237,7 +237,7 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, (unsigned char*)src, src_pitch, 0, 0); exa->pipe->transfer_unmap(exa->pipe, transfer); - exa->pipe->tex_transfer_destroy(exa->pipe, transfer); + exa->pipe->transfer_destroy(exa->pipe, transfer); return TRUE; } @@ -264,20 +264,15 @@ ExaPrepareAccess(PixmapPtr pPix, int index) assert(pPix->drawable.width <= priv->tex->width0); assert(pPix->drawable.height <= priv->tex->height0); - u_box_wh(&box, - pPix->drawable.width, - pPix->drawable.height); - priv->map_transfer = - exa->pipe->get_transfer(exa->pipe, - priv->tex, - u_subresource(0, 0), + pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0, #ifdef EXA_MIXED_PIXMAPS - PIPE_TRANSFER_MAP_DIRECTLY | + PIPE_TRANSFER_MAP_DIRECTLY | #endif - PIPE_TRANSFER_READ_WRITE, - - &box ); + PIPE_TRANSFER_READ_WRITE, + 0, 0, + pPix->drawable.width, + pPix->drawable.height ); if (!priv->map_transfer) #ifdef EXA_MIXED_PIXMAPS return FALSE; @@ -314,7 +309,7 @@ ExaFinishAccess(PixmapPtr pPix, int index) if (--priv->map_count == 0) { assert(priv->map_transfer); exa->pipe->transfer_unmap(exa->pipe, priv->map_transfer); - exa->pipe->tex_transfer_destroy(exa->pipe, priv->map_transfer); + exa->pipe->transfer_destroy(exa->pipe, priv->map_transfer); priv->map_transfer = NULL; pPix->devPrivate.ptr = NULL; } @@ -473,7 +468,7 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, exa->copy.src_texture = renderer_clone_texture( exa->renderer, exa->copy.src->tex ); else - pipe_texture_reference(&exa->copy.src_texture, + pipe_resource_reference(&exa->copy.src_texture, exa->copy.src->tex); exa->copy.dst_surface = @@ -546,7 +541,7 @@ ExaDoneCopy(PixmapPtr pPixmap) exa->copy.dst = NULL; pipe_surface_reference(&exa->copy.src_surface, NULL); pipe_surface_reference(&exa->copy.dst_surface, NULL); - pipe_texture_reference(&exa->copy.src_texture, NULL); + pipe_resource_reference(&exa->copy.src_texture, NULL); } @@ -749,7 +744,7 @@ ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv) if (!priv) return; - pipe_texture_reference(&priv->tex, NULL); + pipe_resource_reference(&priv->tex, NULL); xfree(priv); } @@ -872,8 +867,8 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, !size_match(width, priv->tex->width0) || !size_match(height, priv->tex->height0) || priv->tex_flags != priv->flags)) { - struct pipe_texture *texture = NULL; - struct pipe_texture template; + struct pipe_resource *texture = NULL; + struct pipe_resource template; memset(&template, 0, sizeof(template)); template.target = PIPE_TEXTURE_2D; @@ -891,7 +886,7 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, template.last_level = 0; template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags; priv->tex_flags = priv->flags; - texture = exa->scrn->texture_create(exa->scrn, &template); + texture = exa->scrn->resource_create(exa->scrn, &template); if (priv->tex) { struct pipe_surface *dst_surf; @@ -913,25 +908,25 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, exa->scrn->tex_surface_destroy(src_surf); } - pipe_texture_reference(&priv->tex, texture); + pipe_resource_reference(&priv->tex, texture); /* the texture we create has one reference */ - pipe_texture_reference(&texture, NULL); + pipe_resource_reference(&texture, NULL); } return TRUE; } -struct pipe_texture * +struct pipe_resource * xorg_exa_get_texture(PixmapPtr pPixmap) { struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); - struct pipe_texture *tex = NULL; - pipe_texture_reference(&tex, priv->tex); + struct pipe_resource *tex = NULL; + pipe_resource_reference(&tex, priv->tex); return tex; } Bool -xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex) +xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_resource *tex) { struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); @@ -944,20 +939,20 @@ xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex) pPixmap->drawable.height != tex->height0) return FALSE; - pipe_texture_reference(&priv->tex, tex); + pipe_resource_reference(&priv->tex, tex); priv->tex_flags = tex->tex_usage & mask; return TRUE; } -struct pipe_texture * +struct pipe_resource * xorg_exa_create_root_texture(ScrnInfoPtr pScrn, int width, int height, int depth, int bitsPerPixel) { modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; - struct pipe_texture template; + struct pipe_resource template; int dummy; memset(&template, 0, sizeof(template)); @@ -971,7 +966,7 @@ xorg_exa_create_root_texture(ScrnInfoPtr pScrn, template.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; template.tex_usage |= PIPE_TEXTURE_USAGE_SHARED; - return exa->scrn->texture_create(exa->scrn, &template); + return exa->scrn->resource_create(exa->scrn, &template); } void @@ -980,6 +975,9 @@ xorg_exa_close(ScrnInfoPtr pScrn) modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); + pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); + renderer_destroy(exa->renderer); if (exa->pipe) diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h index f2cefe23b9..a35e9a5c90 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.h +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -18,7 +18,7 @@ struct exa_context struct pipe_screen *scrn; struct xorg_renderer *renderer; - struct pipe_texture *bound_textures[MAX_EXA_SAMPLERS]; + struct pipe_sampler_view *bound_sampler_views[MAX_EXA_SAMPLERS]; int num_bound_samplers; float solid_color[4]; @@ -43,7 +43,7 @@ struct exa_context struct pipe_surface *src_surface; struct pipe_surface *dst_surface; - struct pipe_texture *src_texture; + struct pipe_resource *src_texture; } copy; }; @@ -56,8 +56,8 @@ struct exa_pixmap_priv int picture_format; - struct pipe_texture *tex; - struct pipe_texture *depth_stencil_tex; + struct pipe_resource *tex; + struct pipe_resource *depth_stencil_tex; struct pipe_transfer *map_transfer; unsigned map_count; diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c index 1eb926360b..00ca865f53 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.c +++ b/src/gallium/state_trackers/xorg/xorg_renderer.c @@ -8,6 +8,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_rect.h" +#include "util/u_sampler.h" #include "util/u_inlines.h" @@ -41,14 +42,16 @@ static INLINE void map_point(float *mat, float x, float y, } } -static INLINE struct pipe_buffer * +static INLINE struct pipe_resource * renderer_buffer_create(struct xorg_renderer *r) { - struct pipe_buffer *buf = + struct pipe_resource *buf = pipe_user_buffer_create(r->pipe->screen, r->buffer, sizeof(float)* - r->buffer_size); + r->buffer_size, + (PIPE_BUFFER_USAGE_PIXEL | + PIPE_BUFFER_USAGE_GPU_WRITE)); r->buffer_size = 0; return buf; @@ -58,7 +61,7 @@ static INLINE void renderer_draw(struct xorg_renderer *r) { struct pipe_context *pipe = r->pipe; - struct pipe_buffer *buf = 0; + struct pipe_resource *buf = 0; int num_verts = r->buffer_size/(r->attrs_per_vertex * NUM_COMPONENTS); if (!r->buffer_size) @@ -75,7 +78,7 @@ renderer_draw(struct xorg_renderer *r) num_verts, /* verts */ r->attrs_per_vertex); /* attribs/vert */ - pipe_buffer_reference(&buf, NULL); + pipe_resource_reference(&buf, NULL); } } @@ -160,7 +163,7 @@ static void add_vertex_data1(struct xorg_renderer *r, float srcX, float srcY, float dstX, float dstY, float width, float height, - struct pipe_texture *src, float *src_matrix) + struct pipe_resource *src, float *src_matrix) { float s0, t0, s1, t1, s2, t2, s3, t3; float pt0[2], pt1[2], pt2[2], pt3[2]; @@ -230,8 +233,8 @@ static void add_vertex_data2(struct xorg_renderer *r, float srcX, float srcY, float maskX, float maskY, float dstX, float dstY, float width, float height, - struct pipe_texture *src, - struct pipe_texture *mask, + struct pipe_resource *src, + struct pipe_resource *mask, float *src_matrix, float *mask_matrix) { float src_s0, src_t0, src_s1, src_t1; @@ -283,11 +286,11 @@ add_vertex_data2(struct xorg_renderer *r, src_s0, src_t1, mask_s0, mask_t1); } -static struct pipe_buffer * +static struct pipe_resource * setup_vertex_data_yuv(struct xorg_renderer *r, float srcX, float srcY, float srcW, float srcH, float dstX, float dstY, float dstW, float dstH, - struct pipe_texture **tex) + struct pipe_resource **tex) { float s0, t0, s1, t1; float spt0[2], spt1[2]; @@ -389,14 +392,14 @@ struct xorg_renderer * renderer_create(struct pipe_context *pipe) void renderer_destroy(struct xorg_renderer *r) { - struct pipe_buffer **vsbuf = &r->vs_const_buffer; - struct pipe_buffer **fsbuf = &r->fs_const_buffer; + struct pipe_resource **vsbuf = &r->vs_const_buffer; + struct pipe_resource **fsbuf = &r->fs_const_buffer; if (*vsbuf) - pipe_buffer_reference(vsbuf, NULL); + pipe_resource_reference(vsbuf, NULL); if (*fsbuf) - pipe_buffer_reference(fsbuf, NULL); + pipe_resource_reference(fsbuf, NULL); if (r->shaders) { xorg_shaders_destroy(r->shaders); @@ -419,17 +422,17 @@ void renderer_set_constants(struct xorg_renderer *r, const float *params, int param_bytes) { - struct pipe_buffer **cbuf = + struct pipe_resource **cbuf = (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer : &r->fs_const_buffer; - pipe_buffer_reference(cbuf, NULL); + pipe_resource_reference(cbuf, NULL); *cbuf = pipe_buffer_create(r->pipe->screen, 16, PIPE_BUFFER_USAGE_CONSTANT, param_bytes); if (*cbuf) { - pipe_buffer_write(r->pipe->screen, *cbuf, + pipe_buffer_write(r->pipe, *cbuf, 0, param_bytes, params); } r->pipe->set_constant_buffer(r->pipe, shader_type, 0, *cbuf); @@ -438,7 +441,7 @@ void renderer_set_constants(struct xorg_renderer *r, void renderer_copy_prepare(struct xorg_renderer *r, struct pipe_surface *dst_surface, - struct pipe_texture *src_texture) + struct pipe_resource *src_texture) { struct pipe_context *pipe = r->pipe; struct pipe_screen *screen = pipe->screen; @@ -482,8 +485,17 @@ void renderer_copy_prepare(struct xorg_renderer *r, dst_surface->width, dst_surface->height); - /* texture */ - cso_set_sampler_textures(r->cso, 1, &src_texture); + /* texture/sampler view */ + { + struct pipe_sampler_view templ; + struct pipe_sampler_view *src_view; + u_sampler_view_default_template(&templ, + src_texture, + src_texture->format); + src_view = pipe->create_sampler_view(pipe, src_texture, &templ); + cso_set_fragment_sampler_views(r->cso, 1, &src_view); + pipe_sampler_view_reference(&src_view, NULL); + } /* shaders */ shader = xorg_shaders_get(r->shaders, @@ -496,17 +508,17 @@ void renderer_copy_prepare(struct xorg_renderer *r, r->attrs_per_vertex = 2; } -struct pipe_texture * +struct pipe_resource * renderer_clone_texture(struct xorg_renderer *r, - struct pipe_texture *src) + struct pipe_resource *src) { enum pipe_format format; struct pipe_context *pipe = r->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_texture *pt; - struct pipe_texture templ; + struct pipe_resource *pt; + struct pipe_resource templ; - if (pipe->is_texture_referenced(pipe, src, 0, 0) & + if (pipe->is_resource_referenced(pipe, src, 0, 0) & PIPE_REFERENCED_FOR_WRITE) pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); @@ -526,7 +538,7 @@ renderer_clone_texture(struct xorg_renderer *r, templ.depth0 = 1; templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; - pt = screen->texture_create(screen, &templ); + pt = screen->resource_create(screen, &templ); debug_assert(!pt || pipe_is_referenced(&pt->reference)); @@ -598,10 +610,10 @@ void renderer_copy_pixmap(struct xorg_renderer *r, void renderer_draw_yuv(struct xorg_renderer *r, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, - struct pipe_texture **textures) + struct pipe_resource **textures) { struct pipe_context *pipe = r->pipe; - struct pipe_buffer *buf = 0; + struct pipe_resource *buf = 0; buf = setup_vertex_data_yuv(r, src_x, src_y, src_w, src_h, @@ -618,7 +630,7 @@ void renderer_draw_yuv(struct xorg_renderer *r, 4, /* verts */ num_attribs); /* attribs/vert */ - pipe_buffer_reference(&buf, NULL); + pipe_resource_reference(&buf, NULL); } } @@ -655,7 +667,6 @@ void renderer_draw_flush(struct xorg_renderer *r) } void renderer_begin_textures(struct xorg_renderer *r, - struct pipe_texture **textures, int num_textures) { r->attrs_per_vertex = 1 + num_textures; @@ -665,7 +676,7 @@ void renderer_begin_textures(struct xorg_renderer *r, void renderer_texture(struct xorg_renderer *r, int *pos, int width, int height, - struct pipe_texture **textures, + struct pipe_sampler_view **sampler_view, int num_textures, float *src_matrix, float *mask_matrix) @@ -693,7 +704,7 @@ void renderer_texture(struct xorg_renderer *r, pos[0], pos[1], /* src */ pos[4], pos[5], /* dst */ width, height, - textures[0], src_matrix); + sampler_view[0]->texture, src_matrix); break; case 3: renderer_draw_conditional(r, 4 * 12); @@ -702,7 +713,7 @@ void renderer_texture(struct xorg_renderer *r, pos[2], pos[3], /* mask */ pos[4], pos[5], /* dst */ width, height, - textures[0], textures[1], + sampler_view[0]->texture, sampler_view[1]->texture, src_matrix, mask_matrix); break; default: diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h index 3d00628719..0454a6513d 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.h +++ b/src/gallium/state_trackers/xorg/xorg_renderer.h @@ -23,8 +23,8 @@ struct xorg_renderer { int fb_width; int fb_height; - struct pipe_buffer *vs_const_buffer; - struct pipe_buffer *fs_const_buffer; + struct pipe_resource *vs_const_buffer; + struct pipe_resource *fs_const_buffer; float buffer[BUF_SIZE]; int buffer_size; @@ -56,7 +56,7 @@ void renderer_set_constants(struct xorg_renderer *r, void renderer_draw_yuv(struct xorg_renderer *r, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, - struct pipe_texture **textures); + struct pipe_resource **textures); void renderer_begin_solid(struct xorg_renderer *r); void renderer_solid(struct xorg_renderer *r, @@ -65,25 +65,25 @@ void renderer_solid(struct xorg_renderer *r, float *color); void renderer_begin_textures(struct xorg_renderer *r, - struct pipe_texture **textures, int num_textures); + void renderer_texture(struct xorg_renderer *r, int *pos, int width, int height, - struct pipe_texture **textures, + struct pipe_sampler_view **textures, int num_textures, float *src_matrix, float *mask_matrix); void renderer_draw_flush(struct xorg_renderer *r); -struct pipe_texture * +struct pipe_resource * renderer_clone_texture(struct xorg_renderer *r, - struct pipe_texture *src); + struct pipe_resource *src); void renderer_copy_prepare(struct xorg_renderer *r, struct pipe_surface *dst_surface, - struct pipe_texture *src_texture); + struct pipe_resource *src_texture); void renderer_copy_pixmap(struct xorg_renderer *r, int dx, int dy, diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index c1884ebd11..cb6773424a 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -118,7 +118,7 @@ typedef struct _modesettingRec struct pipe_context *ctx; boolean d_depth_bits_last; boolean ds_depth_bits_last; - struct pipe_texture *root_texture; + struct pipe_resource *root_texture; /* exa */ struct exa_context *exa; @@ -142,7 +142,7 @@ Bool xorg_has_gallium(ScrnInfoPtr pScrn); /*********************************************************************** * xorg_exa.c */ -struct pipe_texture * +struct pipe_resource * xorg_exa_get_texture(PixmapPtr pPixmap); int @@ -152,9 +152,9 @@ int xorg_exa_set_shared_usage(PixmapPtr pPixmap); Bool -xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex); +xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_resource *tex); -struct pipe_texture * +struct pipe_resource * xorg_exa_create_root_texture(ScrnInfoPtr pScrn, int width, int height, int depth, int bpp); diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c index a821762f12..4944cd0e90 100644 --- a/src/gallium/state_trackers/xorg/xorg_xv.c +++ b/src/gallium/state_trackers/xorg/xorg_xv.c @@ -9,6 +9,7 @@ #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" +#include "util/u_sampler.h" #include "pipe/p_screen.h" @@ -90,7 +91,8 @@ struct xorg_xv_port_priv { int current_set; /* juggle two sets of seperate Y, U and V * textures */ - struct pipe_texture *yuv[2][3]; + struct pipe_resource *yuv[2][3]; + struct pipe_sampler_view *yuv_views[2][3]; }; @@ -154,13 +156,13 @@ query_best_size(ScrnInfoPtr pScrn, *p_h = drw_h; } -static INLINE struct pipe_texture * +static INLINE struct pipe_resource * create_component_texture(struct pipe_context *pipe, int width, int height) { struct pipe_screen *screen = pipe->screen; - struct pipe_texture *tex = 0; - struct pipe_texture templ; + struct pipe_resource *tex = 0; + struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; @@ -171,7 +173,7 @@ create_component_texture(struct pipe_context *pipe, templ.depth0 = 1; templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; - tex = screen->texture_create(screen, &templ); + tex = screen->resource_create(screen, &templ); return tex; } @@ -179,33 +181,61 @@ create_component_texture(struct pipe_context *pipe, static int check_yuv_textures(struct xorg_xv_port_priv *priv, int width, int height) { - struct pipe_texture **dst = priv->yuv[priv->current_set]; + struct pipe_resource **dst = priv->yuv[priv->current_set]; + struct pipe_sampler_view **dst_view = priv->yuv_views[priv->current_set]; + struct pipe_sampler_view view_templ; + struct pipe_context *pipe = priv->r->pipe; + if (!dst[0] || dst[0]->width0 != width || dst[0]->height0 != height) { - pipe_texture_reference(&dst[0], NULL); + pipe_resource_reference(&dst[0], NULL); + pipe_sampler_view_reference(&dst_view[0], NULL); } if (!dst[1] || dst[1]->width0 != width || dst[1]->height0 != height) { - pipe_texture_reference(&dst[1], NULL); + pipe_resource_reference(&dst[1], NULL); + pipe_sampler_view_reference(&dst_view[1], NULL); } if (!dst[2] || dst[2]->width0 != width || dst[2]->height0 != height) { - pipe_texture_reference(&dst[2], NULL); + pipe_resource_reference(&dst[2], NULL); + pipe_sampler_view_reference(&dst_view[2], NULL); } - if (!dst[0]) + if (!dst[0]) { dst[0] = create_component_texture(priv->r->pipe, width, height); + if (dst[0]) { + u_sampler_view_default_template(&view_templ, + dst[0], + dst[0]->format); + dst_view[0] = pipe->create_sampler_view(pipe, dst[0], &view_templ); + } + } - if (!dst[1]) + if (!dst[1]) { dst[1] = create_component_texture(priv->r->pipe, width, height); + if (dst[1]) { + u_sampler_view_default_template(&view_templ, + dst[1], + dst[1]->format); + dst_view[1] = pipe->create_sampler_view(pipe, dst[1], &view_templ); + } + } - if (!dst[2]) + if (!dst[2]) { dst[2] = create_component_texture(priv->r->pipe, width, height); + if (dst[2]) { + u_sampler_view_default_template(&view_templ, + dst[2], + dst[2]->format); + dst_view[2] = pipe->create_sampler_view(pipe, dst[2], &view_templ); + } + } - if (!dst[0] || !dst[1] || !dst[2]) + if (!dst[0] || !dst[1] || !dst[2] || !dst_view[0] || !dst_view[1] || !dst_view[2] ) return BadAlloc; return Success; @@ -273,7 +303,7 @@ copy_packed_data(ScrnInfoPtr pScrn, unsigned short w, unsigned short h) { int i, j; - struct pipe_texture **dst = port->yuv[port->current_set]; + struct pipe_resource **dst = port->yuv[port->current_set]; struct pipe_transfer *ytrans, *utrans, *vtrans; struct pipe_context *pipe = port->r->pipe; char *ymap, *vmap, *umap; @@ -281,15 +311,15 @@ copy_packed_data(ScrnInfoPtr pScrn, int yidx, uidx, vidx; int y_array_size = w * h; - ytrans = pipe->get_transfer(pipe, dst[0], + ytrans = pipe_get_transfer(pipe, dst[0], 0, 0, 0, PIPE_TRANSFER_WRITE, left, top, w, h); - utrans = pipe->get_transfer(pipe, dst[1], + utrans = pipe_get_transfer(pipe, dst[1], 0, 0, 0, PIPE_TRANSFER_WRITE, left, top, w, h); - vtrans = pipe->get_transfer(pipe, dst[2], + vtrans = pipe_get_transfer(pipe, dst[2], 0, 0, 0, PIPE_TRANSFER_WRITE, left, top, w, h); @@ -365,9 +395,9 @@ copy_packed_data(ScrnInfoPtr pScrn, pipe->transfer_unmap(pipe, ytrans); pipe->transfer_unmap(pipe, utrans); pipe->transfer_unmap(pipe, vtrans); - pipe->tex_transfer_destroy(pipe, ytrans); - pipe->tex_transfer_destroy(pipe, utrans); - pipe->tex_transfer_destroy(pipe, vtrans); + pipe->transfer_destroy(pipe, ytrans); + pipe->transfer_destroy(pipe, utrans); + pipe->transfer_destroy(pipe, vtrans); } @@ -386,7 +416,7 @@ draw_yuv(struct xorg_xv_port_priv *port, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h) { - struct pipe_texture **textures = port->yuv[port->current_set]; + struct pipe_resource **textures = port->yuv[port->current_set]; /*debug_printf(" draw_yuv([%d, %d, %d ,%d], [%d, %d, %d, %d])\n", src_x, src_y, src_w, src_h, @@ -431,12 +461,12 @@ bind_shaders(struct xorg_xv_port_priv *port) } static INLINE void -conditional_flush(struct pipe_context *pipe, struct pipe_texture **tex, +conditional_flush(struct pipe_context *pipe, struct pipe_resource **tex, int num) { int i; for (i = 0; i < num; ++i) { - if (tex[i] && pipe->is_texture_referenced(pipe, tex[i], 0, 0) & + if (tex[i] && pipe->is_resource_referenced(pipe, tex[i], 0, 0) & PIPE_REFERENCED_FOR_WRITE) { pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); return; @@ -449,7 +479,8 @@ bind_samplers(struct xorg_xv_port_priv *port) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state sampler; - struct pipe_texture **dst = port->yuv[port->current_set]; + struct pipe_resource **dst = port->yuv[port->current_set]; + struct pipe_sampler_view **dst_views = port->yuv_views[port->current_set]; memset(&sampler, 0, sizeof(struct pipe_sampler_state)); @@ -469,8 +500,7 @@ bind_samplers(struct xorg_xv_port_priv *port) cso_set_samplers(port->r->cso, 3, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(port->r->cso, 3, - dst); + cso_set_fragment_sampler_views(port->r->cso, 3, dst_views); } static int diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index 12d94e0c5c..30a2b567db 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -86,8 +86,8 @@ static bool CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, unsigned int height, struct pipe_surface **backbuffer) { - struct pipe_texture template; - struct pipe_texture *tex; + struct pipe_resource template; + struct pipe_resource *tex; assert(vpipe); @@ -108,14 +108,14 @@ CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, u template.depth0 = 1; template.tex_usage = PIPE_TEXTURE_USAGE_SHARED; - tex = vpipe->screen->texture_create(vpipe->screen, &template); + tex = vpipe->screen->resource_create(vpipe->screen, &template); if (!tex) return false; *backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); - pipe_texture_reference(&tex, NULL); + pipe_resource_reference(&tex, NULL); if (!*backbuffer) return false; diff --git a/src/gallium/targets/libgl-xlib/xlib.c b/src/gallium/targets/libgl-xlib/xlib.c index 05dc8db57d..48e79fe4f3 100644 --- a/src/gallium/targets/libgl-xlib/xlib.c +++ b/src/gallium/targets/libgl-xlib/xlib.c @@ -39,9 +39,15 @@ #include "target-helpers/wrap_screen.h" #include "xm_public.h" +#include "state_tracker/st_manager.h" + /* advertise OpenGL support */ PUBLIC const int st_api_OpenGL = 1; +PUBLIC const struct st_module st_module_OpenGL = { + .api = ST_API_OPENGL, + .create_api = st_manager_create_api +}; /* Helper function to build a subset of a driver stack consisting of * one of the software rasterizers (cell, llvmpipe, softpipe) and the @@ -57,6 +63,8 @@ PUBLIC const int st_api_OpenGL = 1; static struct pipe_screen * swrast_xlib_create_screen( Display *display ) { + const char *default_driver; + const char *driver; struct sw_winsys *winsys; struct pipe_screen *screen = NULL; @@ -67,22 +75,36 @@ swrast_xlib_create_screen( Display *display ) if (winsys == NULL) return NULL; +#if defined(GALLIUM_CELL) + default_driver = "cell"; +#elif defined(GALLIUM_LLVMPIPE) + default_driver = "llvmpipe"; +#elif defined(GALLIUM_SOFTPIPE) + default_driver = "softpipe"; +#else + default_driver = ""; +#endif + + driver = debug_get_option("GALLIUM_DRIVER", default_driver); + /* Create a software rasterizer on top of that winsys: */ #if defined(GALLIUM_CELL) if (screen == NULL && - !debug_get_bool_option("GALLIUM_NO_CELL", FALSE)) + strcmp(driver, "cell") == 0) screen = cell_create_screen( winsys ); #endif #if defined(GALLIUM_LLVMPIPE) if (screen == NULL && - !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE)) + strcmp(driver, "llvmpipe") == 0) screen = llvmpipe_create_screen( winsys ); #endif +#if defined(GALLIUM_SOFTPIPE) if (screen == NULL) screen = softpipe_create_screen( winsys ); +#endif if (screen == NULL) goto fail; @@ -98,9 +120,10 @@ fail: return NULL; } -struct xm_driver xlib_driver = +static struct xm_driver xlib_driver = { .create_pipe_screen = swrast_xlib_create_screen, + .create_st_api = st_manager_create_api, }; diff --git a/src/gallium/winsys/drm/Makefile b/src/gallium/winsys/drm/Makefile index fee0191643..a998aff931 100644 --- a/src/gallium/winsys/drm/Makefile +++ b/src/gallium/winsys/drm/Makefile @@ -2,7 +2,7 @@ TOP = ../../../.. include $(TOP)/configs/current -SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS) +SUBDIRS = sw $(GALLIUM_WINSYS_DRM_DIRS) default install clean: @for dir in $(SUBDIRS) ; do \ diff --git a/src/gallium/winsys/drm/i965/dri/Makefile b/src/gallium/winsys/drm/i965/dri/Makefile index f7e81eed87..56690769fc 100644 --- a/src/gallium/winsys/drm/i965/dri/Makefile +++ b/src/gallium/winsys/drm/i965/dri/Makefile @@ -7,6 +7,7 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \ $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/winsys/drm/sw/libswdrm.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(TOP)/src/gallium/drivers/identity/libidentity.a \ $(TOP)/src/gallium/drivers/i965/libi965.a diff --git a/src/gallium/winsys/drm/i965/gem/i965_drm_api.c b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c index 21e82303f7..c644eedcb3 100644 --- a/src/gallium/winsys/drm/i965/gem/i965_drm_api.c +++ b/src/gallium/winsys/drm/i965/gem/i965_drm_api.c @@ -10,6 +10,8 @@ #include "trace/tr_drm.h" +#include "../../sw/sw_drm_api.h" + /* * Helper functions */ @@ -108,5 +110,13 @@ struct drm_api i965_libdrm_api = struct drm_api * drm_api_create() { - return trace_drm_create(&i965_libdrm_api); + struct drm_api *api = NULL; + + if (api == NULL && debug_get_bool_option("BRW_SOFTPIPE", FALSE)) + api = sw_drm_api_create(&i965_libdrm_api); + + if (api == NULL) + api = &i965_libdrm_api; + + return trace_drm_create(api); } diff --git a/src/gallium/winsys/drm/nouveau/dri/Makefile b/src/gallium/winsys/drm/nouveau/dri/Makefile index 7e95f79d03..50ac3f203e 100644 --- a/src/gallium/winsys/drm/nouveau/dri/Makefile +++ b/src/gallium/winsys/drm/nouveau/dri/Makefile @@ -6,8 +6,7 @@ LIBNAME = nouveau_dri.so PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv30/libnv30.a \ - $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c index 4f9c455180..2c8dc38475 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -45,7 +45,7 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen, PIPE_BUFFER_USAGE_GPU_WRITE); /* we don't need the texture from this point on */ - pipe_texture_reference(&pt, NULL); + pipe_resource_reference(&pt, NULL); return ps; } @@ -86,11 +86,9 @@ nouveau_drm_create_screen(struct drm_api *api, int fd, switch (dev->chipset & 0xf0) { case 0x30: - init = nv30_screen_create; - break; case 0x40: case 0x60: - init = nv40_screen_create; + init = nvfx_screen_create; break; case 0x50: case 0x80: diff --git a/src/gallium/winsys/drm/nouveau/egl/Makefile b/src/gallium/winsys/drm/nouveau/egl/Makefile index 2c35260332..47d1127615 100644 --- a/src/gallium/winsys/drm/nouveau/egl/Makefile +++ b/src/gallium/winsys/drm/nouveau/egl/Makefile @@ -7,8 +7,7 @@ EGL_DRIVER_LIBS = -ldrm_nouveau EGL_DRIVER_PIPES = \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv30/libnv30.a \ - $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a diff --git a/src/gallium/winsys/drm/nouveau/xorg/Makefile b/src/gallium/winsys/drm/nouveau/xorg/Makefile index 179b50230b..f7f6fe17dd 100644 --- a/src/gallium/winsys/drm/nouveau/xorg/Makefile +++ b/src/gallium/winsys/drm/nouveau/xorg/Makefile @@ -18,8 +18,7 @@ INCLUDES = \ LIBS = \ $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv30/libnv30.a \ - $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nvfx/libnvfx.a \ $(TOP)/src/gallium/drivers/nv50/libnv50.a \ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ $(GALLIUM_AUXILIARIES) diff --git a/src/gallium/winsys/drm/radeon/core/Makefile b/src/gallium/winsys/drm/radeon/core/Makefile index 860cbb6dbf..13bbbf730d 100644 --- a/src/gallium/winsys/drm/radeon/core/Makefile +++ b/src/gallium/winsys/drm/radeon/core/Makefile @@ -5,7 +5,7 @@ include $(TOP)/configs/current LIBNAME = radeonwinsys C_SOURCES = \ - radeon_buffer.c \ + radeon_drm_buffer.c \ radeon_drm.c \ radeon_r300.c diff --git a/src/gallium/winsys/drm/radeon/core/SConscript b/src/gallium/winsys/drm/radeon/core/SConscript index f4e9c397bd..19e895f10b 100644 --- a/src/gallium/winsys/drm/radeon/core/SConscript +++ b/src/gallium/winsys/drm/radeon/core/SConscript @@ -3,7 +3,7 @@ Import('*') env = drienv.Clone() radeon_sources = [ - 'radeon_buffer.c', + 'radeon_drm_buffer.c', 'radeon_drm.c', 'radeon_r300.c', ] diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c deleted file mode 100644 index 25b58b2926..0000000000 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright © 2008 Jérôme Glisse - * 2009 Corbin Simpson - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS - * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - */ -/* - * Authors: - * Jérôme Glisse <glisse@freedesktop.org> - * Corbin Simpson <MostAwesomeDude@gmail.com> - */ - -#include "radeon_buffer.h" -#include "radeon_drm.h" - -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "radeon_bo_gem.h" -#include <X11/Xutil.h> - -struct radeon_vl_context -{ - Display *display; - int screen; - Drawable drawable; -}; - -static const char *radeon_get_name(struct pipe_winsys *ws) -{ - return "Radeon/GEM+KMS"; -} - -static uint32_t radeon_domain_from_usage(unsigned usage) -{ - uint32_t domain = 0; - - if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) { - domain |= RADEON_GEM_DOMAIN_VRAM; - } - if (usage & PIPE_BUFFER_USAGE_PIXEL) { - domain |= RADEON_GEM_DOMAIN_VRAM; - } - if (usage & PIPE_BUFFER_USAGE_VERTEX) { - domain |= RADEON_GEM_DOMAIN_GTT; - } - if (usage & PIPE_BUFFER_USAGE_INDEX) { - domain |= RADEON_GEM_DOMAIN_GTT; - } - - return domain; -} - -static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct radeon_winsys *radeon_ws = (struct radeon_winsys *)ws; - struct radeon_pipe_buffer *radeon_buffer; - struct pb_desc desc; - uint32_t domain; - - radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer); - if (radeon_buffer == NULL) { - return NULL; - } - - pipe_reference_init(&radeon_buffer->base.reference, 1); - radeon_buffer->base.alignment = alignment; - radeon_buffer->base.usage = usage; - radeon_buffer->base.size = size; - - if (usage & PIPE_BUFFER_USAGE_CONSTANT && is_r3xx(radeon_ws->pci_id)) { - /* Don't bother allocating a BO, as it'll never get to the card. */ - desc.alignment = alignment; - desc.usage = usage; - radeon_buffer->pb = pb_malloc_buffer_create(size, &desc); - return &radeon_buffer->base; - } - - domain = radeon_domain_from_usage(usage); - - radeon_buffer->bo = radeon_bo_open(radeon_ws->priv->bom, 0, size, - alignment, domain, 0); - if (radeon_buffer->bo == NULL) { - FREE(radeon_buffer); - return NULL; - } - return &radeon_buffer->base; -} - -static struct pipe_buffer *radeon_buffer_user_create(struct pipe_winsys *ws, - void *ptr, - unsigned bytes) -{ - struct radeon_pipe_buffer *radeon_buffer; - - radeon_buffer = - (struct radeon_pipe_buffer*)radeon_buffer_create(ws, 0, 0, bytes); - if (radeon_buffer == NULL) { - return NULL; - } - radeon_bo_map(radeon_buffer->bo, 1); - memcpy(radeon_buffer->bo->ptr, ptr, bytes); - radeon_bo_unmap(radeon_buffer->bo); - return &radeon_buffer->base; -} - -static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws, - unsigned width, - unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - /* Radeons enjoy things in multiples of 32. */ - /* XXX this can be 32 when POT */ - const unsigned alignment = 64; - unsigned nblocksy, size; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - size = *stride * nblocksy; - - return radeon_buffer_create(ws, 64, usage, size); -} - -static void radeon_buffer_del(struct pipe_buffer *buffer) -{ - struct radeon_pipe_buffer *radeon_buffer = - (struct radeon_pipe_buffer*)buffer; - - if (radeon_buffer->pb) { - pipe_reference_init(&radeon_buffer->pb->base.reference, 0); - pb_destroy(radeon_buffer->pb); - } - - if (radeon_buffer->bo) { - radeon_bo_unref(radeon_buffer->bo); - } - - FREE(radeon_buffer); -} - -static void *radeon_buffer_map(struct pipe_winsys *ws, - struct pipe_buffer *buffer, - unsigned flags) -{ - struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv; - struct radeon_pipe_buffer *radeon_buffer = - (struct radeon_pipe_buffer*)buffer; - int write = 0; - - if (radeon_buffer->pb) { - return pb_map(radeon_buffer->pb, flags); - } - - if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { - uint32_t domain; - - if (radeon_bo_is_busy(radeon_buffer->bo, &domain)) - return NULL; - } - - if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) { - priv->flush_cb(priv->flush_data); - } - - if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) { - write = 1; - } - - if (radeon_bo_map(radeon_buffer->bo, write)) { - return NULL; - } - - return radeon_buffer->bo->ptr; -} - -static void radeon_buffer_unmap(struct pipe_winsys *ws, - struct pipe_buffer *buffer) -{ - struct radeon_pipe_buffer *radeon_buffer = - (struct radeon_pipe_buffer*)buffer; - - if (radeon_buffer->pb) { - pb_unmap(radeon_buffer->pb); - } else { - radeon_bo_unmap(radeon_buffer->bo); - } -} - -static boolean radeon_is_buffer_referenced(struct radeon_winsys *ws, - struct pipe_buffer *buffer) -{ - struct radeon_pipe_buffer *radeon_buffer = - (struct radeon_pipe_buffer*)buffer; - uint32_t domain; - - /* Referenced by CS or HW. */ - return radeon_bo_is_referenced_by_cs(radeon_buffer->bo, ws->priv->cs) || - radeon_bo_is_busy(radeon_buffer->bo, &domain); -} - -static void radeon_buffer_set_tiling(struct radeon_winsys *ws, - struct pipe_buffer *buffer, - uint32_t pitch, - boolean microtiled, - boolean macrotiled) -{ - struct radeon_winsys_priv *priv = ((struct radeon_winsys *)ws)->priv; - struct radeon_pipe_buffer *radeon_buffer = - (struct radeon_pipe_buffer*)buffer; - uint32_t flags = 0, old_flags, old_pitch; - - if (microtiled) { - flags |= RADEON_BO_FLAGS_MICRO_TILE; - } - if (macrotiled) { - flags |= RADEON_BO_FLAGS_MACRO_TILE; - } - - radeon_bo_get_tiling(radeon_buffer->bo, &old_flags, &old_pitch); - - if (flags != old_flags || pitch != old_pitch) { - /* Tiling determines how DRM treats the buffer data. - * We must flush CS when changing it if the buffer is referenced. */ - if (radeon_bo_is_referenced_by_cs(radeon_buffer->bo, priv->cs)) { - priv->flush_cb(priv->flush_data); - } - - radeon_bo_set_tiling(radeon_buffer->bo, flags, pitch); - } -} - -static void radeon_fence_reference(struct pipe_winsys *ws, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *pfence) -{ -} - -static int radeon_fence_signalled(struct pipe_winsys *ws, - struct pipe_fence_handle *pfence, - unsigned flag) -{ - return 1; -} - -static int radeon_fence_finish(struct pipe_winsys *ws, - struct pipe_fence_handle *pfence, - unsigned flag) -{ - return 0; -} - -/* Create a buffer from a handle. */ -static struct pipe_buffer* radeon_buffer_from_handle(struct radeon_winsys *radeon_ws, - struct pipe_screen *screen, - struct winsys_handle *whandle, - unsigned *stride) -{ - struct radeon_bo_manager* bom = radeon_ws->priv->bom; - struct radeon_pipe_buffer* radeon_buffer; - struct radeon_bo* bo = NULL; - - bo = radeon_bo_open(bom, whandle->handle, 0, 0, 0, 0); - if (bo == NULL) { - return NULL; - } - - radeon_buffer = CALLOC_STRUCT(radeon_pipe_buffer); - if (radeon_buffer == NULL) { - radeon_bo_unref(bo); - return NULL; - } - - pipe_reference_init(&radeon_buffer->base.reference, 1); - radeon_buffer->base.screen = screen; - radeon_buffer->base.usage = PIPE_BUFFER_USAGE_PIXEL; - radeon_buffer->bo = bo; - - *stride = whandle->stride; - - return &radeon_buffer->base; -} - -static boolean radeon_buffer_get_handle(struct radeon_winsys *radeon_ws, - struct pipe_buffer *buffer, - unsigned stride, - struct winsys_handle *whandle) -{ - int retval, fd; - struct drm_gem_flink flink; - struct radeon_pipe_buffer* radeon_buffer; - - radeon_buffer = (struct radeon_pipe_buffer*)buffer; - - - if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { - if (!radeon_buffer->flinked) { - fd = radeon_ws->priv->fd; - - flink.handle = radeon_buffer->bo->handle; - - retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); - if (retval) { - debug_printf("radeon: DRM_IOCTL_GEM_FLINK failed, error %d\n", - retval); - return FALSE; - } - - radeon_buffer->flink = flink.name; - radeon_buffer->flinked = TRUE; - } - - whandle->handle = radeon_buffer->flink; - } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { - whandle->handle = ((struct radeon_pipe_buffer*)buffer)->bo->handle; - } - whandle->stride = stride; - - return TRUE; -} - -struct radeon_winsys* radeon_pipe_winsys(int fd) -{ - struct radeon_winsys* radeon_ws; - - radeon_ws = CALLOC_STRUCT(radeon_winsys); - if (radeon_ws == NULL) { - return NULL; - } - - radeon_ws->priv = CALLOC_STRUCT(radeon_winsys_priv); - if (radeon_ws->priv == NULL) { - FREE(radeon_ws); - return NULL; - } - - radeon_ws->priv->fd = fd; - radeon_ws->priv->bom = radeon_bo_manager_gem_ctor(fd); - - radeon_ws->base.flush_frontbuffer = NULL; /* overriden by co-state tracker */ - - radeon_ws->base.buffer_create = radeon_buffer_create; - radeon_ws->base.user_buffer_create = radeon_buffer_user_create; - radeon_ws->base.surface_buffer_create = radeon_surface_buffer_create; - radeon_ws->base.buffer_map = radeon_buffer_map; - radeon_ws->base.buffer_unmap = radeon_buffer_unmap; - radeon_ws->base.buffer_destroy = radeon_buffer_del; - - radeon_ws->base.fence_reference = radeon_fence_reference; - radeon_ws->base.fence_signalled = radeon_fence_signalled; - radeon_ws->base.fence_finish = radeon_fence_finish; - - radeon_ws->base.get_name = radeon_get_name; - - radeon_ws->buffer_set_tiling = radeon_buffer_set_tiling; - radeon_ws->buffer_from_handle = radeon_buffer_from_handle; - radeon_ws->buffer_get_handle = radeon_buffer_get_handle; - - radeon_ws->is_buffer_referenced = radeon_is_buffer_referenced; - - return radeon_ws; -} diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h deleted file mode 100644 index f776e2d900..0000000000 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright © 2008 Jérôme Glisse - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS - * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - */ -/* - * Authors: - * Jérôme Glisse <glisse@freedesktop.org> - */ -#ifndef RADEON_BUFFER_H -#define RADEON_BUFFER_H - -#include "pipebuffer/pb_buffer.h" - -#include "radeon_bo.h" -#include "radeon_cs.h" - -#include "radeon_winsys.h" - -struct radeon_pipe_buffer { - struct pipe_buffer base; - /* Pointer to GPU-backed BO. */ - struct radeon_bo *bo; - /* Pointer to fallback PB buffer. */ - struct pb_buffer *pb; - boolean flinked; - uint32_t flink; -}; - -#define RADEON_MAX_BOS 24 - -struct radeon_winsys_priv { - /* DRM FD */ - int fd; - - /* Radeon BO manager. */ - struct radeon_bo_manager* bom; - - /* Radeon CS manager. */ - struct radeon_cs_manager* csm; - - /* Current CS. */ - struct radeon_cs* cs; - - /* Flush CB */ - void (*flush_cb)(void *); - void *flush_data; -}; - -struct radeon_winsys* radeon_pipe_winsys(int fb); -#if 0 -struct pipe_surface *radeon_surface_from_handle(struct radeon_context *radeon_context, - uint32_t handle, - enum pipe_format format, - int w, int h, int pitch); -#endif -#endif diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c index 97edb6a47e..acfb36f7e0 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -31,7 +31,6 @@ #include "radeon_drm.h" #include "radeon_r300.h" -#include "radeon_buffer.h" #include "r300_winsys.h" #include "trace/tr_drm.h" @@ -41,8 +40,22 @@ #include "xf86drm.h" #include <sys/ioctl.h> +static struct radeon_libdrm_winsys * +radeon_winsys_create(int fd) +{ + struct radeon_libdrm_winsys *rws; + + rws = CALLOC_STRUCT(radeon_libdrm_winsys); + if (rws == NULL) { + return NULL; + } + + rws->fd = fd; + return rws; +} + /* Helper function to do the ioctls needed for setup and init. */ -static void do_ioctls(int fd, struct radeon_winsys* winsys) +static void do_ioctls(int fd, struct radeon_libdrm_winsys* winsys) { struct drm_radeon_gem_info gem_info = {0}; struct drm_radeon_info info = {0}; @@ -79,6 +92,10 @@ static void do_ioctls(int fd, struct radeon_winsys* winsys) exit(1); } + // Supported since 2.1.0. + winsys->squaretiling = version->version_major > 2 || + version->version_minor >= 1; + info.request = RADEON_INFO_DEVICE_ID; retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { @@ -133,19 +150,28 @@ struct pipe_screen* radeon_create_screen(struct drm_api* api, int drmFB, struct drm_create_screen_arg *arg) { - struct radeon_winsys* rwinsys = radeon_pipe_winsys(drmFB); - do_ioctls(drmFB, rwinsys); + struct radeon_libdrm_winsys* rws; + boolean ret; + + rws = radeon_winsys_create(drmFB); + if (!rws) + return NULL; + + do_ioctls(drmFB, rws); /* The state tracker can organize a softpipe fallback if no hw * driver is found. */ - if (is_r3xx(rwinsys->pci_id)) { - radeon_setup_winsys(drmFB, rwinsys); - return r300_create_screen(rwinsys); - } else { - FREE(rwinsys); - return NULL; + if (is_r3xx(rws->pci_id)) { + ret = radeon_setup_winsys(drmFB, rws); + if (ret == FALSE) + goto fail; + return r300_create_screen(&rws->base); } + +fail: + FREE(rws); + return NULL; } static void radeon_drm_api_destroy(struct drm_api *api) diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c new file mode 100644 index 0000000000..d9870e8519 --- /dev/null +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c @@ -0,0 +1,381 @@ + +#include <sys/ioctl.h> +#include "radeon_drm.h" +#include "radeon_bo_gem.h" +#include "radeon_cs_gem.h" + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" +#include "pipebuffer/pb_buffer.h" +#include "pipebuffer/pb_bufmgr.h" + +#include "radeon_winsys.h" +struct radeon_drm_bufmgr; + +struct radeon_drm_buffer { + struct pb_buffer base; + struct radeon_drm_bufmgr *mgr; + + struct radeon_bo *bo; + + boolean flinked; + uint32_t flink; + + struct radeon_drm_buffer *next, *prev; +}; + +extern const struct pb_vtbl radeon_drm_buffer_vtbl; + + +static INLINE struct radeon_drm_buffer * +radeon_drm_buffer(struct pb_buffer *buf) +{ + assert(buf); + assert(buf->vtbl == &radeon_drm_buffer_vtbl); + return (struct radeon_drm_buffer *)buf; +} + +struct radeon_drm_bufmgr { + struct pb_manager base; + struct radeon_libdrm_winsys *rws; + struct radeon_drm_buffer buffer_map_list; +}; + +static INLINE struct radeon_drm_bufmgr * +radeon_drm_bufmgr(struct pb_manager *mgr) +{ + assert(mgr); + return (struct radeon_drm_bufmgr *)mgr; +} + +static void +radeon_drm_buffer_destroy(struct pb_buffer *_buf) +{ + struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); + + if (buf->bo->ptr != NULL) { + remove_from_list(buf); + radeon_bo_unmap(buf->bo); + buf->bo->ptr = NULL; + } + radeon_bo_unref(buf->bo); + + FREE(buf); +} + +static void * +radeon_drm_buffer_map(struct pb_buffer *_buf, + unsigned flags) +{ + struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); + int write; + + if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { + if ((_buf->base.usage & PIPE_BUFFER_USAGE_VERTEX) || + (_buf->base.usage & PIPE_BUFFER_USAGE_INDEX)) + if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) + return NULL; + } + + if (buf->bo->ptr != NULL) + return buf->bo->ptr; + + if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { + uint32_t domain; + if (radeon_bo_is_busy(buf->bo, &domain)) + return NULL; + } + + if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) { + buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data); + } + + if (flags & PIPE_TRANSFER_WRITE) { + write = 1; + } + + if (radeon_bo_map(buf->bo, write)) { + return NULL; + } + insert_at_tail(&buf->mgr->buffer_map_list, buf); + return buf->bo->ptr; +} + +static void +radeon_drm_buffer_unmap(struct pb_buffer *_buf) +{ + (void)_buf; +} + +static void +radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf, + struct pb_buffer **base_buf, + unsigned *offset) +{ + *base_buf = buf; + *offset = 0; +} + + +static enum pipe_error +radeon_drm_buffer_validate(struct pb_buffer *_buf, + struct pb_validate *vl, + unsigned flags) +{ + /* Always pinned */ + return PIPE_OK; +} + +static void +radeon_drm_buffer_fence(struct pb_buffer *buf, + struct pipe_fence_handle *fence) +{ +} + +const struct pb_vtbl radeon_drm_buffer_vtbl = { + radeon_drm_buffer_destroy, + radeon_drm_buffer_map, + radeon_drm_buffer_unmap, + radeon_drm_buffer_validate, + radeon_drm_buffer_fence, + radeon_drm_buffer_get_base_buffer, +}; + + +static uint32_t radeon_domain_from_usage(unsigned usage) +{ + uint32_t domain = 0; + + if (usage & PIPE_BUFFER_USAGE_GPU_WRITE) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_PIXEL) { + domain |= RADEON_GEM_DOMAIN_VRAM; + } + if (usage & PIPE_BUFFER_USAGE_VERTEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + if (usage & PIPE_BUFFER_USAGE_INDEX) { + domain |= RADEON_GEM_DOMAIN_GTT; + } + + return domain; +} + +struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr, + uint32_t handle) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + struct radeon_libdrm_winsys *rws = mgr->rws; + struct radeon_drm_buffer *buf; + struct radeon_bo *bo; + + bo = radeon_bo_open(rws->bom, handle, 0, + 0, 0, 0); + if (bo == NULL) + return NULL; + + buf = CALLOC_STRUCT(radeon_drm_buffer); + if (!buf) { + radeon_bo_unref(bo); + return NULL; + } + + make_empty_list(buf); + + pipe_reference_init(&buf->base.base.reference, 1); + buf->base.base.alignment = 0; + buf->base.base.usage = PIPE_BUFFER_USAGE_PIXEL; + buf->base.base.size = 0; + buf->base.vtbl = &radeon_drm_buffer_vtbl; + buf->mgr = mgr; + + buf->bo = bo; + + return &buf->base; +} + +static struct pb_buffer * +radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr, + pb_size size, + const struct pb_desc *desc) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + struct radeon_libdrm_winsys *rws = mgr->rws; + struct radeon_drm_buffer *buf; + uint32_t domain; + + buf = CALLOC_STRUCT(radeon_drm_buffer); + if (!buf) + goto error1; + + pipe_reference_init(&buf->base.base.reference, 1); + buf->base.base.alignment = desc->alignment; + buf->base.base.usage = desc->usage; + buf->base.base.size = size; + buf->base.vtbl = &radeon_drm_buffer_vtbl; + buf->mgr = mgr; + + make_empty_list(buf); + domain = radeon_domain_from_usage(desc->usage); + buf->bo = radeon_bo_open(rws->bom, 0, size, + desc->alignment, domain, 0); + if (buf->bo == NULL) + goto error2; + + return &buf->base; + + error2: + FREE(buf); + error1: + return NULL; +} + +static void +radeon_drm_bufmgr_flush(struct pb_manager *mgr) +{ + /* NOP */ +} + +static void +radeon_drm_bufmgr_destroy(struct pb_manager *_mgr) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + FREE(mgr); +} + +struct pb_manager * +radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws) +{ + struct radeon_drm_bufmgr *mgr; + + mgr = CALLOC_STRUCT(radeon_drm_bufmgr); + if (!mgr) + return NULL; + + mgr->base.destroy = radeon_drm_bufmgr_destroy; + mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer; + mgr->base.flush = radeon_drm_bufmgr_flush; + + mgr->rws = rws; + make_empty_list(&mgr->buffer_map_list); + return &mgr->base; +} + +static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf) +{ + struct radeon_drm_buffer *buf; + if (_buf->vtbl == &radeon_drm_buffer_vtbl) { + buf = radeon_drm_buffer(_buf); + } else { + struct pb_buffer *base_buf; + pb_size offset; + pb_get_base_buffer(_buf, &base_buf, &offset); + + buf = radeon_drm_buffer(base_buf); + } + return buf; +} + +boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, + struct winsys_handle *whandle) +{ + int retval, fd; + struct drm_gem_flink flink; + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!buf->flinked) { + fd = buf->mgr->rws->fd; + flink.handle = buf->bo->handle; + + retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); + if (retval) { + return FALSE; + } + + buf->flinked = TRUE; + buf->flink = flink.name; + } + whandle->handle = buf->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = buf->bo->handle; + } + return TRUE; +} + + +void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, + enum r300_buffer_tiling microtiled, + enum r300_buffer_tiling macrotiled, + uint32_t pitch) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + uint32_t flags = 0, old_flags, old_pitch; + if (microtiled == R300_BUFFER_TILED) + flags |= RADEON_BO_FLAGS_MICRO_TILE; + else if (microtiled == R300_BUFFER_SQUARETILED) + flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE; + if (macrotiled == R300_BUFFER_TILED) + flags |= RADEON_BO_FLAGS_MACRO_TILE; + + radeon_bo_get_tiling(buf->bo, &old_flags, &old_pitch); + + if (flags != old_flags || pitch != old_pitch) { + /* Tiling determines how DRM treats the buffer data. + * We must flush CS when changing it if the buffer is referenced. */ + if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) { + buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data); + } + } + radeon_bo_set_tiling(buf->bo, flags, pitch); + +} + +boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf, + uint32_t rd, uint32_t wd) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo, + rd, wd); + return TRUE; +} + +void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf, + uint32_t rd, uint32_t wd, + uint32_t flags) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + int retval; + + retval = radeon_cs_write_reloc(buf->mgr->rws->cs, + buf->bo, rd, wd, flags); + if (retval) { + debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", + buf, rd, wd, flags); + } +} + +boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf) +{ + struct radeon_drm_buffer *buf = get_drm_buffer(_buf); + uint32_t domain; + + return (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs) || + radeon_bo_is_busy(buf->bo, &domain)); +} + + +void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) +{ + struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr); + struct radeon_drm_buffer *rpb, *t_rpb; + + foreach_s(rpb, t_rpb, &mgr->buffer_map_list) { + radeon_bo_unmap(rpb->bo); + rpb->bo->ptr = NULL; + remove_from_list(rpb); + } + + make_empty_list(&mgr->buffer_map_list); +} diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index 122bd21354..2f89484f7d 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -21,33 +21,143 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "radeon_r300.h" -#include "radeon_buffer.h" +#include "radeon_bo_gem.h" #include "radeon_cs_gem.h" +#include "state_tracker/drm_api.h" -static void radeon_set_flush_cb(struct radeon_winsys *winsys, +static struct r300_winsys_buffer * +radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + struct pb_desc desc; + struct pb_manager *provider; + struct pb_buffer *buffer; + + memset(&desc, 0, sizeof(desc)); + desc.alignment = alignment; + desc.usage = usage; + + if (usage & PIPE_BUFFER_USAGE_CONSTANT) + provider = ws->mman; + else if ((usage & PIPE_BUFFER_USAGE_VERTEX) || + (usage & PIPE_BUFFER_USAGE_INDEX)) + provider = ws->cman; + else + provider = ws->kman; + buffer = provider->create_buffer(provider, size, &desc); + if (!buffer) + return NULL; + + return radeon_libdrm_winsys_buffer(buffer); +} + +static void radeon_r300_winsys_buffer_destroy(struct r300_winsys_buffer *buf) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + pb_destroy(_buf); +} +static void radeon_r300_winsys_buffer_set_tiling(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, + uint32_t pitch, + enum r300_buffer_tiling microtiled, + enum r300_buffer_tiling macrotiled) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + radeon_drm_bufmgr_set_tiling(_buf, microtiled, macrotiled, pitch); +} + +static void *radeon_r300_winsys_buffer_map(struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf, + unsigned usage) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + return pb_map(_buf, usage); +} + +static void radeon_r300_winsys_buffer_unmap(struct r300_winsys_screen *ws, + struct r300_winsys_buffer *buf) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + pb_unmap(_buf); +} + +static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws, + struct r300_winsys_buffer **pdst, + struct r300_winsys_buffer *src) +{ + struct pb_buffer *_src = radeon_pb_buffer(src); + struct pb_buffer *_dst = radeon_pb_buffer(*pdst); + + pb_reference(&_dst, _src); + + *pdst = radeon_libdrm_winsys_buffer(_dst); +} + +static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buf); + + return radeon_drm_bufmgr_is_buffer_referenced(_buf); +} + +static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws, + struct pipe_screen *screen, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + struct pb_buffer *_buf; + + _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle); + *stride = whandle->stride; + return radeon_libdrm_winsys_buffer(_buf); +} + +static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buffer, + unsigned stride, + struct winsys_handle *whandle) +{ + struct pb_buffer *_buf = radeon_pb_buffer(buffer); + boolean ret; + ret = radeon_drm_bufmgr_get_handle(_buf, whandle); + if (ret) + whandle->stride = stride; + return ret; +} + +static void radeon_set_flush_cb(struct r300_winsys_screen *rws, void (*flush_cb)(void *), void *data) { - winsys->priv->flush_cb = flush_cb; - winsys->priv->flush_data = data; - radeon_cs_space_set_flush(winsys->priv->cs, flush_cb, data); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + ws->flush_cb = flush_cb; + ws->flush_data = data; + radeon_cs_space_set_flush(ws->cs, flush_cb, data); } -static boolean radeon_add_buffer(struct radeon_winsys* winsys, - struct pipe_buffer* pbuffer, +static boolean radeon_add_buffer(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, uint32_t rd, uint32_t wd) { - struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo; + struct pb_buffer *_buf = radeon_pb_buffer(buf); - radeon_cs_space_add_persistent_bo(winsys->priv->cs, bo, rd, wd); - return TRUE; + return radeon_drm_bufmgr_add_buffer(_buf, rd, wd); } -static boolean radeon_validate(struct radeon_winsys* winsys) +static boolean radeon_validate(struct r300_winsys_screen *rws) { - if (radeon_cs_space_check(winsys->priv->cs) < 0) { + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + if (radeon_cs_space_check(ws->cs) < 0) { return FALSE; } @@ -55,108 +165,183 @@ static boolean radeon_validate(struct radeon_winsys* winsys) return TRUE; } -static boolean radeon_check_cs(struct radeon_winsys* winsys, int size) +static boolean radeon_check_cs(struct r300_winsys_screen *rws, int size) { - struct radeon_cs* cs = winsys->priv->cs; + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + struct radeon_cs *cs = ws->cs; - return radeon_validate(winsys) && cs->cdw + size <= cs->ndw; + return radeon_validate(rws) && cs->cdw + size <= cs->ndw; } -static void radeon_begin_cs(struct radeon_winsys* winsys, +static void radeon_begin_cs(struct r300_winsys_screen *rws, int size, const char* file, const char* function, int line) { - radeon_cs_begin(winsys->priv->cs, size, file, function, line); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_begin(ws->cs, size, file, function, line); } -static void radeon_write_cs_dword(struct radeon_winsys* winsys, +static void radeon_write_cs_dword(struct r300_winsys_screen *rws, uint32_t dword) { - radeon_cs_write_dword(winsys->priv->cs, dword); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_write_dword(ws->cs, dword); } -static void radeon_write_cs_reloc(struct radeon_winsys* winsys, - struct pipe_buffer* pbuffer, +static void radeon_write_cs_reloc(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf, uint32_t rd, uint32_t wd, uint32_t flags) { - int retval = 0; - struct radeon_pipe_buffer* radeon_buffer = - (struct radeon_pipe_buffer*)pbuffer; - - assert(!radeon_buffer->pb); - - retval = radeon_cs_write_reloc(winsys->priv->cs, radeon_buffer->bo, - rd, wd, flags); - - if (retval) { - debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", - pbuffer, rd, wd, flags); - } + struct pb_buffer *_buf = radeon_pb_buffer(buf); + radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags); } -static void radeon_reset_bos(struct radeon_winsys *winsys) +static void radeon_reset_bos(struct r300_winsys_screen *rws) { - radeon_cs_space_reset_bos(winsys->priv->cs); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_space_reset_bos(ws->cs); } -static void radeon_end_cs(struct radeon_winsys* winsys, +static void radeon_end_cs(struct r300_winsys_screen *rws, const char* file, const char* function, int line) { - radeon_cs_end(winsys->priv->cs, file, function, line); + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); + radeon_cs_end(ws->cs, file, function, line); } -static void radeon_flush_cs(struct radeon_winsys* winsys) +static void radeon_flush_cs(struct r300_winsys_screen *rws) { + struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws); int retval; /* Don't flush a zero-sized CS. */ - if (!winsys->priv->cs->cdw) { + if (!ws->cs->cdw) { return; } + radeon_drm_bufmgr_flush_maps(ws->kman); /* Emit the CS. */ - retval = radeon_cs_emit(winsys->priv->cs); + retval = radeon_cs_emit(ws->cs); if (retval) { debug_printf("radeon: Bad CS, dumping...\n"); - radeon_cs_print(winsys->priv->cs, stderr); + radeon_cs_print(ws->cs, stderr); } /* Reset CS. * Someday, when we care about performance, we should really find a way * to rotate between two or three CS objects so that the GPU can be * spinning through one CS while another one is being filled. */ - radeon_cs_erase(winsys->priv->cs); + radeon_cs_erase(ws->cs); } -void -radeon_setup_winsys(int fd, struct radeon_winsys* winsys) +static uint32_t radeon_get_value(struct r300_winsys_screen *rws, + enum r300_value_id id) { - struct radeon_winsys_priv* priv = winsys->priv; + struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws; - priv->csm = radeon_cs_manager_gem_ctor(fd); + switch(id) { + case R300_VID_PCI_ID: + return ws->pci_id; + case R300_VID_GB_PIPES: + return ws->gb_pipes; + case R300_VID_Z_PIPES: + return ws->z_pipes; + case R300_VID_SQUARE_TILING_SUPPORT: + return ws->squaretiling; + } + return 0; +} + +static void +radeon_winsys_destroy(struct r300_winsys_screen *rws) +{ + struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws; + radeon_cs_destroy(ws->cs); + + ws->cman->destroy(ws->cman); + ws->kman->destroy(ws->kman); + ws->mman->destroy(ws->mman); + + radeon_bo_manager_gem_dtor(ws->bom); + radeon_cs_manager_gem_dtor(ws->csm); +} + +boolean +radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws) +{ + + ws->csm = radeon_cs_manager_gem_ctor(fd); + if (!ws->csm) + goto fail; + ws->bom = radeon_bo_manager_gem_ctor(fd); + if (!ws->bom) + goto fail; + ws->kman = radeon_drm_bufmgr_create(ws); + if (!ws->kman) + goto fail; + + ws->cman = pb_cache_manager_create(ws->kman, 100000); + if (!ws->cman) + goto fail; + + ws->mman = pb_malloc_bufmgr_create(); + if (!ws->mman) + goto fail; /* Size limit on IBs is 64 kibibytes. */ - priv->cs = radeon_cs_create(priv->csm, 1024 * 64 / 4); - radeon_cs_set_limit(priv->cs, - RADEON_GEM_DOMAIN_GTT, winsys->gart_size); - radeon_cs_set_limit(priv->cs, - RADEON_GEM_DOMAIN_VRAM, winsys->vram_size); - - winsys->add_buffer = radeon_add_buffer; - winsys->validate = radeon_validate; - - winsys->check_cs = radeon_check_cs; - winsys->begin_cs = radeon_begin_cs; - winsys->write_cs_dword = radeon_write_cs_dword; - winsys->write_cs_reloc = radeon_write_cs_reloc; - winsys->end_cs = radeon_end_cs; - winsys->flush_cs = radeon_flush_cs; - winsys->reset_bos = radeon_reset_bos; - winsys->set_flush_cb = radeon_set_flush_cb; + ws->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4); + if (!ws->cs) + goto fail; + radeon_cs_set_limit(ws->cs, + RADEON_GEM_DOMAIN_GTT, ws->gart_size); + radeon_cs_set_limit(ws->cs, + RADEON_GEM_DOMAIN_VRAM, ws->vram_size); + + ws->base.add_buffer = radeon_add_buffer; + ws->base.validate = radeon_validate; + ws->base.destroy = radeon_winsys_destroy; + ws->base.check_cs = radeon_check_cs; + ws->base.begin_cs = radeon_begin_cs; + ws->base.write_cs_dword = radeon_write_cs_dword; + ws->base.write_cs_reloc = radeon_write_cs_reloc; + ws->base.end_cs = radeon_end_cs; + ws->base.flush_cs = radeon_flush_cs; + ws->base.reset_bos = radeon_reset_bos; + ws->base.set_flush_cb = radeon_set_flush_cb; + ws->base.get_value = radeon_get_value; + + ws->base.buffer_create = radeon_r300_winsys_buffer_create; + ws->base.buffer_destroy = radeon_r300_winsys_buffer_destroy; + ws->base.buffer_set_tiling = radeon_r300_winsys_buffer_set_tiling; + ws->base.buffer_map = radeon_r300_winsys_buffer_map; + ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap; + ws->base.buffer_reference = radeon_r300_winsys_buffer_reference; + ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle; + ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle; + ws->base.is_buffer_referenced = radeon_r300_winsys_is_buffer_referenced; + return TRUE; + +fail: + if (ws->csm) + radeon_cs_manager_gem_dtor(ws->csm); + + if (ws->bom) + radeon_bo_manager_gem_dtor(ws->bom); + + if (ws->cman) + ws->cman->destroy(ws->cman); + if (ws->kman) + ws->kman->destroy(ws->kman); + if (ws->mman) + ws->mman->destroy(ws->mman); + + if (ws->cs) + radeon_cs_destroy(ws->cs); + return FALSE; } diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.h b/src/gallium/winsys/drm/radeon/core/radeon_r300.h index e655dc32c8..2703464ad8 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.h @@ -25,6 +25,6 @@ #include "radeon_winsys.h" -void radeon_setup_winsys(int fd, struct radeon_winsys* winsys); +boolean radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* winsys); #endif /* RADEON_R300_H */ diff --git a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h index 887a381cc4..4260dbaad7 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_winsys.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_winsys.h @@ -30,16 +30,17 @@ #ifndef RADEON_WINSYS_H #define RADEON_WINSYS_H -#include "util/u_simple_screen.h" +#include "r300_winsys.h" -struct radeon_winsys_priv; - -struct radeon_winsys { +struct radeon_libdrm_winsys { /* Parent class. */ - struct pipe_winsys base; + struct r300_winsys_screen base; + + struct pb_manager *kman; + + struct pb_manager *cman; - /* Winsys private */ - struct radeon_winsys_priv* priv; + struct pb_manager *mman; /* PCI ID */ uint32_t pci_id; @@ -56,71 +57,30 @@ struct radeon_winsys { /* VRAM size. */ uint32_t vram_size; - /* Create a buffer from a winsys handle. */ - struct pipe_buffer *(*buffer_from_handle)(struct radeon_winsys *winsys, - struct pipe_screen *screen, - struct winsys_handle *whandle, - unsigned *stride); - - /* Get the handle from a buffer. */ - boolean (*buffer_get_handle)(struct radeon_winsys *winsys, - struct pipe_buffer *buffer, - unsigned stride, - struct winsys_handle *whandle); - - /* Add a pipe_buffer to the list of buffer objects to validate. */ - boolean (*add_buffer)(struct radeon_winsys* winsys, - struct pipe_buffer* pbuffer, - uint32_t rd, - uint32_t wd); - - /* Revalidate all currently setup pipe_buffers. - * Returns TRUE if a flush is required. */ - boolean (*validate)(struct radeon_winsys* winsys); - - /* Check to see if there's room for commands. */ - boolean (*check_cs)(struct radeon_winsys* winsys, int size); - - /* Start a command emit. */ - void (*begin_cs)(struct radeon_winsys* winsys, - int size, - const char* file, - const char* function, - int line); - - /* Write a dword to the command buffer. */ - void (*write_cs_dword)(struct radeon_winsys* winsys, uint32_t dword); - - /* Write a relocated dword to the command buffer. */ - void (*write_cs_reloc)(struct radeon_winsys* winsys, - struct pipe_buffer* bo, - uint32_t rd, - uint32_t wd, - uint32_t flags); - - /* Finish a command emit. */ - void (*end_cs)(struct radeon_winsys* winsys, - const char* file, - const char* function, - int line); - - /* Flush the CS. */ - void (*flush_cs)(struct radeon_winsys* winsys); - - /* winsys flush - callback from winsys when flush required */ - void (*set_flush_cb)(struct radeon_winsys *winsys, - void (*flush_cb)(void *), void *data); - - void (*reset_bos)(struct radeon_winsys *winsys); - - void (*buffer_set_tiling)(struct radeon_winsys* winsys, - struct pipe_buffer* buffer, - uint32_t pitch, - boolean microtiled, - boolean macrotiled); - - boolean (*is_buffer_referenced)(struct radeon_winsys *winsys, - struct pipe_buffer *buffer); + /* Square tiling support. */ + boolean squaretiling; + + /* DRM FD */ + int fd; + + /* Radeon BO manager. */ + struct radeon_bo_manager *bom; + + /* Radeon CS manager. */ + struct radeon_cs_manager *csm; + + /* Current CS. */ + struct radeon_cs *cs; + + /* Flush CB */ + void (*flush_cb)(void *); + void *flush_data; }; +static INLINE struct radeon_libdrm_winsys * +radeon_winsys_screen(struct r300_winsys_screen *base) +{ + return (struct radeon_libdrm_winsys *)base; +} + #endif diff --git a/src/gallium/winsys/drm/sw/Makefile b/src/gallium/winsys/drm/sw/Makefile new file mode 100644 index 0000000000..5f3c3ec325 --- /dev/null +++ b/src/gallium/winsys/drm/sw/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = swdrm + +C_SOURCES = \ + wrapper_sw_winsys.c \ + sw_drm_api.c + +LIBRARY_INCLUDES = + +LIBRARY_DEFINES = + +include ../../../Makefile.template diff --git a/src/gallium/winsys/drm/sw/sw_drm_api.c b/src/gallium/winsys/drm/sw/sw_drm_api.c new file mode 100644 index 0000000000..0fd2163913 --- /dev/null +++ b/src/gallium/winsys/drm/sw/sw_drm_api.c @@ -0,0 +1,97 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "util/u_memory.h" +#include "softpipe/sp_public.h" +#include "state_tracker/drm_api.h" +#include "wrapper_sw_winsys.h" +#include "sw_drm_api.h" + + +/* + * Defines + */ + + +struct sw_drm_api +{ + struct drm_api base; + struct drm_api *api; + struct sw_winsys *sw; +}; + +static INLINE struct sw_drm_api * +sw_drm_api(struct drm_api *api) +{ + return (struct sw_drm_api *)api; +} + + +/* + * Exported functions + */ + + +static struct pipe_screen * +sw_drm_create_screen(struct drm_api *_api, int drmFD, + struct drm_create_screen_arg *arg) +{ + struct sw_drm_api *swapi = sw_drm_api(_api); + struct drm_api *api = swapi->api; + struct sw_winsys *sww; + struct pipe_screen *screen; + + screen = api->create_screen(api, drmFD, arg); + + sww = wrapper_sw_winsys_warp_pipe_screen(screen); + + return softpipe_create_screen(sww); +} + +static void +sw_drm_destroy(struct drm_api *api) +{ + struct sw_drm_api *swapi = sw_drm_api(api); + if (swapi->api->destroy) + swapi->api->destroy(swapi->api); + + FREE(swapi); +} + +struct drm_api * +sw_drm_api_create(struct drm_api *api) +{ + struct sw_drm_api *swapi = CALLOC_STRUCT(sw_drm_api); + + swapi->base.name = "sw"; + swapi->base.driver_name = api->driver_name; + swapi->base.create_screen = sw_drm_create_screen; + swapi->base.destroy = sw_drm_destroy; + + swapi->api = api; + + return &swapi->base; +} diff --git a/src/gallium/winsys/drm/sw/sw_drm_api.h b/src/gallium/winsys/drm/sw/sw_drm_api.h new file mode 100644 index 0000000000..ce90a04ae0 --- /dev/null +++ b/src/gallium/winsys/drm/sw/sw_drm_api.h @@ -0,0 +1,34 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 SW_DRM_API_H +#define SW_DRM_API_H + +struct drm_api; + +struct drm_api * sw_drm_api_create(struct drm_api *api); + +#endif diff --git a/src/gallium/winsys/drm/sw/wrapper_sw_winsys.c b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.c new file mode 100644 index 0000000000..d123cde806 --- /dev/null +++ b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.c @@ -0,0 +1,282 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 "wrapper_sw_winsys.h" + +#include "pipe/p_format.h" +#include "pipe/p_state.h" + +#include "state_tracker/sw_winsys.h" + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +/* + * This code wraps a pipe_screen and exposes a sw_winsys interface for use + * with software resterizers. This code is used by the DRM based winsys to + * allow access to the drm driver. + * + * We must borrow the whole stack because only the pipe screen knows how + * to decode the content of a buffer. Or how to create a buffer that + * can still be used by drivers using real hardware (as the case is + * with software st/xorg but hw st/dri). + * + * We also need a pipe context for the transfers. + */ + +struct wrapper_sw_winsys +{ + struct sw_winsys base; + struct pipe_screen *screen; + struct pipe_context *pipe; +}; + +struct wrapper_sw_displaytarget +{ + struct wrapper_sw_winsys *winsys; + struct pipe_resource *tex; + struct pipe_transfer *transfer; + + unsigned width; + unsigned height; + unsigned map_count; + unsigned stride; /**< because we give stride at create */ + void *ptr; +}; + +static INLINE struct wrapper_sw_winsys * +wrapper_sw_winsys(struct sw_winsys *ws) +{ + return (struct wrapper_sw_winsys *)ws; +} + +static INLINE struct wrapper_sw_displaytarget * +wrapper_sw_displaytarget(struct sw_displaytarget *dt) +{ + return (struct wrapper_sw_displaytarget *)dt; +} + + +/* + * Functions + */ + + +static boolean +wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride) +{ + struct pipe_context *pipe = wdt->winsys->pipe; + struct pipe_resource *tex = wdt->tex; + struct pipe_transfer *tr; + + tr = pipe_get_transfer(pipe, tex, 0, 0, 0, + PIPE_TRANSFER_READ_WRITE, + 0, 0, wdt->width, wdt->height); + if (!tr) + return FALSE; + + *stride = tr->stride; + wdt->stride = tr->stride; + + pipe->transfer_destroy(pipe, tr); + + return TRUE; +} + +static struct sw_displaytarget * +wsw_dt_wrap_texture(struct wrapper_sw_winsys *wsw, + struct pipe_resource *tex, unsigned *stride) +{ + struct wrapper_sw_displaytarget *wdt = CALLOC_STRUCT(wrapper_sw_displaytarget); + if (!wdt) + goto err_unref; + + wdt->tex = tex; + wdt->winsys = wsw; + + if (!wsw_dt_get_stride(wdt, stride)) + goto err_free; + + return (struct sw_displaytarget *)wdt; + +err_free: + FREE(wdt); +err_unref: + pipe_resource_reference(&tex, NULL); + return NULL; +} + +static struct sw_displaytarget * +wsw_dt_create(struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); + struct pipe_resource templ; + struct pipe_resource *tex; + + /* + * XXX Why don't we just get the template. + */ + memset(&templ, 0, sizeof(templ)); + templ.width0 = width; + templ.height0 = height; + templ.format = format; + templ.tex_usage = tex_usage; + + /* XXX alignment: we can't do anything about this */ + + tex = wsw->screen->resource_create(wsw->screen, &templ); + if (!tex) + return NULL; + + return wsw_dt_wrap_texture(wsw, tex, stride); +} + +static struct sw_displaytarget * +wsw_dt_from_handle(struct sw_winsys *ws, + const struct pipe_resource *templ, + struct winsys_handle *whandle, + unsigned *stride) +{ + struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); + struct pipe_resource *tex; + + tex = wsw->screen->resource_from_handle(wsw->screen, templ, whandle); + if (!tex) + return NULL; + + return wsw_dt_wrap_texture(wsw, tex, stride); +} + +static void * +wsw_dt_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags) +{ + struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); + struct pipe_context *pipe = wdt->winsys->pipe; + struct pipe_resource *tex = wdt->tex; + struct pipe_transfer *tr; + void *ptr; + + if (!wdt->map_count) { + + assert(!wdt->transfer); + + tr = pipe_get_transfer(pipe, tex, 0, 0, 0, + PIPE_TRANSFER_READ_WRITE, + 0, 0, wdt->width, wdt->height); + if (!tr) + return NULL; + + ptr = pipe->transfer_map(pipe, tr); + if (!ptr) + goto err; + + wdt->transfer = tr; + wdt->ptr = ptr; + + /* XXX Handle this case */ + assert(tr->stride == wdt->stride); + } + + wdt->map_count++; + + return wdt->ptr; + +err: + pipe->transfer_destroy(pipe, tr); + return NULL; +} + +static void +wsw_dt_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); + struct pipe_context *pipe = wdt->winsys->pipe; + + assert(wdt->transfer); + + wdt->map_count--; + + if (wdt->map_count) + return; + + pipe->transfer_unmap(pipe, wdt->transfer); + pipe->transfer_destroy(pipe, wdt->transfer); + wdt->transfer = NULL; +} + +static void +wsw_dt_destroy(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt); + + pipe_resource_reference(&wdt->tex, NULL); + + FREE(wdt); +} + +static void +wsw_destroy(struct sw_winsys *ws) +{ + struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws); + + wsw->pipe->destroy(wsw->pipe); + wsw->screen->destroy(wsw->screen); + + FREE(wsw); +} + +struct sw_winsys * +wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen) +{ + struct wrapper_sw_winsys *wsw = CALLOC_STRUCT(wrapper_sw_winsys); + + wsw->base.displaytarget_create = wsw_dt_create; + wsw->base.displaytarget_from_handle = wsw_dt_from_handle; + wsw->base.displaytarget_map = wsw_dt_map; + wsw->base.displaytarget_unmap = wsw_dt_unmap; + wsw->base.displaytarget_destroy = wsw_dt_destroy; + wsw->base.destroy = wsw_destroy; + + wsw->screen = screen; + wsw->pipe = screen->context_create(screen, NULL); + if (!wsw->pipe) + goto err; + + return &wsw->base; + +err: + FREE(wsw); + return NULL; +} diff --git a/src/gallium/winsys/drm/sw/wrapper_sw_winsys.h b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.h new file mode 100644 index 0000000000..b5c25a3c50 --- /dev/null +++ b/src/gallium/winsys/drm/sw/wrapper_sw_winsys.h @@ -0,0 +1,35 @@ +/********************************************************** + * Copyright 2010 VMware, Inc. 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, sublicense, 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 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 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * 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 WRAPPER_SW_WINSYS +#define WRAPPER_SW_WINSYS + +struct sw_winsys; +struct pipe_screen; + +struct sw_winsys *wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen); + +#endif diff --git a/src/gallium/winsys/gdi/gdi_sw_winsys.c b/src/gallium/winsys/gdi/gdi_sw_winsys.c index f5c0b7d56e..2e12f6e6cc 100644 --- a/src/gallium/winsys/gdi/gdi_sw_winsys.c +++ b/src/gallium/winsys/gdi/gdi_sw_winsys.c @@ -71,6 +71,7 @@ gdi_sw_displaytarget( struct sw_displaytarget *buf ) static boolean gdi_sw_is_displaytarget_format_supported( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format ) { switch(format) { @@ -119,6 +120,7 @@ gdi_sw_displaytarget_destroy(struct sw_winsys *winsys, static struct sw_displaytarget * gdi_sw_displaytarget_create(struct sw_winsys *winsys, + unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, @@ -168,6 +170,27 @@ no_gdt: } +static struct sw_displaytarget * +gdi_sw_displaytarget_from_handle(struct sw_winsys *winsys, + const struct pipe_resource *templet, + struct winsys_handle *whandle, + unsigned *stride) +{ + assert(0); + return NULL; +} + + +static boolean +gdi_sw_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + assert(0); + return FALSE; +} + + void gdi_sw_display( struct sw_winsys *winsys, struct sw_displaytarget *dt, @@ -212,6 +235,8 @@ gdi_create_sw_winsys(void) winsys->destroy = gdi_sw_destroy; winsys->is_displaytarget_format_supported = gdi_sw_is_displaytarget_format_supported; winsys->displaytarget_create = gdi_sw_displaytarget_create; + winsys->displaytarget_from_handle = gdi_sw_displaytarget_from_handle; + winsys->displaytarget_get_handle = gdi_sw_displaytarget_get_handle; winsys->displaytarget_map = gdi_sw_displaytarget_map; winsys->displaytarget_unmap = gdi_sw_displaytarget_unmap; winsys->displaytarget_display = gdi_sw_displaytarget_display; diff --git a/src/gallium/winsys/null/null_sw_winsys.c b/src/gallium/winsys/null/null_sw_winsys.c index d961d34860..157efa9973 100644 --- a/src/gallium/winsys/null/null_sw_winsys.c +++ b/src/gallium/winsys/null/null_sw_winsys.c @@ -44,6 +44,7 @@ static boolean null_sw_is_displaytarget_format_supported(struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format ) { return FALSE; @@ -78,6 +79,7 @@ null_sw_displaytarget_destroy(struct sw_winsys *winsys, static struct sw_displaytarget * null_sw_displaytarget_create(struct sw_winsys *winsys, + unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, @@ -87,6 +89,26 @@ null_sw_displaytarget_create(struct sw_winsys *winsys, } +static struct sw_displaytarget * +null_sw_displaytarget_from_handle(struct sw_winsys *winsys, + const struct pipe_resource *templet, + struct winsys_handle *whandle, + unsigned *stride) +{ + return NULL; +} + + +static boolean +null_sw_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + assert(0); + return FALSE; +} + + static void null_sw_displaytarget_display(struct sw_winsys *winsys, struct sw_displaytarget *dt, @@ -115,6 +137,8 @@ null_sw_create(void) winsys->destroy = null_sw_destroy; winsys->is_displaytarget_format_supported = null_sw_is_displaytarget_format_supported; winsys->displaytarget_create = null_sw_displaytarget_create; + winsys->displaytarget_from_handle = null_sw_displaytarget_from_handle; + winsys->displaytarget_get_handle = null_sw_displaytarget_get_handle; winsys->displaytarget_map = null_sw_displaytarget_map; winsys->displaytarget_unmap = null_sw_displaytarget_unmap; winsys->displaytarget_display = null_sw_displaytarget_display; diff --git a/src/gallium/winsys/xlib/xlib_sw_winsys.c b/src/gallium/winsys/xlib/xlib_sw_winsys.c index cecfa4a53d..c4782e1a3c 100644 --- a/src/gallium/winsys/xlib/xlib_sw_winsys.c +++ b/src/gallium/winsys/xlib/xlib_sw_winsys.c @@ -49,7 +49,7 @@ #include <X11/extensions/XShm.h> /** - * Subclass of pipe_buffer for Xlib winsys. + * Display target for Xlib winsys. * Low-level OS/window system memory buffer */ struct xm_displaytarget @@ -208,6 +208,7 @@ alloc_ximage(struct xm_displaytarget *xm_dt, static boolean xm_is_displaytarget_format_supported( struct sw_winsys *ws, + unsigned tex_usage, enum pipe_format format ) { /* TODO: check visuals or other sensible thing here */ @@ -358,6 +359,7 @@ xm_displaytarget_display(struct sw_winsys *ws, static struct sw_displaytarget * xm_displaytarget_create(struct sw_winsys *winsys, + unsigned tex_usage, enum pipe_format format, unsigned width, unsigned height, unsigned alignment, @@ -406,6 +408,27 @@ no_xm_dt: } +static struct sw_displaytarget * +xm_displaytarget_from_handle(struct sw_winsys *winsys, + const struct pipe_resource *templet, + struct winsys_handle *whandle, + unsigned *stride) +{ + assert(0); + return NULL; +} + + +static boolean +xm_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + assert(0); + return FALSE; +} + + static void xm_destroy( struct sw_winsys *ws ) { @@ -428,6 +451,8 @@ xlib_create_sw_winsys( Display *display ) ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported; ws->base.displaytarget_create = xm_displaytarget_create; + ws->base.displaytarget_from_handle = xm_displaytarget_from_handle; + ws->base.displaytarget_get_handle = xm_displaytarget_get_handle; ws->base.displaytarget_map = xm_displaytarget_map; ws->base.displaytarget_unmap = xm_displaytarget_unmap; ws->base.displaytarget_destroy = xm_displaytarget_destroy; diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c index 1b94a56fd1..3db2d63f1f 100644 --- a/src/glx/drisw_glx.c +++ b/src/glx/drisw_glx.c @@ -85,11 +85,14 @@ XCreateDrawable(__GLXDRIdrawablePrivate * pdp, visMask = (VisualScreenMask | VisualIDMask); pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals); - pdp->ximage = XCreateImage(dpy, pdp->visinfo->visual, pdp->visinfo->depth, ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 32, /* bitmap_pad */ - 0); /* bytes_per_line */ + pdp->ximage = XCreateImage(dpy, + pdp->visinfo->visual, + pdp->visinfo->depth, + ZPixmap, 0, /* format, offset */ + NULL, /* data */ + 0, 0, /* size */ + 32, /* bitmap_pad */ + 0); /* bytes_per_line */ /* get the true number of bits per pixel */ pdp->bpp = pdp->ximage->bits_per_pixel; @@ -334,10 +337,17 @@ driCreateDrawable(__GLXscreenConfigs * psc, return pdraw; } -static void -driSwapBuffers(__GLXDRIdrawable * pdraw) +static int64_t +driSwapBuffers(__GLXDRIdrawable * pdraw, + int64_t target_msc, int64_t divisor, int64_t remainder) { + (void) target_msc; + (void) divisor; + (void) remainder; + (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable); + + return 0; } static void diff --git a/src/mesa/SConscript b/src/mesa/SConscript index 86da6f58bd..c85085434e 100644 --- a/src/mesa/SConscript +++ b/src/mesa/SConscript @@ -182,6 +182,7 @@ if env['platform'] != 'winddk': 'state_tracker/st_format.c', 'state_tracker/st_framebuffer.c', 'state_tracker/st_gen_mipmap.c', + 'state_tracker/st_manager.c', 'state_tracker/st_mesa_to_tgsi.c', 'state_tracker/st_program.c', 'state_tracker/st_texture.c', diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c index b97b760f18..84a2a5fcb3 100644 --- a/src/mesa/drivers/common/meta.c +++ b/src/mesa/drivers/common/meta.c @@ -429,13 +429,15 @@ _mesa_meta_begin(GLcontext *ctx, GLbitfield state) if (state & META_SHADER) { if (ctx->Extensions.ARB_vertex_program) { save->VertexProgramEnabled = ctx->VertexProgram.Enabled; - save->VertexProgram = ctx->VertexProgram.Current; + _mesa_reference_vertprog(ctx, &save->VertexProgram, + ctx->VertexProgram.Current); _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE); } if (ctx->Extensions.ARB_fragment_program) { save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled; - save->FragmentProgram = ctx->FragmentProgram.Current; + _mesa_reference_fragprog(ctx, &save->FragmentProgram, + ctx->FragmentProgram.Current); _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); } @@ -663,6 +665,7 @@ _mesa_meta_end(GLcontext *ctx) save->VertexProgramEnabled); _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, save->VertexProgram); + _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL); } if (ctx->Extensions.ARB_fragment_program) { @@ -670,6 +673,7 @@ _mesa_meta_end(GLcontext *ctx) save->FragmentProgramEnabled); _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, save->FragmentProgram); + _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); } if (ctx->Extensions.ARB_shader_objects) { @@ -720,6 +724,7 @@ _mesa_meta_end(GLcontext *ctx) for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt], save->CurrentTexture[tgt]); + _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL); } /* Re-enable textures, texgen */ @@ -2062,8 +2067,10 @@ _mesa_meta_Bitmap(GLcontext *ctx, } bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1); - if (!bitmap1) + if (!bitmap1) { + _mesa_meta_end(ctx); return; + } bitmap8 = (GLubyte *) calloc(1, width * height); if (bitmap8) { diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 75c98825b7..badbb5ff82 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -47,28 +47,6 @@ const __DRIextension driReadDrawableExtension = { __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION }; -/** - * Print message to \c stderr if the \c LIBGL_DEBUG environment variable - * is set. - * - * Is called from the drivers. - * - * \param f \c printf like format string. - */ -void -__driUtilMessage(const char *f, ...) -{ - va_list args; - - if (getenv("LIBGL_DEBUG")) { - fprintf(stderr, "libGL: "); - va_start(args, f); - vfprintf(stderr, f, args); - va_end(args); - fprintf(stderr, "\n"); - } -} - GLint driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ) { diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index 99c0f1e442..f63583cebc 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -552,10 +552,6 @@ struct __DRIscreenRec { }; extern void -__driUtilMessage(const char *f, ...); - - -extern void __driUtilUpdateDrawableInfo(__DRIdrawable *pdp); extern float diff --git a/src/mesa/drivers/dri/common/drisw_util.c b/src/mesa/drivers/dri/common/drisw_util.c new file mode 100644 index 0000000000..141ca302d0 --- /dev/null +++ b/src/mesa/drivers/dri/common/drisw_util.c @@ -0,0 +1,267 @@ +/* + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <gsapountzis@gmail.com> + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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. + */ + +/** + * \file drisw_util.c + * + * DRISW utility functions, i.e. dri_util.c stripped from drm-specific bits. + */ + +#include "drisw_util.h" +#include "utils.h" + + +/** + * Screen functions + */ + +static void +setupLoaderExtensions(__DRIscreen *psp, + const __DRIextension **extensions) +{ + int i; + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) + psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; + } +} + +static __DRIscreen * +driCreateNewScreen(int scrn, const __DRIextension **extensions, + const __DRIconfig ***driver_configs, void *data) +{ + static const __DRIextension *emptyExtensionList[] = { NULL }; + __DRIscreen *psp; + + (void) data; + + psp = CALLOC_STRUCT(__DRIscreenRec); + if (!psp) + return NULL; + + setupLoaderExtensions(psp, extensions); + + psp->extensions = emptyExtensionList; + psp->myNum = scrn; + + *driver_configs = driDriverAPI.InitScreen(psp); + + if (*driver_configs == NULL) { + FREE(psp); + return NULL; + } + + return psp; +} + +static void driDestroyScreen(__DRIscreen *psp) +{ + if (psp) { + driDriverAPI.DestroyScreen(psp); + + FREE(psp); + } +} + +static const __DRIextension **driGetExtensions(__DRIscreen *psp) +{ + return psp->extensions; +} + + +/** + * Context functions + */ + +static __DRIcontext * +driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, + __DRIcontext *shared, void *data) +{ + __DRIcontext *pcp; + void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + + pcp = CALLOC_STRUCT(__DRIcontextRec); + if (!pcp) + return NULL; + + pcp->loaderPrivate = data; + + pcp->driScreenPriv = psp; + pcp->driDrawablePriv = NULL; + pcp->driReadablePriv = NULL; + + if (!driDriverAPI.CreateContext(&config->modes, pcp, shareCtx)) { + FREE(pcp); + return NULL; + } + + return pcp; +} + +static void +driDestroyContext(__DRIcontext *pcp) +{ + if (pcp) { + driDriverAPI.DestroyContext(pcp); + FREE(pcp); + } +} + +static int +driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask) +{ + return GL_FALSE; +} + +static void dri_get_drawable(__DRIdrawable *pdp); +static void dri_put_drawable(__DRIdrawable *pdp); + +static int driBindContext(__DRIcontext *pcp, + __DRIdrawable *pdp, + __DRIdrawable *prp) +{ + /* Bind the drawable to the context */ + if (pcp) { + pcp->driDrawablePriv = pdp; + pcp->driReadablePriv = prp; + if (pdp) { + dri_get_drawable(pdp); + } + if ( prp && pdp != prp ) { + dri_get_drawable(prp); + } + } + + return driDriverAPI.MakeCurrent(pcp, pdp, prp); +} + +static int driUnbindContext(__DRIcontext *pcp) +{ + __DRIdrawable *pdp; + __DRIdrawable *prp; + + if (pcp == NULL) + return GL_FALSE; + + pdp = pcp->driDrawablePriv; + prp = pcp->driReadablePriv; + + /* already unbound */ + if (!pdp && !prp) + return GL_TRUE; + + driDriverAPI.UnbindContext(pcp); + + dri_put_drawable(pdp); + + if (prp != pdp) { + dri_put_drawable(prp); + } + + pcp->driDrawablePriv = NULL; + pcp->driReadablePriv = NULL; + + return GL_TRUE; +} + + +/** + * Drawable functions + */ + +static void dri_get_drawable(__DRIdrawable *pdp) +{ + pdp->refcount++; +} + +static void dri_put_drawable(__DRIdrawable *pdp) +{ + if (pdp) { + pdp->refcount--; + if (pdp->refcount) + return; + + driDriverAPI.DestroyBuffer(pdp); + + FREE(pdp); + } +} + +static __DRIdrawable * +driCreateNewDrawable(__DRIscreen *psp, + const __DRIconfig *config, void *data) +{ + __DRIdrawable *pdp; + + pdp = CALLOC_STRUCT(__DRIdrawableRec); + if (!pdp) + return NULL; + + pdp->loaderPrivate = data; + + pdp->driScreenPriv = psp; + + dri_get_drawable(pdp); + + if (!driDriverAPI.CreateBuffer(psp, pdp, &config->modes, GL_FALSE)) { + FREE(pdp); + return NULL; + } + + return pdp; +} + +static void +driDestroyDrawable(__DRIdrawable *pdp) +{ + dri_put_drawable(pdp); +} + +static void driSwapBuffers(__DRIdrawable *pdp) +{ + driDriverAPI.SwapBuffers(pdp); +} + +const __DRIcoreExtension driCoreExtension = { + { __DRI_CORE, __DRI_CORE_VERSION }, + NULL, /* driCreateNewScreen */ + driDestroyScreen, + driGetExtensions, + driGetConfigAttrib, + driIndexConfigAttrib, + NULL, /* driCreateNewDrawable */ + driDestroyDrawable, + driSwapBuffers, + driCreateNewContext, + driCopyContext, + driDestroyContext, + driBindContext, + driUnbindContext +}; + +const __DRIswrastExtension driSWRastExtension = { + { __DRI_SWRAST, __DRI_SWRAST_VERSION }, + driCreateNewScreen, + driCreateNewDrawable +}; diff --git a/src/mesa/drivers/dri/common/drisw_util.h b/src/mesa/drivers/dri/common/drisw_util.h new file mode 100644 index 0000000000..e353e26b34 --- /dev/null +++ b/src/mesa/drivers/dri/common/drisw_util.h @@ -0,0 +1,112 @@ +/* + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <gsapountzis@gmail.com> + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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 _DRI_SW_H +#define _DRI_SW_H + +#include <GL/gl.h> +#include <GL/internal/glcore.h> +#include <GL/internal/dri_interface.h> + + +/** + * Extensions + */ +extern const __DRIcoreExtension driCoreExtension; +extern const __DRIswrastExtension driSWRastExtension; + + +/** + * Data types + */ +struct __DRIscreenRec { + int myNum; + + int fd; + + void *private; + + const __DRIextension **extensions; + + const __DRIswrastLoaderExtension *swrast_loader; +}; + +struct __DRIcontextRec { + + void *driverPrivate; + + void *loaderPrivate; + + __DRIdrawable *driDrawablePriv; + + __DRIdrawable *driReadablePriv; + + __DRIscreen *driScreenPriv; +}; + +struct __DRIdrawableRec { + + void *driverPrivate; + + void *loaderPrivate; + + __DRIscreen *driScreenPriv; + + int refcount; +}; + + +/** + * Driver callback functions + */ +struct __DriverAPIRec { + const __DRIconfig **(*InitScreen) (__DRIscreen * priv); + + void (*DestroyScreen)(__DRIscreen *driScrnPriv); + + GLboolean (*CreateContext)(const __GLcontextModes *glVis, + __DRIcontext *driContextPriv, + void *sharedContextPrivate); + + void (*DestroyContext)(__DRIcontext *driContextPriv); + + GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv, + __DRIdrawable *driDrawPriv, + const __GLcontextModes *glVis, + GLboolean pixmapBuffer); + + void (*DestroyBuffer)(__DRIdrawable *driDrawPriv); + + void (*SwapBuffers)(__DRIdrawable *driDrawPriv); + + GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv, + __DRIdrawable *driDrawPriv, + __DRIdrawable *driReadPriv); + + GLboolean (*UnbindContext)(__DRIcontext *driContextPriv); +}; + +extern const struct __DriverAPIRec driDriverAPI; + +#endif /* _DRI_SW_H */ diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c index b85b364c57..0dd879abc9 100644 --- a/src/mesa/drivers/dri/common/utils.c +++ b/src/mesa/drivers/dri/common/utils.c @@ -37,6 +37,29 @@ #include "utils.h" +/** + * Print message to \c stderr if the \c LIBGL_DEBUG environment variable + * is set. + * + * Is called from the drivers. + * + * \param f \c printf like format string. + */ +void +__driUtilMessage(const char *f, ...) +{ + va_list args; + + if (getenv("LIBGL_DEBUG")) { + fprintf(stderr, "libGL: "); + va_start(args, f); + vfprintf(stderr, f, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + + unsigned driParseDebugString( const char * debug, const struct dri_debug_control * control ) @@ -230,9 +253,6 @@ void driInitSingleExtension( GLcontext * ctx, /** * Utility function used by drivers to test the verions of other components. * - * If one of the version requirements is not met, a message is logged using - * \c __driUtilMessage. - * * \param driver_name Name of the driver. Used in error messages. * \param driActual Actual DRI version supplied __driCreateNewScreen. * \param driExpected Minimum DRI version required by the driver. @@ -244,7 +264,7 @@ void driInitSingleExtension( GLcontext * ctx, * \returns \c GL_TRUE if all version requirements are met. Otherwise, * \c GL_FALSE is returned. * - * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage + * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2 * * \todo * Now that the old \c driCheckDriDdxDrmVersions function is gone, this diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h index 02ca3feb73..de6070c398 100644 --- a/src/mesa/drivers/dri/common/utils.h +++ b/src/mesa/drivers/dri/common/utils.h @@ -69,6 +69,9 @@ struct __DRIutilversionRec2 { int patch; /**< Patch-level. */ }; +extern void +__driUtilMessage(const char *f, ...); + extern unsigned driParseDebugString( const char * debug, const struct dri_debug_control * control ); diff --git a/src/mesa/drivers/dri/common/xmlconfig.c b/src/mesa/drivers/dri/common/xmlconfig.c index 477259ea7e..de4500a39b 100644 --- a/src/mesa/drivers/dri/common/xmlconfig.c +++ b/src/mesa/drivers/dri/common/xmlconfig.c @@ -36,7 +36,7 @@ #include <unistd.h> #include <errno.h> #include "main/imports.h" -#include "dri_util.h" +#include "utils.h" #include "xmlconfig.h" #undef GET_PROGRAM_NAME diff --git a/src/mesa/drivers/dri/i915/i830_texstate.c b/src/mesa/drivers/dri/i915/i830_texstate.c index e8f7e378ec..a28073919c 100644 --- a/src/mesa/drivers/dri/i915/i830_texstate.c +++ b/src/mesa/drivers/dri/i915/i830_texstate.c @@ -146,15 +146,15 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) dri_bo_reference(intelObj->mt->region->buffer); i830->state.tex_buffer[unit] = intelObj->mt->region->buffer; + pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; + /* XXX: This calculation is probably broken for tiled images with * a non-page-aligned offset. */ - i830->state.tex_offset[unit] = (dst_x + dst_y * intelObj->mt->pitch) * - intelObj->mt->cpp; + i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch; format = translate_texture_format(firstImage->TexFormat, firstImage->InternalFormat); - pitch = intelObj->mt->pitch * intelObj->mt->cpp; state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | (LOAD_TEXTURE_MAP0 << unit) | 4); diff --git a/src/mesa/drivers/dri/i915/i915_tex_layout.c b/src/mesa/drivers/dri/i915/i915_tex_layout.c index fe3908f580..702655283b 100644 --- a/src/mesa/drivers/dri/i915/i915_tex_layout.c +++ b/src/mesa/drivers/dri/i915/i915_tex_layout.c @@ -123,13 +123,12 @@ i915_miptree_layout_cube(struct intel_context *intel, assert(lvlWidth == lvlHeight); /* cubemap images are square */ /* double pitch for cube layouts */ - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2); + mt->total_width = dim * 2; mt->total_height = dim * 4; for (level = mt->first_level; level <= mt->last_level; level++) { intel_miptree_set_level_info(mt, level, 6, 0, 0, - /*OLD: mt->pitch, mt->total_height,*/ lvlWidth, lvlHeight, 1); lvlWidth /= 2; @@ -167,7 +166,7 @@ i915_miptree_layout_3d(struct intel_context *intel, GLint level; /* Calculate the size of a single slice. */ - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); + mt->total_width = mt->width0; /* XXX: hardware expects/requires 9 levels at minimum. */ for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) { @@ -210,7 +209,7 @@ i915_miptree_layout_2d(struct intel_context *intel, GLuint img_height; GLint level; - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); + mt->total_width = mt->width0; mt->total_height = 0; for (level = mt->first_level; level <= mt->last_level; level++) { @@ -251,9 +250,8 @@ i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt, 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); + DBG("%s: %dx%dx%d\n", __FUNCTION__, + mt->total_width, mt->total_height, mt->cpp); return GL_TRUE; } @@ -336,9 +334,9 @@ i945_miptree_layout_cube(struct intel_context *intel, * or the final row of 4x4, 2x2 and 1x1 faces below this. */ if (dim > 32) - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2); + mt->total_width = dim * 2; else - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, 14 * 8); + mt->total_width = 14 * 8; if (dim >= 4) mt->total_height = dim * 4 + 4; @@ -423,11 +421,11 @@ i945_miptree_layout_3d(struct intel_context *intel, GLuint pack_y_pitch; GLuint level; - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); + mt->total_width = mt->width0; mt->total_height = 0; pack_y_pitch = MAX2(mt->height0, 2); - pack_x_pitch = mt->pitch; + pack_x_pitch = mt->total_width; pack_x_nr = 1; for (level = mt->first_level; level <= mt->last_level; level++) { @@ -454,7 +452,7 @@ i945_miptree_layout_3d(struct intel_context *intel, if (pack_x_pitch > 4) { pack_x_pitch >>= 1; pack_x_nr <<= 1; - assert(pack_x_pitch * pack_x_nr <= mt->pitch); + assert(pack_x_pitch * pack_x_nr <= mt->total_width); } if (pack_y_pitch > 2) { @@ -491,9 +489,8 @@ i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt, 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); + DBG("%s: %dx%dx%d\n", __FUNCTION__, + mt->total_width, mt->total_height, mt->cpp); return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c index a1ab8f8b6d..ff9ab88c5a 100644 --- a/src/mesa/drivers/dri/i915/i915_texstate.c +++ b/src/mesa/drivers/dri/i915/i915_texstate.c @@ -165,7 +165,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) format = translate_texture_format(firstImage->TexFormat, firstImage->InternalFormat, tObj->DepthMode); - pitch = intelObj->mt->pitch * intelObj->mt->cpp; + pitch = intelObj->mt->region->pitch * intelObj->mt->cpp; state[I915_TEXREG_MS3] = (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index 09edfd81fd..b1f56a8e64 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -58,12 +58,12 @@ GLboolean brw_miptree_layout(struct intel_context *intel, GLuint qpitch = 0; GLuint y_pitch = 0; - mt->pitch = mt->width0; + mt->total_width = mt->width0; intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h); y_pitch = ALIGN(height, align_h); if (mt->compressed) { - mt->pitch = ALIGN(mt->width0, align_w); + mt->total_width = ALIGN(mt->width0, align_w); } if (mt->first_level != mt->last_level) { @@ -77,13 +77,11 @@ GLboolean brw_miptree_layout(struct intel_context *intel, + minify(minify(mt->width0)); } - if (mip1_width > mt->pitch) { - mt->pitch = mip1_width; + if (mip1_width > mt->total_width) { + mt->total_width = mip1_width; } } - mt->pitch = intel_miptree_pitch_align(intel, mt, tiling, mt->pitch); - if (mt->compressed) { qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4; mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6; @@ -137,10 +135,10 @@ GLboolean brw_miptree_layout(struct intel_context *intel, intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h); if (mt->compressed) { - mt->pitch = ALIGN(width, align_w); + mt->total_width = ALIGN(width, align_w); pack_y_pitch = (height + 3) / 4; } else { - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0); + mt->total_width = mt->width0; pack_y_pitch = ALIGN(mt->height0, align_h); } @@ -184,7 +182,7 @@ GLboolean brw_miptree_layout(struct intel_context *intel, if (pack_x_pitch > 4) { pack_x_pitch >>= 1; pack_x_nr <<= 1; - assert(pack_x_pitch * pack_x_nr <= mt->pitch); + assert(pack_x_pitch * pack_x_nr <= mt->total_width); } if (pack_y_pitch > 2) { @@ -211,11 +209,8 @@ GLboolean brw_miptree_layout(struct intel_context *intel, i945_miptree_layout_2d(intel, mt, tiling); 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 ); + DBG("%s: %dx%dx%d\n", __FUNCTION__, + mt->total_width, mt->total_height, mt->cpp); return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index d16e916832..14c3b936b7 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -384,8 +384,9 @@ static void emit_sop( struct brw_vs_compile *c, { struct brw_compile *p = &c->func; - brw_CMP(p, brw_null_reg(), cond, arg1, arg0); - brw_SEL(p, dst, brw_null_reg(), brw_imm_f(1.0f)); + brw_MOV(p, dst, brw_imm_f(0.0f)); + brw_CMP(p, brw_null_reg(), cond, arg0, arg1); + brw_MOV(p, dst, brw_imm_f(1.0f)); brw_set_predicate_control_flag_value(p, 0xff); } diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c index 05e464d4b6..1869fd06d5 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_emit.c +++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c @@ -545,8 +545,11 @@ void emit_sop(struct brw_compile *p, for (i = 0; i < 4; i++) { if (mask & (1<<i)) { brw_push_insn_state(p); - brw_CMP(p, brw_null_reg(), cond, arg1[i], arg0[i]); - brw_SEL(p, dst[i], brw_null_reg(), brw_imm_f(1.0)); + brw_CMP(p, brw_null_reg(), cond, arg0[i], arg1[i]); + brw_set_predicate_control(p, BRW_PREDICATE_NONE); + brw_MOV(p, dst[i], brw_imm_f(0)); + brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); + brw_MOV(p, dst[i], brw_imm_f(1.0)); brw_pop_insn_state(p); } } diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index ce0bf0b97d..6b9e566886 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -261,7 +261,7 @@ brw_update_texture_surface( GLcontext *ctx, GLuint unit ) key.format = firstImage->TexFormat; key.internal_format = firstImage->InternalFormat; - key.pitch = intelObj->mt->pitch; + key.pitch = intelObj->mt->region->pitch; key.depth = firstImage->Depth; key.bo = intelObj->mt->region->buffer; key.offset = 0; diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index f2769aa3e8..4617370339 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -121,22 +121,8 @@ intelEmitCopyBlit(struct intel_context *intel, intel_prepare_render(intel); - if (pass >= 2) { - drm_intel_gem_bo_map_gtt(dst_buffer); - drm_intel_gem_bo_map_gtt(src_buffer); - _mesa_copy_rect((GLubyte *)dst_buffer->virtual + dst_offset, - cpp, - dst_pitch, - dst_x, dst_y, - w, h, - (GLubyte *)src_buffer->virtual + src_offset, - src_pitch, - src_x, src_y); - drm_intel_gem_bo_unmap_gtt(src_buffer); - drm_intel_gem_bo_unmap_gtt(dst_buffer); - - return GL_TRUE; - } + if (pass >= 2) + return GL_FALSE; intel_batchbuffer_require_space(intel->batch, 8 * 4); DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", @@ -482,6 +468,7 @@ intel_emit_linear_blit(struct intel_context *intel, unsigned int size) { GLuint pitch, height; + GLboolean ok; /* Blits are in a different ringbuffer so we don't use them. */ assert(intel->gen < 6); @@ -489,25 +476,27 @@ intel_emit_linear_blit(struct intel_context *intel, /* The pitch is a signed value. */ pitch = MIN2(size, (1 << 15) - 1); height = size / pitch; - intelEmitCopyBlit(intel, 1, - pitch, src_bo, src_offset, I915_TILING_NONE, - pitch, dst_bo, dst_offset, I915_TILING_NONE, - 0, 0, /* src x/y */ - 0, 0, /* dst x/y */ - pitch, height, /* w, h */ - GL_COPY); + ok = intelEmitCopyBlit(intel, 1, + pitch, src_bo, src_offset, I915_TILING_NONE, + pitch, dst_bo, dst_offset, I915_TILING_NONE, + 0, 0, /* src x/y */ + 0, 0, /* dst x/y */ + pitch, height, /* w, h */ + GL_COPY); + assert(ok); src_offset += pitch * height; dst_offset += pitch * height; size -= pitch * height; assert (size < (1 << 15)); if (size != 0) { - intelEmitCopyBlit(intel, 1, - size, src_bo, src_offset, I915_TILING_NONE, - size, dst_bo, dst_offset, I915_TILING_NONE, - 0, 0, /* src x/y */ - 0, 0, /* dst x/y */ - size, 1, /* w, h */ - GL_COPY); + ok = intelEmitCopyBlit(intel, 1, + size, src_bo, src_offset, I915_TILING_NONE, + size, dst_bo, dst_offset, I915_TILING_NONE, + 0, 0, /* src x/y */ + 0, 0, /* dst x/y */ + size, 1, /* w, h */ + GL_COPY); + assert(ok); } } diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index d6a1ba6952..c86dd1d0d9 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -880,12 +880,12 @@ intelMakeCurrent(__DRIcontext * driContextPriv, struct gl_framebuffer *fb = driDrawPriv->driverPrivate; struct gl_framebuffer *readFb = driReadPriv->driverPrivate; - _mesa_make_current(&intel->ctx, fb, readFb); intel->driReadDrawable = driReadPriv; intel->driDrawable = driDrawPriv; driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; intel_prepare_render(intel); + _mesa_make_current(&intel->ctx, fb, readFb); } else { _mesa_make_current(NULL, NULL, NULL); diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index a429f8d003..8278d12bb9 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -104,7 +104,6 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, struct intel_context *intel = intel_context(ctx); struct intel_renderbuffer *irb = intel_renderbuffer(rb); int cpp; - GLuint pitch; ASSERT(rb->Name != 0); @@ -176,15 +175,11 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, /* allocate new memory region/renderbuffer */ - /* Choose a pitch to match hardware requirements: - */ - pitch = ((cpp * width + 63) & ~63) / cpp; - /* alloc hardware renderbuffer */ - DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width, height, pitch); + DBG("Allocating %d x %d Intel RBO\n", width, height); irb->region = intel_region_alloc(intel, I915_TILING_NONE, cpp, - width, height, pitch, GL_TRUE); + width, height, GL_TRUE); if (!irb->region) return GL_FALSE; /* out of memory? */ @@ -573,7 +568,7 @@ intel_render_texture(GLcontext * ctx, att->Zoffset, &dst_x, &dst_y); - intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->pitch + + intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->region->pitch + dst_x) * intel_image->mt->cpp; intel_image->mt->region->draw_x = dst_x; intel_image->mt->region->draw_y = dst_y; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 4f14946ec7..e671355c38 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -83,7 +83,6 @@ intel_miptree_create_internal(struct intel_context *intel, mt->cpp = compress_byte ? compress_byte : cpp; mt->compressed = compress_byte ? 1 : 0; mt->refcount = 1; - mt->pitch = 0; #ifdef I915 if (intel->is_945) @@ -136,7 +135,7 @@ intel_miptree_create(struct intel_context *intel, /* * pitch == 0 || height == 0 indicates the null texture */ - if (!mt || !mt->pitch || !mt->total_height) { + if (!mt || !mt->total_height) { free(mt); return NULL; } @@ -144,9 +143,8 @@ intel_miptree_create(struct intel_context *intel, mt->region = intel_region_alloc(intel, tiling, mt->cpp, - mt->pitch, + mt->total_width, mt->total_height, - mt->pitch, expect_accelerated_upload); if (!mt->region) { @@ -177,81 +175,12 @@ intel_miptree_create_for_region(struct intel_context *intel, I915_TILING_NONE); if (!mt) return mt; -#if 0 - if (mt->pitch != region->pitch) { - fprintf(stderr, - "region pitch (%d) doesn't match mipmap tree pitch (%d)\n", - region->pitch, mt->pitch); - free(mt); - return NULL; - } -#else - /* The mipmap tree pitch is aligned to 64 bytes to make sure render - * to texture works, but we don't need that for texturing from a - * pixmap. Just override it here. */ - mt->pitch = region->pitch; -#endif intel_region_reference(&mt->region, region); return mt; } - -/** - * intel_miptree_pitch_align: - * - * @intel: intel context pointer - * - * @mt: the miptree to compute pitch alignment for - * - * @pitch: the natural pitch value - * - * Given @pitch, compute a larger value which accounts for - * any necessary alignment required by the device - */ -int intel_miptree_pitch_align (struct intel_context *intel, - struct intel_mipmap_tree *mt, - uint32_t tiling, - int pitch) -{ -#ifdef I915 - GLcontext *ctx = &intel->ctx; -#endif - - if (!mt->compressed) { - int pitch_align; - - /* XXX: Align pitch to multiple of 64 bytes for now to allow - * render-to-texture to work in all cases. This should probably be - * replaced at some point by some scheme to only do this when really - * necessary. - */ - pitch_align = 64; - - if (tiling == I915_TILING_X) - pitch_align = 512; - else if (tiling == I915_TILING_Y) - pitch_align = 128; - - pitch = ALIGN(pitch * mt->cpp, pitch_align); - -#ifdef I915 - /* Do a little adjustment to linear allocations so that we avoid - * hitting the same channel of memory for 2 different pages when - * reading a 2x2 subspan or doing bilinear filtering. - */ - if (tiling == I915_TILING_NONE && !(pitch & 511) && - (pitch + pitch_align) < (1 << ctx->Const.MaxTextureLevels)) - pitch += pitch_align; -#endif - - pitch /= mt->cpp; - } - return pitch; -} - - void intel_miptree_reference(struct intel_mipmap_tree **dst, struct intel_mipmap_tree *src) @@ -351,13 +280,12 @@ intel_miptree_set_level_info(struct intel_mipmap_tree *mt, mt->level[level].width = w; mt->level[level].height = h; mt->level[level].depth = d; - mt->level[level].level_offset = (x + y * mt->pitch) * mt->cpp; mt->level[level].level_x = x; mt->level[level].level_y = y; mt->level[level].nr_images = nr_images; - DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, - level, w, h, d, x, y, mt->level[level].level_offset); + DBG("%s level %d size: %d,%d,%d offset %d,%d\n", __FUNCTION__, + level, w, h, d, x, y); assert(nr_images); assert(!mt->level[level].x_offset); @@ -424,7 +352,7 @@ intel_miptree_image_map(struct intel_context * intel, DBG("%s \n", __FUNCTION__); if (row_stride) - *row_stride = mt->pitch * mt->cpp; + *row_stride = mt->region->pitch * mt->cpp; if (mt->target == GL_TEXTURE_3D) { int i; @@ -433,7 +361,7 @@ intel_miptree_image_map(struct intel_context * intel, intel_miptree_get_image_offset(mt, level, face, i, &x, &y); - image_offsets[i] = x + y * mt->pitch; + image_offsets[i] = x + y * mt->region->pitch; } return intel_region_map(intel, mt->region); @@ -444,7 +372,7 @@ intel_miptree_image_map(struct intel_context * intel, image_offsets[0] = 0; return intel_region_map(intel, mt->region) + - (x + y * mt->pitch) * mt->cpp; + (x + y * mt->region->pitch) * mt->cpp; } } @@ -525,7 +453,8 @@ intel_miptree_image_copy(struct intel_context *intel, intel_miptree_get_image_offset(dst, level, face, i, &dst_x, &dst_y); success = intel_region_copy(intel, dst->region, 0, dst_x, dst_y, - src->region, 0, src_x, src_y, width, height, + src->region, 0, src_x, src_y, + width, height, GL_FALSE, GL_COPY); if (!success) { GLubyte *src_ptr, *dst_ptr; @@ -533,13 +462,13 @@ intel_miptree_image_copy(struct intel_context *intel, src_ptr = intel_region_map(intel, src->region); dst_ptr = intel_region_map(intel, dst->region); - _mesa_copy_rect(dst_ptr + dst->cpp * (dst_x + dst_y * dst->pitch), + _mesa_copy_rect(dst_ptr, dst->cpp, - dst->pitch, - 0, 0, width, height, - src_ptr + src->cpp * (src_x + src_y * src->pitch), - src->pitch, - 0, 0); + dst->region->pitch, + dst_x, dst_y, width, height, + src_ptr, + src->region->pitch, + src_x, src_y); intel_region_unmap(intel, src->region); intel_region_unmap(intel, dst->region); } diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index b19c548def..21db2f4d3b 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -62,14 +62,6 @@ */ struct intel_mipmap_level { - /** - * Byte offset to the base of this level. - * - * This is used for mipmap levels of 1D/2D/3D textures. However, CUBE - * layouts spread images around the whole tree, so the level offset is - * always zero in that case. - */ - GLuint level_offset; /** Offset to this miptree level, used in computing x_offset. */ GLuint level_x; /** Offset to this miptree level, used in computing y_offset. */ @@ -81,8 +73,8 @@ struct intel_mipmap_level /** Number of images at this level: 1 for 1D/2D, 6 for CUBE, depth for 3D */ GLuint nr_images; - /** - * Byte offset from level_offset to the image for each cube face or depth + /** @{ + * offsets from level_[xy] to the image for each cube face or depth * level. * * Pretty much have to accept that hardware formats @@ -91,6 +83,7 @@ struct intel_mipmap_level * so have to store them as a lookup table. */ GLuint *x_offset, *y_offset; + /** @} */ }; struct intel_mipmap_tree @@ -109,8 +102,7 @@ struct intel_mipmap_tree /* Derived from the above: */ - GLuint pitch; - GLuint depth_pitch; /* per-image on i945? */ + GLuint total_width; GLuint total_height; /* Includes image offset tables: diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c index f4f3fd6d88..8efb7a60c2 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c @@ -116,6 +116,7 @@ do_blit_copypixels(GLcontext * ctx, GLint orig_dsty; GLint orig_srcx; GLint orig_srcy; + GLboolean flip = GL_FALSE; if (type == GL_DEPTH || type == GL_STENCIL) { if (INTEL_DEBUG & DEBUG_FALLBACKS) @@ -140,8 +141,6 @@ do_blit_copypixels(GLcontext * ctx, intel_prepare_render(intel); - /* XXX: We fail to handle different inversion between read and draw framebuffer. */ - /* Clip to destination buffer. */ orig_dstx = dstx; orig_dsty = dsty; @@ -164,23 +163,23 @@ do_blit_copypixels(GLcontext * ctx, dstx += srcx - orig_srcx; dsty += srcy - orig_srcy; - /* Convert from GL to hardware coordinates: */ + /* Flip dest Y if it's a window system framebuffer. */ if (fb->Name == 0) { - /* copypixels to a system framebuffer */ + /* copypixels to a window system framebuffer */ dsty = fb->Height - dsty - height; - } else { - /* copypixels to a user framebuffer object */ - dsty = dsty; + flip = !flip; } - /* Flip source Y if it's a system framebuffer. */ - if (read_fb->Name == 0) - srcy = fb->Height - srcy - height; + /* Flip source Y if it's a window system framebuffer. */ + if (read_fb->Name == 0) { + srcy = read_fb->Height - srcy - height; + flip = !flip; + } if (!intel_region_copy(intel, dst, 0, dstx, dsty, src, 0, srcx, srcy, - width, height, + width, height, flip, ctx->Color.ColorLogicOpEnabled ? ctx->Color.LogicOp : GL_COPY)) { DBG("%s: blit failure\n", __FUNCTION__); diff --git a/src/mesa/drivers/dri/intel/intel_regions.c b/src/mesa/drivers/dri/intel/intel_regions.c index f042bcbc28..1172de90b1 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.c +++ b/src/mesa/drivers/dri/intel/intel_regions.c @@ -164,7 +164,6 @@ intel_region_alloc_internal(struct intel_context *intel, /* Default to no tiling */ region->tiling = I915_TILING_NONE; - region->bit_6_swizzle = I915_BIT_6_SWIZZLE_NONE; _DBG("%s <-- %p\n", __FUNCTION__, region); return region; @@ -173,7 +172,7 @@ intel_region_alloc_internal(struct intel_context *intel, struct intel_region * intel_region_alloc(struct intel_context *intel, uint32_t tiling, - GLuint cpp, GLuint width, GLuint height, GLuint pitch, + GLuint cpp, GLuint width, GLuint height, GLboolean expect_accelerated_upload) { dri_bo *buffer; @@ -187,19 +186,10 @@ intel_region_alloc(struct intel_context *intel, buffer = drm_intel_bo_alloc_tiled(intel->bufmgr, "region", width, height, cpp, &tiling, &aligned_pitch, flags); - /* We've already chosen a pitch as part of miptree layout. It had - * better be the same. - */ - assert(aligned_pitch == pitch * cpp); region = intel_region_alloc_internal(intel, cpp, width, height, - pitch, buffer); - - if (tiling != I915_TILING_NONE) { - assert(((pitch * cpp) & 127) == 0); - drm_intel_bo_set_tiling(buffer, &tiling, pitch * cpp); - drm_intel_bo_get_tiling(buffer, ®ion->tiling, ®ion->bit_6_swizzle); - } + aligned_pitch / cpp, buffer); + region->tiling = tiling; return region; } @@ -213,6 +203,7 @@ intel_region_alloc_for_handle(struct intel_context *intel, struct intel_region *region, *dummy; dri_bo *buffer; int ret; + uint32_t bit_6_swizzle; region = _mesa_HashLookup(intel->intelScreen->named_regions, handle); if (region != NULL) { @@ -236,7 +227,7 @@ intel_region_alloc_for_handle(struct intel_context *intel, return region; ret = dri_bo_get_tiling(region->buffer, ®ion->tiling, - ®ion->bit_6_swizzle); + &bit_6_swizzle); if (ret != 0) { fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n", handle, name, strerror(-ret)); @@ -316,7 +307,7 @@ _mesa_copy_rect(GLubyte * dst, dst += dst_x * cpp; src += src_x * cpp; dst += dst_y * dst_pitch; - src += src_y * dst_pitch; + src += src_y * src_pitch; width *= cpp; if (width == dst_pitch && width == src_pitch) @@ -380,8 +371,11 @@ intel_region_copy(struct intel_context *intel, struct intel_region *src, GLuint src_offset, GLuint srcx, GLuint srcy, GLuint width, GLuint height, + GLboolean flip, GLenum logicop) { + uint32_t src_pitch = src->pitch; + _DBG("%s\n", __FUNCTION__); if (intel == NULL) @@ -397,9 +391,12 @@ intel_region_copy(struct intel_context *intel, assert(src->cpp == dst->cpp); + if (flip) + src_pitch = -src_pitch; + return intelEmitCopyBlit(intel, dst->cpp, - src->pitch, src->buffer, src_offset, src->tiling, + src_pitch, src->buffer, src_offset, src->tiling, dst->pitch, dst->buffer, dst_offset, dst->tiling, srcx, srcy, dstx, dsty, width, height, logicop); diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h index 7ee6a988ea..2459c9a924 100644 --- a/src/mesa/drivers/dri/intel/intel_regions.h +++ b/src/mesa/drivers/dri/intel/intel_regions.h @@ -65,7 +65,6 @@ struct intel_region GLuint draw_x, draw_y; /**< Offset of drawing within the region */ uint32_t tiling; /**< Which tiling mode the region is in */ - uint32_t bit_6_swizzle; /**< GEM flag for address swizzling requirement */ struct intel_buffer_object *pbo; /* zero-copy uploads */ uint32_t name; /**< Global name for the bo */ @@ -79,7 +78,7 @@ struct intel_region struct intel_region *intel_region_alloc(struct intel_context *intel, uint32_t tiling, GLuint cpp, GLuint width, - GLuint height, GLuint pitch, + GLuint height, GLboolean expect_accelerated_upload); struct intel_region * @@ -122,6 +121,7 @@ intel_region_copy(struct intel_context *intel, struct intel_region *src, GLuint src_offset, GLuint srcx, GLuint srcy, GLuint width, GLuint height, + GLboolean flip, GLenum logicop); /* Helpers for zerocopy uploads, particularly texture image uploads: diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 6e4bb64365..5e3f40836d 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -312,18 +312,13 @@ intelCreateBuffer(__DRIscreen * driScrnPriv, } if (mesaVis->depthBits == 24) { - if (mesaVis->stencilBits == 8) { - /* combined depth/stencil buffer */ - struct intel_renderbuffer *depthStencilRb - = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); - /* note: bind RB to two attachment points */ - _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); - _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); - } else { - struct intel_renderbuffer *depthRb - = intel_create_renderbuffer(MESA_FORMAT_X8_Z24); - _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); - } + assert(mesaVis->stencilBits == 8); + /* combined depth/stencil buffer */ + struct intel_renderbuffer *depthStencilRb + = intel_create_renderbuffer(MESA_FORMAT_S8_Z24); + /* 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 == 16) { /* just 16-bit depth buffer, no hw stencil */ diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index fb5c01bc4d..c1e15d1b0f 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -48,11 +48,11 @@ intel_set_span_functions(struct intel_context *intel, #define LOCAL_VARS \ struct intel_renderbuffer *irb = intel_renderbuffer(rb); \ - const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \ - const GLint yBias = ctx->DrawBuffer->Name ? 0 : irb->Base.Height - 1;\ + const GLint yScale = rb->Name ? 1 : -1; \ + const GLint yBias = rb->Name ? 0 : rb->Height - 1; \ int minx = 0, miny = 0; \ - int maxx = ctx->DrawBuffer->Width; \ - int maxy = ctx->DrawBuffer->Height; \ + int maxx = rb->Width; \ + int maxy = rb->Height; \ int pitch = irb->region->pitch * irb->region->cpp; \ void *buf = irb->region->buffer->virtual; \ GLuint p; \ @@ -108,11 +108,11 @@ intel_set_span_functions(struct intel_context *intel, #define LOCAL_DEPTH_VARS \ struct intel_renderbuffer *irb = intel_renderbuffer(rb); \ - const GLint yScale = ctx->DrawBuffer->Name ? 1 : -1; \ - const GLint yBias = ctx->DrawBuffer->Name ? 0 : irb->Base.Height - 1;\ + const GLint yScale = rb->Name ? 1 : -1; \ + const GLint yBias = rb->Name ? 0 : rb->Height - 1; \ int minx = 0, miny = 0; \ - int maxx = ctx->DrawBuffer->Width; \ - int maxy = ctx->DrawBuffer->Height; \ + int maxx = rb->Width; \ + int maxy = rb->Height; \ int pitch = irb->region->pitch * irb->region->cpp; \ void *buf = irb->region->buffer->virtual; \ (void)buf; (void)pitch; /* unused for non-gttmap. */ \ @@ -134,7 +134,7 @@ intel_set_span_functions(struct intel_context *intel, (*(uint32_t *)(irb->region->buffer->virtual + NO_TILE(_x, _y)) = d) #define READ_DEPTH(d, _x, _y) \ d = *(uint32_t *)(irb->region->buffer->virtual + NO_TILE(_x, _y)) -#define TAG(x) intel_##x##_z24_x8 +#define TAG(x) intel_##x##_z24_s8 #include "depthtmp.h" void @@ -361,7 +361,7 @@ intel_set_span_functions(struct intel_context *intel, break; case MESA_FORMAT_X8_Z24: case MESA_FORMAT_S8_Z24: - intel_InitDepthPointers_z24_x8(rb); + intel_InitDepthPointers_z24_s8(rb); break; default: _mesa_problem(NULL, diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index 13b8bcfa86..618f690a5f 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -155,7 +155,7 @@ do_copy_texsubimage(struct intel_context *intel, src->buffer, 0, src->tiling, - intelImage->mt->pitch, + intelImage->mt->region->pitch, dst_bo, 0, intelImage->mt->region->tiling, diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index bac36eeb56..9db96acdc0 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -236,7 +236,7 @@ try_pbo_upload(struct intel_context *intel, intelImage->face, 0, &dst_x, &dst_y); - dst_stride = intelImage->mt->pitch; + dst_stride = intelImage->mt->region->pitch; if (drm_intel_bo_references(intel->batch->buf, dst_buffer)) intelFlush(&intel->ctx); @@ -290,7 +290,7 @@ try_pbo_zcopy(struct intel_context *intel, intelImage->face, 0, &dst_x, &dst_y); - dst_stride = intelImage->mt->pitch; + dst_stride = intelImage->mt->region->pitch; if (src_stride != dst_stride || dst_x != 0 || dst_y != 0 || src_offset != 0) { diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c index 7d69ea4484..d132e19e83 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -74,14 +74,14 @@ void i945_miptree_layout_2d( struct intel_context *intel, GLuint width = mt->width0; GLuint height = mt->height0; - mt->pitch = mt->width0; + mt->total_width = mt->width0; intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h); if (mt->compressed) { - mt->pitch = ALIGN(mt->width0, align_w); + mt->total_width = ALIGN(mt->width0, align_w); } - /* May need to adjust pitch to accomodate the placement of + /* May need to adjust width to accomodate the placement of * the 2nd mipmap. This occurs when the alignment * constraints of mipmap placement push the right edge of the * 2nd mipmap out past the width of its parent. @@ -97,15 +97,11 @@ void i945_miptree_layout_2d( struct intel_context *intel, + minify(minify(mt->width0)); } - if (mip1_width > mt->pitch) { - mt->pitch = mip1_width; + if (mip1_width > mt->total_width) { + mt->total_width = mip1_width; } } - /* Pitch must be a whole number of dwords, even though we - * express it in texels. - */ - mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->pitch); mt->total_height = 0; for ( level = mt->first_level ; level <= mt->last_level ; level++ ) { diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c index 77e7e53ce0..73b1e08d4b 100644 --- a/src/mesa/drivers/dri/mach64/mach64_context.c +++ b/src/mesa/drivers/dri/mach64/mach64_context.c @@ -31,6 +31,7 @@ #include "main/glheader.h" #include "main/context.h" +#include "main/extensions.h" #include "main/simple_list.h" #include "main/imports.h" diff --git a/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h b/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h index 00007a9a35..fbeed3baea 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h @@ -260,4 +260,23 @@ nvgl_filter_mode(unsigned filter) } } +static inline unsigned +nvgl_texgen_mode(unsigned mode) +{ + switch (mode) { + case GL_EYE_LINEAR: + return 0x2400; + case GL_OBJECT_LINEAR: + return 0x2401; + case GL_SPHERE_MAP: + return 0x2402; + case GL_NORMAL_MAP: + return 0x8511; + case GL_REFLECTION_MAP: + return 0x8512; + default: + assert(0); + } +} + #endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_render.h b/src/mesa/drivers/dri/nouveau/nouveau_render.h index bff0ccfd76..923b79b2cf 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_render.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_render.h @@ -32,8 +32,8 @@ struct nouveau_array_state; typedef void (*dispatch_t)(GLcontext *, unsigned int, int, unsigned int); -typedef unsigned (*extract_u_t)(struct nouveau_array_state *a, int i, int j); -typedef float (*extract_f_t)(struct nouveau_array_state *a, int i, int j); +typedef unsigned (*extract_u_t)(struct nouveau_array_state *, int, int); +typedef float (*extract_f_t)(struct nouveau_array_state *, int, int); struct nouveau_attr_info { int vbo_index; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_render_t.c b/src/mesa/drivers/dri/nouveau/nouveau_render_t.c index c0505781cf..7ccd7e6416 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_render_t.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_render_t.c @@ -254,7 +254,7 @@ get_scratch_vbo(GLcontext *ctx, unsigned size, struct nouveau_bo **bo, */ static inline unsigned get_max_vertices(GLcontext *ctx, const struct _mesa_index_buffer *ib, - unsigned n) + int n) { struct nouveau_render_state *render = to_render_state(ctx); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.c b/src/mesa/drivers/dri/nouveau/nouveau_state.c index bc610451b4..7697090f6a 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.c @@ -189,6 +189,7 @@ nouveau_enable(GLcontext *ctx, GLenum cap, GLboolean state) case GL_LIGHTING: context_dirty(ctx, FRAG); context_dirty(ctx, MODELVIEW); + context_dirty(ctx, LIGHT_MODEL); context_dirty(ctx, LIGHT_ENABLE); for (i = 0; i < MAX_LIGHTS; i++) { @@ -234,6 +235,13 @@ nouveau_enable(GLcontext *ctx, GLenum cap, GLboolean state) context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); break; + case GL_TEXTURE_GEN_S: + case GL_TEXTURE_GEN_T: + case GL_TEXTURE_GEN_R: + case GL_TEXTURE_GEN_Q: + context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + context_dirty(ctx, MODELVIEW); + break; } } @@ -368,7 +376,15 @@ static void nouveau_tex_gen(GLcontext *ctx, GLenum coord, GLenum pname, const GLfloat *params) { - context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + switch (pname) { + case GL_TEXTURE_GEN_MODE: + context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + context_dirty(ctx, MODELVIEW); + break; + default: + context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); + break; + } } static void @@ -454,12 +470,19 @@ nouveau_state_emit(GLcontext *ctx) static void nouveau_update_state(GLcontext *ctx, GLbitfield new_state) { + int i; + if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW)) context_dirty(ctx, PROJECTION); if (new_state & _NEW_MODELVIEW) context_dirty(ctx, MODELVIEW); + if (new_state & _NEW_TEXTURE_MATRIX) { + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) + context_dirty_i(ctx, TEX_MAT, i); + } + if (new_state & _NEW_CURRENT_ATTRIB && new_state & _NEW_LIGHT) { context_dirty(ctx, MATERIAL_FRONT_AMBIENT); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_state.h b/src/mesa/drivers/dri/nouveau/nouveau_state.h index d01d962c9f..38ac9753c8 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_state.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_state.h @@ -89,6 +89,10 @@ enum { NOUVEAU_STATE_TEX_GEN1, NOUVEAU_STATE_TEX_GEN2, NOUVEAU_STATE_TEX_GEN3, + NOUVEAU_STATE_TEX_MAT0, + NOUVEAU_STATE_TEX_MAT1, + NOUVEAU_STATE_TEX_MAT2, + NOUVEAU_STATE_TEX_MAT3, NOUVEAU_STATE_TEX_OBJ0, NOUVEAU_STATE_TEX_OBJ1, NOUVEAU_STATE_TEX_OBJ2, diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.c b/src/mesa/drivers/dri/nouveau/nouveau_texture.c index bf365bfca3..e89018653b 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_texture.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.c @@ -177,15 +177,15 @@ nouveau_choose_tex_format(GLcontext *ctx, GLint internalFormat, } static GLboolean -teximage_fits(struct gl_texture_object *t, int level, - struct gl_texture_image *ti) +teximage_fits(struct gl_texture_object *t, int level) { struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level]; + struct gl_texture_image *ti = t->Image[0][level]; - return t->Target == GL_TEXTURE_RECTANGLE || - (s->bo && s->width == ti->Width && - s->height == ti->Height && - s->format == ti->TexFormat); + return ti && (t->Target == GL_TEXTURE_RECTANGLE || + (s->bo && s->width == ti->Width && + s->height == ti->Height && + s->format == ti->TexFormat)); } static GLboolean @@ -195,7 +195,7 @@ validate_teximage(GLcontext *ctx, struct gl_texture_object *t, { struct gl_texture_image *ti = t->Image[0][level]; - if (ti && teximage_fits(t, level, ti)) { + if (teximage_fits(t, level)) { struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; @@ -296,6 +296,8 @@ nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t) validate_teximage(ctx, t, i, 0, 0, 0, s->width, s->height, 1); } + + FIRE_RING(context_chan(ctx)); } return GL_TRUE; @@ -304,9 +306,12 @@ nouveau_texture_validate(GLcontext *ctx, struct gl_texture_object *t) void nouveau_texture_reallocate(GLcontext *ctx, struct gl_texture_object *t) { - texture_dirty(t); - relayout_texture(ctx, t); - nouveau_texture_validate(ctx, t); + if (!teximage_fits(t, t->BaseLevel) || + !teximage_fits(t, get_last_level(t))) { + texture_dirty(t); + relayout_texture(ctx, t); + nouveau_texture_validate(ctx, t); + } } static unsigned @@ -364,7 +369,7 @@ nouveau_teximage(GLcontext *ctx, GLint dims, GLenum target, GLint level, } if (level == t->BaseLevel) { - if (!teximage_fits(t, level, ti)) + if (!teximage_fits(t, level)) relayout_texture(ctx, t); nouveau_texture_validate(ctx, t); } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_texture.h b/src/mesa/drivers/dri/nouveau/nouveau_texture.h index b91facbdeb..251f537bba 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_texture.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_texture.h @@ -41,7 +41,7 @@ struct nouveau_texture { #define to_nouveau_texture(x) ((struct nouveau_texture *)(x)) #define texture_dirty(t) \ - to_nouveau_texture(t)->dirty = GL_TRUE; + to_nouveau_texture(t)->dirty = GL_TRUE void nouveau_set_texbuffer(__DRIcontext *dri_ctx, diff --git a/src/mesa/drivers/dri/nouveau/nouveau_util.h b/src/mesa/drivers/dri/nouveau/nouveau_util.h index d6007aba2b..584cb80ef6 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_util.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_util.h @@ -191,4 +191,22 @@ is_texture_source(int s) return s == GL_TEXTURE || (s >= GL_TEXTURE0 && s <= GL_TEXTURE31); } +static inline struct gl_texgen * +get_texgen_coord(struct gl_texture_unit *u, int i) +{ + return ((struct gl_texgen *[]) + { &u->GenS, &u->GenT, &u->GenR, &u->GenQ }) [i]; +} + +static inline float * +get_texgen_coeff(struct gl_texgen *c) +{ + if (c->Mode == GL_OBJECT_LINEAR) + return c->ObjectPlane; + else if (c->Mode == GL_EYE_LINEAR) + return c->EyePlane; + else + return NULL; +} + #endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c index a365b977f2..e5858f8268 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c @@ -85,6 +85,18 @@ vbo_deinit_array(struct nouveau_array_state *a) a->fields = 0; } +static int +get_array_stride(GLcontext *ctx, const struct gl_client_array *a) +{ + struct nouveau_render_state *render = to_render_state(ctx); + + if (render->mode == VBO && !_mesa_is_bufferobj(a->BufferObj)) + /* Pack client buffers. */ + return align(_mesa_sizeof_type(a->Type) * a->Size, 4); + else + return a->StrideB; +} + static void vbo_init_arrays(GLcontext *ctx, const struct _mesa_index_buffer *ib, const struct gl_client_array **arrays) @@ -101,18 +113,10 @@ vbo_init_arrays(GLcontext *ctx, const struct _mesa_index_buffer *ib, if (attr >= 0) { const struct gl_client_array *array = arrays[attr]; - int stride; - - if (render->mode == VBO && - !_mesa_is_bufferobj(array->BufferObj)) - /* Pack client buffers. */ - stride = align(_mesa_sizeof_type(array->Type) - * array->Size, 4); - else - stride = array->StrideB; vbo_init_array(&render->attrs[attr], attr, - stride, array->Size, array->Type, + get_array_stride(ctx, array), + array->Size, array->Type, array->BufferObj, array->Ptr, render->mode == IMM); } @@ -224,9 +228,11 @@ vbo_choose_attrs(GLcontext *ctx, const struct gl_client_array **arrays) if (ctx->Fog.Enabled && ctx->Fog.FogCoordinateSource == GL_FOG_COORD) vbo_emit_attr(ctx, arrays, VERT_ATTRIB_FOG); - if (ctx->Light.Enabled) { + if (ctx->Light.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)) vbo_emit_attr(ctx, arrays, VERT_ATTRIB_NORMAL); + if (ctx->Light.Enabled) { vbo_emit_attr(ctx, arrays, MAT(FRONT_AMBIENT)); vbo_emit_attr(ctx, arrays, MAT(FRONT_DIFFUSE)); vbo_emit_attr(ctx, arrays, MAT(FRONT_SPECULAR)); @@ -243,18 +249,21 @@ vbo_choose_attrs(GLcontext *ctx, const struct gl_client_array **arrays) vbo_emit_attr(ctx, arrays, VERT_ATTRIB_POS); } -static unsigned -get_max_client_stride(GLcontext *ctx) +static int +get_max_client_stride(GLcontext *ctx, const struct gl_client_array **arrays) { struct nouveau_render_state *render = to_render_state(ctx); int i, s = 0; for (i = 0; i < render->attr_count; i++) { int attr = render->map[i]; - struct nouveau_array_state *a = &render->attrs[attr]; - if (attr >= 0 && !a->bo) - s = MAX2(a->stride, s); + if (attr >= 0) { + const struct gl_client_array *a = arrays[attr]; + + if (!_mesa_is_bufferobj(a->BufferObj)) + s = MAX2(s, get_array_stride(ctx, a)); + } } return s; @@ -275,14 +284,15 @@ vbo_maybe_split(GLcontext *ctx, const struct gl_client_array **arrays, { struct nouveau_context *nctx = to_nouveau_context(ctx); struct nouveau_render_state *render = to_render_state(ctx); - unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * nctx->bo.count, + unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * (nctx->bo.count + + render->attr_count), vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail), idx_avail = get_max_vertices(ctx, ib, pushbuf_avail); int stride; /* Try to keep client buffers smaller than the scratch BOs. */ if (render->mode == VBO && - (stride = get_max_client_stride(ctx))) + (stride = get_max_client_stride(ctx, arrays))) vert_avail = MIN2(vert_avail, RENDER_SCRATCH_SIZE / stride); @@ -321,6 +331,7 @@ vbo_bind_vertices(GLcontext *ctx, const struct gl_client_array **arrays, * array->StrideB; if (a->bo) { + /* Array in a buffer obj. */ a->offset = (intptr_t)array->Ptr + delta; } else { int j, n = max_index - min_index + 1; @@ -328,6 +339,8 @@ vbo_bind_vertices(GLcontext *ctx, const struct gl_client_array **arrays, char *dp = get_scratch_vbo(ctx, n * a->stride, &a->bo, &a->offset); + /* Array in client memory, move it to + * a scratch buffer obj. */ for (j = 0; j < n; j++) memcpy(dp + j * a->stride, sp + j * array->StrideB, @@ -371,8 +384,6 @@ vbo_draw_vbo(GLcontext *ctx, const struct gl_client_array **arrays, dispatch(ctx, start, delta, count); BATCH_END(); } - - FIRE_RING(chan); } /* Immediate rendering path. */ @@ -416,8 +427,6 @@ vbo_draw_imm(GLcontext *ctx, const struct gl_client_array **arrays, BATCH_END(); } - - FIRE_RING(chan); } /* draw_prims entry point when we're doing hw-tnl. */ diff --git a/src/mesa/drivers/dri/nouveau/nv04_context.c b/src/mesa/drivers/dri/nouveau/nv04_context.c index 3624b3af92..6834f7cd3d 100644 --- a/src/mesa/drivers/dri/nouveau/nv04_context.c +++ b/src/mesa/drivers/dri/nouveau/nv04_context.c @@ -276,6 +276,10 @@ const struct nouveau_driver nv04_driver = { nouveau_emit_nothing, nouveau_emit_nothing, nouveau_emit_nothing, + nouveau_emit_nothing, + nouveau_emit_nothing, + nouveau_emit_nothing, + nouveau_emit_nothing, nv04_emit_tex_obj, nv04_emit_tex_obj, nouveau_emit_nothing, diff --git a/src/mesa/drivers/dri/nouveau/nv10_context.c b/src/mesa/drivers/dri/nouveau/nv10_context.c index 860d0aeb8f..b6d10361de 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_context.c +++ b/src/mesa/drivers/dri/nouveau/nv10_context.c @@ -212,7 +212,7 @@ nv10_hwctx_init(GLcontext *ctx) OUT_RING(chan, 0); BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1); OUT_RING(chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_S(0), 8); + BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_MODE_S(0), 8); for (i = 0; i < 8; i++) OUT_RING(chan, 0); @@ -412,6 +412,10 @@ const struct nouveau_driver nv10_driver = { nv10_emit_tex_gen, nouveau_emit_nothing, nouveau_emit_nothing, + nv10_emit_tex_mat, + nv10_emit_tex_mat, + nouveau_emit_nothing, + nouveau_emit_nothing, nv10_emit_tex_obj, nv10_emit_tex_obj, nouveau_emit_nothing, diff --git a/src/mesa/drivers/dri/nouveau/nv10_driver.h b/src/mesa/drivers/dri/nouveau/nv10_driver.h index d662712533..cefd6c6fba 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_driver.h +++ b/src/mesa/drivers/dri/nouveau/nv10_driver.h @@ -134,6 +134,9 @@ void nv10_emit_tex_gen(GLcontext *ctx, int emit); void +nv10_emit_tex_mat(GLcontext *ctx, int emit); + +void nv10_emit_tex_obj(GLcontext *ctx, int emit); /* nv10_state_tnl.c */ diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_fb.c b/src/mesa/drivers/dri/nouveau/nv10_state_fb.c index 6bd383ebcd..a2fcb6b695 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_fb.c @@ -71,6 +71,7 @@ setup_lma_buffer(GLcontext *ctx) nouveau_bo_markl(bctx, celsius, NV17TCL_LMA_DEPTH_BUFFER_OFFSET, nfb->lma_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); + WAIT_RING(chan, 9); BEGIN_RING(chan, celsius, NV17TCL_LMA_DEPTH_WINDOW_X, 4); OUT_RINGf(chan, - 1792); OUT_RINGf(chan, - 2304 + fb->Height); @@ -171,15 +172,13 @@ nv10_emit_viewport(GLcontext *ctx, int emit) struct nouveau_grobj *celsius = context_eng3d(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; float a[4] = {}; - int i; get_viewport_translate(ctx, a); a[0] -= 2048; a[1] -= 2048; BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_TRANSLATE_X, 4); - for (i = 0; i < 4; i++) - OUT_RINGf(chan, a[i]); + OUT_RINGp(chan, a, 4); BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1); OUT_RING(chan, (fb->Width - 1) << 16 | 0x08000800); diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c index 02a5ca797a..6dedb18c72 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_tex.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_tex.c @@ -32,9 +32,64 @@ #include "nouveau_util.h" #include "nv10_driver.h" +#define TX_GEN_MODE(i, j) (NV10TCL_TX_GEN_MODE_S(i) + 4 * (j)) +#define TX_GEN_COEFF(i, j) (NV10TCL_TX_GEN_COEFF_S_A(i) + 16 * (j)) +#define TX_MATRIX(i) (NV10TCL_TX0_MATRIX(0) + 64 * (i)) + void nv10_emit_tex_gen(GLcontext *ctx, int emit) { + const int i = emit - NOUVEAU_STATE_TEX_GEN0; + struct nouveau_context *nctx = to_nouveau_context(ctx); + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *celsius = context_eng3d(ctx); + struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; + int j; + + for (j = 0; j < 4; j++) { + if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) { + struct gl_texgen *coord = get_texgen_coord(unit, j); + float *k = get_texgen_coeff(coord); + + if (k) { + BEGIN_RING(chan, celsius, + TX_GEN_COEFF(i, j), 4); + OUT_RINGp(chan, k, 4); + } + + BEGIN_RING(chan, celsius, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, nvgl_texgen_mode(coord->Mode)); + + } else { + BEGIN_RING(chan, celsius, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, 0); + } + } + + context_dirty_i(ctx, TEX_MAT, i); +} + +void +nv10_emit_tex_mat(GLcontext *ctx, int emit) +{ + const int i = emit - NOUVEAU_STATE_TEX_MAT0; + struct nouveau_context *nctx = to_nouveau_context(ctx); + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *celsius = context_eng3d(ctx); + + if (nctx->fallback == HWTNL && + ((ctx->Texture._TexMatEnabled & 1 << i) || + ctx->Texture.Unit[i]._GenFlags)) { + BEGIN_RING(chan, celsius, NV10TCL_TX_MATRIX_ENABLE(i), 1); + OUT_RING(chan, 1); + + BEGIN_RING(chan, celsius, TX_MATRIX(i), 16); + OUT_RINGm(chan, ctx->TextureMatrixStack[i].Top->m); + + } else { + BEGIN_RING(chan, celsius, NV10TCL_TX_MATRIX_ENABLE(i), 1); + OUT_RING(chan, 0); + } } static uint32_t diff --git a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c index 406e24c455..0e592a1629 100644 --- a/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c @@ -140,9 +140,7 @@ nv10_emit_fog(GLcontext *ctx, int emit) OUT_RING(chan, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color)); BEGIN_RING(chan, celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3); - OUT_RINGf(chan, k[0]); - OUT_RINGf(chan, k[1]); - OUT_RINGf(chan, k[2]); + OUT_RINGp(chan, k, 3); context_dirty(ctx, FRAG); } @@ -284,9 +282,7 @@ nv10_emit_light_source(GLcontext *ctx, int emit) if (l->_Flags & LIGHT_POSITIONAL) { BEGIN_RING(chan, celsius, NV10TCL_LIGHT_POSITION_X(i), 3); - OUT_RINGf(chan, l->_Position[0]); - OUT_RINGf(chan, l->_Position[1]); - OUT_RINGf(chan, l->_Position[2]); + OUT_RINGp(chan, l->_Position, 3); BEGIN_RING(chan, celsius, NV10TCL_LIGHT_ATTENUATION_CONSTANT(i), 3); @@ -296,14 +292,10 @@ nv10_emit_light_source(GLcontext *ctx, int emit) } else { BEGIN_RING(chan, celsius, NV10TCL_LIGHT_DIRECTION_X(i), 3); - OUT_RINGf(chan, l->_VP_inf_norm[0]); - OUT_RINGf(chan, l->_VP_inf_norm[1]); - OUT_RINGf(chan, l->_VP_inf_norm[2]); + OUT_RINGp(chan, l->_VP_inf_norm, 3); BEGIN_RING(chan, celsius, NV10TCL_LIGHT_HALF_VECTOR_X(i), 3); - OUT_RINGf(chan, l->_h_inf_norm[0]); - OUT_RINGf(chan, l->_h_inf_norm[1]); - OUT_RINGf(chan, l->_h_inf_norm[2]); + OUT_RINGp(chan, l->_h_inf_norm, 3); } if (l->_Flags & LIGHT_SPOT) { @@ -312,13 +304,7 @@ nv10_emit_light_source(GLcontext *ctx, int emit) nv10_get_spot_coeff(l, k); BEGIN_RING(chan, celsius, NV10TCL_LIGHT_SPOT_CUTOFF_A(i), 7); - OUT_RINGf(chan, k[0]); - OUT_RINGf(chan, k[1]); - OUT_RINGf(chan, k[2]); - OUT_RINGf(chan, k[3]); - OUT_RINGf(chan, k[4]); - OUT_RINGf(chan, k[5]); - OUT_RINGf(chan, k[6]); + OUT_RINGp(chan, k, 7); } } @@ -350,15 +336,11 @@ nv10_emit_material_ambient(GLcontext *ctx, int emit) } BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL_AMBIENT_R, 3); - OUT_RINGf(chan, c_scene[0]); - OUT_RINGf(chan, c_scene[1]); - OUT_RINGf(chan, c_scene[2]); + OUT_RINGp(chan, c_scene, 3); if (ctx->Light.ColorMaterialEnabled) { BEGIN_RING(chan, celsius, NV10TCL_MATERIAL_FACTOR_R, 3); - OUT_RINGf(chan, c_factor[0]); - OUT_RINGf(chan, c_factor[1]); - OUT_RINGf(chan, c_factor[2]); + OUT_RINGp(chan, c_factor, 3); } foreach(l, &ctx->Light.EnabledList) { @@ -368,9 +350,7 @@ nv10_emit_material_ambient(GLcontext *ctx, int emit) l->_MatAmbient[0]); BEGIN_RING(chan, celsius, NV10TCL_LIGHT_AMBIENT_R(i), 3); - OUT_RINGf(chan, c_light[0]); - OUT_RINGf(chan, c_light[1]); - OUT_RINGf(chan, c_light[2]); + OUT_RINGp(chan, c_light, 3); } } @@ -392,9 +372,7 @@ nv10_emit_material_diffuse(GLcontext *ctx, int emit) l->_MatDiffuse[0]); BEGIN_RING(chan, celsius, NV10TCL_LIGHT_DIFFUSE_R(i), 3); - OUT_RINGf(chan, c_light[0]); - OUT_RINGf(chan, c_light[1]); - OUT_RINGf(chan, c_light[2]); + OUT_RINGp(chan, c_light, 3); } } @@ -412,9 +390,7 @@ nv10_emit_material_specular(GLcontext *ctx, int emit) l->_MatSpecular[0]); BEGIN_RING(chan, celsius, NV10TCL_LIGHT_SPECULAR_R(i), 3); - OUT_RINGf(chan, c_light[0]); - OUT_RINGf(chan, c_light[1]); - OUT_RINGf(chan, c_light[2]); + OUT_RINGp(chan, c_light, 3); } } @@ -455,12 +431,7 @@ nv10_emit_material_shininess(GLcontext *ctx, int emit) k); BEGIN_RING(chan, celsius, NV10TCL_MATERIAL_SHININESS(0), 6); - OUT_RINGf(chan, k[0]); - OUT_RINGf(chan, k[1]); - OUT_RINGf(chan, k[2]); - OUT_RINGf(chan, k[3]); - OUT_RINGf(chan, k[4]); - OUT_RINGf(chan, k[5]); + OUT_RINGp(chan, k, 6); } void @@ -474,12 +445,14 @@ nv10_emit_modelview(GLcontext *ctx, int emit) if (nctx->fallback != HWTNL) return; - if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) { + if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { BEGIN_RING(chan, celsius, NV10TCL_MODELVIEW0_MATRIX(0), 16); OUT_RINGm(chan, m->m); } - if (ctx->Light.Enabled) { + if (ctx->Light.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { int i, j; BEGIN_RING(chan, celsius, diff --git a/src/mesa/drivers/dri/nouveau/nv20_context.c b/src/mesa/drivers/dri/nouveau/nv20_context.c index db39ef7075..789dcaa6b4 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_context.c +++ b/src/mesa/drivers/dri/nouveau/nv20_context.c @@ -297,9 +297,9 @@ nv20_hwctx_init(GLcontext *ctx) BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_STIPPLE_ENABLE, 1); OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_S(0), - 4 * NV20TCL_TX_GEN_S__SIZE); - for (i=0; i < 4 * NV20TCL_TX_GEN_S__SIZE; i++) + BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_MODE_S(0), + 4 * NV20TCL_TX_GEN_MODE_S__SIZE); + for (i=0; i < 4 * NV20TCL_TX_GEN_MODE_S__SIZE; i++) OUT_RING(chan, 0); BEGIN_RING(chan, kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3); @@ -497,10 +497,14 @@ const struct nouveau_driver nv20_driver = { nv20_emit_tex_env, nv20_emit_tex_env, nv20_emit_tex_env, - nv10_emit_tex_gen, - nv10_emit_tex_gen, - nv10_emit_tex_gen, - nv10_emit_tex_gen, + nv20_emit_tex_gen, + nv20_emit_tex_gen, + nv20_emit_tex_gen, + nv20_emit_tex_gen, + nv20_emit_tex_mat, + nv20_emit_tex_mat, + nv20_emit_tex_mat, + nv20_emit_tex_mat, nv20_emit_tex_obj, nv20_emit_tex_obj, nv20_emit_tex_obj, diff --git a/src/mesa/drivers/dri/nouveau/nv20_driver.h b/src/mesa/drivers/dri/nouveau/nv20_driver.h index 18574e9be6..8adecef2c4 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_driver.h +++ b/src/mesa/drivers/dri/nouveau/nv20_driver.h @@ -68,6 +68,12 @@ nv20_emit_frag(GLcontext *ctx, int emit); /* nv20_state_tex.c */ void +nv20_emit_tex_gen(GLcontext *ctx, int emit); + +void +nv20_emit_tex_mat(GLcontext *ctx, int emit); + +void nv20_emit_tex_obj(GLcontext *ctx, int emit); void diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_fb.c b/src/mesa/drivers/dri/nouveau/nv20_state_fb.c index d638541df9..21da4f7af1 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_fb.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_fb.c @@ -106,13 +106,11 @@ nv20_emit_viewport(GLcontext *ctx, int emit) struct nouveau_grobj *kelvin = context_eng3d(ctx); struct gl_framebuffer *fb = ctx->DrawBuffer; float a[4] = {}; - int i; get_viewport_translate(ctx, a); BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_TRANSLATE_X, 4); - for (i = 0; i < 4; i++) - OUT_RINGf(chan, a[i]); + OUT_RINGp(chan, a, 4); BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(0), 1); OUT_RING(chan, (fb->Width - 1) << 16); diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c index 92870105f9..e46118e4fc 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_tex.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_tex.c @@ -32,6 +32,62 @@ #include "nouveau_util.h" #include "nv20_driver.h" +#define TX_GEN_MODE(i, j) (NV20TCL_TX_GEN_MODE_S(i) + 4 * (j)) +#define TX_GEN_COEFF(i, j) (NV20TCL_TX_GEN_COEFF_S_A(i) + 16 * (j)) +#define TX_MATRIX(i) (NV20TCL_TX0_MATRIX(0) + 64 * (i)) + +void +nv20_emit_tex_gen(GLcontext *ctx, int emit) +{ + const int i = emit - NOUVEAU_STATE_TEX_GEN0; + struct nouveau_context *nctx = to_nouveau_context(ctx); + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *kelvin = context_eng3d(ctx); + struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; + int j; + + for (j = 0; j < 4; j++) { + if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) { + struct gl_texgen *coord = get_texgen_coord(unit, j); + float *k = get_texgen_coeff(coord); + + if (k) { + BEGIN_RING(chan, kelvin, TX_GEN_COEFF(i, j), 4); + OUT_RINGp(chan, k, 4); + } + + BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, nvgl_texgen_mode(coord->Mode)); + + } else { + BEGIN_RING(chan, kelvin, TX_GEN_MODE(i, j), 1); + OUT_RING(chan, 0); + } + } +} + +void +nv20_emit_tex_mat(GLcontext *ctx, int emit) +{ + const int i = emit - NOUVEAU_STATE_TEX_MAT0; + struct nouveau_context *nctx = to_nouveau_context(ctx); + struct nouveau_channel *chan = context_chan(ctx); + struct nouveau_grobj *kelvin = context_eng3d(ctx); + + if (nctx->fallback == HWTNL && + (ctx->Texture._TexMatEnabled & 1 << i)) { + BEGIN_RING(chan, kelvin, NV20TCL_TX_MATRIX_ENABLE(i), 1); + OUT_RING(chan, 1); + + BEGIN_RING(chan, kelvin, TX_MATRIX(i), 16); + OUT_RINGm(chan, ctx->TextureMatrixStack[i].Top->m); + + } else { + BEGIN_RING(chan, kelvin, NV20TCL_TX_MATRIX_ENABLE(i), 1); + OUT_RING(chan, 0); + } +} + static uint32_t get_tex_format_pot(struct gl_texture_image *ti) { diff --git a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c index 43f8c72312..62efe80fe4 100644 --- a/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c +++ b/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c @@ -139,9 +139,7 @@ nv20_emit_fog(GLcontext *ctx, int emit) OUT_RING(chan, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color)); BEGIN_RING(chan, kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3); - OUT_RINGf(chan, k[0]); - OUT_RINGf(chan, k[1]); - OUT_RINGf(chan, k[2]); + OUT_RINGp(chan, k, 3); } void @@ -176,9 +174,7 @@ nv20_emit_light_source(GLcontext *ctx, int emit) if (l->_Flags & LIGHT_POSITIONAL) { BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_POSITION_X(i), 3); - OUT_RINGf(chan, l->_Position[0]); - OUT_RINGf(chan, l->_Position[1]); - OUT_RINGf(chan, l->_Position[2]); + OUT_RINGp(chan, l->_Position, 3); BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_ATTENUATION_CONSTANT(i), 3); OUT_RINGf(chan, l->ConstantAttenuation); @@ -187,14 +183,10 @@ nv20_emit_light_source(GLcontext *ctx, int emit) } else { BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_DIRECTION_X(i), 3); - OUT_RINGf(chan, l->_VP_inf_norm[0]); - OUT_RINGf(chan, l->_VP_inf_norm[1]); - OUT_RINGf(chan, l->_VP_inf_norm[2]); + OUT_RINGp(chan, l->_VP_inf_norm, 3); BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_HALF_VECTOR_X(i), 3); - OUT_RINGf(chan, l->_h_inf_norm[0]); - OUT_RINGf(chan, l->_h_inf_norm[1]); - OUT_RINGf(chan, l->_h_inf_norm[2]); + OUT_RINGp(chan, l->_h_inf_norm, 3); } if (l->_Flags & LIGHT_SPOT) { @@ -203,13 +195,7 @@ nv20_emit_light_source(GLcontext *ctx, int emit) nv10_get_spot_coeff(l, k); BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_SPOT_CUTOFF_A(i), 7); - OUT_RINGf(chan, k[0]); - OUT_RINGf(chan, k[1]); - OUT_RINGf(chan, k[2]); - OUT_RINGf(chan, k[3]); - OUT_RINGf(chan, k[4]); - OUT_RINGf(chan, k[5]); - OUT_RINGf(chan, k[6]); + OUT_RINGp(chan, k, 7); } } @@ -246,15 +232,11 @@ nv20_emit_material_ambient(GLcontext *ctx, int emit) } BEGIN_RING(chan, kelvin, m_scene[side], 3); - OUT_RINGf(chan, c_scene[0]); - OUT_RINGf(chan, c_scene[1]); - OUT_RINGf(chan, c_scene[2]); + OUT_RINGp(chan, c_scene, 3); if (ctx->Light.ColorMaterialEnabled) { BEGIN_RING(chan, kelvin, m_factor[side], 3); - OUT_RINGf(chan, c_factor[0]); - OUT_RINGf(chan, c_factor[1]); - OUT_RINGf(chan, c_factor[2]); + OUT_RINGp(chan, c_factor, 3); } foreach(l, &ctx->Light.EnabledList) { @@ -266,9 +248,7 @@ nv20_emit_material_ambient(GLcontext *ctx, int emit) l->_MatAmbient[side]); BEGIN_RING(chan, kelvin, m_light[side], 3); - OUT_RINGf(chan, c_light[0]); - OUT_RINGf(chan, c_light[1]); - OUT_RINGf(chan, c_light[2]); + OUT_RINGp(chan, c_light, 3); } } @@ -295,9 +275,7 @@ nv20_emit_material_diffuse(GLcontext *ctx, int emit) l->_MatDiffuse[side]); BEGIN_RING(chan, kelvin, m_light[side], 3); - OUT_RINGf(chan, c_light[0]); - OUT_RINGf(chan, c_light[1]); - OUT_RINGf(chan, c_light[2]); + OUT_RINGp(chan, c_light, 3); } } @@ -318,9 +296,7 @@ nv20_emit_material_specular(GLcontext *ctx, int emit) l->_MatSpecular[side]); BEGIN_RING(chan, kelvin, m_light[side], 3); - OUT_RINGf(chan, c_light[0]); - OUT_RINGf(chan, c_light[1]); - OUT_RINGf(chan, c_light[2]); + OUT_RINGp(chan, c_light, 3); } } @@ -340,12 +316,7 @@ nv20_emit_material_shininess(GLcontext *ctx, int emit) k); BEGIN_RING(chan, kelvin, mthd[side], 6); - OUT_RINGf(chan, k[0]); - OUT_RINGf(chan, k[1]); - OUT_RINGf(chan, k[2]); - OUT_RINGf(chan, k[3]); - OUT_RINGf(chan, k[4]); - OUT_RINGf(chan, k[5]); + OUT_RINGp(chan, k, 6); } void @@ -359,12 +330,14 @@ nv20_emit_modelview(GLcontext *ctx, int emit) if (nctx->fallback != HWTNL) return; - if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled) { + if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { BEGIN_RING(chan, kelvin, NV20TCL_MODELVIEW0_MATRIX(0), 16); OUT_RINGm(chan, m->m); } - if (ctx->Light.Enabled) { + if (ctx->Light.Enabled || + (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { int i, j; BEGIN_RING(chan, kelvin, diff --git a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c index 710cae727a..4e84eefd65 100644 --- a/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c +++ b/src/mesa/drivers/dri/r300/compiler/r500_fragprog_emit.c @@ -469,9 +469,8 @@ void r500BuildFragmentProgramHwCode(struct r300_fragment_program_compiler *compi if (compiler->Base.Error) return; - assert(code->inst_end >= 0); - - if ((code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) { + if (code->inst_end == -1 || + (code->inst[code->inst_end].inst0 & R500_INST_TYPE_MASK) != R500_INST_TYPE_OUT) { /* This may happen when dead-code elimination is disabled or * when most of the fragment program logic is leading to a KIL */ if (code->inst_end >= 511) { diff --git a/src/mesa/drivers/dri/r600/r700_state.c b/src/mesa/drivers/dri/r600/r700_state.c index 2953ffd028..1ff233d91e 100644 --- a/src/mesa/drivers/dri/r600/r700_state.c +++ b/src/mesa/drivers/dri/r600/r700_state.c @@ -615,7 +615,7 @@ static GLuint translate_logicop(GLenum logicop) case GL_XOR: return 0x66; case GL_EQUIV: - return 0xaa; + return 0x99; case GL_AND_REVERSE: return 0x44; case GL_AND_INVERTED: diff --git a/src/mesa/drivers/dri/radeon/radeon_dma.c b/src/mesa/drivers/dri/radeon/radeon_dma.c index 22499bc38d..6b7690cf8b 100644 --- a/src/mesa/drivers/dri/radeon/radeon_dma.c +++ b/src/mesa/drivers/dri/radeon/radeon_dma.c @@ -184,9 +184,6 @@ void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size) radeon_print(RADEON_DMA, RADEON_NORMAL, "%s size %d minimum_size %d\n", __FUNCTION__, size, rmesa->dma.minimum_size); - if (!is_empty_list(&rmesa->dma.reserved)) - radeon_bo_unmap(first_elem(&rmesa->dma.reserved)->bo); - if (is_empty_list(&rmesa->dma.free) || last_elem(&rmesa->dma.free)->bo->size < size) { dma_bo = CALLOC_STRUCT(radeon_dma_bo); @@ -336,9 +333,6 @@ void radeonReleaseDmaRegions(radeonContextPtr rmesa) legacy_track_pending(rmesa->radeonScreen->bom, 0); } - if (!is_empty_list(&rmesa->dma.reserved)) - radeon_bo_unmap(first_elem(&rmesa->dma.reserved)->bo); - /* move waiting bos to free list. wait list provides gpu time to handle data before reuse */ foreach_s(dma_bo, temp, &rmesa->dma.wait) { @@ -368,6 +362,7 @@ void radeonReleaseDmaRegions(radeonContextPtr rmesa) /* move reserved to wait list */ foreach_s(dma_bo, temp, &rmesa->dma.reserved) { + radeon_bo_unmap(dma_bo->bo); /* free objects that are too small to be used because of large request */ if (dma_bo->bo->size < rmesa->dma.minimum_size) { radeon_bo_unref(dma_bo->bo); diff --git a/src/mesa/drivers/dri/swrast/Makefile b/src/mesa/drivers/dri/swrast/Makefile index 771169c1ff..d2cf6dbc55 100644 --- a/src/mesa/drivers/dri/swrast/Makefile +++ b/src/mesa/drivers/dri/swrast/Makefile @@ -5,6 +5,8 @@ include $(TOP)/configs/current LIBNAME = swrast_dri.so +DRIVER_DEFINES = -D__NOT_HAVE_DRM_H + DRIVER_SOURCES = \ swrast.c \ swrast_span.c @@ -17,7 +19,8 @@ ASM_SOURCES = SWRAST_COMMON_SOURCES = \ ../../common/driverfuncs.c \ - ../common/utils.c + ../common/utils.c \ + ../common/drisw_util.c include ../Makefile.template diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c index 03c672ecf1..e9ca99a86f 100644 --- a/src/mesa/drivers/dri/swrast/swrast.c +++ b/src/mesa/drivers/dri/swrast/swrast.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 George Sapountzis <gsap7@yahoo.gr> + * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -54,17 +54,9 @@ * Screen and config-related functions */ -static void -setupLoaderExtensions(__DRIscreen *psp, - const __DRIextension **extensions) -{ - int i; - - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) - psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; - } -} +static const __DRIextension *dri_screen_extensions[] = { + NULL +}; static __DRIconfig ** swrastFillInModes(__DRIscreen *psp, @@ -143,26 +135,14 @@ swrastFillInModes(__DRIscreen *psp, return configs; } -static __DRIscreen * -driCreateNewScreen(int scrn, const __DRIextension **extensions, - const __DRIconfig ***driver_configs, void *data) +static const __DRIconfig ** +dri_init_screen(__DRIscreen * psp) { - static const __DRIextension *emptyExtensionList[] = { NULL }; - __DRIscreen *psp; __DRIconfig **configs8, **configs16, **configs24, **configs32; - (void) data; - TRACE; - psp = calloc(1, sizeof(*psp)); - if (!psp) - return NULL; - - setupLoaderExtensions(psp, extensions); - - psp->num = scrn; - psp->extensions = emptyExtensionList; + psp->extensions = dri_screen_extensions; configs8 = swrastFillInModes(psp, 8, 8, 0, 1); configs16 = swrastFillInModes(psp, 16, 16, 0, 1); @@ -171,28 +151,15 @@ driCreateNewScreen(int scrn, const __DRIextension **extensions, configs16 = driConcatConfigs(configs8, configs16); configs24 = driConcatConfigs(configs16, configs24); - *driver_configs = (const __DRIconfig **) - driConcatConfigs(configs24, configs32); - - driInitExtensions( NULL, NULL, GL_FALSE ); - - return psp; -} - -static void driDestroyScreen(__DRIscreen *psp) -{ - TRACE; + configs32 = driConcatConfigs(configs24, configs32); - if (psp) { - free(psp); - } + return (const __DRIconfig **)configs32; } -static const __DRIextension **driGetExtensions(__DRIscreen *psp) +static void +dri_destroy_screen(__DRIscreen * sPriv) { TRACE; - - return psp->extensions; } @@ -336,94 +303,116 @@ swrast_new_renderbuffer(const GLvisual *visual, GLboolean front) return xrb; } -static __DRIdrawable * -driCreateNewDrawable(__DRIscreen *screen, - const __DRIconfig *config, void *data) +static GLboolean +dri_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const __GLcontextModes * visual, GLboolean isPixmap) { - __DRIdrawable *buf; + struct dri_drawable *drawable = NULL; + GLframebuffer *fb; struct swrast_renderbuffer *frontrb, *backrb; TRACE; - buf = calloc(1, sizeof *buf); - if (!buf) - return NULL; + drawable = CALLOC_STRUCT(dri_drawable); + if (drawable == NULL) + goto drawable_fail; - buf->loaderPrivate = data; + dPriv->driverPrivate = drawable; + drawable->dPriv = dPriv; - buf->driScreenPriv = screen; + drawable->row = malloc(MAX_WIDTH * 4); + if (drawable->row == NULL) + goto drawable_fail; - buf->row = malloc(MAX_WIDTH * 4); + fb = &drawable->Base; /* basic framebuffer setup */ - _mesa_initialize_window_framebuffer(&buf->Base, &config->modes); + _mesa_initialize_window_framebuffer(fb, visual); /* add front renderbuffer */ - frontrb = swrast_new_renderbuffer(&config->modes, GL_TRUE); - _mesa_add_renderbuffer(&buf->Base, BUFFER_FRONT_LEFT, &frontrb->Base); + frontrb = swrast_new_renderbuffer(visual, GL_TRUE); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base); /* add back renderbuffer */ - if (config->modes.doubleBufferMode) { - backrb = swrast_new_renderbuffer(&config->modes, GL_FALSE); - _mesa_add_renderbuffer(&buf->Base, BUFFER_BACK_LEFT, &backrb->Base); + if (visual->doubleBufferMode) { + backrb = swrast_new_renderbuffer(visual, GL_FALSE); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base); } /* add software renderbuffers */ - _mesa_add_soft_renderbuffers(&buf->Base, + _mesa_add_soft_renderbuffers(fb, GL_FALSE, /* color */ - config->modes.haveDepthBuffer, - config->modes.haveStencilBuffer, - config->modes.haveAccumBuffer, + visual->haveDepthBuffer, + visual->haveStencilBuffer, + visual->haveAccumBuffer, GL_FALSE, /* alpha */ GL_FALSE /* aux bufs */); - return buf; + return GL_TRUE; + +drawable_fail: + + if (drawable) + free(drawable->row); + + FREE(drawable); + + return GL_FALSE; } static void -driDestroyDrawable(__DRIdrawable *buf) +dri_destroy_buffer(__DRIdrawable * dPriv) { TRACE; - if (buf) { - struct gl_framebuffer *fb = &buf->Base; + if (dPriv) { + struct dri_drawable *drawable = dri_drawable(dPriv); + GLframebuffer *fb; - free(buf->row); + free(drawable->row); + + fb = &drawable->Base; fb->DeletePending = GL_TRUE; _mesa_reference_framebuffer(&fb, NULL); } } -static void driSwapBuffers(__DRIdrawable *buf) +static void +dri_swap_buffers(__DRIdrawable * dPriv) { - GET_CURRENT_CONTEXT(ctx); + __DRIscreen *sPriv = dPriv->driScreenPriv; - struct swrast_renderbuffer *frontrb = - swrast_renderbuffer(buf->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - struct swrast_renderbuffer *backrb = - swrast_renderbuffer(buf->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); + GET_CURRENT_CONTEXT(ctx); - __DRIscreen *screen = buf->driScreenPriv; + struct dri_drawable *drawable = dri_drawable(dPriv); + GLframebuffer *fb; + struct swrast_renderbuffer *frontrb, *backrb; TRACE; + fb = &drawable->Base; + + frontrb = swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + backrb = swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + /* check for signle-buffered */ if (backrb == NULL) return; /* check if swapping currently bound buffer */ - if (ctx && ctx->DrawBuffer == &(buf->Base)) { + if (ctx && ctx->DrawBuffer == fb) { /* flush pending rendering */ _mesa_notifySwapBuffers(ctx); } - screen->swrast_loader->putImage(buf, __DRI_SWRAST_IMAGE_OP_SWAP, - 0, 0, - frontrb->Base.Width, - frontrb->Base.Height, - backrb->Base.Data, - buf->loaderPrivate); + sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + 0, 0, + frontrb->Base.Width, + frontrb->Base.Height, + backrb->Base.Data, + dPriv->loaderPrivate); } @@ -434,13 +423,13 @@ static void driSwapBuffers(__DRIdrawable *buf) static void get_window_size( GLframebuffer *fb, GLsizei *w, GLsizei *h ) { - __DRIdrawable *buf = swrast_drawable(fb); - __DRIscreen *screen = buf->driScreenPriv; + __DRIdrawable *dPriv = swrast_drawable(fb)->dPriv; + __DRIscreen *sPriv = dPriv->driScreenPriv; int x, y; - screen->swrast_loader->getDrawableInfo(buf, - &x, &y, w, h, - buf->loaderPrivate); + sPriv->swrast_loader->getDrawableInfo(dPriv, + &x, &y, w, h, + dPriv->loaderPrivate); } static void @@ -502,37 +491,40 @@ swrast_init_driver_functions(struct dd_function_table *driver) * Context-related functions. */ -static __DRIcontext * -driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, - __DRIcontext *shared, void *data) +static GLboolean +dri_create_context(const __GLcontextModes * visual, + __DRIcontext * cPriv, void *sharedContextPrivate) { - __DRIcontext *ctx; - GLcontext *mesaCtx; + struct dri_context *ctx = NULL; + struct dri_context *share = (struct dri_context *)sharedContextPrivate; + GLcontext *mesaCtx = NULL; + GLcontext *sharedCtx = NULL; struct dd_function_table functions; TRACE; - ctx = calloc(1, sizeof *ctx); - if (!ctx) - return NULL; - - ctx->loaderPrivate = data; + ctx = CALLOC_STRUCT(dri_context); + if (ctx == NULL) + goto context_fail; - ctx->driScreenPriv = screen; + cPriv->driverPrivate = ctx; + ctx->cPriv = cPriv; /* build table of device driver functions */ _mesa_init_driver_functions(&functions); swrast_init_driver_functions(&functions); - if (!_mesa_initialize_context(&ctx->Base, &config->modes, - shared ? &shared->Base : NULL, - &functions, (void *) ctx)) { - free(ctx); - return NULL; + if (share) { + sharedCtx = &share->Base; } mesaCtx = &ctx->Base; + /* basic context setup */ + if (!_mesa_initialize_context(mesaCtx, visual, sharedCtx, &functions, (void *) cPriv)) { + goto context_fail; + } + /* do bounds checking to prevent segfaults and server crashes! */ mesaCtx->Const.CheckArrayBounds = GL_TRUE; @@ -558,17 +550,28 @@ driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, _mesa_meta_init(mesaCtx); - return ctx; + driInitExtensions( mesaCtx, NULL, GL_FALSE ); + + return GL_TRUE; + +context_fail: + + FREE(ctx); + + return GL_FALSE; } static void -driDestroyContext(__DRIcontext *ctx) +dri_destroy_context(__DRIcontext * cPriv) { - GLcontext *mesaCtx; TRACE; - if (ctx) { + if (cPriv) { + struct dri_context *ctx = dri_context(cPriv); + GLcontext *mesaCtx; + mesaCtx = &ctx->Base; + _mesa_meta_free(mesaCtx); _swsetup_DestroyContext( mesaCtx ); _swrast_DestroyContext( mesaCtx ); @@ -578,26 +581,22 @@ driDestroyContext(__DRIcontext *ctx) } } -static int -driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask) -{ - TRACE; - - _mesa_copy_context(&src->Base, &dst->Base, mask); - return GL_TRUE; -} - -static int driBindContext(__DRIcontext *ctx, - __DRIdrawable *draw, - __DRIdrawable *read) +static GLboolean +dri_make_current(__DRIcontext * cPriv, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv) { GLcontext *mesaCtx; GLframebuffer *mesaDraw; GLframebuffer *mesaRead; TRACE; - if (ctx) { - if (!draw || !read) + if (cPriv) { + struct dri_context *ctx = dri_context(cPriv); + struct dri_drawable *draw = dri_drawable(driDrawPriv); + struct dri_drawable *read = dri_drawable(driReadPriv); + + if (!driDrawPriv || !driReadPriv) return GL_FALSE; mesaCtx = &ctx->Base; @@ -614,7 +613,7 @@ static int driBindContext(__DRIcontext *ctx, _glapi_check_multithread(); swrast_check_and_update_window_size(mesaCtx, mesaDraw); - if (read != draw) + if (mesaRead != mesaDraw) swrast_check_and_update_window_size(mesaCtx, mesaRead); _mesa_make_current( mesaCtx, @@ -629,35 +628,25 @@ static int driBindContext(__DRIcontext *ctx, return GL_TRUE; } -static int driUnbindContext(__DRIcontext *ctx) +static GLboolean +dri_unbind_context(__DRIcontext * cPriv) { TRACE; - (void) ctx; + (void) cPriv; return GL_TRUE; } -static const __DRIcoreExtension driCoreExtension = { - { __DRI_CORE, __DRI_CORE_VERSION }, - NULL, /* driCreateNewScreen */ - driDestroyScreen, - driGetExtensions, - driGetConfigAttrib, - driIndexConfigAttrib, - NULL, /* driCreateNewDrawable */ - driDestroyDrawable, - driSwapBuffers, - driCreateNewContext, - driCopyContext, - driDestroyContext, - driBindContext, - driUnbindContext -}; - -static const __DRIswrastExtension driSWRastExtension = { - { __DRI_SWRAST, __DRI_SWRAST_VERSION }, - driCreateNewScreen, - driCreateNewDrawable +const struct __DriverAPIRec driDriverAPI = { + .InitScreen = dri_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .SwapBuffers = dri_swap_buffers, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, }; /* This is the table of extensions that the loader will dlsym() for. */ diff --git a/src/mesa/drivers/dri/swrast/swrast_priv.h b/src/mesa/drivers/dri/swrast/swrast_priv.h index 4722007f95..007642be95 100644 --- a/src/mesa/drivers/dri/swrast/swrast_priv.h +++ b/src/mesa/drivers/dri/swrast/swrast_priv.h @@ -3,6 +3,7 @@ * Version: 7.1 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,11 +23,6 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Authors: - * George Sapountzis <gsap7@yahoo.gr> - */ - #ifndef _SWRAST_PRIV_H #define _SWRAST_PRIV_H @@ -34,6 +30,7 @@ #include <GL/gl.h> #include <GL/internal/dri_interface.h> #include "main/mtypes.h" +#include "drisw_util.h" /** @@ -58,33 +55,51 @@ /** * Data types */ -struct __DRIscreenRec { - int num; - - const __DRIextension **extensions; +struct dri_context +{ + /* mesa, base class, must be first */ + GLcontext Base; - const __DRIswrastLoaderExtension *swrast_loader; + /* dri */ + __DRIcontext *cPriv; }; -struct __DRIcontextRec { - GLcontext Base; - - void *loaderPrivate; +static INLINE struct dri_context * +dri_context(__DRIcontext * driContextPriv) +{ + return (struct dri_context *)driContextPriv->driverPrivate; +} - __DRIscreen *driScreenPriv; -}; +static INLINE struct dri_context * +swrast_context(GLcontext *ctx) +{ + return (struct dri_context *) ctx; +} -struct __DRIdrawableRec { +struct dri_drawable +{ + /* mesa, base class, must be first */ GLframebuffer Base; - void *loaderPrivate; - - __DRIscreen *driScreenPriv; + /* dri */ + __DRIdrawable *dPriv; /* scratch row for optimized front-buffer rendering */ char *row; }; +static INLINE struct dri_drawable * +dri_drawable(__DRIdrawable * driDrawPriv) +{ + return (struct dri_drawable *)driDrawPriv->driverPrivate; +} + +static INLINE struct dri_drawable * +swrast_drawable(GLframebuffer *fb) +{ + return (struct dri_drawable *) fb; +} + struct swrast_renderbuffer { struct gl_renderbuffer Base; @@ -94,18 +109,6 @@ struct swrast_renderbuffer { GLuint bpp; }; -static INLINE __DRIcontext * -swrast_context(GLcontext *ctx) -{ - return (__DRIcontext *) ctx; -} - -static INLINE __DRIdrawable * -swrast_drawable(GLframebuffer *fb) -{ - return (__DRIdrawable *) fb; -} - static INLINE struct swrast_renderbuffer * swrast_renderbuffer(struct gl_renderbuffer *rb) { diff --git a/src/mesa/drivers/dri/swrast/swrast_span.c b/src/mesa/drivers/dri/swrast/swrast_span.c index 5290dc82b9..c5681e34a9 100644 --- a/src/mesa/drivers/dri/swrast/swrast_span.c +++ b/src/mesa/drivers/dri/swrast/swrast_span.c @@ -3,6 +3,7 @@ * Version: 7.1 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,11 +23,6 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Authors: - * George Sapountzis <gsap7@yahoo.gr> - */ - #include "swrast_priv.h" #define YFLIP(_xrb, Y) ((_xrb)->Base.Height - (Y) - 1) diff --git a/src/mesa/drivers/dri/swrast/swrast_spantemp.h b/src/mesa/drivers/dri/swrast/swrast_spantemp.h index 879a0c12e7..079726ae4a 100644 --- a/src/mesa/drivers/dri/swrast/swrast_spantemp.h +++ b/src/mesa/drivers/dri/swrast/swrast_spantemp.h @@ -39,8 +39,8 @@ static INLINE void PUT_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; @@ -53,8 +53,8 @@ PUT_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) static INLINE void GET_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; @@ -65,8 +65,8 @@ GET_PIXEL( GLcontext *glCtx, GLint x, GLint y, GLubyte *p ) static INLINE void PUT_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *draw = swrast_drawable(glCtx->DrawBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; @@ -78,8 +78,8 @@ PUT_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) static INLINE void GET_ROW( GLcontext *glCtx, GLint x, GLint y, GLuint n, char *row ) { - __DRIcontext *ctx = swrast_context(glCtx); - __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer); + __DRIcontext *ctx = swrast_context(glCtx)->cPriv; + __DRIdrawable *read = swrast_drawable(glCtx->ReadBuffer)->dPriv; __DRIscreen *screen = ctx->driScreenPriv; diff --git a/src/mesa/glapi/glapi_entrypoint.c b/src/mesa/glapi/glapi_entrypoint.c index c4f43f66a1..239780e753 100644 --- a/src/mesa/glapi/glapi_entrypoint.c +++ b/src/mesa/glapi/glapi_entrypoint.c @@ -56,7 +56,7 @@ extern const GLubyte gl_dispatch_functions_start[]; #if defined(DISPATCH_FUNCTION_SIZE) _glapi_proc -get_entrypoint_address(GLuint functionOffset) +get_entrypoint_address(unsigned int functionOffset) { return (_glapi_proc) (gl_dispatch_functions_start + (DISPATCH_FUNCTION_SIZE * functionOffset)); @@ -97,7 +97,7 @@ init_glapi_relocs( void ) * We need assembly language in order to accomplish this. */ _glapi_proc -generate_entrypoint(GLuint functionOffset) +generate_entrypoint(unsigned int functionOffset) { /* 32 is chosen as something of a magic offset. For x86, the dispatch * at offset 32 is the first one where the offset in the @@ -122,7 +122,7 @@ generate_entrypoint(GLuint functionOffset) * stub that was generated with the preceeding function. */ void -fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) +fill_in_entrypoint_offset(_glapi_proc entrypoint, unsigned int offset) { GLubyte * const code = (GLubyte *) entrypoint; diff --git a/src/mesa/glapi/glapi_execmem.c b/src/mesa/glapi/glapi_execmem.c index 6a1fac597f..57f00be8dc 100644 --- a/src/mesa/glapi/glapi_execmem.c +++ b/src/mesa/glapi/glapi_execmem.c @@ -40,6 +40,7 @@ #endif #include "glapi/glthread.h" +#include "glapi/glapi_priv.h" #if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun) diff --git a/src/mesa/glapi/glapi_priv.h b/src/mesa/glapi/glapi_priv.h index 0e2de460f2..da6fee63fe 100644 --- a/src/mesa/glapi/glapi_priv.h +++ b/src/mesa/glapi/glapi_priv.h @@ -27,6 +27,8 @@ #define _GLAPI_PRIV_H #include "glthread.h" +#include "glapi.h" + /* getproc */ @@ -42,7 +44,7 @@ _glapi_check_table(const struct _glapi_table *table); /* execmem */ extern void * -_glapi_exec_malloc(GLuint size); +_glapi_exec_malloc(unsigned int size); /* entrypoint */ @@ -52,15 +54,15 @@ init_glapi_relocs_once(void); extern _glapi_proc -generate_entrypoint(GLuint functionOffset); +generate_entrypoint(unsigned int functionOffset); extern void -fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset); +fill_in_entrypoint_offset(_glapi_proc entrypoint, unsigned int offset); extern _glapi_proc -get_entrypoint_address(GLuint functionOffset); +get_entrypoint_address(unsigned int functionOffset); /** diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 71d1514fe4..dbaba2975e 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -32,6 +32,7 @@ #include "glheader.h" +#include "enums.h" #include "hash.h" #include "imports.h" #include "image.h" @@ -1376,31 +1377,49 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) bufObj = get_buffer(ctx, target); if (!bufObj) { - _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" ); + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)" ); return; } if (!_mesa_is_bufferobj(bufObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" ); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameterivARB" ); return; } switch (pname) { case GL_BUFFER_SIZE_ARB: *params = (GLint) bufObj->Size; - break; + return; case GL_BUFFER_USAGE_ARB: *params = bufObj->Usage; - break; + return; case GL_BUFFER_ACCESS_ARB: *params = simplified_access_mode(bufObj->AccessFlags); - break; + return; case GL_BUFFER_MAPPED_ARB: *params = _mesa_bufferobj_mapped(bufObj); - break; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)"); return; + case GL_BUFFER_ACCESS_FLAGS: + if (ctx->VersionMajor < 3) + goto invalid_pname; + *params = bufObj->AccessFlags; + return; + case GL_BUFFER_MAP_OFFSET: + if (ctx->VersionMajor < 3) + goto invalid_pname; + *params = (GLint) bufObj->Offset; + return; + case GL_BUFFER_MAP_LENGTH: + if (ctx->VersionMajor < 3) + goto invalid_pname; + *params = (GLint) bufObj->Length; + return; + default: + ; /* fall-through */ } + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); } @@ -1418,31 +1437,50 @@ _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) bufObj = get_buffer(ctx, target); if (!bufObj) { - _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameteri64v(target)" ); + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(target)" ); return; } if (!_mesa_is_bufferobj(bufObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameteri64v" ); + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameteri64v" ); return; } switch (pname) { case GL_BUFFER_SIZE_ARB: *params = bufObj->Size; - break; + return; case GL_BUFFER_USAGE_ARB: *params = bufObj->Usage; - break; + return; case GL_BUFFER_ACCESS_ARB: *params = simplified_access_mode(bufObj->AccessFlags); - break; + return; + case GL_BUFFER_ACCESS_FLAGS: + if (ctx->VersionMajor < 3) + goto invalid_pname; + *params = bufObj->AccessFlags; + return; case GL_BUFFER_MAPPED_ARB: *params = _mesa_bufferobj_mapped(bufObj); - break; + return; + case GL_BUFFER_MAP_OFFSET: + if (ctx->VersionMajor < 3) + goto invalid_pname; + *params = bufObj->Offset; + return; + case GL_BUFFER_MAP_LENGTH: + if (ctx->VersionMajor < 3) + goto invalid_pname; + *params = bufObj->Length; + return; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname)"); + ; /* fall-through */ return; } + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); } diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 7c442e390c..0782734869 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -180,8 +180,12 @@ _mesa_get_attachment(GLcontext *ctx, struct gl_framebuffer *fb, return &fb->Attachment[BUFFER_COLOR0 + i]; case GL_DEPTH_STENCIL_ATTACHMENT: /* fall-through */ + case GL_DEPTH_BUFFER: + /* fall-through / new in GL 3.0 */ case GL_DEPTH_ATTACHMENT_EXT: return &fb->Attachment[BUFFER_DEPTH]; + case GL_STENCIL_BUFFER: + /* fall-through / new in GL 3.0 */ case GL_STENCIL_ATTACHMENT_EXT: return &fb->Attachment[BUFFER_STENCIL]; default: diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index edc4400912..523dc2e4f7 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -917,6 +917,10 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params ) CHECK_EXT1(MESA_texture_array, "GetBooleanv"); params[0] = INT_TO_BOOLEAN(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name); break; + case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT: + CHECK_EXT1(MESA_texture_array, "GetBooleanv"); + params[0] = INT_TO_BOOLEAN(ctx->Const.MaxArrayTextureLayers); + break; case GL_TEXTURE_GEN_S: params[0] = ((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0); break; @@ -1932,6 +1936,9 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params ) case GL_MINOR_VERSION: params[0] = INT_TO_BOOLEAN(ctx->VersionMinor); break; + case GL_CONTEXT_FLAGS: + params[0] = INT_TO_BOOLEAN(ctx->Const.ContextFlags); + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname); } @@ -2786,6 +2793,10 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params ) CHECK_EXT1(MESA_texture_array, "GetFloatv"); params[0] = (GLfloat)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name); break; + case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT: + CHECK_EXT1(MESA_texture_array, "GetFloatv"); + params[0] = (GLfloat)(ctx->Const.MaxArrayTextureLayers); + break; case GL_TEXTURE_GEN_S: params[0] = BOOLEAN_TO_FLOAT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)); break; @@ -3801,6 +3812,9 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params ) case GL_MINOR_VERSION: params[0] = (GLfloat)(ctx->VersionMinor); break; + case GL_CONTEXT_FLAGS: + params[0] = (GLfloat)(ctx->Const.ContextFlags); + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(pname=0x%x)", pname); } @@ -4655,6 +4669,10 @@ _mesa_GetIntegerv( GLenum pname, GLint *params ) CHECK_EXT1(MESA_texture_array, "GetIntegerv"); params[0] = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name; break; + case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT: + CHECK_EXT1(MESA_texture_array, "GetIntegerv"); + params[0] = ctx->Const.MaxArrayTextureLayers; + break; case GL_TEXTURE_GEN_S: params[0] = BOOLEAN_TO_INT(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)); break; @@ -5670,6 +5688,9 @@ _mesa_GetIntegerv( GLenum pname, GLint *params ) case GL_MINOR_VERSION: params[0] = ctx->VersionMinor; break; + case GL_CONTEXT_FLAGS: + params[0] = ctx->Const.ContextFlags; + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname); } @@ -6525,6 +6546,10 @@ _mesa_GetInteger64v( GLenum pname, GLint64 *params ) CHECK_EXT1(MESA_texture_array, "GetInteger64v"); params[0] = (GLint64)(ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name); break; + case GL_MAX_ARRAY_TEXTURE_LAYERS_EXT: + CHECK_EXT1(MESA_texture_array, "GetInteger64v"); + params[0] = (GLint64)(ctx->Const.MaxArrayTextureLayers); + break; case GL_TEXTURE_GEN_S: params[0] = BOOLEAN_TO_INT64(((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)); break; @@ -7540,6 +7565,9 @@ _mesa_GetInteger64v( GLenum pname, GLint64 *params ) case GL_MINOR_VERSION: params[0] = (GLint64)(ctx->VersionMinor); break; + case GL_CONTEXT_FLAGS: + params[0] = (GLint64)(ctx->Const.ContextFlags); + break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetInteger64v(pname=0x%x)", pname); } diff --git a/src/mesa/main/get_gen.py b/src/mesa/main/get_gen.py index 9d5a51d58c..0ef9d8fe94 100644 --- a/src/mesa/main/get_gen.py +++ b/src/mesa/main/get_gen.py @@ -457,6 +457,8 @@ StateVars = [ ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_1D_ARRAY_INDEX]->Name"], "", ["MESA_texture_array"] ), ( "GL_TEXTURE_BINDING_2D_ARRAY_EXT", GLint, ["ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentTex[TEXTURE_2D_ARRAY_INDEX]->Name"], "", ["MESA_texture_array"] ), + ( "GL_MAX_ARRAY_TEXTURE_LAYERS_EXT", GLint, + ["ctx->Const.MaxArrayTextureLayers"], "", ["MESA_texture_array"] ), ( "GL_TEXTURE_GEN_S", GLboolean, ["((ctx->Texture.Unit[ctx->Texture.CurrentUnit].TexGenEnabled & S_BIT) ? 1 : 0)"], "", None ), ( "GL_TEXTURE_GEN_T", GLboolean, @@ -1062,7 +1064,8 @@ StateVars = [ # GL3 ( "GL_NUM_EXTENSIONS", GLint, ["_mesa_get_extension_count(ctx)"], "", None ), ( "GL_MAJOR_VERSION", GLint, ["ctx->VersionMajor"], "", None ), - ( "GL_MINOR_VERSION", GLint, ["ctx->VersionMinor"], "", None ) + ( "GL_MINOR_VERSION", GLint, ["ctx->VersionMinor"], "", None ), + ( "GL_CONTEXT_FLAGS", GLint, ["ctx->Const.ContextFlags"], "", None ) ] diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h index 72717d6787..9b34be0dfa 100644 --- a/src/mesa/main/image.h +++ b/src/mesa/main/image.h @@ -303,7 +303,7 @@ _mesa_clip_drawpixels(const GLcontext *ctx, extern GLboolean _mesa_clip_readpixels(const GLcontext *ctx, - GLint *destX, GLint *destY, + GLint *srcX, GLint *srcY, GLsizei *width, GLsizei *height, struct gl_pixelstore_attrib *pack); diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c index 56e8195810..1ae0853364 100644 --- a/src/mesa/main/imports.c +++ b/src/mesa/main/imports.c @@ -795,18 +795,20 @@ _mesa_strdup( const char *s ) } } -/** Wrapper around strtod() */ -double -_mesa_strtod( const char *s, char **end ) +/** Wrapper around strtof() */ +float +_mesa_strtof( const char *s, char **end ) { #ifdef _GNU_SOURCE static locale_t loc = NULL; if (!loc) { loc = newlocale(LC_CTYPE_MASK, "C", NULL); } - return strtod_l(s, end, loc); + return strtof_l(s, end, loc); +#elif defined(_ISOC99_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) + return strtof(s, end); #else - return strtod(s, end); + return (float)strtod(s, end); #endif } diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index fb4a00eca7..d28f4ad125 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -575,8 +575,8 @@ _mesa_getenv( const char *var ); extern char * _mesa_strdup( const char *s ); -extern double -_mesa_strtod( const char *s, char **end ); +extern float +_mesa_strtof( const char *s, char **end ); extern unsigned int _mesa_str_checksum(const char *str); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 9d9b475dd1..82e004f348 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2385,6 +2385,9 @@ struct gl_constants /**< GL_EXT_provoking_vertex */ GLboolean QuadsFollowProvokingVertexConvention; + + /**< OpenGL version 3.x */ + GLbitfield ContextFlags; /**< Ex: GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT */ }; diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 0fde89b507..714c4cfd52 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -940,6 +940,18 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, "glGetTexLevelParameter[if]v(pname)"); } break; + case GL_TEXTURE_SHARED_SIZE: + if (ctx->VersionMajor >= 3) { + /* XXX return number of exponent bits for shared exponent texture + * formats, like GL_RGB9_E5. + */ + *params = 0; + } + else { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetTexLevelParameter[if]v(pname)"); + } + break; /* GL_ARB_texture_compression */ case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: diff --git a/src/mesa/shader/lex.yy.c b/src/mesa/shader/lex.yy.c index a08617ff8d..4c5c644a6e 100644 --- a/src/mesa/shader/lex.yy.c +++ b/src/mesa/shader/lex.yy.c @@ -2198,7 +2198,7 @@ case 142: YY_RULE_SETUP #line 326 "program_lexer.l" { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } YY_BREAK @@ -2210,7 +2210,7 @@ YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 330 "program_lexer.l" { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } YY_BREAK @@ -2218,7 +2218,7 @@ case 144: YY_RULE_SETUP #line 334 "program_lexer.l" { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } YY_BREAK @@ -2226,7 +2226,7 @@ case 145: YY_RULE_SETUP #line 338 "program_lexer.l" { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } YY_BREAK diff --git a/src/mesa/shader/nvfragparse.c b/src/mesa/shader/nvfragparse.c index d03cb4e493..0de3c5804d 100644 --- a/src/mesa/shader/nvfragparse.c +++ b/src/mesa/shader/nvfragparse.c @@ -456,7 +456,7 @@ Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number) { char *end = NULL; - *number = (GLfloat) _mesa_strtod((const char *) parseState->pos, &end); + *number = (GLfloat) _mesa_strtof((const char *) parseState->pos, &end); if (end && end > (char *) parseState->pos) { /* got a number */ diff --git a/src/mesa/shader/program_lexer.l b/src/mesa/shader/program_lexer.l index b00765793d..fe18272cdb 100644 --- a/src/mesa/shader/program_lexer.l +++ b/src/mesa/shader/program_lexer.l @@ -324,19 +324,19 @@ ARRAYSHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require return INTEGER; } {num}?{frac}{exp}? { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } {num}"."/[^.] { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } {num}{exp} { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } {num}"."{exp} { - yylval->real = (float) _mesa_strtod(yytext, NULL); + yylval->real = _mesa_strtof(yytext, NULL); return REAL; } diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index b95c15fea6..ad86676157 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -246,7 +246,7 @@ parse_general_number(slang_parse_ctx *ctx, float *number) if (flt[strlen(flt) - 1] == 'f' || flt[strlen(flt) - 1] == 'F') { flt[strlen(flt) - 1] = '\0'; } - *number = (float)_mesa_strtod(flt, (char **)NULL); + *number = _mesa_strtof(flt, (char **)NULL); free(flt); return 1; @@ -312,7 +312,7 @@ parse_float(slang_parse_ctx * C, float *number) slang_string_concat(whole, "E"); slang_string_concat(whole, exponent); - *number = (float) (_mesa_strtod(whole, (char **) NULL)); + *number = _mesa_strtof(whole, (char **) NULL); _slang_free(whole); } diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak index d59e24de1f..d6ae696e39 100644 --- a/src/mesa/sources.mak +++ b/src/mesa/sources.mak @@ -214,6 +214,7 @@ STATETRACKER_SOURCES = \ state_tracker/st_format.c \ state_tracker/st_framebuffer.c \ state_tracker/st_gen_mipmap.c \ + state_tracker/st_manager.c \ state_tracker/st_mesa_to_tgsi.c \ state_tracker/st_program.c \ state_tracker/st_texture.c diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 7806df4a53..9fa4dae5ca 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -34,6 +34,7 @@ #include "st_atom.h" #include "st_cb_bitmap.h" #include "st_program.h" +#include "st_manager.h" #include "pipe/p_context.h" @@ -136,9 +137,7 @@ void st_validate_state( struct st_context *st ) check_program_state( st ); - if (st->pipe->screen->update_buffer) - st->pipe->screen->update_buffer(st->pipe->screen, - st->pipe->priv); + st_manager_validate_framebuffers(st); if (state->st == 0) return; diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index ff715478e5..7b62ac4cc8 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -38,7 +38,6 @@ #include "st_texture.h" #include "pipe/p_context.h" #include "cso_cache/cso_context.h" -#include "util/u_rect.h" #include "util/u_math.h" #include "util/u_inlines.h" @@ -165,17 +164,10 @@ update_framebuffer_state( struct st_context *st ) (void) st_get_framebuffer_surface(stfb, ST_SURFACE_FRONT_LEFT, &surf_front); (void) st_get_framebuffer_surface(stfb, ST_SURFACE_BACK_LEFT, &surf_back); - if (st->pipe->surface_copy) { - st->pipe->surface_copy(st->pipe, - surf_front, 0, 0, /* dest */ - surf_back, 0, 0, /* src */ - fb->Width, fb->Height); - } else { - util_surface_copy(st->pipe, FALSE, - surf_front, 0, 0, - surf_back, 0, 0, - fb->Width, fb->Height); - } + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); } /* we're assuming we'll really draw to the front buffer */ st->frontbuffer_status = FRONT_STATUS_DIRTY; diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index 55821fba1e..bcbd995a80 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -69,6 +69,7 @@ st_BlitFramebuffer(GLcontext *ctx, const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); struct st_context *st = ctx->st; + struct pipe_context *pipe = st->pipe; const uint pFilter = ((filter == GL_NEAREST) ? PIPE_TEX_MIPFILTER_NEAREST : PIPE_TEX_MIPFILTER_LINEAR); @@ -111,8 +112,8 @@ st_BlitFramebuffer(GLcontext *ctx, &readFB->Attachment[readFB->_ColorReadBufferIndex]; if(srcAtt->Type == GL_TEXTURE) { - struct pipe_screen *screen = ctx->st->pipe->screen; - const struct st_texture_object *srcObj = + struct pipe_screen *screen = pipe->screen; + struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture); struct st_renderbuffer *dstRb = st_renderbuffer(drawFB->_ColorDrawBuffers[0]); @@ -132,7 +133,8 @@ st_BlitFramebuffer(GLcontext *ctx, return; util_blit_pixels(st->blit, - srcSurf, srcX0, srcY0, srcX1, srcY1, + srcSurf, st_get_stobj_sampler_view(srcObj), + srcX0, srcY0, srcX1, srcY1, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); @@ -144,10 +146,11 @@ st_BlitFramebuffer(GLcontext *ctx, struct st_renderbuffer *dstRb = st_renderbuffer(drawFB->_ColorDrawBuffers[0]); struct pipe_surface *srcSurf = srcRb->surface; + struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcRb, pipe); struct pipe_surface *dstSurf = dstRb->surface; util_blit_pixels(st->blit, - srcSurf, srcX0, srcY0, srcX1, srcY1, + srcSurf, srcView, srcX0, srcY0, srcX1, srcY1, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } @@ -179,11 +182,13 @@ st_BlitFramebuffer(GLcontext *ctx, if ((mask & depthStencil) == depthStencil && srcDepthSurf == srcStencilSurf && dstDepthSurf == dstStencilSurf) { + struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcDepthRb, pipe); + /* Blitting depth and stencil values between combined * depth/stencil buffers. This is the ideal case for such buffers. */ util_blit_pixels(st->blit, - srcDepthSurf, srcX0, srcY0, srcX1, srcY1, + srcDepthSurf, srcView, srcX0, srcY0, srcX1, srcY1, dstDepthSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 8e59fca1e9..6c5f9630bd 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -59,7 +59,6 @@ #include "util/u_draw_quad.h" #include "util/u_format.h" #include "util/u_math.h" -#include "util/u_rect.h" #include "shader/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -968,39 +967,13 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, GLfloat *color; enum pipe_format srcFormat, texFormat; GLboolean invertTex = GL_FALSE; + GLint readX, readY, readW, readH; + struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); st_validate_state(st); - if (srcx < 0) { - width -= -srcx; - dstx += -srcx; - srcx = 0; - } - - if (srcy < 0) { - height -= -srcy; - dsty += -srcy; - srcy = 0; - } - - if (dstx < 0) { - width -= -dstx; - srcx += -dstx; - dstx = 0; - } - - if (dsty < 0) { - height -= -dsty; - srcy += -dsty; - dsty = 0; - } - - if (width < 0 || height < 0) - return; - - if (type == GL_STENCIL) { /* can't use texturing to do stencil */ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); @@ -1033,7 +1006,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL); - assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ + assert(texFormat != PIPE_FORMAT_NONE); } else { /* default color format */ @@ -1043,20 +1016,26 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, } } + /* Invert src region if needed */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { srcy = ctx->ReadBuffer->Height - srcy - height; - - if (srcy < 0) { - height -= -srcy; - srcy = 0; - } - - if (height < 0) - return; - invertTex = !invertTex; } + /* Clip the read region against the src buffer bounds. + * We'll still allocate a temporary buffer/texture for the original + * src region size but we'll only read the region which is on-screen. + * This may mean that we draw garbage pixels into the dest region, but + * that's expected. + */ + readX = srcx; + readY = srcy; + readW = width; + readH = height; + _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &unpack); + readW = MAX2(0, readW); + readH = MAX2(0, readH); + /* alloc temporary texture */ pt = alloc_texture(st, width, height, texFormat); if (!pt) @@ -1069,7 +1048,6 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, } /* Make temporary texture which is a copy of the src region. - * We'll draw a quad with this texture to draw the dest image. */ if (srcFormat == texFormat) { /* copy source framebuffer surface into mipmap/texture */ @@ -1079,19 +1057,11 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_RENDER_TARGET | PIPE_BUFFER_USAGE_BLIT_DESTINATION); - if (pipe->surface_copy) { - pipe->surface_copy(pipe, - psTex, /* dest */ - 0, 0, /* destx/y */ - psRead, - srcx, srcy, width, height); - } else { - util_surface_copy(pipe, FALSE, - psTex, - 0, 0, - psRead, - srcx, srcy, width, height); - } + pipe->surface_copy(pipe, + psTex, /* dest surf */ + unpack.SkipPixels, unpack.SkipRows, /* dest pos */ + psRead, /* src surf */ + readX, readY, readW, readH); /* src region */ if (0) { /* debug */ @@ -1106,8 +1076,8 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, - PIPE_TRANSFER_READ, srcx, srcy, width, - height); + PIPE_TRANSFER_READ, + readX, readY, readW, readH); struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; @@ -1122,20 +1092,21 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage, 0, 0, width, height); + /* copy image from ptRead surface to ptTex surface */ if (type == GL_COLOR) { /* alternate path using get/put_tile() */ GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - - pipe_get_tile_rgba(pipe, ptRead, 0, 0, width, height, buf); - pipe_put_tile_rgba(pipe, ptTex, 0, 0, width, height, buf); - + pipe_get_tile_rgba(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_rgba(pipe, ptTex, unpack.SkipPixels, unpack.SkipRows, + readW, readH, buf); free(buf); } else { /* GL_DEPTH */ GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(pipe, ptRead, 0, 0, width, height, buf); - pipe_put_tile_z(pipe, ptTex, 0, 0, width, height, buf); + pipe_get_tile_z(pipe, ptRead, readX, readY, readW, readH, buf); + pipe_put_tile_z(pipe, ptTex, unpack.SkipPixels, unpack.SkipRows, + readW, readH, buf); free(buf); } @@ -1143,7 +1114,9 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, pipe->transfer_destroy(pipe, ptTex); } - /* draw textured quad */ + /* OK, the texture 'pt' contains the src image/pixels. Now draw a + * textured quad with that texture. + */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, sv, diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index b27c663d51..69d83719c6 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -48,9 +48,9 @@ #include "st_format.h" #include "st_public.h" #include "st_texture.h" +#include "st_manager.h" #include "util/u_format.h" -#include "util/u_rect.h" #include "util/u_inlines.h" @@ -103,6 +103,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, */ pipe_surface_reference( &strb->surface, NULL ); pipe_resource_reference( &strb->texture, NULL ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); /* Setup new texture template. */ @@ -157,6 +158,7 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb) ASSERT(strb); pipe_surface_reference(&strb->surface, NULL); pipe_resource_reference(&strb->texture, NULL); + pipe_sampler_view_reference(&strb->sampler_view, NULL); free(strb->data); free(strb); } @@ -363,6 +365,8 @@ st_render_texture(GLcontext *ctx, pipe_surface_reference(&strb->surface, NULL); + pipe_sampler_view_reference(&strb->sampler_view, st_get_stobj_sampler_view(stObj)); + assert(strb->rtt_level <= strb->texture->last_level); /* new surface for rendering into the texture */ @@ -507,17 +511,10 @@ copy_back_to_front(struct st_context *st, (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back); if (surf_front && surf_back) { - if (st->pipe->surface_copy) { - st->pipe->surface_copy(st->pipe, - surf_front, 0, 0, /* dest */ - surf_back, 0, 0, /* src */ - fb->Width, fb->Height); - } else { - util_surface_copy(st->pipe, FALSE, - surf_front, 0, 0, - surf_back, 0, 0, - fb->Width, fb->Height); - } + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); } } @@ -608,8 +605,18 @@ check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb) static void st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) { + GLframebuffer *fb = ctx->DrawBuffer; + GLuint i; + (void) count; (void) buffers; + + /* add the renderbuffers on demand */ + for (i = 0; i < fb->_NumColorDrawBuffers; i++) { + gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i]; + st_manager_add_color_renderbuffer(ctx->st, fb, idx); + } + check_create_front_buffers(ctx, ctx->DrawBuffer); } @@ -620,8 +627,13 @@ st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) static void st_ReadBuffer(GLcontext *ctx, GLenum buffer) { + GLframebuffer *fb = ctx->ReadBuffer; + (void) buffer; - check_create_front_buffers(ctx, ctx->ReadBuffer); + + /* add the renderbuffer on demand */ + st_manager_add_color_renderbuffer(ctx->st, fb, fb->_ColorReadBufferIndex); + check_create_front_buffers(ctx, fb); } @@ -641,3 +653,14 @@ void st_init_fbo_functions(struct dd_function_table *functions) functions->DrawBuffers = st_DrawBuffers; functions->ReadBuffer = st_ReadBuffer; } + +struct pipe_sampler_view * +st_renderbuffer_get_sampler_view(struct st_renderbuffer *rb, + struct pipe_context *pipe) +{ + if (!rb->sampler_view) { + rb->sampler_view = st_sampler_view_from_texture(pipe, rb->texture); + } + + return rb->sampler_view; +} diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index 50de67269a..5f11a7cd8a 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -39,6 +39,7 @@ struct st_renderbuffer struct gl_renderbuffer Base; struct pipe_resource *texture; struct pipe_surface *surface; /* temporary view into texture */ + struct pipe_sampler_view *sampler_view; enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ GLboolean defined; /**< defined contents? */ @@ -55,6 +56,7 @@ struct st_renderbuffer /** Render to texture state */ struct pipe_resource *texture_save; struct pipe_surface *surface_save; + struct pipe_sampler_view *sampler_view_save; }; @@ -71,5 +73,9 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw); extern void st_init_fbo_functions(struct dd_function_table *functions); +extern struct pipe_sampler_view * +st_renderbuffer_get_sampler_view(struct st_renderbuffer *rb, + struct pipe_context *pipe); + #endif /* ST_CB_FBO_H */ diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 28a384ba49..30e7afcf2a 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -40,6 +40,7 @@ #include "st_cb_clear.h" #include "st_cb_fbo.h" #include "st_public.h" +#include "st_manager.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -74,12 +75,9 @@ display_front_buffer(struct st_context *st) = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); if (strb) { - struct pipe_surface *front_surf = strb->surface; - /* Hook for copying "fake" frontbuffer if necessary: */ - st->pipe->screen->flush_frontbuffer( st->pipe->screen, front_surf, - st->winsys_drawable_handle ); + st_manager_flush_frontbuffer(st); /* st->frontbuffer_status = FRONT_STATUS_UNDEFINED; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 7c211a3a68..19af934f1b 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -45,6 +45,7 @@ #include "st_debug.h" #include "st_context.h" +#include "st_atom.h" #include "st_cb_readpixels.h" #include "st_cb_fbo.h" #include "st_public.h" @@ -350,6 +351,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* XXX convolution not done yet */ assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0); + st_validate_state(ctx->st); + /* Do all needed clipping here, so that we can forget about it later */ if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) { /* The ReadPixels transfer is totally outside the window bounds */ diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index b9d3229904..3e0ccb8799 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -63,6 +63,7 @@ #include "util/u_blit.h" #include "util/u_format.h" #include "util/u_surface.h" +#include "util/u_sampler.h" #include "util/u_math.h" @@ -380,6 +381,8 @@ compress_with_blit(GLcontext * ctx, gl_format mesa_format; struct pipe_resource templ; struct pipe_resource *src_tex; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; struct pipe_surface *dst_surface; struct pipe_transfer *tex_xfer; void *map; @@ -441,9 +444,16 @@ compress_with_blit(GLcontext * ctx, pipe_transfer_unmap(pipe, tex_xfer); pipe->transfer_destroy(pipe, tex_xfer); + /* Create temporary sampler view */ + u_sampler_view_default_template(&view_templ, + src_tex, + src_tex->format); + src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ); + + /* copy / compress image */ util_blit_pixels_tex(ctx->st->blit, - src_tex, /* pipe_resource (src) */ + src_view, /* sampler view (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ @@ -455,6 +465,7 @@ compress_with_blit(GLcontext * ctx, pipe_surface_reference(&dst_surface, NULL); pipe_resource_reference(&src_tex, NULL); + pipe_sampler_view_reference(&src_view, NULL); return GL_TRUE; } @@ -560,6 +571,7 @@ st_TexImage(GLcontext * ctx, DBG("release it\n"); pipe_resource_reference(&stObj->pt, NULL); assert(!stObj->pt); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); stObj->teximage_realloc = FALSE; } } @@ -817,6 +829,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); + struct st_texture_object *stObj = st_texture_object(texObj); + struct pipe_sampler_view *src_view = st_get_stobj_sampler_view(stObj); const GLuint width = texImage->Width; const GLuint height = texImage->Height; struct pipe_surface *dst_surface; @@ -833,7 +847,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, /* blit/render/decompress */ util_blit_pixels_tex(ctx->st->blit, - stImage->pt, /* pipe_resource (src) */ + src_view, /* pipe_resource (src) */ 0, 0, /* src x0, y0 */ width, height, /* src x1, y1 */ dst_surface, /* pipe_surface (dst) */ @@ -886,6 +900,8 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, _mesa_unmap_pbo_dest(ctx, &ctx->Pack); + pipe->transfer_destroy(pipe, tex_xfer); + /* destroy the temp / dest surface */ util_destroy_rgba_surface(dst_texture, dst_surface); } @@ -1544,8 +1560,7 @@ st_copy_texsubimage(GLcontext *ctx, if (ctx->_ImageTransferState == 0x0) { - if (pipe->surface_copy && - matching_base_formats && + if (matching_base_formats && src_format == dest_format && !do_flip) { @@ -1597,6 +1612,7 @@ st_copy_texsubimage(GLcontext *ctx, } util_blit_pixels_writemask(ctx->st->blit, strb->surface, + st_renderbuffer_get_sampler_view(strb, pipe), srcX, srcY0, srcX + width, srcY1, dest_surface, @@ -1793,6 +1809,7 @@ st_finalize_texture(GLcontext *ctx, firstImage->pt != stObj->pt && firstImage->pt->last_level >= stObj->lastLevel) { pipe_resource_reference(&stObj->pt, firstImage->pt); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); } /* bytes per pixel block (blocks are usually 1x1) */ @@ -1812,6 +1829,7 @@ st_finalize_texture(GLcontext *ctx, stObj->pt->depth0 != firstImage->base.Depth2) { pipe_resource_reference(&stObj->pt, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER; } } diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 85dd9df7ce..c06a382a33 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -30,9 +30,9 @@ #include "vbo/vbo.h" #include "shader/shader_api.h" #include "glapi/glapi.h" +#include "st_context.h" #include "st_public.h" #include "st_debug.h" -#include "st_context.h" #include "st_cb_accum.h" #include "st_cb_bitmap.h" #include "st_cb_blit.h" @@ -63,6 +63,7 @@ #include "st_program.h" #include "pipe/p_context.h" #include "util/u_inlines.h" +#include "util/u_rect.h" #include "draw/draw_context.h" #include "cso_cache/cso_context.h" @@ -97,6 +98,19 @@ st_get_msaa(void) } +/** Default method for pipe_context::surface_copy() */ +static void +st_surface_copy(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned dst_x, unsigned dst_y, + struct pipe_surface *src, + unsigned src_x, unsigned src_y, + unsigned w, unsigned h) +{ + util_surface_copy(pipe, FALSE, dst, dst_x, dst_y, src, src_x, src_y, w, h); +} + + static struct st_context * st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) { @@ -166,6 +180,10 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) st_init_limits(st); st_init_extensions(st); + /* plug in helper driver functions if needed */ + if (!pipe->surface_copy) + pipe->surface_copy = st_surface_copy; + return st; } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index b78887970a..f28d5aa3ed 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -31,6 +31,7 @@ #include "main/mtypes.h" #include "shader/prog_cache.h" #include "pipe/p_state.h" +#include "state_tracker/st_api.h" struct st_context; @@ -73,6 +74,8 @@ struct st_tracked_state { struct st_context { + struct st_context_iface iface; + GLcontext *ctx; struct pipe_context *pipe; @@ -207,6 +210,11 @@ struct st_framebuffer GLframebuffer Base; void *Private; GLuint InitWidth, InitHeight; + + struct st_framebuffer_iface *iface; + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned num_statts; + int32_t revalidate; }; diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index 9cc42f2f5e..819b4487ac 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -197,6 +197,7 @@ st_set_framebuffer_surface(struct st_framebuffer *stfb, /* replace the renderbuffer's surface/texture pointers */ pipe_surface_reference( &strb->surface, surf ); pipe_resource_reference( &strb->texture, surf->texture ); + pipe_sampler_view_reference(&strb->sampler_view, NULL); if (ctx) { /* If ctx isn't set, we've likely not made current yet. diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index ebd0b9cadf..a255cb5ae6 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -79,22 +79,23 @@ st_destroy_generate_mipmap(struct st_context *st) static boolean st_render_mipmap(struct st_context *st, GLenum target, - struct pipe_resource *pt, + struct st_texture_object *stObj, uint baseLevel, uint lastLevel) { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; + struct pipe_sampler_view *psv = st_get_stobj_sampler_view(stObj); const uint face = _mesa_tex_target_to_face(target); assert(target != GL_TEXTURE_3D); /* not done yet */ /* check if we can render in the texture's format */ - if (!screen->is_format_supported(screen, pt->format, pt->target, + if (!screen->is_format_supported(screen, psv->format, psv->texture->target, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { return FALSE; } - util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel, + util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel, PIPE_TEX_FILTER_LINEAR); return TRUE; @@ -211,6 +212,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) { struct st_context *st = ctx->st; + struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_resource *pt = st_get_texobj_texture(texObj); const uint baseLevel = texObj->BaseLevel; uint lastLevel; @@ -229,7 +231,6 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* The current gallium texture doesn't have space for all the * mipmap levels we need to generate. So allocate a new texture. */ - struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_resource *oldTex = stObj->pt; GLboolean needFlush; @@ -255,6 +256,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* release the old tex (will likely be freed too) */ pipe_resource_reference(&oldTex, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); pt = stObj->pt; } @@ -264,7 +266,7 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, /* Recall that the Mesa BaseLevel image is stored in the gallium * texture's level[0] position. So pass baseLevel=0 here. */ - if (!st_render_mipmap(st, target, pt, 0, lastLevel)) { + if (!st_render_mipmap(st, target, stObj, 0, lastLevel)) { fallback_generate_mipmap(ctx, target, texObj); } diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c new file mode 100644 index 0000000000..a9f77c2617 --- /dev/null +++ b/src/mesa/state_tracker/st_manager.c @@ -0,0 +1,800 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "state_tracker/st_api.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_format.h" +#include "util/u_pointer.h" +#include "util/u_inlines.h" +#include "util/u_atomic.h" + +#include "main/mtypes.h" +#include "main/context.h" +#include "main/texobj.h" +#include "main/teximage.h" +#include "main/texstate.h" +#include "main/texfetch.h" +#include "main/fbobject.h" +#include "main/framebuffer.h" +#include "main/renderbuffer.h" +#include "st_texture.h" + +#include "st_context.h" +#include "st_format.h" +#include "st_cb_fbo.h" +#include "st_manager.h" + +/* these functions are defined in st_context.c */ +struct st_context * +st_create_context(struct pipe_context *pipe, + const __GLcontextModes *visual, + struct st_context *share); +void st_destroy_context(struct st_context *st); +void st_flush(struct st_context *st, uint pipeFlushFlags, + struct pipe_fence_handle **fence); + +/** + * Note that this function may fail. + */ +static INLINE struct st_framebuffer * +st_framebuffer(GLframebuffer *fb) +{ + /* FBO cannot be casted. See st_new_framebuffer */ + return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL); +} + +/** + * Map an attachment to a buffer index. + */ +static INLINE gl_buffer_index +attachment_to_buffer_index(enum st_attachment_type statt) +{ + gl_buffer_index index; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + index = BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + index = BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + index = BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + index = BUFFER_BACK_RIGHT; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + index = BUFFER_DEPTH; + break; + case ST_ATTACHMENT_ACCUM: + index = BUFFER_ACCUM; + break; + case ST_ATTACHMENT_SAMPLE: + default: + index = BUFFER_COUNT; + break; + } + + return index; +} + +/** + * Map a buffer index to an attachment. + */ +static INLINE enum st_attachment_type +buffer_index_to_attachment(gl_buffer_index index) +{ + enum st_attachment_type statt; + + switch (index) { + case BUFFER_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + case BUFFER_FRONT_RIGHT: + statt = ST_ATTACHMENT_FRONT_RIGHT; + break; + case BUFFER_BACK_RIGHT: + statt = ST_ATTACHMENT_BACK_RIGHT; + break; + case BUFFER_DEPTH: + statt = ST_ATTACHMENT_DEPTH_STENCIL; + break; + case BUFFER_ACCUM: + statt = ST_ATTACHMENT_ACCUM; + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + return statt; +} + +/** + * Validate a framebuffer to make sure up-to-date pipe_textures are used. + */ +static void +st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) +{ + struct pipe_screen *screen = st->pipe->screen; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + uint width, height; + unsigned i; + boolean changed = FALSE; + + if (!p_atomic_read(&stfb->revalidate)) + return; + + /* validate the fb */ + if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures)) + return; + + width = stfb->Base.Width; + height = stfb->Base.Height; + + for (i = 0; i < stfb->num_statts; i++) { + struct st_renderbuffer *strb; + struct pipe_surface *ps; + gl_buffer_index idx; + + if (!textures[i]) + continue; + + idx = attachment_to_buffer_index(stfb->statts[i]); + if (idx >= BUFFER_COUNT) { + pipe_resource_reference(&textures[i], NULL); + continue; + } + + strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); + assert(strb); + if (strb->texture == textures[i]) { + pipe_resource_reference(&textures[i], NULL); + continue; + } + + ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); + if (ps) { + pipe_surface_reference(&strb->surface, ps); + pipe_resource_reference(&strb->texture, ps->texture); + /* ownership transfered */ + pipe_surface_reference(&ps, NULL); + + changed = TRUE; + + strb->Base.Width = strb->surface->width; + strb->Base.Height = strb->surface->height; + + width = strb->Base.Width; + height = strb->Base.Height; + } + + pipe_resource_reference(&textures[i], NULL); + } + + if (changed) { + st->dirty.st |= ST_NEW_FRAMEBUFFER; + _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height); + + assert(stfb->Base.Width == width); + assert(stfb->Base.Height == height); + } + + p_atomic_set(&stfb->revalidate, FALSE); +} + +/** + * Update the attachments to validate by looping the existing renderbuffers. + */ +static void +st_framebuffer_update_attachments(struct st_framebuffer *stfb) +{ + gl_buffer_index idx; + + stfb->num_statts = 0; + for (idx = 0; idx < BUFFER_COUNT; idx++) { + struct st_renderbuffer *strb; + enum st_attachment_type statt; + + strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); + if (!strb || strb->software) + continue; + + statt = buffer_index_to_attachment(idx); + if (statt != ST_ATTACHMENT_INVALID && + st_visual_have_buffers(stfb->iface->visual, 1 << statt)) + stfb->statts[stfb->num_statts++] = statt; + } + + p_atomic_set(&stfb->revalidate, TRUE); +} + +/** + * Add a renderbuffer to the framebuffer. + */ +static boolean +st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, + gl_buffer_index idx) +{ + struct gl_renderbuffer *rb; + enum pipe_format format; + int samples; + boolean sw; + + /* do not distinguish depth/stencil buffers */ + if (idx == BUFFER_STENCIL) + idx = BUFFER_DEPTH; + + switch (idx) { + case BUFFER_DEPTH: + format = stfb->iface->visual->depth_stencil_format; + sw = FALSE; + break; + case BUFFER_ACCUM: + format = stfb->iface->visual->accum_format; + sw = TRUE; + break; + default: + format = stfb->iface->visual->color_format; + sw = FALSE; + break; + } + + if (format == PIPE_FORMAT_NONE) + return FALSE; + + samples = stfb->iface->visual->samples; + if (!samples) + samples = st_get_msaa(); + + rb = st_new_renderbuffer_fb(format, samples, sw); + if (!rb) + return FALSE; + + if (idx != BUFFER_DEPTH) { + _mesa_add_renderbuffer(&stfb->Base, idx, rb); + } + else { + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) + _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb); + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) + _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb); + } + + return TRUE; +} + +/** + * Intialize a __GLcontextModes from a visual. + */ +static void +st_visual_to_context_mode(const struct st_visual *visual, + __GLcontextModes *mode) +{ + memset(mode, 0, sizeof(*mode)); + + if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK)) + mode->doubleBufferMode = GL_TRUE; + if (st_visual_have_buffers(visual, + ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK)) + mode->stereoMode = GL_TRUE; + + if (visual->color_format != PIPE_FORMAT_NONE) { + mode->rgbMode = GL_TRUE; + + mode->redBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + mode->greenBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 1); + mode->blueBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 2); + mode->alphaBits = + util_format_get_component_bits(visual->color_format, + UTIL_FORMAT_COLORSPACE_RGB, 3); + + mode->rgbBits = mode->redBits + + mode->greenBits + mode->blueBits + mode->alphaBits; + } + + if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { + mode->haveDepthBuffer = GL_TRUE; + mode->haveStencilBuffer = GL_TRUE; + + mode->depthBits = + util_format_get_component_bits(visual->depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, 0); + mode->stencilBits = + util_format_get_component_bits(visual->depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, 1); + } + + if (visual->accum_format != PIPE_FORMAT_NONE) { + mode->haveAccumBuffer = GL_TRUE; + + mode->accumRedBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 0); + mode->accumGreenBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 1); + mode->accumBlueBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 2); + mode->accumAlphaBits = + util_format_get_component_bits(visual->accum_format, + UTIL_FORMAT_COLORSPACE_RGB, 3); + } + + if (visual->samples) { + mode->sampleBuffers = 1; + mode->samples = visual->samples; + } +} + +/** + * Determine the default draw or read buffer from a visual. + */ +static void +st_visual_to_default_buffer(const struct st_visual *visual, + GLenum *buffer, GLint *index) +{ + enum st_attachment_type statt; + GLenum buf; + gl_buffer_index idx; + + statt = visual->render_buffer; + /* do nothing if an invalid render buffer is specified */ + if (statt == ST_ATTACHMENT_INVALID || + !st_visual_have_buffers(visual, 1 << statt)) + return; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + buf = GL_FRONT_LEFT; + idx = BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + buf = GL_BACK_LEFT; + idx = BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + buf = GL_FRONT_RIGHT; + idx = BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + buf = GL_BACK_RIGHT; + idx = BUFFER_BACK_RIGHT; + break; + default: + buf = GL_NONE; + idx = BUFFER_COUNT; + break; + } + + if (buf != GL_NONE) { + if (buffer) + *buffer = buf; + if (index) + *index = idx; + } +} + +/** + * Create a framebuffer from a manager interface. + */ +static struct st_framebuffer * +st_framebuffer_create(struct st_framebuffer_iface *stfbi) +{ + struct st_framebuffer *stfb; + __GLcontextModes mode; + gl_buffer_index idx; + + stfb = CALLOC_STRUCT(st_framebuffer); + if (!stfb) + return NULL; + + st_visual_to_context_mode(stfbi->visual, &mode); + _mesa_initialize_window_framebuffer(&stfb->Base, &mode); + + /* modify the draw/read buffers of the fb */ + st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0], + &stfb->Base._ColorDrawBufferIndexes[0]); + st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer, + &stfb->Base._ColorReadBufferIndex); + + stfb->iface = stfbi; + + /* add the color buffer */ + idx = stfb->Base._ColorDrawBufferIndexes[0]; + if (!st_framebuffer_add_renderbuffer(stfb, idx)) { + FREE(stfb); + return NULL; + } + + st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH); + st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM); + + st_framebuffer_update_attachments(stfb); + + stfb->Base.Initialized = GL_TRUE; + + return stfb; +} + +/** + * Reference a framebuffer. + */ +static void +st_framebuffer_reference(struct st_framebuffer **ptr, + struct st_framebuffer *stfb) +{ + GLframebuffer *fb = &stfb->Base; + _mesa_reference_framebuffer((GLframebuffer **) ptr, fb); +} + +static void +st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi) +{ + struct st_context *st = (struct st_context *) stctxi; + struct st_framebuffer *stfb; + + /* either draw or read winsys fb */ + stfb = st_framebuffer(st->ctx->WinSysDrawBuffer); + if (!stfb || stfb->iface != stfbi) + stfb = st_framebuffer(st->ctx->WinSysReadBuffer); + assert(stfb && stfb->iface == stfbi); + + p_atomic_set(&stfb->revalidate, TRUE); +} + +static void +st_context_flush(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct st_context *st = (struct st_context *) stctxi; + st_flush(st, flags, fence); + if (flags & PIPE_FLUSH_RENDER_CACHE) + st_manager_flush_frontbuffer(st); +} + +static boolean +st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target, + int level, enum pipe_format internal_format, + struct pipe_resource *tex, boolean mipmap) +{ + struct st_context *st = (struct st_context *) stctxi; + GLcontext *ctx = st->ctx; + struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); + struct gl_texture_object *texObj; + struct gl_texture_image *texImage; + struct st_texture_object *stObj; + struct st_texture_image *stImage; + GLenum internalFormat; + + switch (target) { + case ST_TEXTURE_1D: + target = GL_TEXTURE_1D; + break; + case ST_TEXTURE_2D: + target = GL_TEXTURE_2D; + break; + case ST_TEXTURE_3D: + target = GL_TEXTURE_3D; + break; + case ST_TEXTURE_RECT: + target = GL_TEXTURE_RECTANGLE_ARB; + break; + default: + return FALSE; + break; + } + + if (util_format_get_component_bits(internal_format, + UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) + internalFormat = GL_RGBA; + else + internalFormat = GL_RGB; + + texObj = _mesa_select_tex_object(ctx, texUnit, target); + _mesa_lock_texture(ctx, texObj); + + stObj = st_texture_object(texObj); + /* switch to surface based */ + if (!stObj->surface_based) { + _mesa_clear_texture_object(ctx, texObj); + stObj->surface_based = GL_TRUE; + } + + texImage = _mesa_get_tex_image(ctx, texObj, target, level); + stImage = st_texture_image(texImage); + if (tex) { + _mesa_init_teximage_fields(ctx, target, texImage, + tex->width0, tex->height0, 1, 0, internalFormat); + texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, + GL_RGBA, GL_UNSIGNED_BYTE); + _mesa_set_fetch_functions(texImage, 2); + } + else { + _mesa_clear_texture_image(ctx, texImage); + } + + stObj->pipe = st->pipe; + pipe_resource_reference(&stImage->pt, tex); + + _mesa_dirty_texobj(ctx, texObj, GL_TRUE); + _mesa_unlock_texture(ctx, texObj); + + return TRUE; +} + +static void +st_context_destroy(struct st_context_iface *stctxi) +{ + struct st_context *st = (struct st_context *) stctxi; + st_destroy_context(st); +} + +static struct st_context_iface * +st_api_create_context(struct st_api *stapi, struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *shared_stctxi) +{ + struct st_context *shared_ctx = (struct st_context *) shared_stctxi; + struct st_context *st; + struct pipe_context *pipe; + __GLcontextModes mode; + + pipe = smapi->screen->context_create(smapi->screen, NULL); + if (!pipe) + return NULL; + + st_visual_to_context_mode(visual, &mode); + st = st_create_context(pipe, &mode, shared_ctx); + if (!st) { + pipe->destroy(pipe); + return NULL; + } + + st->iface.destroy = st_context_destroy; + + st->iface.notify_invalid_framebuffer = + st_context_notify_invalid_framebuffer; + st->iface.flush = st_context_flush; + + st->iface.teximage = st_context_teximage; + st->iface.copy = NULL; + + st->iface.st_context_private = (void *) smapi; + + return &st->iface; +} + +static boolean +st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct st_context *st = (struct st_context *) stctxi; + struct st_framebuffer *stdraw, *stread, *stfb; + boolean ret; + + _glapi_check_multithread(); + + if (st) { + /* reuse/create the draw fb */ + stfb = st_framebuffer(st->ctx->WinSysDrawBuffer); + if (stfb && stfb->iface == stdrawi) { + stdraw = NULL; + st_framebuffer_reference(&stdraw, stfb); + } + else { + stdraw = st_framebuffer_create(stdrawi); + } + + /* reuse/create the read fb */ + stfb = st_framebuffer(st->ctx->WinSysReadBuffer); + if (!stfb || stfb->iface != streadi) + stfb = stdraw; + if (stfb && stfb->iface == streadi) { + stread = NULL; + st_framebuffer_reference(&stread, stfb); + } + else { + stread = st_framebuffer_create(streadi); + } + + if (stdraw && stread) { + st_framebuffer_validate(stdraw, st); + if (stread != stdraw) + st_framebuffer_validate(stread, st); + + /* modify the draw/read buffers of the context */ + st_visual_to_default_buffer(stdraw->iface->visual, + &st->ctx->Color.DrawBuffer[0], NULL); + st_visual_to_default_buffer(stread->iface->visual, + &st->ctx->Pixel.ReadBuffer, NULL); + + ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); + } + else { + ret = FALSE; + } + + st_framebuffer_reference(&stdraw, NULL); + st_framebuffer_reference(&stread, NULL); + } + else { + ret = _mesa_make_current(NULL, NULL, NULL); + } + + return ret; +} + +static struct st_context_iface * +st_api_get_current(struct st_api *stapi) +{ + GET_CURRENT_CONTEXT(ctx); + struct st_context *st = (ctx) ? ctx->st : NULL; + + return (st) ? &st->iface : NULL; +} + +static boolean +st_api_is_visual_supported(struct st_api *stapi, + const struct st_visual *visual) +{ + return TRUE; +} + +static st_proc_t +st_api_get_proc_address(struct st_api *stapi, const char *procname) +{ + return (st_proc_t) _glapi_get_proc_address(procname); +} + +static void +st_api_destroy(struct st_api *stapi) +{ + FREE(stapi); +} + +/** + * Flush the front buffer if the current context renders to the front buffer. + */ +void +st_manager_flush_frontbuffer(struct st_context *st) +{ + struct st_framebuffer *stfb = st_framebuffer(st->ctx->DrawBuffer); + struct st_renderbuffer *strb = NULL; + + if (stfb) + strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + if (!strb) + return; + + /* st_public.h */ + if (!stfb->iface) { + struct pipe_surface *front_surf = strb->surface; + st->pipe->screen->flush_frontbuffer(st->pipe->screen, + front_surf, st->winsys_drawable_handle); + return; + } + + stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT); +} + +/** + * Re-validate the framebuffers. + */ +void +st_manager_validate_framebuffers(struct st_context *st) +{ + struct st_framebuffer *stdraw = st_framebuffer(st->ctx->DrawBuffer); + struct st_framebuffer *stread = st_framebuffer(st->ctx->ReadBuffer); + + /* st_public.h */ + if ((stdraw && !stdraw->iface) || (stread && !stread->iface)) { + struct pipe_screen *screen = st->pipe->screen; + if (screen->update_buffer) + screen->update_buffer(screen, st->pipe->priv); + return; + } + + if (stdraw) + st_framebuffer_validate(stdraw, st); + if (stread && stread != stdraw) + st_framebuffer_validate(stread, st); +} + +/** + * Add a color renderbuffer on demand. + */ +boolean +st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, + gl_buffer_index idx) +{ + struct st_framebuffer *stfb = st_framebuffer(fb); + + /* FBO or st_public.h */ + if (!stfb || !stfb->iface) + return FALSE; + + if (stfb->Base.Attachment[idx].Renderbuffer) + return TRUE; + + switch (idx) { + case BUFFER_FRONT_LEFT: + case BUFFER_BACK_LEFT: + case BUFFER_FRONT_RIGHT: + case BUFFER_BACK_RIGHT: + break; + default: + return FALSE; + break; + } + + if (!st_framebuffer_add_renderbuffer(stfb, idx)) + return FALSE; + + st_framebuffer_update_attachments(stfb); + st_invalidate_state(st->ctx, _NEW_BUFFERS); + + return TRUE; +} + +/** + * Create an st_api to manage the state tracker. + */ +struct st_api * +st_manager_create_api(void) +{ + struct st_api *stapi; + + stapi = CALLOC_STRUCT(st_api); + if (stapi) { + stapi->destroy = st_api_destroy; + stapi->get_proc_address = st_api_get_proc_address; + stapi->is_visual_supported = st_api_is_visual_supported; + + stapi->create_context = st_api_create_context; + stapi->make_current = st_api_make_current; + stapi->get_current = st_api_get_current; + } + + return stapi; +} diff --git a/src/mesa/state_tracker/st_manager.h b/src/mesa/state_tracker/st_manager.h new file mode 100644 index 0000000000..a3f5199223 --- /dev/null +++ b/src/mesa/state_tracker/st_manager.h @@ -0,0 +1,47 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL 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: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef ST_MANAGER_H +#define ST_MANAGER_H + +#include "state_tracker/st_api.h" +#include "st_context.h" + +void +st_manager_flush_frontbuffer(struct st_context *st); + +void +st_manager_validate_framebuffers(struct st_context *st); + +boolean +st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, + gl_buffer_index idx); + +struct st_api * +st_manager_create_api(void); + +#endif /* ST_MANAGER_H */ diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index fea815dce3..96eb6e0301 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -342,21 +342,12 @@ st_texture_image_copy(struct pipe_context *pipe, src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i, PIPE_BUFFER_USAGE_BLIT_SOURCE); - if (pipe->surface_copy) { - pipe->surface_copy(pipe, - dst_surface, - 0, 0, /* destX, Y */ - src_surface, - 0, 0, /* srcX, Y */ - width, height); - } else { - util_surface_copy(pipe, FALSE, - dst_surface, - 0, 0, /* destX, Y */ - src_surface, - 0, 0, /* srcX, Y */ - width, height); - } + pipe->surface_copy(pipe, + dst_surface, + 0, 0, /* destX, Y */ + src_surface, + 0, 0, /* srcX, Y */ + width, height); pipe_surface_reference(&src_surface, NULL); pipe_surface_reference(&dst_surface, NULL); @@ -528,15 +519,22 @@ st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex, /* save the renderbuffer's surface/texture info */ pipe_resource_reference(&strb->texture_save, strb->texture); pipe_surface_reference(&strb->surface_save, strb->surface); + pipe_sampler_view_reference(&strb->sampler_view_save, strb->sampler_view); /* plug in new surface/texture info */ pipe_resource_reference(&strb->texture, stImage->pt); + + /* XXX: Shouldn't we release reference to old surface here? + */ + strb->surface = screen->get_tex_surface(screen, strb->texture, face, level, slice, (PIPE_BUFFER_USAGE_RENDER_TARGET | PIPE_BUFFER_USAGE_BLIT_SOURCE | PIPE_BUFFER_USAGE_BLIT_DESTINATION)); + pipe_sampler_view_reference(&strb->sampler_view, NULL); + st->dirty.st |= ST_NEW_FRAMEBUFFER; return 1; @@ -566,9 +564,11 @@ st_release_teximage(struct st_framebuffer *stfb, uint surfIndex, /* free tex surface, restore original */ pipe_surface_reference(&strb->surface, strb->surface_save); pipe_resource_reference(&strb->texture, strb->texture_save); + pipe_sampler_view_reference(&strb->sampler_view, strb->sampler_view_save); pipe_surface_reference(&strb->surface_save, NULL); pipe_resource_reference(&strb->texture_save, NULL); + pipe_sampler_view_reference(&strb->sampler_view, NULL); st->dirty.st |= ST_NEW_FRAMEBUFFER; diff --git a/src/mesa/swrast/s_aatriangle.c b/src/mesa/swrast/s_aatriangle.c index fe3338ecef..1d90f322a3 100644 --- a/src/mesa/swrast/s_aatriangle.c +++ b/src/mesa/swrast/s_aatriangle.c @@ -268,88 +268,6 @@ compute_coveragef(const GLfloat v0[3], const GLfloat v1[3], -/* - * Compute how much (area) of the given pixel is inside the triangle. - * Vertices MUST be specified in counter-clockwise order. - * Return: coverage in [0, 15]. - */ -static GLint -compute_coveragei(const GLfloat v0[3], const GLfloat v1[3], - const GLfloat v2[3], GLint winx, GLint winy) -{ - /* NOTE: 15 samples instead of 16. */ - static const GLfloat samples[15][2] = { - /* start with the four corners */ - { POS(0, 2), POS(0, 0) }, - { POS(3, 3), POS(0, 2) }, - { POS(0, 0), POS(3, 1) }, - { POS(3, 1), POS(3, 3) }, - /* continue with interior samples */ - { POS(1, 1), POS(0, 1) }, - { POS(2, 0), POS(0, 3) }, - { POS(0, 3), POS(1, 3) }, - { POS(1, 2), POS(1, 0) }, - { POS(2, 3), POS(1, 2) }, - { POS(3, 2), POS(1, 1) }, - { POS(0, 1), POS(2, 2) }, - { POS(1, 0), POS(2, 1) }, - { POS(2, 1), POS(2, 3) }, - { POS(3, 0), POS(2, 0) }, - { POS(1, 3), POS(3, 0) } - }; - const GLfloat x = (GLfloat) winx; - const GLfloat y = (GLfloat) winy; - const GLfloat dx0 = v1[0] - v0[0]; - const GLfloat dy0 = v1[1] - v0[1]; - const GLfloat dx1 = v2[0] - v1[0]; - const GLfloat dy1 = v2[1] - v1[1]; - const GLfloat dx2 = v0[0] - v2[0]; - const GLfloat dy2 = v0[1] - v2[1]; - GLint stop = 4, i; - GLint insideCount = 15; - -#ifdef DEBUG - { - const GLfloat area = dx0 * dy1 - dx1 * dy0; - ASSERT(area >= 0.0); - } -#endif - - for (i = 0; i < stop; i++) { - const GLfloat sx = x + samples[i][0]; - const GLfloat sy = y + samples[i][1]; - const GLfloat fx0 = sx - v0[0]; - const GLfloat fy0 = sy - v0[1]; - const GLfloat fx1 = sx - v1[0]; - const GLfloat fy1 = sy - v1[1]; - const GLfloat fx2 = sx - v2[0]; - const GLfloat fy2 = sy - v2[1]; - /* cross product determines if sample is inside or outside each edge */ - GLfloat cross0 = (dx0 * fy0 - dy0 * fx0); - GLfloat cross1 = (dx1 * fy1 - dy1 * fx1); - GLfloat cross2 = (dx2 * fy2 - dy2 * fx2); - /* Check if the sample is exactly on an edge. If so, let cross be a - * positive or negative value depending on the direction of the edge. - */ - if (cross0 == 0.0F) - cross0 = dx0 + dy0; - if (cross1 == 0.0F) - cross1 = dx1 + dy1; - if (cross2 == 0.0F) - cross2 = dx2 + dy2; - if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F) { - /* point is outside triangle */ - insideCount--; - stop = 15; - } - } - if (stop == 4) - return 15; - else - return insideCount; -} - - static void rgba_aa_tri(GLcontext *ctx, const SWvertex *v0, |