diff options
Diffstat (limited to 'src')
115 files changed, 20465 insertions, 117 deletions
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template index 6f2314ee8cb..43c0e912bf2 100644 --- a/src/mesa/drivers/dri/Makefile.template +++ b/src/mesa/drivers/dri/Makefile.template @@ -85,7 +85,7 @@ $(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME) depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) touch depend $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \ - $(ASM_SOURCES) 2>&1 /dev/null + $(ASM_SOURCES) 2> /dev/null # Emacs tags diff --git a/src/mesa/drivers/dri/i915tex/i915_vtbl.c b/src/mesa/drivers/dri/i915tex/i915_vtbl.c index ad333b490b7..0e7ca9586e8 100644 --- a/src/mesa/drivers/dri/i915tex/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915tex/i915_vtbl.c @@ -464,6 +464,7 @@ i915_state_draw_region(struct intel_context *intel, * Set stride/cpp values */ if (color_region) { +// fprintf(stderr, "color pitch %d\n", color_region->pitch); state->Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD; state->Buffer[I915_DESTREG_CBUFADDR1] = (BUF_3D_ID_COLOR_BACK | @@ -472,6 +473,7 @@ i915_state_draw_region(struct intel_context *intel, } if (depth_region) { +// fprintf(stderr, "depth pitch %d\n", depth_region->pitch); state->Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD; state->Buffer[I915_DESTREG_DBUFADDR1] = (BUF_3D_ID_DEPTH | diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c index dbe4ba2ac5e..c755eac6b2c 100644 --- a/src/mesa/drivers/dri/i915tex/intel_blit.c +++ b/src/mesa/drivers/dri/i915tex/intel_blit.c @@ -79,15 +79,25 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, */ LOCK_HARDWARE(intel); + if (intel->revalidateDrawable) { + __DRIscreenPrivate *sPriv = intel->driScreen; + if (dPriv) { + DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); + } + } + if (dPriv && dPriv->numClipRects) { struct intel_framebuffer *intel_fb = dPriv->driverPrivate; const struct intel_region *frontRegion - = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); + = intelScreen->front_region; const struct intel_region *backRegion - = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); + = intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT ? + intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT) : + intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); const int nbox = dPriv->numClipRects; const drm_clip_rect_t *pbox = dPriv->pClipRects; const int pitch = frontRegion->pitch; + const int srcpitch = backRegion->pitch; const int cpp = frontRegion->cpp; int BR13, CMD; int i; @@ -96,9 +106,12 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ ASSERT(frontRegion); ASSERT(backRegion); - ASSERT(frontRegion->pitch == backRegion->pitch); +// ASSERT(frontRegion->pitch == backRegion->pitch); ASSERT(frontRegion->cpp == backRegion->cpp); + DBG("front pitch %d back pitch %d\n", + frontRegion->pitch, backRegion->pitch); + if (cpp == 2) { BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); CMD = XY_SRC_COPY_BLT_CMD; @@ -111,6 +124,7 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, for (i = 0; i < nbox; i++, pbox++) { drm_clip_rect_t box; + drm_clip_rect_t sbox; if (pbox->x1 > pbox->x2 || pbox->y1 > pbox->y2 || @@ -133,6 +147,14 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, continue; } + DBG("box x1 x2 y1 y2 %d %d %d %d\n", + box.x1, box.x2, box.y1, box.y2); + + /* XXX should make sure only the minimum area based on + old draw buffer and new front clip rects is copied */ + sbox.x1 = box.x1 - dPriv->x; + sbox.y1 = box.y1 - dPriv->y; + BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); OUT_BATCH(CMD); OUT_BATCH(BR13); @@ -141,8 +163,8 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); - OUT_BATCH((pbox->y1 << 16) | pbox->x1); - OUT_BATCH(BR13 & 0xffff); + OUT_BATCH((sbox.y1 << 16) | sbox.x1); + OUT_BATCH((srcpitch * cpp) & 0xffff); OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); @@ -156,6 +178,12 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv, } UNLOCK_HARDWARE(intel); + + if (intel->revalidateDrawable) { + intel->revalidateDrawable = GL_FALSE; + intelWindowMoved(intel); + } + } @@ -409,9 +437,8 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask) b = *box; } - if (0) - _mesa_printf("clear %d,%d..%d,%d, mask %x\n", - b.x1, b.y1, b.x2, b.y2, mask); + DBG("clear %d,%d..%d,%d, mask %x\n", + b.x1, b.y1, b.x2, b.y2, mask); /* Loop over all renderbuffers */ for (buf = 0; buf < BUFFER_COUNT && clearMask; buf++) { diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 15d02f8e2cf..17b4feadf85 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -146,57 +146,30 @@ intelSetRenderbufferClipRects(struct intel_context *intel) intel->drawY = 0; } - /** - * As above, but for rendering to front buffer of a window. - * \sa intelSetRenderbufferClipRects + * As above, but for rendering private front/back buffer of a window. + * \sa intelSetPrivbufClipRects */ -static void -intelSetFrontClipRects(struct intel_context *intel) -{ - __DRIdrawablePrivate *dPriv = intel->driDrawable; - - if (!dPriv) - return; - - intel->numClipRects = dPriv->numClipRects; - intel->pClipRects = dPriv->pClipRects; - intel->drawX = dPriv->x; - intel->drawY = dPriv->y; -} - -/** - * As above, but for rendering to back buffer of a window. - */ static void -intelSetBackClipRects(struct intel_context *intel) +intelSetPrivbufClipRects(struct intel_context *intel) { __DRIdrawablePrivate *dPriv = intel->driDrawable; - struct intel_framebuffer *intel_fb; - if (!dPriv) return; - intel_fb = dPriv->driverPrivate; - - if (intel_fb->pf_active || dPriv->numBackClipRects == 0) { - /* use the front clip rects */ - intel->numClipRects = dPriv->numClipRects; - intel->pClipRects = dPriv->pClipRects; - intel->drawX = dPriv->x; - intel->drawY = dPriv->y; - } - else { - /* use the back clip rects */ - intel->numClipRects = dPriv->numBackClipRects; - intel->pClipRects = dPriv->pBackClipRects; - intel->drawX = dPriv->backX; - intel->drawY = dPriv->backY; - } + intel->fakeClipRect.x1 = 0; + intel->fakeClipRect.y1 = 0; + intel->fakeClipRect.x2 = dPriv->w; + intel->fakeClipRect.y2 = dPriv->h; + intel->numClipRects = 1; + intel->pClipRects = &intel->fakeClipRect; + intel->drawX = 0; + intel->drawY = 0; } + /** * This will be called whenever the currently bound window is moved/resized. * XXX: actually, it seems to NOT be called when the window is only moved (BP). @@ -210,27 +183,10 @@ intelWindowMoved(struct intel_context *intel) if (!intel->ctx.DrawBuffer) { /* when would this happen? -BP */ - intelSetFrontClipRects(intel); - } - else if (intel->ctx.DrawBuffer->Name != 0) { - /* drawing to user-created FBO - do nothing */ - /* Cliprects would be set from intelDrawBuffer() */ - } - else { - /* drawing to a window */ - switch (intel_fb->Base._ColorDrawBufferMask[0]) { - case BUFFER_BIT_FRONT_LEFT: - intelSetFrontClipRects(intel); - break; - case BUFFER_BIT_BACK_LEFT: - intelSetBackClipRects(intel); - break; - default: - /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ - intelSetFrontClipRects(intel); - } + intel->numClipRects = 0; } + if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) { drmI830Sarea *sarea = intel->sarea; drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w, @@ -482,6 +438,7 @@ void intelRotateWindow(struct intel_context *intel, __DRIdrawablePrivate * dPriv, GLuint srcBuf) { + intelScreenPrivate *screen = intel->intelScreen; drm_clip_rect_t fullRect; struct intel_framebuffer *intel_fb; @@ -913,7 +870,7 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv) GLboolean missed_target; struct intel_framebuffer *intel_fb = dPriv->driverPrivate; int64_t ust; - + _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ if (screen->current_rotation != 0 || @@ -957,10 +914,17 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) if (ctx->Visual.doubleBufferMode) { drm_clip_rect_t rect; +#if 1 rect.x1 = x + dPriv->x; rect.y1 = (dPriv->h - y - h) + dPriv->y; rect.x2 = rect.x1 + w; rect.y2 = rect.y1 + h; +#else + rect.x1 = x; + rect.y1 = dPriv->h - y; + rect.x2 = rect.x1 + w; + rect.y2 = rect.y1 + h; +#endif _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ intelCopyBuffer(dPriv, &rect); } @@ -995,7 +959,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) return; } - /* Do this here, note core Mesa, since this function is called from + /* Do this here, not core Mesa, since this function is called from * many places within the driver. */ if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { @@ -1019,12 +983,7 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) /* * How many color buffers are we drawing into? */ - if (fb->_NumColorDrawBuffers[0] != 1 -#if 0 - /* XXX FBO temporary - always use software rendering */ - || 1 -#endif - ) { + if (fb->_NumColorDrawBuffers[0] != 1) { /* writing to 0 or 2 or 4 color buffers */ /*_mesa_debug(ctx, "Software rendering\n");*/ FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); @@ -1044,13 +1003,12 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) * And set up cliprects. */ if (fb->Name == 0) { + intelSetPrivbufClipRects(intel); /* drawing to window system buffer */ if (front) { - intelSetFrontClipRects(intel); colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); } else { - intelSetBackClipRects(intel); colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT); } } diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index 40ea7564126..61842da29d9 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -60,6 +60,10 @@ #include "intel_buffer_objects.h" #include "intel_fbo.h" +#include "pipe/softpipe/sp_context.h" +#include "state_tracker/st_public.h" + + #include "drirenderbuffer.h" #include "vblank.h" #include "utils.h" @@ -256,6 +260,9 @@ intelInvalidateState(GLcontext * ctx, GLuint new_state) _vbo_InvalidateState(ctx, new_state); _tnl_InvalidateState(ctx, new_state); _tnl_invalidate_vertex_state(ctx, new_state); + + st_invalidate_state( ctx, new_state ); + intel_context(ctx)->NewGLState |= new_state; } @@ -282,18 +289,22 @@ intelFlush(GLcontext * ctx) * Check if we need to rotate/warp the front color buffer to the * rotated screen. We generally need to do this when we get a glFlush * or glFinish after drawing to the front color buffer. + * If no rotation, just copy the private fake front buffer to the real one. */ static void -intelCheckFrontRotate(GLcontext * ctx) +intelCheckFrontUpdate(GLcontext * ctx) { struct intel_context *intel = intel_context(ctx); if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) { intelScreenPrivate *screen = intel->intelScreen; + __DRIdrawablePrivate *dPriv = intel->driDrawable; if (screen->current_rotation != 0) { - __DRIdrawablePrivate *dPriv = intel->driDrawable; intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); } + else { + intelCopyBuffer(dPriv, NULL); + } } } @@ -305,7 +316,7 @@ static void intelglFlush(GLcontext * ctx) { intelFlush(ctx); - intelCheckFrontRotate(ctx); + intelCheckFrontUpdate(ctx); } void @@ -319,7 +330,7 @@ intelFinish(GLcontext * ctx) driFenceUnReference(intel->batch->last_fence); intel->batch->last_fence = NULL; } - intelCheckFrontRotate(ctx); + intelCheckFrontUpdate(ctx); } @@ -505,6 +516,11 @@ intelInitContext(struct intel_context *intel, FALLBACK(intel, INTEL_FALLBACK_USER, 1); } + + st_create_context( &intel->ctx, + softpipe_create() ); + + return GL_TRUE; } @@ -569,6 +585,13 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, __DRIdrawablePrivate * driReadPriv) { +#if 0 + if (driDrawPriv) { + fprintf(stderr, "x %d, y %d, width %d, height %d\n", + driDrawPriv->x, driDrawPriv->y, driDrawPriv->w, driDrawPriv->h); + } +#endif + if (driContextPriv) { struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; @@ -576,6 +599,9 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, (struct intel_framebuffer *) driDrawPriv->driverPrivate; GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate; + /* this is a hack so we have a valid context when the region allocation + is done. Need a per-screen context? */ + intel->intelScreen->dummyctxptr = intel; /* XXX FBO temporary fix-ups! */ /* if the renderbuffers don't have regions, init them from the context */ @@ -613,6 +639,7 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, } _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb); + intel->intelScreen->dummyctxptr = &intel->ctx; /* The drawbuffer won't always be updated by _mesa_make_current: */ @@ -669,7 +696,8 @@ intelContendedLock(struct intel_context *intel, GLuint flags) * checking must be done *after* this call: */ if (dPriv) - DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); + intel->revalidateDrawable = GL_TRUE; +// DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); if (sarea->width != intelScreen->width || sarea->height != intelScreen->height || @@ -678,6 +706,7 @@ intelContendedLock(struct intel_context *intel, GLuint flags) intelUpdateScreenRotation(sPriv, sarea); } +#if 0 if (sarea->width != intel->width || sarea->height != intel->height || sarea->rotation != intel->current_rotation) { @@ -710,13 +739,7 @@ intelContendedLock(struct intel_context *intel, GLuint flags) intel->height = sarea->height; intel->current_rotation = sarea->rotation; } - - /* Drawable changed? - */ - if (dPriv && intel->lastStamp != dPriv->lastStamp) { - intelWindowMoved(intel); - intel->lastStamp = dPriv->lastStamp; - } +#endif } diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index 9d060eb866f..7b97c564a3e 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -254,6 +254,7 @@ struct intel_context GLuint numClipRects; /**< cliprects for drawing */ drm_clip_rect_t *pClipRects; drm_clip_rect_t fboRect; /**< cliprect for FBO rendering */ + drm_clip_rect_t fakeClipRect; /**< cliprect for priv back/fake front buffers rendering */ int perf_boxes; @@ -272,6 +273,7 @@ struct intel_context drmI830Sarea *sarea; GLuint lastStamp; + GLuint revalidateDrawable; /** * Configuration cache @@ -353,7 +355,7 @@ __memcpy(void *to, const void *from, size_t n) /* ================================================================ * Debugging: */ -#define DO_DEBUG 0 +#define DO_DEBUG 1 #if DO_DEBUG extern int INTEL_DEBUG; #else diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c index 6f99f401c7c..a09db46163d 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.c +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.c @@ -176,7 +176,7 @@ intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb, /** * Called via glRenderbufferStorageEXT() to set the format and allocate - * storage for a user-created renderbuffer. + * storage for a user-created (or priv buffer) renderbuffer. */ static GLboolean intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, @@ -188,8 +188,6 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, GLboolean softwareBuffer = GL_FALSE; int cpp; - ASSERT(rb->Name != 0); - switch (internalFormat) { case GL_R3_G3_B2: case GL_RGB4: @@ -257,7 +255,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, break; default: _mesa_problem(ctx, - "Unexpected format in intel_alloc_renderbuffer_storage"); + "Unexpected format (%x) in intel_alloc_renderbuffer_storage", internalFormat); return GL_FALSE; } @@ -453,6 +451,29 @@ intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height, return irb; } +struct gl_renderbuffer * +intel_new_renderbuffer_fb(GLcontext * ctx, GLuint intFormat) +{ + struct intel_renderbuffer *irb; + + irb = CALLOC_STRUCT(intel_renderbuffer); + if (!irb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); + return NULL; + } + + _mesa_init_renderbuffer(&irb->Base, 0); + irb->Base.ClassID = INTEL_RB_CLASS; + irb->Base.InternalFormat = intFormat; + + /* intel-specific methods */ + irb->Base.Delete = intel_delete_renderbuffer; + irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; + irb->Base.GetPointer = intel_get_pointer; + /* span routines set in alloc_storage function */ + + return &irb->Base; +} /** * Create a new renderbuffer object. diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c index 2acdead63d5..08057a66006 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.c +++ b/src/mesa/drivers/dri/i915tex/intel_screen.c @@ -88,6 +88,7 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv) _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!"); } +#if 0 if (0) _mesa_printf("Back 0x%08x ", intelScreen->back.handle); if (drmMap(sPriv->fd, @@ -119,6 +120,7 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv) intelUnmapScreenRegions(intelScreen); return GL_FALSE; } +#endif #if 0 _mesa_printf("TEX 0x%08x ", intelScreen->tex.handle); @@ -156,7 +158,7 @@ intel_recreate_static(intelScreenPrivate *intelScreen, } return region; } - + /* Create intel_region structs to describe the static front,back,depth * buffers created by the xserver. @@ -172,6 +174,7 @@ intel_recreate_static(intelScreenPrivate *intelScreen, static void intel_recreate_static_regions(intelScreenPrivate *intelScreen) { +/* this is the real front buffer which is only used for blitting to */ intelScreen->front_region = intel_recreate_static(intelScreen, intelScreen->front_region, @@ -192,7 +195,7 @@ intel_recreate_static_regions(intelScreenPrivate *intelScreen) intelScreen->rotated.pitch / intelScreen->cpp, intelScreen->height); - +#if 0 intelScreen->back_region = intel_recreate_static(intelScreen, intelScreen->back_region, @@ -226,6 +229,7 @@ intel_recreate_static_regions(intelScreenPrivate *intelScreen) intelScreen->cpp, intelScreen->depth.pitch / intelScreen->cpp, intelScreen->height); +#endif } /** @@ -382,7 +386,7 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen, intelScreen->rotatedWidth = sarea->virtualX; intelScreen->rotatedHeight = sarea->virtualY; - if (0) + if (1) intelPrintSAREA(sarea); } @@ -600,6 +604,7 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis); +#if 0 /* setup the hardware-based renderbuffers */ { intel_fb->color_rb[0] @@ -640,7 +645,6 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base); } } - if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { /* combined depth/stencil buffer */ struct intel_renderbuffer *depthStencilRb @@ -670,6 +674,50 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); } +#else + { + /* fake frontbuffer */ + /* XXX allocation should only happen in the unusual case + it's actually needed */ + intel_fb->color_rb[0] + = intel_new_renderbuffer_fb(NULL, rgbFormat); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, + &intel_fb->color_rb[0]->Base); + } + + if (mesaVis->doubleBufferMode) { + intel_fb->color_rb[1] + = intel_new_renderbuffer_fb(NULL, rgbFormat); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, + &intel_fb->color_rb[1]->Base); + + if (screen->third.handle) { + struct gl_renderbuffer *tmp_rb = NULL; + + intel_fb->color_rb[2] + = intel_new_renderbuffer_fb(NULL, rgbFormat); + _mesa_reference_renderbuffer(&tmp_rb, &intel_fb->color_rb[2]->Base); + } + } + if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { + /* combined depth/stencil buffer */ + struct intel_renderbuffer *depthStencilRb + = intel_new_renderbuffer_fb(NULL, GL_DEPTH24_STENCIL8_EXT); + /* note: bind RB to two attachment points */ + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, + &depthStencilRb->Base); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, + &depthStencilRb->Base); + } + else if (mesaVis->depthBits == 16) { + /* just 16-bit depth buffer, no hw stencil */ + struct intel_renderbuffer *depthRb + = intel_new_renderbuffer_fb(NULL, GL_DEPTH_COMPONENT16); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); + } + +#endif + /* now add any/all software-based renderbuffers we may need */ _mesa_add_soft_renderbuffers(&intel_fb->Base, GL_FALSE, /* never sw color */ @@ -939,11 +987,18 @@ struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) * context at screen creation. For now just use the current context. */ - GET_CURRENT_CONTEXT(ctx); +/* GET_CURRENT_CONTEXT(ctx); if (ctx == NULL) { _mesa_problem(NULL, "No current context in intelScreenContext\n"); return NULL; } return intel_context(ctx); +*/ + if (intelScreen->dummyctxptr == NULL) { + _mesa_problem(NULL, "No current context in intelScreenContext\n"); + return NULL; + } + return intelScreen->dummyctxptr; + } diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.h b/src/mesa/drivers/dri/i915tex/intel_screen.h index bac43aadddf..783ee35524b 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.h +++ b/src/mesa/drivers/dri/i915tex/intel_screen.h @@ -96,6 +96,7 @@ typedef struct struct _DriBufferPool *staticPool; unsigned int maxBatchSize; GLboolean havePools; + struct intel_context *dummyctxptr; } intelScreenPrivate; diff --git a/src/mesa/drivers/dri/i915tex/intel_state.c b/src/mesa/drivers/dri/i915tex/intel_state.c index 271511037e9..b2773990e4b 100644 --- a/src/mesa/drivers/dri/i915tex/intel_state.c +++ b/src/mesa/drivers/dri/i915tex/intel_state.c @@ -205,25 +205,17 @@ intelCalcViewport(GLcontext * ctx) GLfloat *m = intel->ViewportMatrix.m; GLfloat yScale, yBias; - if (ctx->DrawBuffer->Name) { - /* User created FBO */ - struct intel_renderbuffer *irb + struct intel_renderbuffer *irb = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]); - if (irb && !irb->RenderToTexture) { - /* y=0=top */ - yScale = -1.0; - yBias = irb->Base.Height; - } - else { - /* y=0=bottom */ - yScale = 1.0; - yBias = 0.0; - } + if (irb && !irb->RenderToTexture) { + /* y=0=top */ + yScale = -1.0; + yBias = irb->Base.Height; } else { - /* window buffer, y=0=top */ - yScale = -1.0; - yBias = (intel->driDrawable) ? intel->driDrawable->h : 0.0F; + /* y=0=bottom */ + yScale = 1.0; + yBias = 0.0; } m[MAT_SX] = v[MAT_SX]; diff --git a/src/mesa/drivers/x11/Makefile b/src/mesa/drivers/x11/Makefile new file mode 100644 index 00000000000..0ab1dc6e6bd --- /dev/null +++ b/src/mesa/drivers/x11/Makefile @@ -0,0 +1,2 @@ +default: + cd ../.. ; make
\ No newline at end of file diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index eaa277db4ad..f20e8104fb3 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -81,6 +81,9 @@ #include "tnl/t_pipeline.h" #include "drivers/common/driverfuncs.h" +#include "state_tracker/st_public.h" +#include "pipe/softpipe/sp_context.h" + /** * Global X driver lock */ @@ -1566,6 +1569,10 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) xmesa_register_swrast_functions( mesaCtx ); _swsetup_Wakeup(mesaCtx); + + st_create_context( mesaCtx, + softpipe_create() ); + return c; } diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index c8546236fbf..57254148561 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -53,6 +53,10 @@ #include "tnl/tnl.h" #include "tnl/t_context.h" +#include "pipe/softpipe/sp_context.h" +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_draw.h" /* @@ -391,6 +395,7 @@ clear_buffers(GLcontext *ctx, GLbitfield buffers) /* we can't handle color or index masking */ if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) { +#if 0 if (buffers & BUFFER_BIT_FRONT_LEFT) { /* clear front color buffer */ struct gl_renderbuffer *frontRb @@ -414,6 +419,15 @@ clear_buffers(GLcontext *ctx, GLbitfield buffers) buffers &= ~BUFFER_BIT_BACK_LEFT; } } +#else + /* Clear with state-tracker/pipe interface */ + struct st_context *st = st_context(ctx); + GLboolean color = (buffers & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) ? 1: 0; + GLboolean depth = (buffers & BUFFER_BIT_DEPTH) ? 1 : 0; + GLboolean stencil = (buffers & BUFFER_BIT_STENCIL) ? 1 : 0; + GLboolean accum = (buffers & BUFFER_BIT_ACCUM) ? 1 : 0; + st_clear(st, color, depth, stencil, accum); +#endif } } if (buffers) @@ -828,6 +842,9 @@ xmesa_update_state( GLcontext *ctx, GLbitfield new_state ) _vbo_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); + st_invalidate_state( ctx, new_state ); + + if (ctx->DrawBuffer->Name != 0) return; diff --git a/src/mesa/drivers/x11/xm_span.c b/src/mesa/drivers/x11/xm_span.c index a24966b3aeb..3776891e2ec 100644 --- a/src/mesa/drivers/x11/xm_span.c +++ b/src/mesa/drivers/x11/xm_span.c @@ -1303,6 +1303,17 @@ static void put_row_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS ) } + +static void *get_pointer_4_ximage( GLcontext *ctx, + struct gl_renderbuffer *rb, + GLint x, GLint y ) +{ + GET_XRB(xrb); + return PIXEL_ADDR4(xrb, x, y); +} + + + /* * Write a span of PF_8A8B8G8R-format pixels to an ximage. */ @@ -4593,6 +4604,7 @@ xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb, xrb->Base.PutMonoRow = put_mono_row_8A8B8G8R_ximage; xrb->Base.PutValues = put_values_8A8B8G8R_ximage; xrb->Base.PutMonoValues = put_mono_values_8A8B8G8R_ximage; + xrb->Base.GetPointer = get_pointer_4_ximage; } break; case PF_8A8R8G8B: @@ -4609,6 +4621,7 @@ xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb, xrb->Base.PutMonoRow = put_mono_row_8A8R8G8B_ximage; xrb->Base.PutValues = put_values_8A8R8G8B_ximage; xrb->Base.PutMonoValues = put_mono_values_8A8R8G8B_ximage; + xrb->Base.GetPointer = get_pointer_4_ximage; } break; case PF_8R8G8B: diff --git a/src/mesa/drivers/x11/xm_surface.c b/src/mesa/drivers/x11/xm_surface.c new file mode 100644 index 00000000000..58081a36a03 --- /dev/null +++ b/src/mesa/drivers/x11/xm_surface.c @@ -0,0 +1,395 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * 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 xm_surface.h + * Code to allow the softpipe code to write to X windows/buffers. + * This is a bit of a hack for now. We've basically got two different + * abstractions for color buffers: gl_renderbuffer and softpipe_surface. + * They'll need to get merged someday... + * For now, they're separate things that point to each other. + */ + + +#include "glxheader.h" +#include "GL/xmesa.h" +#include "xmesaP.h" +#include "context.h" +#include "imports.h" +#include "macros.h" +#include "framebuffer.h" +#include "renderbuffer.h" + +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "pipe/softpipe/sp_context.h" +#include "pipe/softpipe/sp_surface.h" + + +/** + * An xm_surface is derived from a softpipe_surface + */ +struct xmesa_surface +{ + struct softpipe_surface sps; + struct xmesa_renderbuffer *xrb; /** ptr back to matching xmesa_renderbuffer */ + struct gl_renderbuffer *rb; /* ptr to matching gl_renderbuffer */ +}; + + +/** + * Cast wrapper + */ +static INLINE struct xmesa_surface * +xmesa_surface(struct softpipe_surface *sps) +{ + return (struct xmesa_surface *) sps; +} + + +/** + * quad reading/writing + * These functions are just wrappers around the existing renderbuffer + * functions. + */ + +static void +read_quad_f(struct softpipe_surface *gs, GLint x, GLint y, + GLfloat (*rgba)[NUM_CHANNELS]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(gs); + struct xmesa_renderbuffer *xrb = xmsurf->xrb; + GLubyte temp[16]; + GLfloat *dst = (GLfloat *) rgba; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, temp); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8); + for (i = 0; i < 16; i++) { + dst[i] = UBYTE_TO_FLOAT(temp[i]); + } +} + +static void +read_quad_f_swz(struct softpipe_surface *gs, GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(gs); + struct xmesa_renderbuffer *xrb = xmsurf->xrb; + GLubyte temp[16]; + GLfloat *dst = (GLfloat *) rrrr; + GLuint i, j; + GET_CURRENT_CONTEXT(ctx); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, temp); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + dst[j * 4 + i] = UBYTE_TO_FLOAT(temp[i * 4 + j]); + } + } +} + +static void +write_quad_f(struct softpipe_surface *gs, GLint x, GLint y, + GLfloat (*rgba)[NUM_CHANNELS]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(gs); + struct xmesa_renderbuffer *xrb = xmsurf->xrb; + GLubyte temp[16]; + const GLfloat *src = (const GLfloat *) rgba; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + for (i = 0; i < 16; i++) { + UNCLAMPED_FLOAT_TO_UBYTE(temp[i], src[i]); + } + xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y, temp, NULL); + xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8, NULL); +} + +static void +write_quad_f_swz(struct softpipe_surface *gs, GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(gs); + struct xmesa_renderbuffer *xrb = xmsurf->xrb; + GLubyte temp[16]; + const GLfloat *src = (const GLfloat *) rrrr; + GLuint i, j; + GET_CURRENT_CONTEXT(ctx); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + i], src[i * 4 + j]); + } + } + xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y, temp, NULL); + xrb->Base.PutRow(ctx, &xrb->Base, 2, x, y + 1, temp + 8, NULL); +} + +static void +read_quad_ub(struct softpipe_surface *gs, GLint x, GLint y, + GLubyte (*rgba)[NUM_CHANNELS]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(gs); + struct xmesa_renderbuffer *xrb = xmsurf->xrb; + GET_CURRENT_CONTEXT(ctx); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, rgba); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, rgba + 2); +} + +static void +write_quad_ub(struct softpipe_surface *gs, GLint x, GLint y, + GLubyte (*rgba)[NUM_CHANNELS]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(gs); + struct xmesa_renderbuffer *xrb = xmsurf->xrb; + GET_CURRENT_CONTEXT(ctx); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y, rgba); + xrb->Base.GetRow(ctx, &xrb->Base, 2, x, y + 1, rgba + 2); +} + +static void +write_mono_row_ub(struct softpipe_surface *gs, GLuint count, GLint x, GLint y, + GLubyte rgba[NUM_CHANNELS]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(gs); + struct xmesa_renderbuffer *xrb = xmsurf->xrb; + GET_CURRENT_CONTEXT(ctx); + xrb->Base.PutMonoRow(ctx, &xrb->Base, count, x, y, rgba, NULL); +} + + +static struct xmesa_surface * +create_surface(XMesaContext xmctx, struct xmesa_renderbuffer *xrb) +{ + struct xmesa_surface *xmsurf; + + xmsurf = CALLOC_STRUCT(xmesa_surface); + if (xmsurf) { + xmsurf->xrb = xrb; + xmsurf->sps.surface.width = xrb->Base.Width; + xmsurf->sps.surface.height = xrb->Base.Height; + + xmsurf->sps.read_quad_f = read_quad_f; + xmsurf->sps.read_quad_f_swz = read_quad_f_swz; + xmsurf->sps.read_quad_ub = read_quad_ub; + xmsurf->sps.write_quad_f = write_quad_f; + xmsurf->sps.write_quad_f_swz = write_quad_f_swz; + xmsurf->sps.write_quad_ub = write_quad_ub; + xmsurf->sps.write_mono_row_ub = write_mono_row_ub; + +#if 0 + if (xrb->ximage) { + xmsurf->sps.surface.ptr = (GLubyte *) xrb->ximage->data; + xmsurf->sps.surface.stride = xrb->ximage->bytes_per_line; + xmsurf->sps.surface.cpp = xrb->ximage->depth; + + } +#endif + } + return xmsurf; +} + + +static void +free_surface(struct softpipe_surface *sps) +{ + /* XXX may need to do more in the future */ + free(sps); +} + + +/** + * Return generic surface pointer corresponding to the current color buffer. + */ +struct pipe_surface * +xmesa_get_color_surface(GLcontext *ctx, GLuint buf) +{ + XMesaContext xmctx = XMESA_CONTEXT(ctx); + struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][buf]; + struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); + struct softpipe_surface *sps = (struct softpipe_surface *) xrb->pSurface; + + if (!sps) { + xrb->pSurface = create_surface(xmctx, xrb); + } + else if (sps->surface.width != rb->Width || + sps->surface.height != rb->Height) { + free_surface(sps); + xrb->pSurface = create_surface(xmctx, xrb); + } + + return (struct pipe_surface *) xrb->pSurface; +} + + + + +static void +read_quad_z(struct softpipe_surface *sps, + GLint x, GLint y, GLuint zzzz[QUAD_SIZE]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(sps); + struct gl_renderbuffer *rb = xmsurf->rb; + GLushort temp[4]; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + rb->GetRow(ctx, rb, 2, x, y, temp); + rb->GetRow(ctx, rb, 2, x, y + 1, temp + 2); + /* convert from GLushort to GLuint */ + for (i = 0; i < 4; i++) { + zzzz[i] = temp[i]; + } +} + +static void +write_quad_z(struct softpipe_surface *sps, + GLint x, GLint y, const GLuint zzzz[QUAD_SIZE]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(sps); + struct gl_renderbuffer *rb = xmsurf->rb; + GLushort temp[4]; + GLuint i; + GET_CURRENT_CONTEXT(ctx); + /* convert from GLuint to GLushort */ + for (i = 0; i < 4; i++) { + temp[i] = zzzz[i]; + } + rb->PutRow(ctx, rb, 2, x, y, temp, NULL); + rb->PutRow(ctx, rb, 2, x, y + 1, temp + 2, NULL); +} + + +static struct xmesa_surface * +create_z_surface(XMesaContext xmctx, struct gl_renderbuffer *rb) +{ + struct xmesa_surface *xmsurf; + + xmsurf = CALLOC_STRUCT(xmesa_surface); + if (xmsurf) { + xmsurf->sps.surface.format = PIPE_FORMAT_U_Z16; + xmsurf->sps.surface.width = rb->Width; + xmsurf->sps.surface.height = rb->Height; + xmsurf->sps.read_quad_z = read_quad_z; + xmsurf->sps.write_quad_z = write_quad_z; + xmsurf->rb = rb; + } + return xmsurf; +} + + + + +static void +read_quad_stencil(struct softpipe_surface *sps, + GLint x, GLint y, GLubyte ssss[QUAD_SIZE]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(sps); + struct gl_renderbuffer *rb = xmsurf->rb; + GET_CURRENT_CONTEXT(ctx); + rb->GetRow(ctx, rb, 2, x, y, ssss); + rb->GetRow(ctx, rb, 2, x, y + 1, ssss + 2); +} + +static void +write_quad_stencil(struct softpipe_surface *sps, + GLint x, GLint y, const GLubyte ssss[QUAD_SIZE]) +{ + struct xmesa_surface *xmsurf = xmesa_surface(sps); + struct gl_renderbuffer *rb = xmsurf->rb; + GET_CURRENT_CONTEXT(ctx); + rb->PutRow(ctx, rb, 2, x, y, ssss, NULL); + rb->PutRow(ctx, rb, 2, x, y + 1, ssss + 2, NULL); +} + +static struct xmesa_surface * +create_stencil_surface(XMesaContext xmctx, struct gl_renderbuffer *rb) +{ + struct xmesa_surface *xmsurf; + + xmsurf = CALLOC_STRUCT(xmesa_surface); + if (xmsurf) { + xmsurf->sps.surface.format = PIPE_FORMAT_U_S8; + xmsurf->sps.surface.width = rb->Width; + xmsurf->sps.surface.height = rb->Height; + xmsurf->sps.read_quad_stencil = read_quad_stencil; + xmsurf->sps.write_quad_stencil = write_quad_stencil; + xmsurf->rb = rb; + } + return xmsurf; +} + + + + +/** + * Return a pipe_surface that wraps the current Z/depth buffer. + * XXX this is pretty much a total hack until gl_renderbuffers and + * pipe_surfaces are merged... + */ +struct pipe_surface * +xmesa_get_z_surface(GLcontext *ctx) +{ + XMesaContext xmctx = XMESA_CONTEXT(ctx); + struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer; + static struct xmesa_surface *xms = NULL; + + if (!rb) + return NULL; + + if (!xms) { + xms = create_z_surface(xmctx, rb); + } + else if (xms->sps.surface.width != rb->Width || + xms->sps.surface.height != rb->Height) { + free_surface(&xms->sps); + xms = create_z_surface(xmctx, rb); + } + + return (struct pipe_surface *) &xms->sps.surface; +} + + +struct pipe_surface * +xmesa_get_stencil_surface(GLcontext *ctx) +{ + XMesaContext xmctx = XMESA_CONTEXT(ctx); + struct gl_renderbuffer *rb = ctx->DrawBuffer->_StencilBuffer; + static struct xmesa_surface *xms = NULL; + + if (!rb) + return NULL; + + if (!xms) { + xms = create_stencil_surface(xmctx, rb); + } + else if (xms->sps.surface.width != rb->Width || + xms->sps.surface.height != rb->Height) { + free_surface(&xms->sps); + xms = create_stencil_surface(xmctx, rb); + } + + return (struct pipe_surface *) &xms->sps.surface; +} + diff --git a/src/mesa/drivers/x11/xm_tri.c b/src/mesa/drivers/x11/xm_tri.c index 95c6d7c1d20..9f17083f901 100644 --- a/src/mesa/drivers/x11/xm_tri.c +++ b/src/mesa/drivers/x11/xm_tri.c @@ -1443,6 +1443,46 @@ do { \ #endif +#if 0 +GLboolean xmesa_get_cbuf_details( GLcontext *ctx, + void **ptr, + GLuint *cpp, + GLint *stride, + GLuint *format ) +{ + XMesaContext xmesa = XMESA_CONTEXT(ctx); + struct gl_framebuffer *fb = ctx->DrawBuffer; + struct gl_renderbuffer *crb = fb->_ColorDrawBuffers[0][0]; + struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(crb->Wrapped); + + *ptr = crb->GetPointer(ctx, crb, 0, 0); + *stride = ((GLubyte *)crb->GetPointer(ctx, crb, 0, 1) - + (GLubyte *)crb->GetPointer(ctx, crb, 0, 0)); + + if (!ptr) + goto bad; + + switch (xmesa->pixelformat) { + case PF_8A8B8G8R: + case PF_8A8R8G8B: + *format = 1; /* whatever */ + *cpp = 4; + break; + default: + goto bad; + } + + return GL_TRUE; + + bad: + *ptr = NULL; + *stride = 0; + *format = 0; + return GL_FALSE; +} +#endif + + /** * Return pointer to line drawing function, or NULL if we should use a * swrast fallback. diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h index e3d7cf381f7..8648b199399 100644 --- a/src/mesa/drivers/x11/xmesaP.h +++ b/src/mesa/drivers/x11/xmesaP.h @@ -196,6 +196,8 @@ struct xmesa_renderbuffer GLint bottom; /* used for FLIP macro, equals height - 1 */ ClearFunc clearFunc; + + void *pSurface; /** pipe surface */ }; @@ -583,4 +585,23 @@ extern void xmesa_register_swrast_functions( GLcontext *ctx ); #define ENABLE_EXT_timer_query 0 /* may not have 64-bit GLuint64EXT */ #endif +#if 0 +GLboolean xmesa_get_cbuf_details( GLcontext *ctx, + void **ptr, + GLuint *cpp, + GLint *stride, + GLuint *format ); +#endif + +struct pipe_surface; +struct pipe_surface * +xmesa_get_color_surface(GLcontext *ctx, GLuint buf); + +struct pipe_surface * +xmesa_get_z_surface(GLcontext *ctx); + +struct pipe_surface * +xmesa_get_stencil_surface(GLcontext *ctx); + + #endif diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 3e4c49249a0..52448ee04eb 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -126,6 +126,7 @@ struct gl_pixelstore_attrib; struct gl_texture_format; struct gl_texture_image; struct gl_texture_object; +struct st_context; typedef struct __GLcontextRec GLcontext; typedef struct __GLcontextModesRec GLvisual; typedef struct gl_framebuffer GLframebuffer; @@ -3102,7 +3103,7 @@ struct __GLcontextRec void *swsetup_context; void *swtnl_context; void *swtnl_im; - void *acache_context; + struct st_context *st; void *aelt_context; /*@}*/ }; diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index 0e59ba615a7..fc04dde3f49 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -30,6 +30,11 @@ #include "queryobj.h" #include "mtypes.h" +#if 1 /*PIPE*/ +#include "pipe/p_context.h" +#include "state_tracker/st_context.h" +#endif + /** * Allocate a new query object. This is a fallback routine called via @@ -220,6 +225,10 @@ _mesa_BeginQueryARB(GLenum target, GLuint id) q->Result = 0; q->Ready = GL_FALSE; +#if 1 /*PIPE*/ + ctx->st->pipe->reset_occlusion_counter(ctx->st->pipe); +#endif + if (target == GL_SAMPLES_PASSED_ARB) { ctx->Query.CurrentOcclusionObject = q; } @@ -282,6 +291,12 @@ _mesa_EndQueryARB(GLenum target) /* if we're using software rendering/querying */ q->Ready = GL_TRUE; } + +#if 1 /*PIPE*/ + if (target == GL_SAMPLES_PASSED_ARB) { + q->Result = ctx->st->pipe->get_occlusion_counter(ctx->st->pipe); + } +#endif } diff --git a/src/mesa/pipe/Makefile b/src/mesa/pipe/Makefile new file mode 100644 index 00000000000..451911a3545 --- /dev/null +++ b/src/mesa/pipe/Makefile @@ -0,0 +1,2 @@ +default: + cd .. ; make diff --git a/src/mesa/pipe/draw/draw_clip.c b/src/mesa/pipe/draw/draw_clip.c new file mode 100644 index 00000000000..f8bacf8a818 --- /dev/null +++ b/src/mesa/pipe/draw/draw_clip.c @@ -0,0 +1,463 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \brief Clipping stage + * + * \author Keith Whitwell <[email protected]> + */ + + +#include "main/macros.h" +#include "draw_private.h" + + +struct clipper { + struct draw_stage stage; /**< base class */ + + GLuint active_user_planes; + GLfloat (*plane)[4]; +}; + + +/* This is a bit confusing: + */ +static INLINE struct clipper *clipper_stage( struct draw_stage *stage ) +{ + return (struct clipper *)stage; +} + + +#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT))) + + +/* All attributes are float[4], so this is easy: + */ +static void interp_attr( GLfloat *fdst, + GLfloat t, + const GLfloat *fin, + const GLfloat *fout ) +{ + fdst[0] = LINTERP( t, fout[0], fin[0] ); + fdst[1] = LINTERP( t, fout[1], fin[1] ); + fdst[2] = LINTERP( t, fout[2], fin[2] ); + fdst[3] = LINTERP( t, fout[3], fin[3] ); +} + + + + +/* Interpolate between two vertices to produce a third. + */ +static void interp( const struct clipper *clip, + struct vertex_header *dst, + GLfloat t, + const struct vertex_header *out, + const struct vertex_header *in ) +{ + const GLuint nr_attrs = clip->stage.draw->nr_attrs; + GLuint j; + + /* Vertex header. + */ + { + dst->clipmask = 0; + dst->edgeflag = 0; + dst->pad = 0; + } + + /* Clip coordinates: interpolate normally + */ + { + interp_attr(dst->clip, t, in->clip, out->clip); + } + + /* Do the projective divide and insert window coordinates: + */ + { + const GLfloat *pos = dst->clip; + const GLfloat *scale = clip->stage.draw->viewport.scale; + const GLfloat *trans = clip->stage.draw->viewport.translate; + const GLfloat oow = 1.0 / pos[3]; + + dst->data[0][0] = pos[0] * oow * scale[0] + trans[0]; + dst->data[0][1] = pos[1] * oow * scale[1] + trans[1]; + dst->data[0][2] = pos[2] * oow * scale[2] + trans[2]; + dst->data[0][3] = oow; + } + + /* Other attributes + * Note: start at 1 to skip winpos (data[0]) since we just computed + * it above. + * Subtract two from nr_attrs since the first two attribs (always + * VF_ATTRIB_VERTEX_HEADER and VF_ATTRIB_CLIP_POS, see + * draw_set_vertex_attributes()) are in the vertex_header struct, + * not in the data[] array. + */ + for (j = 1; j < nr_attrs - 2; j++) { + interp_attr(dst->data[j], t, in->data[j], out->data[j]); + } +} + + +#define CLIP_USER_BIT 0x40 +#define CLIP_CULL_BIT 0x80 + + +static INLINE GLfloat dot4( const GLfloat *a, + const GLfloat *b ) +{ + GLfloat result = (a[0]*b[0] + + a[1]*b[1] + + a[2]*b[2] + + a[3]*b[3]); + + return result; +} + + +#if 0 +static INLINE void do_tri( struct draw_stage *next, + struct prim_header *header ) +{ + GLuint i; + for (i = 0; i < 3; i++) { + GLfloat *ndc = header->v[i]->data[0]; + _mesa_printf("ndc %f %f %f\n", ndc[0], ndc[1], ndc[2]); + assert(ndc[0] >= -1 && ndc[0] <= 641); + assert(ndc[1] >= 30 && ndc[1] <= 481); + } + _mesa_printf("\n"); + next->tri(next, header); +} +#endif + + +static void emit_poly( struct draw_stage *stage, + struct vertex_header **inlist, + GLuint n ) +{ + struct prim_header header; + GLuint i; + + for (i = 2; i < n; i++) { + header.v[0] = inlist[0]; + header.v[1] = inlist[i-1]; + header.v[2] = inlist[i]; + + { + GLuint tmp0 = header.v[0]->edgeflag; + GLuint tmp2 = header.v[2]->edgeflag; + + if (i != 2) header.v[0]->edgeflag = 0; + if (i != n-1) header.v[2]->edgeflag = 0; + + stage->next->tri( stage->next, &header ); + + header.v[0]->edgeflag = tmp0; + header.v[2]->edgeflag = tmp2; + } + } +} + + +#if 0 +static void emit_poly( struct draw_stage *stage ) +{ + GLuint i; + + for (i = 2; i < n; i++) { + header->v[0] = inlist[0]; + header->v[1] = inlist[i-1]; + header->v[2] = inlist[i]; + + stage->next->tri( stage->next, header ); + } +} +#endif + + +/* Clip a triangle against the viewport and user clip planes. + */ +static void +do_clip_tri( struct draw_stage *stage, + struct prim_header *header, + GLuint clipmask ) +{ + struct clipper *clipper = clipper_stage( stage ); + struct vertex_header *a[MAX_CLIPPED_VERTICES]; + struct vertex_header *b[MAX_CLIPPED_VERTICES]; + struct vertex_header **inlist = a; + struct vertex_header **outlist = b; + GLuint tmpnr = 0; + GLuint n = 3; + GLuint i; + + inlist[0] = header->v[0]; + inlist[1] = header->v[1]; + inlist[2] = header->v[2]; + + /* XXX: Note stupid hack to deal with tnl's 8-bit clipmask. Remove + * this once we correctly use 16bit masks for userclip planes. + */ + clipmask &= ~CLIP_CULL_BIT; + if (clipmask & CLIP_USER_BIT) { + clipmask &= ~CLIP_USER_BIT; + clipmask |= clipper->active_user_planes; + } + + while (clipmask && n >= 3) { + GLuint plane_idx = ffs(clipmask)-1; + const GLfloat *plane = clipper->plane[plane_idx]; + struct vertex_header *vert_prev = inlist[0]; + GLfloat dp_prev = dot4( vert_prev->clip, plane ); + GLuint outcount = 0; + + clipmask &= ~(1<<plane_idx); + + inlist[n] = inlist[0]; /* prevent rotation of vertices */ + + for (i = 1; i <= n; i++) { + struct vertex_header *vert = inlist[i]; + + GLfloat dp = dot4( vert->clip, plane ); + + if (!IS_NEGATIVE(dp_prev)) { + outlist[outcount++] = vert_prev; + } + + if (DIFFERENT_SIGNS(dp, dp_prev)) { + struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++]; + outlist[outcount++] = new_vert; + + if (IS_NEGATIVE(dp)) { + /* Going out of bounds. Avoid division by zero as we + * know dp != dp_prev from DIFFERENT_SIGNS, above. + */ + GLfloat t = dp / (dp - dp_prev); + interp( clipper, new_vert, t, vert, vert_prev ); + + /* Force edgeflag true in this case: + */ + new_vert->edgeflag = 1; + } else { + /* Coming back in. + */ + GLfloat t = dp_prev / (dp_prev - dp); + interp( clipper, new_vert, t, vert_prev, vert ); + + /* Copy starting vert's edgeflag: + */ + new_vert->edgeflag = vert_prev->edgeflag; + } + } + + vert_prev = vert; + dp_prev = dp; + } + + { + struct vertex_header **tmp = inlist; + inlist = outlist; + outlist = tmp; + n = outcount; + } + } + + /* Emit the polygon as triangles to the setup stage: + */ + if (n >= 3) + emit_poly( stage, inlist, n ); +} + + +/* Clip a line against the viewport and user clip planes. + */ +static void +do_clip_line( struct draw_stage *stage, + struct prim_header *header, + GLuint clipmask ) +{ + const struct clipper *clipper = clipper_stage( stage ); + struct vertex_header *v0 = header->v[0]; + struct vertex_header *v1 = header->v[1]; + const GLfloat *pos0 = v0->clip; + const GLfloat *pos1 = v1->clip; + GLfloat t0 = 0; + GLfloat t1 = 0; + struct prim_header newprim; + + /* XXX: Note stupid hack to deal with tnl's 8-bit clipmask. Remove + * this once we correctly use 16bit masks for userclip planes. + */ + clipmask &= ~CLIP_CULL_BIT; + if (clipmask & CLIP_USER_BIT) { + clipmask &= ~CLIP_USER_BIT; + clipmask |= clipper->active_user_planes; + } + + while (clipmask) { + const GLuint plane_idx = ffs(clipmask)-1; + const GLfloat *plane = clipper->plane[plane_idx]; + const GLfloat dp0 = dot4( pos0, plane ); + const GLfloat dp1 = dot4( pos1, plane ); + + if (dp1 < 0) { + GLfloat t = dp1 / (dp1 - dp0); + t1 = MAX2(t1, t); + } + + if (dp0 < 0) { + GLfloat t = dp0 / (dp0 - dp1); + t0 = MAX2(t0, t); + } + + if (t0 + t1 >= 1.0) + return; /* discard */ + + clipmask &= ~(1 << plane_idx); /* turn off this plane's bit */ + } + + if (v0->clipmask) { + interp( clipper, stage->tmp[0], t0, v0, v1 ); + newprim.v[0] = stage->tmp[0]; + } + else { + newprim.v[0] = v0; + } + + if (v1->clipmask) { + interp( clipper, stage->tmp[1], t1, v1, v0 ); + newprim.v[1] = stage->tmp[1]; + } + else { + newprim.v[1] = v1; + } + + stage->next->line( stage->next, &newprim ); +} + + +static void clip_begin( struct draw_stage *stage ) +{ + struct clipper *clipper = clipper_stage(stage); + GLuint nr = stage->draw->nr_planes; + + /* sanity checks. If these fail, review the clip/interp code! */ + assert(stage->draw->nr_attrs >= 3); + assert(stage->draw->attrs[0].attrib == VF_ATTRIB_VERTEX_HEADER); + assert(stage->draw->attrs[1].attrib == VF_ATTRIB_CLIP_POS); + + /* Hacky bitmask to use when we hit CLIP_USER_BIT: + */ + clipper->active_user_planes = ((1<<nr)-1) & ~((1<<6)-1); + + stage->next->begin( stage->next ); +} + + +static void +clip_point( struct draw_stage *stage, + struct prim_header *header ) +{ + if (header->v[0]->clipmask == 0) + stage->next->point( stage->next, header ); +} + + +static void +clip_line( struct draw_stage *stage, + struct prim_header *header ) +{ + GLuint clipmask = (header->v[0]->clipmask | + header->v[1]->clipmask); + + if (clipmask == 0) { + /* no clipping needed */ + stage->next->line( stage->next, header ); + } + else if ((header->v[0]->clipmask & + header->v[1]->clipmask) == 0) { + do_clip_line(stage, header, clipmask); + } +} + + +static void +clip_tri( struct draw_stage *stage, + struct prim_header *header ) +{ + GLuint clipmask = (header->v[0]->clipmask | + header->v[1]->clipmask | + header->v[2]->clipmask); + + if (clipmask == 0) { + /* no clipping needed */ + stage->next->tri( stage->next, header ); + } + else if ((header->v[0]->clipmask & + header->v[1]->clipmask & + header->v[2]->clipmask) == 0) { + do_clip_tri(stage, header, clipmask); + } +} + + +static void clip_end( struct draw_stage *stage ) +{ + stage->next->end( stage->next ); +} + + +static void clip_reset_stipple_counter( struct draw_stage *stage ) +{ + stage->next->reset_stipple_counter( stage->next ); +} + + +/** + * Allocate a new clipper stage. + * \return pointer to new stage object + */ +struct draw_stage *draw_clip_stage( struct draw_context *draw ) +{ + struct clipper *clipper = CALLOC_STRUCT(clipper); + + draw_alloc_tmps( &clipper->stage, MAX_CLIPPED_VERTICES ); + + clipper->stage.draw = draw; + clipper->stage.begin = clip_begin; + clipper->stage.point = clip_point; + clipper->stage.line = clip_line; + clipper->stage.tri = clip_tri; + clipper->stage.end = clip_end; + clipper->stage.reset_stipple_counter = clip_reset_stipple_counter; + + clipper->plane = draw->plane; + + return &clipper->stage; +} diff --git a/src/mesa/pipe/draw/draw_context.c b/src/mesa/pipe/draw/draw_context.c new file mode 100644 index 00000000000..a97f4883873 --- /dev/null +++ b/src/mesa/pipe/draw/draw_context.c @@ -0,0 +1,183 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "imports.h" +#include "macros.h" + +#include "draw_context.h" +#include "draw_private.h" + + +struct draw_context *draw_create( void ) +{ + struct draw_context *draw = CALLOC_STRUCT( draw_context ); + + /* create pipeline stages */ + draw->pipeline.unfilled = draw_unfilled_stage( draw ); + draw->pipeline.twoside = draw_twoside_stage( draw ); + draw->pipeline.offset = draw_offset_stage( draw ); + draw->pipeline.clip = draw_clip_stage( draw ); + draw->pipeline.flatshade = draw_flatshade_stage( draw ); + draw->pipeline.cull = draw_cull_stage( draw ); + + ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 ); + ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 ); + ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 ); + ASSIGN_4V( draw->plane[3], 0, 1, 0, 1 ); + ASSIGN_4V( draw->plane[4], 0, 0, 1, 1 ); /* yes these are correct */ + ASSIGN_4V( draw->plane[5], 0, 0, -1, 1 ); /* mesa's a bit wonky */ + draw->nr_planes = 6; + + draw->vf = vf_create( GL_TRUE ); + + return draw; +} + + +void draw_destroy( struct draw_context *draw ) +{ + if (draw->header.storage) + ALIGN_FREE( draw->header.storage ); + + vf_destroy( draw->vf ); + + FREE( draw ); +} + + +/** + * Rebuild the rendering pipeline. + */ +static void validate_pipeline( struct draw_context *draw ) +{ + struct draw_stage *next = draw->pipeline.setup; + + /* + * NOTE: we build up the pipeline in end-to-start order. + * + * TODO: make the current primitive part of the state and build + * shorter pipelines for lines & points. + */ + + if (draw->setup.fill_cw != PIPE_POLYGON_MODE_FILL || + draw->setup.fill_ccw != PIPE_POLYGON_MODE_FILL) { + draw->pipeline.unfilled->next = next; + next = draw->pipeline.unfilled; + } + + if (draw->setup.offset_cw || + draw->setup.offset_ccw) { + draw->pipeline.offset->next = next; + next = draw->pipeline.offset; + } + + if (draw->setup.light_twoside) { + draw->pipeline.twoside->next = next; + next = draw->pipeline.twoside; + } + + /* Always run the cull stage as we calculate determinant there + * also. Fix this.. + */ + { + draw->pipeline.cull->next = next; + next = draw->pipeline.cull; + } + + /* Clip stage + */ + { + draw->pipeline.clip->next = next; + next = draw->pipeline.clip; + } + + /* Do software flatshading prior to clipping. XXX: should only do + * this for clipped primitives, ie it is a part of the clip + * routine. + */ + if (draw->setup.flatshade) { + draw->pipeline.flatshade->next = next; + next = draw->pipeline.flatshade; + } + + draw->pipeline.first = next; +} + + +/** + * Register new primitive setup/rendering state. + * This causes the drawing pipeline to be rebuilt. + */ +void draw_set_setup_state( struct draw_context *draw, + const struct pipe_setup_state *setup ) +{ + memcpy( &draw->setup, setup, sizeof(*setup) ); + validate_pipeline( draw ); +} + + +/** + * Plug in the primitive rendering/rasterization stage. + * This is provided by the device driver. + */ +void draw_set_setup_stage( struct draw_context *draw, + struct draw_stage *stage ) +{ + draw->pipeline.setup = stage; +} + + +/** + * Set the draw module's clipping state. + */ +void draw_set_clip_state( struct draw_context *draw, + const struct pipe_clip_state *clip ) +{ + memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0])); + draw->nr_planes = 6 + clip->nr; +} + + +/** + * Set the draw module's viewport state. + */ +void draw_set_viewport_state( struct draw_context *draw, + const struct pipe_viewport_state *viewport ) +{ + draw->viewport = *viewport; /* struct copy */ + + vf_set_vp_scale_translate( draw->vf, viewport->scale, viewport->translate ); + + /* Using tnl/ and vf/ modules is temporary while getting started. + * Full pipe will have vertex shader, vertex fetch of its own. + */ +} diff --git a/src/mesa/pipe/draw/draw_context.h b/src/mesa/pipe/draw/draw_context.h new file mode 100644 index 00000000000..c298d4f46d2 --- /dev/null +++ b/src/mesa/pipe/draw/draw_context.h @@ -0,0 +1,74 @@ + +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \brief Public interface into the drawing module. + */ + +/* Authors: Keith Whitwell <[email protected]> + */ + + +#ifndef DRAW_CONTEXT_H +#define DRAW_CONTEXT_H + + +#include "glheader.h" +#include "pipe/p_state.h" + + +struct vertex_buffer; +struct draw_context; +struct draw_stage; + + +struct draw_context *draw_create( void ); + +void draw_destroy( struct draw_context *draw ); + +void draw_set_viewport_state( struct draw_context *draw, + const struct pipe_viewport_state *viewport ); + +void draw_set_clip_state( struct draw_context *pipe, + const struct pipe_clip_state *clip ); + +void draw_set_setup_state( struct draw_context *draw, + const struct pipe_setup_state *setup ); + +void draw_set_setup_stage( struct draw_context *draw, + struct draw_stage *stage ); + +void draw_set_vertex_attributes( struct draw_context *draw, + const GLuint *attrs, + GLuint nr_attrs ); + +void draw_vb(struct draw_context *draw, + struct vertex_buffer *VB ); + + +#endif /* DRAW_CONTEXT_H */ diff --git a/src/mesa/pipe/draw/draw_cull.c b/src/mesa/pipe/draw/draw_cull.c new file mode 100644 index 00000000000..8b2ac5ea5f9 --- /dev/null +++ b/src/mesa/pipe/draw/draw_cull.c @@ -0,0 +1,138 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \brief Drawing stage for polygon culling + */ + +/* Authors: Keith Whitwell <[email protected]> + */ + + +#include "main/imports.h" +#include "pipe/p_defines.h" +#include "draw_private.h" + + +struct cull_stage { + struct draw_stage stage; + GLuint winding; /**< which winding(s) to cull (one of PIPE_WINDING_x) */ +}; + + +static INLINE struct cull_stage *cull_stage( struct draw_stage *stage ) +{ + return (struct cull_stage *)stage; +} + + +static void cull_begin( struct draw_stage *stage ) +{ + struct cull_stage *cull = cull_stage(stage); + + cull->winding = stage->draw->setup.cull_mode; + + stage->next->begin( stage->next ); +} + + +static void cull_tri( struct draw_stage *stage, + struct prim_header *header ) +{ + /* Window coords: */ + const GLfloat *v0 = header->v[0]->data[0]; + const GLfloat *v1 = header->v[1]->data[0]; + const GLfloat *v2 = header->v[2]->data[0]; + + /* edge vectors e = v0 - v2, f = v1 - v2 */ + GLfloat ex = v0[0] - v2[0]; + GLfloat ey = v0[1] - v2[1]; + GLfloat fx = v1[0] - v2[0]; + GLfloat fy = v1[1] - v2[1]; + + /* det = cross(e,f).z */ + header->det = ex * fy - ey * fx; + + if (header->det != 0) { + /* if (det > 0 then Z points toward camera and triangle is + * counter-clockwise winding. + */ + GLuint winding = (header->det > 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW; + + if ((winding & cull_stage(stage)->winding) == 0) { + /* triangle is not culled, pass to next stage */ + stage->next->tri( stage->next, header ); + } + } +} + + +static void cull_line( struct draw_stage *stage, + struct prim_header *header ) +{ + stage->next->line( stage->next, header ); +} + + +static void cull_point( struct draw_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + + +static void cull_end( struct draw_stage *stage ) +{ + stage->next->end( stage->next ); +} + + +static void cull_reset_stipple_counter( struct draw_stage *stage ) +{ + stage->next->reset_stipple_counter( stage->next ); +} + +/** + * Create a new polygon culling stage. + */ +struct draw_stage *draw_cull_stage( struct draw_context *draw ) +{ + struct cull_stage *cull = CALLOC_STRUCT(cull_stage); + + draw_alloc_tmps( &cull->stage, 0 ); + + cull->stage.draw = draw; + cull->stage.next = NULL; + cull->stage.begin = cull_begin; + cull->stage.point = cull_point; + cull->stage.line = cull_line; + cull->stage.tri = cull_tri; + cull->stage.end = cull_end; + cull->stage.reset_stipple_counter = cull_reset_stipple_counter; + + return &cull->stage; +} diff --git a/src/mesa/pipe/draw/draw_flatshade.c b/src/mesa/pipe/draw/draw_flatshade.c new file mode 100644 index 00000000000..cf5e762079a --- /dev/null +++ b/src/mesa/pipe/draw/draw_flatshade.c @@ -0,0 +1,162 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#include "main/imports.h" +#include "draw_private.h" + + +struct flatshade_stage { + struct draw_stage stage; + + const GLuint *lookup; +}; + + + +static INLINE struct flatshade_stage *flatshade_stage( struct draw_stage *stage ) +{ + return (struct flatshade_stage *)stage; +} + + +static void flatshade_begin( struct draw_stage *stage ) +{ + stage->next->begin( stage->next ); +} + + + +static INLINE void copy_attr( GLuint attr, + struct vertex_header *dst, + const struct vertex_header *src ) +{ + if (attr) { + memcpy( dst->data[attr], + src->data[attr], + sizeof(src->data[0]) ); + } +} + + +static INLINE void copy_colors( struct draw_stage *stage, + struct vertex_header *dst, + const struct vertex_header *src ) +{ + const struct flatshade_stage *flatshade = flatshade_stage(stage); + const GLuint *lookup = flatshade->lookup; + + copy_attr( lookup[VF_ATTRIB_COLOR0], dst, src ); + copy_attr( lookup[VF_ATTRIB_COLOR1], dst, src ); + copy_attr( lookup[VF_ATTRIB_BFC0], dst, src ); + copy_attr( lookup[VF_ATTRIB_BFC1], dst, src ); +} + + +/** + * Flatshade tri. Required for clipping and when unfilled tris are + * active, otherwise handled by hardware. + */ +static void flatshade_tri( struct draw_stage *stage, + struct prim_header *header ) +{ + struct prim_header tmp; + + tmp.det = header->det; + tmp.v[0] = dup_vert(stage, header->v[0], 0); + tmp.v[1] = dup_vert(stage, header->v[1], 1); + tmp.v[2] = header->v[2]; + + copy_colors(stage, tmp.v[0], tmp.v[2]); + copy_colors(stage, tmp.v[1], tmp.v[2]); + + stage->next->tri( stage->next, &tmp ); +} + + +/** + * Flatshade line. Required for clipping. + */ +static void flatshade_line( struct draw_stage *stage, + struct prim_header *header ) +{ + struct prim_header tmp; + + tmp.v[0] = dup_vert(stage, header->v[0], 0); + tmp.v[1] = header->v[1]; + + copy_colors(stage, tmp.v[0], tmp.v[1]); + + stage->next->line( stage->next, &tmp ); +} + + +static void flatshade_point( struct draw_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + + +static void flatshade_end( struct draw_stage *stage ) +{ + stage->next->end( stage->next ); +} + + +static void flatshade_reset_stipple_counter( struct draw_stage *stage ) +{ + stage->next->reset_stipple_counter( stage->next ); +} + + +/** + * Create flatshading drawing stage. + */ +struct draw_stage *draw_flatshade_stage( struct draw_context *draw ) +{ + struct flatshade_stage *flatshade = CALLOC_STRUCT(flatshade_stage); + + draw_alloc_tmps( &flatshade->stage, 2 ); + + flatshade->stage.draw = draw; + flatshade->stage.next = NULL; + flatshade->stage.begin = flatshade_begin; + flatshade->stage.point = flatshade_point; + flatshade->stage.line = flatshade_line; + flatshade->stage.tri = flatshade_tri; + flatshade->stage.end = flatshade_end; + flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter; + + flatshade->lookup = draw->vf_attr_to_slot; + + return &flatshade->stage; +} + + diff --git a/src/mesa/pipe/draw/draw_offset.c b/src/mesa/pipe/draw/draw_offset.c new file mode 100644 index 00000000000..9f665663538 --- /dev/null +++ b/src/mesa/pipe/draw/draw_offset.c @@ -0,0 +1,173 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \brief polygon offset state + * + * \author Keith Whitwell <[email protected]> + * \author Brian Paul + */ + +#include "main/imports.h" +#include "main/macros.h" +#include "draw_private.h" + + + +struct offset_stage { + struct draw_stage stage; + + GLfloat scale; + GLfloat units; +}; + + + +static INLINE struct offset_stage *offset_stage( struct draw_stage *stage ) +{ + return (struct offset_stage *) stage; +} + + +static void offset_begin( struct draw_stage *stage ) +{ + struct offset_stage *offset = offset_stage(stage); + GLfloat mrd = 1.0 / 65535.0; /* XXX this depends on depthbuffer bits! */ + + offset->units = stage->draw->setup.offset_units * mrd; + offset->scale = stage->draw->setup.offset_scale; + + stage->next->begin( stage->next ); +} + + +/** + * Offset tri Z. Some hardware can handle this, but not usually when + * doing unfilled rendering. + */ +static void do_offset_tri( struct draw_stage *stage, + struct prim_header *header ) +{ + struct offset_stage *offset = offset_stage(stage); + GLfloat inv_det = 1.0 / header->det; + + /* Window coords: + */ + GLfloat *v0 = header->v[0]->data[0]; + GLfloat *v1 = header->v[1]->data[0]; + GLfloat *v2 = header->v[2]->data[0]; + + /* edge vectors e = v0 - v2, f = v1 - v2 */ + GLfloat ex = v0[0] - v2[0]; + GLfloat ey = v0[1] - v2[1]; + GLfloat ez = v0[2] - v2[2]; + GLfloat fx = v1[0] - v2[0]; + GLfloat fy = v1[1] - v2[1]; + GLfloat fz = v1[2] - v2[2]; + + /* (a,b) = cross(e,f).xy */ + GLfloat a = ey*fz - ez*fy; + GLfloat b = ez*fx - ex*fz; + + GLfloat dzdx = FABSF(a * inv_det); + GLfloat dzdy = FABSF(b * inv_det); + + GLfloat zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale; + + /* + * Note: we're applying the offset and clamping per-vertex. + * Ideally, the offset is applied per-fragment prior to fragment shading. + */ + v0[2] = CLAMP(v0[2] + zoffset, 0.0, 1.0); + v1[2] = CLAMP(v1[2] + zoffset, 0.0, 1.0); + v2[2] = CLAMP(v2[2] + zoffset, 0.0, 1.0); + + stage->next->tri( stage->next, header ); +} + + +static void offset_tri( struct draw_stage *stage, + struct prim_header *header ) +{ + struct prim_header tmp; + + tmp.det = header->det; + tmp.v[0] = dup_vert(stage, header->v[0], 0); + tmp.v[1] = dup_vert(stage, header->v[1], 1); + tmp.v[2] = dup_vert(stage, header->v[2], 2); + + do_offset_tri( stage, &tmp ); +} + + + +static void offset_line( struct draw_stage *stage, + struct prim_header *header ) +{ + stage->next->line( stage->next, header ); +} + + +static void offset_point( struct draw_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + + +static void offset_end( struct draw_stage *stage ) +{ + stage->next->end( stage->next ); +} + + +static void offset_reset_stipple_counter( struct draw_stage *stage ) +{ + stage->next->reset_stipple_counter( stage->next ); +} + + +/** + * Create polygon offset drawing stage. + */ +struct draw_stage *draw_offset_stage( struct draw_context *draw ) +{ + struct offset_stage *offset = CALLOC_STRUCT(offset_stage); + + draw_alloc_tmps( &offset->stage, 3 ); + + offset->stage.draw = draw; + offset->stage.next = NULL; + offset->stage.begin = offset_begin; + offset->stage.point = offset_point; + offset->stage.line = offset_line; + offset->stage.tri = offset_tri; + offset->stage.end = offset_end; + offset->stage.reset_stipple_counter = offset_reset_stipple_counter; + + return &offset->stage; +} diff --git a/src/mesa/pipe/draw/draw_private.h b/src/mesa/pipe/draw/draw_private.h new file mode 100644 index 00000000000..3dfaa0581db --- /dev/null +++ b/src/mesa/pipe/draw/draw_private.h @@ -0,0 +1,184 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * Private data structures, etc for the draw module. + */ + + +/** + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + + +#ifndef DRAW_PRIVATE_H +#define DRAW_PRIVATE_H + + +#include "main/glheader.h" +#include "pipe/p_state.h" +#include "pipe/p_defines.h" +#include "vf/vf.h" + + +/** + * Basic vertex info. + * Carry some useful information around with the vertices in the prim pipe. + */ +struct vertex_header { + GLuint clipmask:12; + GLuint edgeflag:1; + GLuint pad:19; + + GLfloat clip[4]; + + GLfloat data[][4]; /* Note variable size */ +}; + + +/** + * Basic info for a point/line/triangle primitive. + */ +struct prim_header { + GLfloat det; /**< front/back face determinant */ + struct vertex_header *v[3]; /**< 1 to 3 vertex pointers */ +}; + + + +struct draw_context; + +/** + * Base class for all primitive drawing stages. + */ +struct draw_stage +{ + struct draw_context *draw; /**< parent context */ + + struct draw_stage *next; /**< next stage in pipeline */ + + struct vertex_header **tmp; + GLuint nr_tmps; + + void (*begin)( struct draw_stage * ); + + void (*point)( struct draw_stage *, + struct prim_header * ); + + void (*line)( struct draw_stage *, + struct prim_header * ); + + void (*tri)( struct draw_stage *, + struct prim_header * ); + + void (*end)( struct draw_stage * ); + + void (*reset_stipple_counter)( struct draw_stage * ); +}; + + +/** + * Private context for the drawing module. + */ +struct draw_context +{ + struct { + struct draw_stage *first; /**< one of the following */ + + /* stages (in logical order) */ + struct draw_stage *flatshade; + struct draw_stage *clip; + struct draw_stage *cull; + struct draw_stage *twoside; + struct draw_stage *offset; + struct draw_stage *unfilled; + struct draw_stage *setup; /* aka render/rasterize */ + } pipeline; + + /* pipe state that we need: */ + struct pipe_setup_state setup; + struct pipe_viewport_state viewport; + + /* Clip derived state: + */ + GLfloat plane[12][4]; + GLuint nr_planes; + + GLuint vf_attr_to_slot[PIPE_ATTRIB_MAX]; + + struct vf_attr_map attrs[VF_ATTRIB_MAX]; + GLuint nr_attrs; + GLuint vertex_size; /**< in bytes */ + struct vertex_fetch *vf; + + GLubyte *verts; + GLuint nr_vertices; + GLboolean in_vb; + + GLenum prim; /**< GL_POINTS, GL_LINE_STRIP, GL_QUADS, etc */ + + /* Helper for tnl: + */ + GLvector4f header; +}; + + + +extern struct draw_stage *draw_unfilled_stage( struct draw_context *context ); +extern struct draw_stage *draw_twoside_stage( struct draw_context *context ); +extern struct draw_stage *draw_offset_stage( struct draw_context *context ); +extern struct draw_stage *draw_clip_stage( struct draw_context *context ); +extern struct draw_stage *draw_flatshade_stage( struct draw_context *context ); +extern struct draw_stage *draw_cull_stage( struct draw_context *context ); + + +extern void draw_free_tmps( struct draw_stage *stage ); +extern void draw_alloc_tmps( struct draw_stage *stage, GLuint nr ); + + + +/** + * Get a writeable copy of a vertex. + * \param stage drawing stage info + * \param vert the vertex to copy (source) + * \param idx index into stage's tmp[] array to put the copy (dest) + * \return pointer to the copied vertex + */ +static INLINE struct vertex_header * +dup_vert( struct draw_stage *stage, + const struct vertex_header *vert, + GLuint idx ) +{ + struct vertex_header *tmp = stage->tmp[idx]; + memcpy(tmp, vert, stage->draw->vertex_size ); + return tmp; +} + + +#endif /* DRAW_PRIVATE_H */ diff --git a/src/mesa/pipe/draw/draw_twoside.c b/src/mesa/pipe/draw/draw_twoside.c new file mode 100644 index 00000000000..fdda6b362fa --- /dev/null +++ b/src/mesa/pipe/draw/draw_twoside.c @@ -0,0 +1,169 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#include "main/imports.h" +#include "pipe/p_defines.h" +#include "draw_private.h" + + +struct twoside_stage { + struct draw_stage stage; + GLfloat sign; /**< +1 or -1 */ + const GLuint *lookup; +}; + + +static INLINE struct twoside_stage *twoside_stage( struct draw_stage *stage ) +{ + return (struct twoside_stage *)stage; +} + + +static void twoside_begin( struct draw_stage *stage ) +{ + struct twoside_stage *twoside = twoside_stage(stage); + + /* + * We'll multiply the primitive's determinant by this sign to determine + * if the triangle is back-facing (negative). + * sign = 1 for CCW, -1 for CW + */ + twoside->sign = (stage->draw->setup.front_winding == PIPE_WINDING_CCW) ? 1 : -1; + + stage->next->begin( stage->next ); +} + + +static INLINE void copy_color( GLuint attr_dst, + GLuint attr_src, + struct vertex_header *v ) +{ + if (attr_dst && attr_src) { + memcpy( v->data[attr_dst], + v->data[attr_src], + sizeof(v->data[0]) ); + } +} + + +static struct vertex_header *copy_bfc( struct twoside_stage *twoside, + const struct vertex_header *v, + GLuint idx ) +{ + struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx ); + + copy_color( twoside->lookup[VF_ATTRIB_COLOR0], + twoside->lookup[VF_ATTRIB_BFC0], + tmp ); + + copy_color( twoside->lookup[VF_ATTRIB_COLOR1], + twoside->lookup[VF_ATTRIB_BFC1], + tmp ); + + return tmp; +} + + +/* Twoside tri: + */ +static void twoside_tri( struct draw_stage *stage, + struct prim_header *header ) +{ + struct twoside_stage *twoside = twoside_stage(stage); + + if (header->det * twoside->sign < 0.0) { + /* this is a back-facing triangle */ + struct prim_header tmp; + + tmp.det = header->det; + /* copy back colors to front color slots */ + tmp.v[0] = copy_bfc(twoside, header->v[0], 0); + tmp.v[1] = copy_bfc(twoside, header->v[1], 1); + tmp.v[2] = copy_bfc(twoside, header->v[2], 2); + + stage->next->tri( stage->next, &tmp ); + } + else { + stage->next->tri( stage->next, header ); + } +} + + +static void twoside_line( struct draw_stage *stage, + struct prim_header *header ) +{ + /* pass-through */ + stage->next->line( stage->next, header ); +} + + +static void twoside_point( struct draw_stage *stage, + struct prim_header *header ) +{ + /* pass-through */ + stage->next->point( stage->next, header ); +} + + +static void twoside_end( struct draw_stage *stage ) +{ + /* pass-through */ + stage->next->end( stage->next ); +} + + +static void twoside_reset_stipple_counter( struct draw_stage *stage ) +{ + stage->next->reset_stipple_counter( stage->next ); +} + + +/** + * Create twoside pipeline stage. + */ +struct draw_stage *draw_twoside_stage( struct draw_context *draw ) +{ + struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage); + + draw_alloc_tmps( &twoside->stage, 3 ); + + twoside->stage.draw = draw; + twoside->stage.next = NULL; + twoside->stage.begin = twoside_begin; + twoside->stage.point = twoside_point; + twoside->stage.line = twoside_line; + twoside->stage.tri = twoside_tri; + twoside->stage.end = twoside_end; + twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter; + + twoside->lookup = draw->vf_attr_to_slot; + + return &twoside->stage; +} diff --git a/src/mesa/pipe/draw/draw_unfilled.c b/src/mesa/pipe/draw/draw_unfilled.c new file mode 100644 index 00000000000..82e8775f59f --- /dev/null +++ b/src/mesa/pipe/draw/draw_unfilled.c @@ -0,0 +1,185 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \brief Drawing stage for handling glPolygonMode(line/point). + * Convert triangles to points or lines as needed. + */ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#include "main/imports.h" +#include "pipe/p_defines.h" +#include "draw_private.h" + + +struct unfilled_stage { + struct draw_stage stage; + + /** [0] = front face, [1] = back face. + * legal values: PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE, + * and PIPE_POLYGON_MODE_POINT, + */ + GLuint mode[2]; +}; + + +static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage ) +{ + return (struct unfilled_stage *)stage; +} + + +static void unfilled_begin( struct draw_stage *stage ) +{ + struct unfilled_stage *unfilled = unfilled_stage(stage); + + unfilled->mode[0] = stage->draw->setup.fill_ccw; /* front */ + unfilled->mode[1] = stage->draw->setup.fill_cw; /* back */ + + stage->next->begin( stage->next ); +} + +static void point( struct draw_stage *stage, + struct vertex_header *v0 ) +{ + struct prim_header tmp; + tmp.v[0] = v0; + stage->next->point( stage->next, &tmp ); +} + +static void line( struct draw_stage *stage, + struct vertex_header *v0, + struct vertex_header *v1 ) +{ + struct prim_header tmp; + tmp.v[0] = v0; + tmp.v[1] = v1; + stage->next->line( stage->next, &tmp ); +} + + +static void points( struct draw_stage *stage, + struct prim_header *header ) +{ + struct vertex_header *v0 = header->v[0]; + struct vertex_header *v1 = header->v[1]; + struct vertex_header *v2 = header->v[2]; + + if (v0->edgeflag) point( stage, v0 ); + if (v1->edgeflag) point( stage, v1 ); + if (v2->edgeflag) point( stage, v2 ); +} + + +static void lines( struct draw_stage *stage, + struct prim_header *header ) +{ + struct vertex_header *v0 = header->v[0]; + struct vertex_header *v1 = header->v[1]; + struct vertex_header *v2 = header->v[2]; + + if (v0->edgeflag) line( stage, v0, v1 ); + if (v1->edgeflag) line( stage, v1, v2 ); + if (v2->edgeflag) line( stage, v2, v0 ); +} + + +/* Unfilled tri: + * + * Note edgeflags in the vertex struct is not sufficient as we will + * need to manipulate them when decomposing primitives??? + */ +static void unfilled_tri( struct draw_stage *stage, + struct prim_header *header ) +{ + struct unfilled_stage *unfilled = unfilled_stage(stage); + GLuint mode = unfilled->mode[header->det > 0.0]; + + switch (mode) { + case PIPE_POLYGON_MODE_FILL: + stage->next->tri( stage->next, header ); + break; + case PIPE_POLYGON_MODE_LINE: + lines( stage, header ); + break; + case PIPE_POLYGON_MODE_POINT: + points( stage, header ); + break; + default: + abort(); + } +} + +static void unfilled_line( struct draw_stage *stage, + struct prim_header *header ) +{ + stage->next->line( stage->next, header ); +} + + +static void unfilled_point( struct draw_stage *stage, + struct prim_header *header ) +{ + stage->next->point( stage->next, header ); +} + + +static void unfilled_end( struct draw_stage *stage ) +{ + stage->next->end( stage->next ); +} + + +static void unfilled_reset_stipple_counter( struct draw_stage *stage ) +{ + stage->next->reset_stipple_counter( stage->next ); +} + + +/** + * Create unfilled triangle stage. + */ +struct draw_stage *draw_unfilled_stage( struct draw_context *draw ) +{ + struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage); + + draw_alloc_tmps( &unfilled->stage, 0 ); + + unfilled->stage.draw = draw; + unfilled->stage.next = NULL; + unfilled->stage.tmp = NULL; + unfilled->stage.begin = unfilled_begin; + unfilled->stage.point = unfilled_point; + unfilled->stage.line = unfilled_line; + unfilled->stage.tri = unfilled_tri; + unfilled->stage.end = unfilled_end; + unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter; + + return &unfilled->stage; +} diff --git a/src/mesa/pipe/draw/draw_vb.c b/src/mesa/pipe/draw/draw_vb.c new file mode 100644 index 00000000000..ac126c5baa5 --- /dev/null +++ b/src/mesa/pipe/draw/draw_vb.c @@ -0,0 +1,728 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "imports.h" +#include "macros.h" + +#include "tnl/t_context.h" +#include "vf/vf.h" + +#include "draw_private.h" +#include "draw_context.h" + + +/* This file is a temporary set of hooks to allow us to use the tnl/ + * and vf/ modules until we have replacements in pipe. + */ + + +static struct vertex_header *get_vertex( struct draw_context *pipe, + GLuint i ) +{ + return (struct vertex_header *)(pipe->verts + i * pipe->vertex_size); +} + + + +static void draw_allocate_vertices( struct draw_context *draw, + GLuint nr_vertices ) +{ + draw->nr_vertices = nr_vertices; + draw->verts = MALLOC( nr_vertices * draw->vertex_size ); + + draw->pipeline.first->begin( draw->pipeline.first ); +} + +static void draw_set_prim( struct draw_context *draw, + GLenum prim ) +{ + draw->prim = prim; + + /* Not done yet - need to force edgeflags to 1 in strip/fan + * primitives. + */ +#if 0 + switch (prim) { + case GL_TRIANGLES: + case GL_POLYGON: + case GL_QUADS: + case GL_QUAD_STRIP: /* yes, we need this */ + respect_edgeflags( pipe, GL_TRUE ); + break; + + default: + respect_edgeflags( pipe, GL_FALSE ); + break; + } +#endif +} + + + +static void do_quad( struct draw_stage *first, + struct vertex_header *v0, + struct vertex_header *v1, + struct vertex_header *v2, + struct vertex_header *v3 ) +{ + struct prim_header prim; + + { + GLuint tmp = v1->edgeflag; + v1->edgeflag = 0; + + prim.v[0] = v0; + prim.v[1] = v1; + prim.v[2] = v3; + first->tri( first, &prim ); + + v1->edgeflag = tmp; + } + + { + GLuint tmp = v3->edgeflag; + v3->edgeflag = 0; + + prim.v[0] = v1; + prim.v[1] = v2; + prim.v[2] = v3; + first->tri( first, &prim ); + + v3->edgeflag = tmp; + } +} + + + + +static void draw_indexed_prim( struct draw_context *draw, + const GLuint *elts, + GLuint count ) +{ + struct draw_stage * const first = draw->pipeline.first; + struct prim_header prim; + GLuint i; + + prim.det = 0; /* valid from cull stage onwards */ + prim.v[0] = 0; + prim.v[1] = 0; + prim.v[2] = 0; + + switch (draw->prim) { + case GL_POINTS: + for (i = 0; i < count; i ++) { + prim.v[0] = get_vertex( draw, elts[i] ); + + first->point( first, &prim ); + } + break; + + case GL_LINES: + for (i = 0; i+1 < count; i += 2) { + prim.v[0] = get_vertex( draw, elts[i + 0] ); + prim.v[1] = get_vertex( draw, elts[i + 1] ); + + first->reset_stipple_counter( first ); + first->line( first, &prim ); + } + break; + + case GL_LINE_LOOP: + if (count >= 2) { + first->reset_stipple_counter( first ); + for (i = 1; i < count; i++) { + prim.v[0] = get_vertex( draw, elts[i-1] ); + prim.v[1] = get_vertex( draw, elts[i] ); + first->line( first, &prim ); + } + + prim.v[0] = get_vertex( draw, elts[count-1] ); + prim.v[1] = get_vertex( draw, elts[0] ); + first->line( first, &prim ); + } + break; + + case GL_LINE_STRIP: + /* I'm guessing it will be necessary to have something like a + * render->reset_line_stipple() method to properly support + * splitting strips into primitives like this. Alternately we + * could just scan ahead to find individual clipped lines and + * otherwise leave the strip intact - that might be better, but + * require more complex code here. + */ + if (count >= 2) { + first->reset_stipple_counter( first ); + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, elts[0] ); + + for (i = 1; i < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, elts[i] ); + + first->line( first, &prim ); + } + } + break; + + case GL_TRIANGLES: + for (i = 0; i+2 < count; i += 3) { + prim.v[0] = get_vertex( draw, elts[i + 0] ); + prim.v[1] = get_vertex( draw, elts[i + 1] ); + prim.v[2] = get_vertex( draw, elts[i + 2] ); + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_STRIP: + for (i = 0; i+2 < count; i++) { + if (i & 1) { + prim.v[0] = get_vertex( draw, elts[i + 1] ); + prim.v[1] = get_vertex( draw, elts[i + 0] ); + prim.v[2] = get_vertex( draw, elts[i + 2] ); + } + else { + prim.v[0] = get_vertex( draw, elts[i + 0] ); + prim.v[1] = get_vertex( draw, elts[i + 1] ); + prim.v[2] = get_vertex( draw, elts[i + 2] ); + } + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_FAN: + if (count >= 3) { + prim.v[0] = get_vertex( draw, elts[0] ); + prim.v[1] = 0; + prim.v[2] = get_vertex( draw, elts[1] ); + + for (i = 0; i+2 < count; i++) { + prim.v[1] = prim.v[2]; + prim.v[2] = get_vertex( draw, elts[i+2] ); + + first->tri( first, &prim ); + } + } + break; + + case GL_QUADS: + for (i = 0; i+3 < count; i += 4) { + do_quad( first, + get_vertex( draw, elts[i + 0] ), + get_vertex( draw, elts[i + 1] ), + get_vertex( draw, elts[i + 2] ), + get_vertex( draw, elts[i + 3] )); + } + break; + + case GL_QUAD_STRIP: + for (i = 0; i+3 < count; i += 2) { + do_quad( first, + get_vertex( draw, elts[i + 2] ), + get_vertex( draw, elts[i + 0] ), + get_vertex( draw, elts[i + 1] ), + get_vertex( draw, elts[i + 3] )); + } + break; + + + case GL_POLYGON: + if (count >= 3) { + int e1save, e2save; + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, elts[1] ); + prim.v[2] = get_vertex( draw, elts[0] ); + e2save = prim.v[2]->edgeflag; + + for (i = 0; i+2 < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, elts[i+2] ); + + /* save v1 edge flag, and clear if not last triangle */ + e1save = prim.v[1]->edgeflag; + if (i + 3 < count) + prim.v[1]->edgeflag = 0; + + /* draw */ + first->tri( first, &prim ); + + prim.v[1]->edgeflag = e1save; /* restore */ + prim.v[2]->edgeflag = 0; /* disable edge after 1st tri */ + } + prim.v[2]->edgeflag = e2save; + } + break; + + default: + assert(0); + break; + } +} + +static void draw_prim( struct draw_context *draw, + GLuint start, + GLuint count ) +{ + struct draw_stage * const first = draw->pipeline.first; + struct prim_header prim; + GLuint i; + +// _mesa_printf("%s (%d) %d/%d\n", __FUNCTION__, draw->prim, start, count ); + + prim.det = 0; /* valid from cull stage onwards */ + prim.v[0] = 0; + prim.v[1] = 0; + prim.v[2] = 0; + + switch (draw->prim) { + case GL_POINTS: + for (i = 0; i < count; i ++) { + prim.v[0] = get_vertex( draw, start + i ); + first->point( first, &prim ); + } + break; + + case GL_LINES: + for (i = 0; i+1 < count; i += 2) { + prim.v[0] = get_vertex( draw, start + i + 0 ); + prim.v[1] = get_vertex( draw, start + i + 1 ); + + first->reset_stipple_counter( first ); + first->line( first, &prim ); + } + break; + + case GL_LINE_LOOP: + if (count >= 2) { + first->reset_stipple_counter( first ); + for (i = 1; i < count; i++) { + prim.v[0] = get_vertex( draw, start + i - 1 ); + prim.v[1] = get_vertex( draw, start + i ); + first->line( first, &prim ); + } + + prim.v[0] = get_vertex( draw, start + count - 1 ); + prim.v[1] = get_vertex( draw, start + 0 ); + first->line( first, &prim ); + } + break; + + case GL_LINE_STRIP: + if (count >= 2) { + first->reset_stipple_counter( first ); + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, start + 0 ); + + for (i = 1; i < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, start + i ); + + first->line( first, &prim ); + } + } + break; + + case GL_TRIANGLES: + for (i = 0; i+2 < count; i += 3) { + prim.v[0] = get_vertex( draw, start + i + 0 ); + prim.v[1] = get_vertex( draw, start + i + 1 ); + prim.v[2] = get_vertex( draw, start + i + 2 ); + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_STRIP: + for (i = 0; i+2 < count; i++) { + if (i & 1) { + prim.v[0] = get_vertex( draw, start + i + 1 ); + prim.v[1] = get_vertex( draw, start + i + 0 ); + prim.v[2] = get_vertex( draw, start + i + 2 ); + } + else { + prim.v[0] = get_vertex( draw, start + i + 0 ); + prim.v[1] = get_vertex( draw, start + i + 1 ); + prim.v[2] = get_vertex( draw, start + i + 2 ); + } + + first->tri( first, &prim ); + } + break; + + case GL_TRIANGLE_FAN: + if (count >= 3) { + prim.v[0] = get_vertex( draw, start + 0 ); + prim.v[1] = 0; + prim.v[2] = get_vertex( draw, start + 1 ); + + for (i = 0; i+2 < count; i++) { + prim.v[1] = prim.v[2]; + prim.v[2] = get_vertex( draw, start + i + 2 ); + + first->tri( first, &prim ); + } + } + break; + + + case GL_QUADS: + for (i = 0; i+3 < count; i += 4) { + do_quad( first, + get_vertex( draw, start + i + 0 ), + get_vertex( draw, start + i + 1 ), + get_vertex( draw, start + i + 2 ), + get_vertex( draw, start + i + 3 )); + } + break; + + case GL_QUAD_STRIP: + for (i = 0; i+3 < count; i += 2) { + do_quad( first, + get_vertex( draw, start + i + 2 ), + get_vertex( draw, start + i + 0 ), + get_vertex( draw, start + i + 1 ), + get_vertex( draw, start + i + 3 )); + } + break; + + case GL_POLYGON: + if (count >= 3) { + int e1save, e2save; + prim.v[0] = 0; + prim.v[1] = get_vertex( draw, start + 1 ); + prim.v[2] = get_vertex( draw, start + 0 ); + e2save = prim.v[2]->edgeflag; + + for (i = 0; i+2 < count; i++) { + prim.v[0] = prim.v[1]; + prim.v[1] = get_vertex( draw, start + i + 2 ); + + /* save v1 edge flag, and clear if not last triangle */ + e1save = prim.v[1]->edgeflag; + if (i + 3 < count) + prim.v[1]->edgeflag = 0; + + /* draw */ + first->tri( first, &prim ); + + prim.v[1]->edgeflag = e1save; /* restore */ + prim.v[2]->edgeflag = 0; /* disable edge after 1st tri */ + } + prim.v[2]->edgeflag = e2save; + } + break; + + default: + assert(0); + break; + } +} + + +static void draw_release_vertices( struct draw_context *draw ) +{ + draw->pipeline.first->end( draw->pipeline.first ); + + FREE(draw->verts); + draw->verts = NULL; +} + + +struct header_dword { + GLuint clipmask:12; + GLuint edgeflag:1; + GLuint pad:19; +}; + + +static void +build_vertex_headers( struct draw_context *draw, + struct vertex_buffer *VB ) +{ + if (draw->header.storage == NULL) { + draw->header.stride = sizeof(GLfloat); + draw->header.size = 1; + draw->header.storage = ALIGN_MALLOC( VB->Size * sizeof(GLfloat), 32 ); + draw->header.data = draw->header.storage; + draw->header.count = 0; + draw->header.flags = VEC_SIZE_1 | VEC_MALLOC; + } + + /* Build vertex header attribute. + * + */ + + { + GLuint i; + struct header_dword *header = (struct header_dword *)draw->header.storage; + + /* yes its a hack + */ + assert(sizeof(*header) == sizeof(GLfloat)); + + draw->header.count = VB->Count; + + if (VB->EdgeFlag) { + for (i = 0; i < VB->Count; i++) { + header[i].clipmask = VB->ClipMask[i]; + header[i].edgeflag = VB->EdgeFlag[i]; + header[i].pad = 0; + } + } + else if (VB->ClipOrMask) { + for (i = 0; i < VB->Count; i++) { + header[i].clipmask = VB->ClipMask[i]; + header[i].edgeflag = 0; + header[i].pad = 0; + } + } + else { + for (i = 0; i < VB->Count; i++) { + header[i].clipmask = 0; + header[i].edgeflag = 0; + header[i].pad = 0; + } + } + } + + VB->AttribPtr[VF_ATTRIB_VERTEX_HEADER] = &draw->header; +} + + + + + +static GLuint draw_prim_info(GLenum mode, GLuint *first, GLuint *incr) +{ + switch (mode) { + case GL_POINTS: + *first = 1; + *incr = 1; + return 0; + case GL_LINES: + *first = 2; + *incr = 2; + return 0; + case GL_LINE_STRIP: + *first = 2; + *incr = 1; + return 0; + case GL_LINE_LOOP: + *first = 2; + *incr = 1; + return 1; + case GL_TRIANGLES: + *first = 3; + *incr = 3; + return 0; + case GL_TRIANGLE_STRIP: + *first = 3; + *incr = 1; + return 0; + case GL_TRIANGLE_FAN: + case GL_POLYGON: + *first = 3; + *incr = 1; + return 1; + case GL_QUADS: + *first = 4; + *incr = 4; + return 0; + case GL_QUAD_STRIP: + *first = 4; + *incr = 2; + return 0; + default: + assert(0); + *first = 1; + *incr = 1; + return 0; + } +} + + +static GLuint trim( GLuint count, GLuint first, GLuint incr ) +{ + if (count < first) + return 0; + else + return count - (count - first) % incr; +} + + +/* This is a hack & will all go away. + */ +void draw_vb(struct draw_context *draw, + struct vertex_buffer *VB ) +{ + GLuint i; + + VB->AttribPtr[VF_ATTRIB_POS] = VB->NdcPtr; + VB->AttribPtr[VF_ATTRIB_BFC0] = VB->ColorPtr[1]; + VB->AttribPtr[VF_ATTRIB_BFC1] = VB->SecondaryColorPtr[1]; + VB->AttribPtr[VF_ATTRIB_CLIP_POS] = VB->ClipPtr; + + /* Build vertex headers: + */ + build_vertex_headers( draw, VB ); + + draw->in_vb = 1; + + /* Allocate the vertices: + */ + draw_allocate_vertices( draw, VB->Count ); + + /* Bind the vb outputs: + */ + vf_set_sources( draw->vf, VB->AttribPtr, 0 ); + + /* Build the hardware or prim-pipe vertices: + */ + vf_emit_vertices( draw->vf, VB->Count, draw->verts ); + + + for (i = 0; i < VB->PrimitiveCount; i++) { + + GLenum mode = VB->Primitive[i].mode; + GLuint start = VB->Primitive[i].start; + GLuint length, first, incr; + + /* Trim the primitive down to a legal size. + */ + draw_prim_info( mode, &first, &incr ); + length = trim( VB->Primitive[i].count, first, incr ); + + if (!length) + continue; + + if (draw->prim != mode) + draw_set_prim( draw, mode ); + + if (VB->Elts) { + draw_indexed_prim( draw, + VB->Elts + start, + length ); + } + else { + draw_prim( draw, + start, + length ); + } + } + + draw_release_vertices( draw ); + draw->verts = NULL; + draw->in_vb = 0; +} + + +/** + * Accumulate another attribute's info. + * Note the "- 2" factor here. We need this because the vertex->data[] + * array does not include the first two attributes we emit (VERTEX_HEADER + * and CLIP_POS). So, the 3rd attribute actually winds up in the 1st + * position of the data[] array. + */ +#define EMIT_ATTR( VF_ATTR, STYLE ) \ +do { \ + if (draw->nr_attrs >= 2) \ + draw->vf_attr_to_slot[VF_ATTR] = draw->nr_attrs - 2; \ + draw->attrs[draw->nr_attrs].attrib = VF_ATTR; \ + draw->attrs[draw->nr_attrs].format = STYLE; \ + draw->nr_attrs++; \ +} while (0) + + +/** + * Tell the draw module about the layout of attributes in the vertex. + * We need this in order to know which vertex slot has color0, etc. + * + * \param slot_to_vf_attr an array which maps slot indexes to vertex + * format tokens (VF_*). + * \param nr_attrs the size of the slot_to_vf_attr array + * (and number of attributes) + */ +void draw_set_vertex_attributes( struct draw_context *draw, + const GLuint *slot_to_vf_attr, + GLuint nr_attrs ) +{ + GLuint i; + + memset(draw->vf_attr_to_slot, 0, sizeof(draw->vf_attr_to_slot)); + draw->nr_attrs = 0; + + /* + * First three attribs are always the same: header, clip pos, winpos + */ + EMIT_ATTR(VF_ATTRIB_VERTEX_HEADER, EMIT_1F); + EMIT_ATTR(VF_ATTRIB_CLIP_POS, EMIT_4F); + + assert(slot_to_vf_attr[0] == VF_ATTRIB_POS); + EMIT_ATTR(slot_to_vf_attr[0], EMIT_4F_VIEWPORT); + + /* + * Remaining attribs (color, texcoords, etc) + */ + for (i = 1; i < nr_attrs; i++) + EMIT_ATTR(slot_to_vf_attr[i], EMIT_4F); + + /* tell the vertex format module how to construct vertices for us */ + draw->vertex_size = vf_set_vertex_attributes( draw->vf, draw->attrs, + draw->nr_attrs, 0 ); +} + + +#define MAX_VERTEX_SIZE ((2 + FRAG_ATTRIB_MAX) * 4 * sizeof(GLfloat)) + +void draw_alloc_tmps( struct draw_stage *stage, GLuint nr ) +{ + stage->nr_tmps = nr; + + if (nr) { + GLubyte *store = MALLOC(MAX_VERTEX_SIZE * nr); + GLuint i; + + stage->tmp = MALLOC(sizeof(struct vertex_header *) * nr); + + for (i = 0; i < nr; i++) + stage->tmp[i] = (struct vertex_header *)(store + i * MAX_VERTEX_SIZE); + } +} + +void draw_free_tmps( struct draw_stage *stage ) +{ + if (stage->tmp) { + FREE(stage->tmp[0]); + FREE(stage->tmp); + } +} diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h new file mode 100644 index 00000000000..05a175c8dc0 --- /dev/null +++ b/src/mesa/pipe/p_context.h @@ -0,0 +1,120 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef PIPE_CONTEXT_H +#define PIPE_CONTEXT_H + +#include "main/mtypes.h" +#include "p_state.h" + + +/* Kludge: + */ +extern struct pipe_context *softpipe_create( void ); + +/* Drawing currently kludged up via the existing tnl/ module. + */ +struct vertex_buffer; + + +/** + * Software pipeline rendering context. Basically a collection of + * state setting functions, plus VBO drawing entrypoint. + */ +struct pipe_context { + + void (*destroy)( struct pipe_context * ); + + /* + * Drawing + */ + void (*draw_vb)( struct pipe_context *pipe, + struct vertex_buffer *VB ); + + /** Clear framebuffer */ + void (*clear)(struct pipe_context *pipe, GLboolean color, GLboolean depth, + GLboolean stencil, GLboolean accum); + + /** occlusion counting (XXX this may be temporary - we should probably + * have generic query objects with begin/end methods) + */ + void (*reset_occlusion_counter)(struct pipe_context *pipe); + GLuint (*get_occlusion_counter)(struct pipe_context *pipe); + + /* + * State functions + */ + void (*set_alpha_test_state)( struct pipe_context *, + const struct pipe_alpha_test_state * ); + + void (*set_blend_state)( struct pipe_context *, + const struct pipe_blend_state * ); + + void (*set_blend_color)( struct pipe_context *, + const struct pipe_blend_color * ); + + void (*set_clip_state)( struct pipe_context *, + const struct pipe_clip_state * ); + + void (*set_clear_color_state)( struct pipe_context *, + const struct pipe_clear_color_state * ); + + void (*set_depth_state)( struct pipe_context *, + const struct pipe_depth_state * ); + + void (*set_framebuffer_state)( struct pipe_context *, + const struct pipe_framebuffer_state * ); + + void (*set_fs_state)( struct pipe_context *, + const struct pipe_fs_state * ); + + void (*set_polygon_stipple)( struct pipe_context *, + const struct pipe_poly_stipple * ); + + void (*set_setup_state)( struct pipe_context *, + const struct pipe_setup_state * ); + + void (*set_scissor_state)( struct pipe_context *, + const struct pipe_scissor_state * ); + + void (*set_stencil_state)( struct pipe_context *, + const struct pipe_stencil_state * ); + + void (*set_sampler_state)( struct pipe_context *, + GLuint unit, + const struct pipe_sampler_state * ); + + void (*set_texture_state)( struct pipe_context *, + GLuint unit, + struct pipe_texture_object * ); + + void (*set_viewport_state)( struct pipe_context *, + const struct pipe_viewport_state * ); +}; + + +#endif diff --git a/src/mesa/pipe/p_defines.h b/src/mesa/pipe/p_defines.h new file mode 100644 index 00000000000..1b799f14516 --- /dev/null +++ b/src/mesa/pipe/p_defines.h @@ -0,0 +1,165 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef PIPE_DEFINES_H +#define PIPE_DEFINES_H + +#define PIPE_BLENDFACTOR_ONE 0x1 +#define PIPE_BLENDFACTOR_SRC_COLOR 0x2 +#define PIPE_BLENDFACTOR_SRC_ALPHA 0x3 +#define PIPE_BLENDFACTOR_DST_ALPHA 0x4 +#define PIPE_BLENDFACTOR_DST_COLOR 0x5 +#define PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6 +#define PIPE_BLENDFACTOR_CONST_COLOR 0x7 +#define PIPE_BLENDFACTOR_CONST_ALPHA 0x8 +#define PIPE_BLENDFACTOR_SRC1_COLOR 0x9 +#define PIPE_BLENDFACTOR_SRC1_ALPHA 0x0A +#define PIPE_BLENDFACTOR_ZERO 0x11 +#define PIPE_BLENDFACTOR_INV_SRC_COLOR 0x12 +#define PIPE_BLENDFACTOR_INV_SRC_ALPHA 0x13 +#define PIPE_BLENDFACTOR_INV_DST_ALPHA 0x14 +#define PIPE_BLENDFACTOR_INV_DST_COLOR 0x15 +#define PIPE_BLENDFACTOR_INV_CONST_COLOR 0x17 +#define PIPE_BLENDFACTOR_INV_CONST_ALPHA 0x18 +#define PIPE_BLENDFACTOR_INV_SRC1_COLOR 0x19 +#define PIPE_BLENDFACTOR_INV_SRC1_ALPHA 0x1A + +#define PIPE_BLEND_ADD 0 +#define PIPE_BLEND_SUBTRACT 1 +#define PIPE_BLEND_REVERSE_SUBTRACT 2 +#define PIPE_BLEND_MIN 3 +#define PIPE_BLEND_MAX 4 + +#define PIPE_LOGICOP_CLEAR 0 +#define PIPE_LOGICOP_NOR 1 +#define PIPE_LOGICOP_AND_INVERTED 2 +#define PIPE_LOGICOP_COPY_INVERTED 3 +#define PIPE_LOGICOP_AND_REVERSE 4 +#define PIPE_LOGICOP_INVERT 5 +#define PIPE_LOGICOP_XOR 6 +#define PIPE_LOGICOP_NAND 7 +#define PIPE_LOGICOP_AND 8 +#define PIPE_LOGICOP_EQUIV 9 +#define PIPE_LOGICOP_NOOP 10 +#define PIPE_LOGICOP_OR_INVERTED 11 +#define PIPE_LOGICOP_COPY 12 +#define PIPE_LOGICOP_OR_REVERSE 13 +#define PIPE_LOGICOP_OR 14 +#define PIPE_LOGICOP_SET 15 + +#define PIPE_MASK_R 0x1 +#define PIPE_MASK_G 0x2 +#define PIPE_MASK_B 0x4 +#define PIPE_MASK_A 0x8 + +/** + * Inequality functions. Used for depth test, stencil compare, alpha + * test, shadow compare, etc. + */ +#define PIPE_FUNC_NEVER 0 +#define PIPE_FUNC_LESS 1 +#define PIPE_FUNC_EQUAL 2 +#define PIPE_FUNC_LEQUAL 3 +#define PIPE_FUNC_GREATER 4 +#define PIPE_FUNC_NOTEQUAL 5 +#define PIPE_FUNC_GEQUAL 6 +#define PIPE_FUNC_ALWAYS 7 + +/** Polygon fill mode */ +#define PIPE_POLYGON_MODE_FILL 0 +#define PIPE_POLYGON_MODE_LINE 1 +#define PIPE_POLYGON_MODE_POINT 2 + +/** Polygon front/back window, also for culling */ +#define PIPE_WINDING_NONE 0 +#define PIPE_WINDING_CW 1 +#define PIPE_WINDING_CCW 2 +#define PIPE_WINDING_BOTH (PIPE_WINDING_CW | PIPE_WINDING_CCW) + +/** Stencil ops */ +#define PIPE_STENCIL_OP_KEEP 0 +#define PIPE_STENCIL_OP_ZERO 1 +#define PIPE_STENCIL_OP_REPLACE 2 +#define PIPE_STENCIL_OP_INCR 3 +#define PIPE_STENCIL_OP_DECR 4 +#define PIPE_STENCIL_OP_INCR_WRAP 5 +#define PIPE_STENCIL_OP_DECR_WRAP 6 +#define PIPE_STENCIL_OP_INVERT 7 + +#define PIPE_TEX_WRAP_REPEAT 0 +#define PIPE_TEX_WRAP_CLAMP 1 +#define PIPE_TEX_WRAP_CLAMP_TO_EDGE 2 +#define PIPE_TEX_WRAP_CLAMP_TO_BORDER 3 +#define PIPE_TEX_WRAP_MIRROR_REPEAT 4 +#define PIPE_TEX_WRAP_MIRROR_CLAMP 5 +#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE 6 +#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER 7 + +#define PIPE_TEX_FILTER_NEAREST 0 +#define PIPE_TEX_FILTER_LINEAR 1 +#define PIPE_TEX_FILTER_NEAREST_MIPMAP_NEAREST 2 +#define PIPE_TEX_FILTER_NEAREST_MIPMAP_LINEAR 3 +#define PIPE_TEX_FILTER_LINEAR_MIPMAP_NEAREST 4 +#define PIPE_TEX_FILTER_LINEAR_MIPMAP_LINEAR 5 + +#define PIPE_TEX_COMPARE_NONE 0 +#define PIPE_TEX_COMPARE_R_TO_TEXTURE 1 + +/** + * Texture/surface image formats (preliminary) + */ +#define PIPE_FORMAT_U_R8_G8_B8_A8 0 /**< ubyte[4] RGBA */ +#define PIPE_FORMAT_U_A8_R8_G8_B8 1 /**< ubyte[4] ARGB */ +#define PIPE_FORMAT_U_R5_G6_B5 2 /**< 5/6/5 RGB */ +#define PIPE_FORMAT_U_L8 3 /**< ubyte luminance */ +#define PIPE_FORMAT_U_A8 4 /**< ubyte alpha */ +#define PIPE_FORMAT_U_I8 5 /**< ubyte intensity */ +#define PIPE_FORMAT_U_L8_A8 6 /**< ubyte luminance, alpha */ +#define PIPE_FORMAT_U_Z16 7 /**< ushort Z/depth */ +#define PIPE_FORMAT_F_Z32 8 /**< float Z/depth */ +#define PIPE_FORMAT_YCBCR 9 +#define PIPE_FORMAT_YCBCR_REV 10 +#define PIPE_FORMAT_U_S8 11 /**< 8-bit stencil */ +#define PIPE_FORMAT_Z24_S8 12 /**< 24-bit Z + 8-bit stencil */ + + +/** + * Texture typess + */ +#define PIPE_TEXTURE_1D 0 +#define PIPE_TEXTURE_2D 1 +#define PIPE_TEXTURE_3D 2 +#define PIPE_TEXTURE_CUBE 3 + +/** + * Buffer mapping access modes + */ +#define PIPE_MAP_READ 1 +#define PIPE_MAP_WRITE 2 +#define PIPE_MAP_READ_WRITE 3 + +#endif diff --git a/src/mesa/pipe/p_state.h b/src/mesa/pipe/p_state.h new file mode 100644 index 00000000000..4ae8928018e --- /dev/null +++ b/src/mesa/pipe/p_state.h @@ -0,0 +1,301 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + +/** + * Abstract graphics pipe state objects. + * + * Basic notes: + * 1. Want compact representations, so we use bitfields. + * 2. Put bitfields before other (GLfloat) fields. + */ + + +#ifndef PIPE_STATE_H +#define PIPE_STATE_H + +#include "mtypes.h" + + + +/** + * Implementation limits + */ +#define PIPE_MAX_SAMPLERS 8 +#define PIPE_MAX_CLIP_PLANES 6 +#define PIPE_MAX_CONSTANT 32 +#define PIPE_ATTRIB_MAX 32 +#define PIPE_MAX_COLOR_BUFS 8 + + +/* fwd decl */ +struct pipe_surface; + + +/*** + *** State objects + ***/ + + +/** + * Primitive (point/line/tri) setup info + */ +struct pipe_setup_state +{ + GLuint flatshade:1; + GLuint light_twoside:1; + + GLuint front_winding:2; /**< PIPE_WINDING_x */ + + GLuint cull_mode:2; /**< PIPE_WINDING_x */ + + GLuint fill_cw:2; /**< PIPE_POLYGON_MODE_x */ + GLuint fill_ccw:2; /**< PIPE_POLYGON_MODE_x */ + + GLuint offset_cw:1; + GLuint offset_ccw:1; + + GLuint scissor:1; + + GLuint poly_smooth:1; + GLuint poly_stipple_enable:1; + + GLuint line_smooth:1; + GLuint line_stipple_enable:1; + + GLuint point_smooth:1; + + GLuint multisample:1; /* XXX maybe more ms state in future */ + + GLubyte line_stipple_factor; /**< [1..256] actually */ + GLushort line_stipple_pattern; + GLfloat line_width; + GLfloat point_size; /**< used when no per-vertex size */ + GLfloat offset_units; + GLfloat offset_scale; +}; + +struct pipe_poly_stipple { + GLuint stipple[32]; +}; + + +struct pipe_viewport_state { + GLfloat scale[4]; + GLfloat translate[4]; +}; + +struct pipe_scissor_state { + GLshort minx; + GLshort miny; + GLshort maxx; + GLshort maxy; +}; + +struct pipe_clip_state { + GLfloat ucp[PIPE_MAX_CLIP_PLANES][4]; + GLuint nr; +}; + + +struct pipe_constant_buffer { + GLfloat constant[PIPE_MAX_CONSTANT][4]; + GLuint nr_constants; +}; + + +struct pipe_fs_state { + GLbitfield inputs_read; /* FRAG_ATTRIB_* */ + const struct tgsi_token *tokens; + struct pipe_constant_buffer *constants; /* XXX temporary? */ +}; + +struct pipe_depth_state +{ + GLuint enabled:1; /**< depth test enabled? */ + GLuint writemask:1; /**< allow depth buffer writes? */ + GLuint func:3; /**< depth test func (PIPE_FUNC_x) */ + GLuint occlusion_count:1; /**< XXX move this elsewhere? */ + GLfloat clear; /**< Clear value in [0,1] (XXX correct place?) */ +}; + +struct pipe_alpha_test_state { + GLuint enabled:1; + GLuint func:3; /**< PIPE_FUNC_x */ + GLfloat ref; /**< reference value */ +}; + +struct pipe_blend_state { + GLuint blend_enable:1; + + GLuint rgb_func:3; /**< PIPE_BLEND_x */ + GLuint rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */ + GLuint rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ + + GLuint alpha_func:3; /**< PIPE_BLEND_x */ + GLuint alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */ + GLuint alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ + + GLuint logicop_enable:1; + GLuint logicop_func:4; /**< PIPE_LOGICOP_x */ + + GLuint colormask:4; /**< bitmask of PIPE_MASK_R/G/B/A */ + GLuint dither:1; +}; + +struct pipe_blend_color { + GLfloat color[4]; +}; + +struct pipe_clear_color_state +{ + GLfloat color[4]; +}; + +struct pipe_stencil_state { + GLuint front_enabled:1; + GLuint front_func:3; /**< PIPE_FUNC_x */ + GLuint front_fail_op:3; /**< PIPE_STENCIL_OP_x */ + GLuint front_zpass_op:3; /**< PIPE_STENCIL_OP_x */ + GLuint front_zfail_op:3; /**< PIPE_STENCIL_OP_x */ + GLuint back_enabled:1; + GLuint back_func:3; /**< PIPE_FUNC_x */ + GLuint back_fail_op:3; /**< PIPE_STENCIL_OP_x */ + GLuint back_zpass_op:3; /**< PIPE_STENCIL_OP_x */ + GLuint back_zfail_op:3; /**< PIPE_STENCIL_OP_x */ + GLubyte ref_value[2]; /**< [0] = front, [1] = back */ + GLubyte value_mask[2]; + GLubyte write_mask[2]; + GLubyte clear_value; +}; + + +struct pipe_framebuffer_state +{ + /** multiple colorbuffers for multiple render targets */ + GLuint num_cbufs; + struct pipe_surface *cbufs[PIPE_MAX_COLOR_BUFS]; + + struct pipe_surface *zbuf; /**< Z buffer */ + struct pipe_surface *sbuf; /**< Stencil buffer */ + struct pipe_surface *abuf; /**< Accum buffer */ +}; + + +/** + * Texture sampler state. + */ +struct pipe_sampler_state +{ + GLuint wrap_s:3; /**< PIPE_TEX_WRAP_x */ + GLuint wrap_t:3; /**< PIPE_TEX_WRAP_x */ + GLuint wrap_r:3; /**< PIPE_TEX_WRAP_x */ + GLuint min_filter:3; /**< PIPE_TEX_FILTER_x */ + GLuint mag_filter:1; /**< PIPE_TEX_FILTER_LINEAR or _NEAREST */ + GLuint compare:1; /**< shadow/depth compare enabled? */ + GLenum compare_mode:1; /**< PIPE_TEX_COMPARE_x */ + GLenum compare_func:3; /**< PIPE_FUNC_x */ + GLfloat shadow_ambient; /**< shadow test fail color/intensity */ + GLfloat min_lod; + GLfloat max_lod; + GLfloat lod_bias; +#if 0 /* need these? */ + GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */ + GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */ + GLfloat border_color[4]; +#endif + GLfloat max_anisotropy; +}; + + +/*** + *** Non-state Objects + ***/ + + +/** + * A mappable buffer (vertex data, pixel data, etc) + */ +struct pipe_buffer +{ + void (*buffer_data)(struct pipe_buffer *pb, GLuint size, const void *src); + void (*buffer_sub_data)(struct pipe_buffer *pb, GLuint offset, GLuint size, + const void *src); + void *(*map)(struct pipe_buffer *pb, GLuint access_mode); + void (*unmap)(struct pipe_buffer *pb); + void *ptr; /**< address, only valid while mapped */ + GLuint mode; /**< PIPE_MAP_x, only valid while mapped */ +}; + + +/** + * 2D surface. + * May be a renderbuffer, texture mipmap level, etc. + */ +struct pipe_surface +{ + struct pipe_buffer buffer; /**< surfaces can be mapped */ + GLuint format:5; /**< PIPE_FORMAT_x */ + GLuint width, height; +#if 0 + GLubyte *ptr; + GLint stride; + GLuint cpp; + GLuint format; +#endif +}; + + +/** + * Texture object. + * Mipmap levels, cube faces, 3D slices can be accessed as surfaces. + */ +struct pipe_texture_object +{ + GLuint type:2; /**< PIPE_TEXTURE_x */ + GLuint format:5; /**< PIPE_FORMAT_x */ + GLuint width:13; /**< 13 bits = 8K max size */ + GLuint height:13; + GLuint depth:13; + GLuint mipmapped:1; + + /** to access a 1D or 2D texture object as a surface */ + struct pipe_surface *(*get_2d_surface)(struct pipe_texture_object *pto, + GLuint level); + /** to access a 3D texture object as a surface */ + struct pipe_surface *(*get_3d_surface)(struct pipe_texture_object *pto, + GLuint level, GLuint slice); + /** to access a cube texture object as a surface */ + struct pipe_surface *(*get_cube_surface)(struct pipe_texture_object *pto, + GLuint face, GLuint level); + /** when finished with surface: */ + void (*release_surface)(struct pipe_texture_object *pto, + struct pipe_surface *ps); +}; + + +#endif diff --git a/src/mesa/pipe/softpipe/Makefile b/src/mesa/pipe/softpipe/Makefile new file mode 100644 index 00000000000..12a8bd0409e --- /dev/null +++ b/src/mesa/pipe/softpipe/Makefile @@ -0,0 +1,3 @@ +default: + cd ../.. ; make + diff --git a/src/mesa/pipe/softpipe/sp_clear.c b/src/mesa/pipe/softpipe/sp_clear.c new file mode 100644 index 00000000000..e83bc053ef7 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_clear.c @@ -0,0 +1,71 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Author: + * Brian Paul + */ + + +#include "sp_clear.h" +#include "sp_context.h" +#include "sp_surface.h" +#include "colormac.h" + + +void +softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, + GLboolean stencil, GLboolean accum) +{ + const struct softpipe_context *softpipe = softpipe_context(pipe); + const GLint x = softpipe->scissor.minx; + const GLint y = softpipe->scissor.miny; + const GLint w = softpipe->scissor.maxx - x; + const GLint h = softpipe->scissor.maxy - y; + + if (color) { + GLuint i; + GLubyte clr[4]; + + UNCLAMPED_FLOAT_TO_UBYTE(clr[0], softpipe->clear_color.color[0]); + UNCLAMPED_FLOAT_TO_UBYTE(clr[1], softpipe->clear_color.color[1]); + UNCLAMPED_FLOAT_TO_UBYTE(clr[2], softpipe->clear_color.color[2]); + UNCLAMPED_FLOAT_TO_UBYTE(clr[3], softpipe->clear_color.color[3]); + + for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) { + struct pipe_surface *ps = softpipe->framebuffer.cbufs[i]; + struct softpipe_surface *sps = softpipe_surface(ps); + GLint j; + for (j = 0; j < h; j++) { + sps->write_mono_row_ub(sps, w, x, y + j, clr); + } + } + } + + if (depth) { + } + +} diff --git a/src/mesa/pipe/softpipe/sp_clear.h b/src/mesa/pipe/softpipe/sp_clear.h new file mode 100644 index 00000000000..f9db99dd32a --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_clear.h @@ -0,0 +1,43 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Author: + * Brian Paul + */ + +#ifndef SP_CLEAR_H +#define SP_CLEAR_H + +#include "pipe/p_state.h" +struct pipe_context; + +extern void +softpipe_clear(struct pipe_context *pipe, GLboolean color, GLboolean depth, + GLboolean stencil, GLboolean accum); + + +#endif /* SP_CLEAR_H */ diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c new file mode 100644 index 00000000000..3bb04a68357 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -0,0 +1,126 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Author: + * Keith Whitwell <[email protected]> + */ + +#include "main/imports.h" +#include "main/macros.h" +#include "pipe/draw/draw_context.h" +#include "sp_context.h" +#include "sp_clear.h" +#include "sp_state.h" +#include "sp_prim_setup.h" + + +static void softpipe_destroy( struct pipe_context *pipe ) +{ + struct softpipe_context *softpipe = softpipe_context( pipe ); + + draw_destroy( softpipe->draw ); + + free( softpipe ); +} + + +static void softpipe_draw_vb( struct pipe_context *pipe, + struct vertex_buffer *VB ) +{ + struct softpipe_context *softpipe = softpipe_context( pipe ); + + if (softpipe->dirty) + softpipe_update_derived( softpipe ); + + draw_vb( softpipe->draw, VB ); +} + + +static void softpipe_reset_occlusion_counter(struct pipe_context *pipe) +{ + struct softpipe_context *softpipe = softpipe_context( pipe ); + softpipe->occlusion_counter = 0; +} + +/* XXX pipe param should be const */ +static GLuint softpipe_get_occlusion_counter(struct pipe_context *pipe) +{ + struct softpipe_context *softpipe = softpipe_context( pipe ); + return softpipe->occlusion_counter; +} + + +struct pipe_context *softpipe_create( void ) +{ + struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context); + + softpipe->pipe.destroy = softpipe_destroy; + softpipe->pipe.set_alpha_test_state = softpipe_set_alpha_test_state; + softpipe->pipe.set_blend_color = softpipe_set_blend_color; + softpipe->pipe.set_blend_state = softpipe_set_blend_state; + softpipe->pipe.set_clip_state = softpipe_set_clip_state; + softpipe->pipe.set_clear_color_state = softpipe_set_clear_color_state; + softpipe->pipe.set_depth_state = softpipe_set_depth_test_state; + softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; + softpipe->pipe.set_fs_state = softpipe_set_fs_state; + softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple; + softpipe->pipe.set_sampler_state = softpipe_set_sampler_state; + softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; + softpipe->pipe.set_setup_state = softpipe_set_setup_state; + softpipe->pipe.set_stencil_state = softpipe_set_stencil_state; + softpipe->pipe.set_texture_state = softpipe_set_texture_state; + softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; + softpipe->pipe.draw_vb = softpipe_draw_vb; + softpipe->pipe.clear = softpipe_clear; + softpipe->pipe.reset_occlusion_counter = softpipe_reset_occlusion_counter; + softpipe->pipe.get_occlusion_counter = softpipe_get_occlusion_counter; + + softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe); + softpipe->quad.shade = sp_quad_shade_stage(softpipe); + softpipe->quad.alpha_test = sp_quad_alpha_test_stage(softpipe); + softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe); + softpipe->quad.stencil_test = sp_quad_stencil_test_stage(softpipe); + softpipe->quad.occlusion = sp_quad_occlusion_stage(softpipe); + softpipe->quad.coverage = sp_quad_coverage_stage(softpipe); + softpipe->quad.bufloop = sp_quad_bufloop_stage(softpipe); + softpipe->quad.blend = sp_quad_blend_stage(softpipe); + softpipe->quad.colormask = sp_quad_colormask_stage(softpipe); + softpipe->quad.output = sp_quad_output_stage(softpipe); + + /* + * Create drawing context and plug our rendering stage into it. + */ + softpipe->draw = draw_create(); + draw_set_setup_stage(softpipe->draw, sp_draw_render_stage(softpipe)); + + /* + * XXX we could plug GL selection/feedback into the drawing pipeline + * by specifying a different setup/render stage. + */ + + return &softpipe->pipe; +} diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h new file mode 100644 index 00000000000..8871b45d4ff --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -0,0 +1,157 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#ifndef SP_CONTEXT_H +#define SP_CONTEXT_H + +#include "glheader.h" + +#include "pipe/p_state.h" +#include "pipe/p_context.h" + +#include "sp_quad.h" + + +struct softpipe_surface; +struct draw_context; +struct draw_stage; + + +enum interp_mode { + INTERP_CONSTANT, + INTERP_LINEAR, + INTERP_PERSPECTIVE +}; + + +#define SP_NEW_VIEWPORT 0x1 +#define SP_NEW_SETUP 0x2 +#define SP_NEW_FS 0x4 +#define SP_NEW_BLEND 0x8 +#define SP_NEW_CLIP 0x10 +#define SP_NEW_SCISSOR 0x20 +#define SP_NEW_STIPPLE 0x40 +#define SP_NEW_FRAMEBUFFER 0x80 +#define SP_NEW_ALPHA_TEST 0x100 +#define SP_NEW_DEPTH_TEST 0x200 +#define SP_NEW_SAMPLER 0x400 +#define SP_NEW_TEXTURE 0x800 +#define SP_NEW_STENCIL 0x1000 + + +struct softpipe_context { + struct pipe_context pipe; /**< base class */ + + /* The most recent drawing state as set by the driver: + */ + struct pipe_alpha_test_state alpha_test; + struct pipe_blend_state blend; + struct pipe_blend_color blend_color; + struct pipe_clear_color_state clear_color; + struct pipe_clip_state clip; + struct pipe_depth_state depth_test; + struct pipe_framebuffer_state framebuffer; + struct pipe_fs_state fs; + struct pipe_poly_stipple poly_stipple; + struct pipe_scissor_state scissor; + struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS]; + struct pipe_setup_state setup; + struct pipe_stencil_state stencil; + struct pipe_texture_object *texture[PIPE_MAX_SAMPLERS]; + struct pipe_viewport_state viewport; + GLuint dirty; + + /* Setup derived state. TODO: this should be passed in the program + * tokens as parameters to DECL instructions. + * + * For now we just set colors to CONST on flatshade, textures to + * perspective always and everything else to linear. + */ + enum interp_mode interp[PIPE_ATTRIB_MAX]; + + + /* FS + setup derived state: + */ + + /** Map fragment program attribute to quad/coef array slot */ + GLuint fp_attr_to_slot[PIPE_ATTRIB_MAX]; + /** Map vertex format attribute to a vertex attribute slot */ + GLuint vf_attr_to_slot[PIPE_ATTRIB_MAX]; + GLuint nr_attrs; + GLuint nr_frag_attrs; /**< number of active fragment attribs */ + GLbitfield attr_mask; /**< bitfield of VF_ATTRIB_ indexes/bits */ + + GLboolean need_z; /**< produce quad/fragment Z values? */ + GLboolean need_w; /**< produce quad/fragment W values? */ + +#if 0 + /* Stipple derived state: + */ + GLubyte stipple_masks[16][16]; +#endif + + GLuint occlusion_counter; + + GLuint line_stipple_counter; + + /** Software quad rendering pipeline */ + struct { + struct quad_stage *polygon_stipple; + struct quad_stage *shade; + struct quad_stage *alpha_test; + struct quad_stage *stencil_test; + struct quad_stage *depth_test; + struct quad_stage *occlusion; + struct quad_stage *coverage; + struct quad_stage *bufloop; + struct quad_stage *blend; + struct quad_stage *colormask; + struct quad_stage *output; + + struct quad_stage *first; /**< points to one of the above stages */ + } quad; + + /** The primitive drawing context */ + struct draw_context *draw; + + struct pipe_surface *cbuf; /**< current color buffer (one of cbufs) */ +}; + + + + +static INLINE struct softpipe_context * +softpipe_context( struct pipe_context *pipe ) +{ + return (struct softpipe_context *)pipe; +} + + +#endif /* SP_CONTEXT_H */ diff --git a/src/mesa/pipe/softpipe/sp_headers.h b/src/mesa/pipe/softpipe/sp_headers.h new file mode 100644 index 00000000000..68a84621f2c --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_headers.h @@ -0,0 +1,95 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#ifndef SP_HEADERS_H +#define SP_HEADERS_H + + +#define PRIM_POINT 1 +#define PRIM_LINE 2 +#define PRIM_TRI 3 + + +/* The rasterizer generates 2x2 quads of fragment and feeds them to + * the current fp_machine (see below). + */ +#define QUAD_BOTTOM_LEFT 0 +#define QUAD_BOTTOM_RIGHT 1 +#define QUAD_TOP_LEFT 2 +#define QUAD_TOP_RIGHT 3 +#define QUAD_SIZE (2*2) + +#define MASK_BOTTOM_LEFT 0x1 +#define MASK_BOTTOM_RIGHT 0x2 +#define MASK_TOP_LEFT 0x4 +#define MASK_TOP_RIGHT 0x8 +#define MASK_ALL 0xf + + +#define NUM_CHANNELS 4 /* avoid confusion between 4 pixels and 4 channels */ + + +struct setup_coefficient { + GLfloat a0[NUM_CHANNELS]; /* in an xyzw layout */ + GLfloat dadx[NUM_CHANNELS]; + GLfloat dady[NUM_CHANNELS]; +}; + + + +/** + * Encodes everything we need to know about a 2x2 pixel block. Uses + * "Channel-Serial" or "SoA" layout. + */ +struct quad_header { + GLint x0; + GLint y0; + GLuint mask:4; + GLuint facing:1; /**< Front (0) or back (1) facing? */ + GLuint prim:2; /**< PRIM_POINT, LINE, TRI */ + + struct { + GLfloat color[4][QUAD_SIZE]; /* rrrr, gggg, bbbb, aaaa */ + GLfloat depth[QUAD_SIZE]; + } outputs; + + GLfloat coverage[QUAD_SIZE]; /** fragment coverage for antialiasing */ + + const struct setup_coefficient *coef; + + const enum interp_mode *interp; /* XXX: this information should be + * encoded in fragment program DECL + * statements. */ + + GLuint nr_attrs; +}; + + +#endif /* SP_HEADERS_H */ diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.c b/src/mesa/pipe/softpipe/sp_prim_setup.c new file mode 100644 index 00000000000..091a2343a9c --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_prim_setup.c @@ -0,0 +1,1039 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \brief Primitive rasterization/rendering (points, lines, triangles) + * + * \author Keith Whitwell <[email protected]> + * \author Brian Paul + */ + + +#include "imports.h" +#include "macros.h" + +#include "sp_context.h" +#include "sp_headers.h" +#include "pipe/draw/draw_private.h" +#include "sp_quad.h" +#include "sp_prim_setup.h" + + + +/** + * Emit/render a quad. + * This passes the quad to the first stage of per-fragment operations. + */ +static INLINE void +quad_emit(struct softpipe_context *sp, struct quad_header *quad) +{ + sp->quad.first->run(sp->quad.first, quad); +} + + +/** + * Triangle edge info + */ +struct edge { + GLfloat dx; /* X(v1) - X(v0), used only during setup */ + GLfloat dy; /* Y(v1) - Y(v0), used only during setup */ + GLfloat dxdy; /* dx/dy */ + GLfloat sx; /* first sample point x coord */ + GLfloat sy; + GLint lines; /* number of lines on this edge */ +}; + + +/** + * Triangle setup info (derived from draw_stage). + * Also used for line drawing (taking some liberties). + */ +struct setup_stage { + struct draw_stage stage; /**< This must be first (base class) */ + + /*XXX NEW */ + struct softpipe_context *softpipe; + + /* Vertices are just an array of floats making up each attribute in + * turn. Currently fixed at 4 floats, but should change in time. + * Codegen will help cope with this. + */ + const struct vertex_header *vmax; + const struct vertex_header *vmid; + const struct vertex_header *vmin; + const struct vertex_header *vprovoke; + + struct edge ebot; + struct edge etop; + struct edge emaj; + + GLfloat oneoverarea; + + struct setup_coefficient coef[FRAG_ATTRIB_MAX]; + struct quad_header quad; + + struct { + GLint left[2]; /**< [0] = row0, [1] = row1 */ + GLint right[2]; + GLint y; + GLuint y_flags; + GLuint mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */ + } span; +}; + + + +/** + * Basically a cast wrapper. + */ +static inline struct setup_stage *setup_stage( struct draw_stage *stage ) +{ + return (struct setup_stage *)stage; +} + + +/** + * Given an X or Y coordinate, return the block/quad coordinate that it + * belongs to. + */ +static inline GLint block( GLint x ) +{ + return x & ~1; +} + + + +/** + * Run shader on a quad/block. + */ +static void run_shader_block( struct setup_stage *setup, + GLint x, GLint y, GLuint mask ) +{ + setup->quad.x0 = x; + setup->quad.y0 = y; + setup->quad.mask = mask; + + quad_emit(setup->softpipe, &setup->quad); +} + + +/** + * Compute mask which indicates which pixels in the 2x2 quad are actually inside + * the triangle's bounds. + * + * this is pretty nasty... may need to rework flush_spans again to + * fix it, if possible. + */ +static GLuint calculate_mask( struct setup_stage *setup, + GLint x ) +{ + GLuint mask = 0; + + if (x >= setup->span.left[0] && x < setup->span.right[0]) + mask |= MASK_BOTTOM_LEFT; + + if (x >= setup->span.left[1] && x < setup->span.right[1]) + mask |= MASK_TOP_LEFT; + + if (x+1 >= setup->span.left[0] && x+1 < setup->span.right[0]) + mask |= MASK_BOTTOM_RIGHT; + + if (x+1 >= setup->span.left[1] && x+1 < setup->span.right[1]) + mask |= MASK_TOP_RIGHT; + + return mask; +} + + +/** + * Render a horizontal span of quads + */ +static void flush_spans( struct setup_stage *setup ) +{ + GLint minleft, maxright; + GLint x; + + switch (setup->span.y_flags) { + case 3: + minleft = MIN2(setup->span.left[0], setup->span.left[1]); + maxright = MAX2(setup->span.right[0], setup->span.right[1]); + break; + + case 1: + minleft = setup->span.left[0]; + maxright = setup->span.right[0]; + break; + + case 2: + minleft = setup->span.left[1]; + maxright = setup->span.right[1]; + break; + + default: + return; + } + + + for (x = block(minleft); x <= block(maxright); ) + { + run_shader_block( setup, x, + setup->span.y, + calculate_mask( setup, x ) ); + x += 2; + } + + setup->span.y = 0; + setup->span.y_flags = 0; + setup->span.right[0] = 0; + setup->span.right[1] = 0; +} + + +static GLboolean setup_sort_vertices( struct setup_stage *setup, + const struct prim_header *prim ) +{ + const struct vertex_header *v0 = prim->v[0]; + const struct vertex_header *v1 = prim->v[1]; + const struct vertex_header *v2 = prim->v[2]; + + setup->vprovoke = v2; + + /* determine bottom to top order of vertices */ + { + GLfloat y0 = v0->data[0][1]; + GLfloat y1 = v1->data[0][1]; + GLfloat y2 = v2->data[0][1]; + if (y0 <= y1) { + if (y1 <= y2) { + /* y0<=y1<=y2 */ + setup->vmin = v0; + setup->vmid = v1; + setup->vmax = v2; + } + else if (y2 <= y0) { + /* y2<=y0<=y1 */ + setup->vmin = v2; + setup->vmid = v0; + setup->vmax = v1; + } + else { + /* y0<=y2<=y1 */ + setup->vmin = v0; + setup->vmid = v2; + setup->vmax = v1; + } + } + else { + if (y0 <= y2) { + /* y1<=y0<=y2 */ + setup->vmin = v1; + setup->vmid = v0; + setup->vmax = v2; + } + else if (y2 <= y1) { + /* y2<=y1<=y0 */ + setup->vmin = v2; + setup->vmid = v1; + setup->vmax = v0; + } + else { + /* y1<=y2<=y0 */ + setup->vmin = v1; + setup->vmid = v2; + setup->vmax = v0; + } + } + } + + setup->ebot.dx = setup->vmid->data[0][0] - setup->vmin->data[0][0]; + setup->ebot.dy = setup->vmid->data[0][1] - setup->vmin->data[0][1]; + setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0]; + setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1]; + setup->etop.dx = setup->vmax->data[0][0] - setup->vmid->data[0][0]; + setup->etop.dy = setup->vmax->data[0][1] - setup->vmid->data[0][1]; + + /* + * Compute triangle's area. Use 1/area to compute partial + * derivatives of attributes later. + * + * The area will be the same as prim->det, but the sign may be + * different depending on how the vertices get sorted above. + * + * To determine whether the primitive is front or back facing we + * use the prim->det value because its sign is correct. + */ + { + const GLfloat area = (setup->emaj.dx * setup->ebot.dy - + setup->ebot.dx * setup->emaj.dy); + + setup->oneoverarea = 1.0 / area; + /* + _mesa_printf("%s one-over-area %f area %f det %f\n", + __FUNCTION__, setup->oneoverarea, area, prim->det ); + */ + } + + /* We need to know if this is a front or back-facing triangle for: + * - the GLSL gl_FrontFacing fragment attribute (bool) + * - two-sided stencil test + */ + setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->setup.front_winding == PIPE_WINDING_CW); + + return GL_TRUE; +} + + +/** + * Compute a0 for a constant-valued coefficient (GL_FLAT shading). + * The value value comes from vertex->data[slot][i]. + * The result will be put into setup->coef[slot].a0[i]. + * \param slot which attribute slot + * \param i which component of the slot (0..3) + */ +static void const_coeff( struct setup_stage *setup, + GLuint slot, + GLuint i ) +{ + assert(slot < FRAG_ATTRIB_MAX); + assert(i <= 3); + + setup->coef[slot].dadx[i] = 0; + setup->coef[slot].dady[i] = 0; + + /* need provoking vertex info! + */ + setup->coef[slot].a0[i] = setup->vprovoke->data[slot][i]; +} + + +/** + * Compute a0, dadx and dady for a linearly interpolated coefficient, + * for a triangle. + */ +static void tri_linear_coeff( struct setup_stage *setup, + GLuint slot, + GLuint i) +{ + GLfloat botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i]; + GLfloat majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i]; + GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy; + GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx; + + assert(slot < FRAG_ATTRIB_MAX); + assert(i <= 3); + + setup->coef[slot].dadx[i] = a * setup->oneoverarea; + setup->coef[slot].dady[i] = b * setup->oneoverarea; + + /* calculate a0 as the value which would be sampled for the + * fragment at (0,0), taking into account that we want to sample at + * pixel centers, in other words (0.5, 0.5). + * + * this is neat but unfortunately not a good way to do things for + * triangles with very large values of dadx or dady as it will + * result in the subtraction and re-addition from a0 of a very + * large number, which means we'll end up loosing a lot of the + * fractional bits and precision from a0. the way to fix this is + * to define a0 as the sample at a pixel center somewhere near vmin + * instead - i'll switch to this later. + */ + setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] - + (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) + + setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5))); + + /* + _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n", + slot, "xyzw"[i], + setup->coef[slot].a0[i], + setup->coef[slot].dadx[i], + setup->coef[slot].dady[i]); + */ +} + + +/** + * Compute a0, dadx and dady for a perspective-corrected interpolant, + * for a triangle. + */ +static void tri_persp_coeff( struct setup_stage *setup, + GLuint slot, + GLuint i ) +{ + /* premultiply by 1/w: + */ + GLfloat mina = setup->vmin->data[slot][i] * setup->vmin->data[0][3]; + GLfloat mida = setup->vmid->data[slot][i] * setup->vmid->data[0][3]; + GLfloat maxa = setup->vmax->data[slot][i] * setup->vmax->data[0][3]; + + GLfloat botda = mida - mina; + GLfloat majda = maxa - mina; + GLfloat a = setup->ebot.dy * majda - botda * setup->emaj.dy; + GLfloat b = setup->emaj.dx * botda - majda * setup->ebot.dx; + + assert(slot < FRAG_ATTRIB_MAX); + assert(i <= 3); + + setup->coef[slot].dadx[i] = a * setup->oneoverarea; + setup->coef[slot].dady[i] = b * setup->oneoverarea; + setup->coef[slot].a0[i] = (mina - + (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) + + setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5))); +} + + + +/** + * Compute the setup->coef[] array dadx, dady, a0 values. + * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized. + */ +static void setup_tri_coefficients( struct setup_stage *setup ) +{ + const enum interp_mode *interp = setup->softpipe->interp; + GLuint slot, j; + + /* z and w are done by linear interpolation: + */ + tri_linear_coeff(setup, 0, 2); + tri_linear_coeff(setup, 0, 3); + + /* setup interpolation for all the remaining attributes: + */ + for (slot = 1; slot < setup->quad.nr_attrs; slot++) { + switch (interp[slot]) { + case INTERP_CONSTANT: + for (j = 0; j < NUM_CHANNELS; j++) + const_coeff(setup, slot, j); + break; + + case INTERP_LINEAR: + for (j = 0; j < NUM_CHANNELS; j++) + tri_linear_coeff(setup, slot, j); + break; + + case INTERP_PERSPECTIVE: + for (j = 0; j < NUM_CHANNELS; j++) + tri_persp_coeff(setup, slot, j); + break; + } + } +} + + + +static void setup_tri_edges( struct setup_stage *setup ) +{ + GLfloat vmin_x = setup->vmin->data[0][0] + 0.5; + GLfloat vmid_x = setup->vmid->data[0][0] + 0.5; + + GLfloat vmin_y = setup->vmin->data[0][1] - 0.5; + GLfloat vmid_y = setup->vmid->data[0][1] - 0.5; + GLfloat vmax_y = setup->vmax->data[0][1] - 0.5; + + setup->emaj.sy = ceilf(vmin_y); + setup->emaj.lines = (GLint) ceilf(vmax_y - setup->emaj.sy); + setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy; + setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy; + + setup->etop.sy = ceilf(vmid_y); + setup->etop.lines = (GLint) ceilf(vmax_y - setup->etop.sy); + setup->etop.dxdy = setup->etop.dx / setup->etop.dy; + setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy; + + setup->ebot.sy = ceilf(vmin_y); + setup->ebot.lines = (GLint) ceilf(vmid_y - setup->ebot.sy); + setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy; + setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy; +} + + +/** + * Render the upper or lower half of a triangle. + * Scissoring is applied here too. + */ +static void subtriangle( struct setup_stage *setup, + struct edge *eleft, + struct edge *eright, + GLuint lines ) +{ + GLint y, start_y, finish_y; + GLint sy = (GLint)eleft->sy; + + assert((GLint)eleft->sy == (GLint) eright->sy); + assert((GLint)eleft->sy >= 0); /* catch bug in x64? */ + + /* scissor y: + */ + if (setup->softpipe->setup.scissor) { + start_y = sy; + finish_y = start_y + lines; + + if (start_y < setup->softpipe->scissor.miny) + start_y = setup->softpipe->scissor.miny; + + if (finish_y > setup->softpipe->scissor.maxy) + finish_y = setup->softpipe->scissor.maxy; + + start_y -= sy; + finish_y -= sy; + } + else { + start_y = 0; + finish_y = lines; + } + + /* + _mesa_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y); + */ + + for (y = start_y; y < finish_y; y++) { + + /* avoid accumulating adds as floats don't have the precision to + * accurately iterate large triangle edges that way. luckily we + * can just multiply these days. + * + * this is all drowned out by the attribute interpolation anyway. + */ + GLint left = (GLint)(eleft->sx + y * eleft->dxdy); + GLint right = (GLint)(eright->sx + y * eright->dxdy); + + /* scissor x: + */ + if (setup->softpipe->setup.scissor) { + if (left < setup->softpipe->scissor.minx) + left = setup->softpipe->scissor.minx; + + if (right > setup->softpipe->scissor.maxx) + right = setup->softpipe->scissor.maxx; + } + + if (left < right) { + GLint _y = sy+y; + if (block(_y) != setup->span.y) { + flush_spans(setup); + setup->span.y = block(_y); + } + + setup->span.left[_y&1] = left; + setup->span.right[_y&1] = right; + setup->span.y_flags |= 1<<(_y&1); + } + } + + + /* save the values so that emaj can be restarted: + */ + eleft->sx += lines * eleft->dxdy; + eright->sx += lines * eright->dxdy; + eleft->sy += lines; + eright->sy += lines; +} + + +/** + * Do setup for triangle rasterization, then render the triangle. + */ +static void setup_tri( struct draw_stage *stage, + struct prim_header *prim ) +{ + struct setup_stage *setup = setup_stage( stage ); + + /* + _mesa_printf("%s\n", __FUNCTION__ ); + */ + + setup_sort_vertices( setup, prim ); + setup_tri_coefficients( setup ); + setup_tri_edges( setup ); + + setup->quad.prim = PRIM_TRI; + + setup->span.y = 0; + setup->span.y_flags = 0; + setup->span.right[0] = 0; + setup->span.right[1] = 0; + /* setup->span.z_mode = tri_z_mode( setup->ctx ); */ + + /* init_constant_attribs( setup ); */ + + if (setup->oneoverarea < 0.0) { + /* emaj on left: + */ + subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines ); + subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines ); + } + else { + /* emaj on right: + */ + subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines ); + subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines ); + } + + flush_spans( setup ); +} + + + +/** + * Compute a0, dadx and dady for a linearly interpolated coefficient, + * for a line. + */ +static void +line_linear_coeff(struct setup_stage *setup, GLuint slot, GLuint i) +{ + const GLfloat dz = setup->vmax->data[slot][i] - setup->vmin->data[slot][i]; + const GLfloat dadx = dz * setup->emaj.dx * setup->oneoverarea; + const GLfloat dady = dz * setup->emaj.dy * setup->oneoverarea; + setup->coef[slot].dadx[i] = dadx; + setup->coef[slot].dady[i] = dady; + setup->coef[slot].a0[i] + = (setup->vmin->data[slot][i] - + (dadx * (setup->vmin->data[0][0] - 0.5) + + dady * (setup->vmin->data[0][1] - 0.5))); +} + + +/** + * Compute a0, dadx and dady for a perspective-corrected interpolant, + * for a line. + */ +static void +line_persp_coeff(struct setup_stage *setup, GLuint slot, GLuint i) +{ + /* XXX to do */ + line_linear_coeff(setup, slot, i); /* XXX temporary */ +} + + +/** + * Compute the setup->coef[] array dadx, dady, a0 values. + * Must be called after setup->vmin,vmax are initialized. + */ +static INLINE void +setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim) +{ + const enum interp_mode *interp = setup->softpipe->interp; + GLuint slot, j; + + /* use setup->vmin, vmax to point to vertices */ + setup->vprovoke = prim->v[1]; + setup->vmin = prim->v[0]; + setup->vmax = prim->v[1]; + + setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0]; + setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1]; + /* NOTE: this is not really 1/area */ + setup->oneoverarea = 1.0 / (setup->emaj.dx * setup->emaj.dx + + setup->emaj.dy * setup->emaj.dy); + + /* z and w are done by linear interpolation: + */ + line_linear_coeff(setup, 0, 2); + line_linear_coeff(setup, 0, 3); + + /* setup interpolation for all the remaining attributes: + */ + for (slot = 1; slot < setup->quad.nr_attrs; slot++) { + switch (interp[slot]) { + case INTERP_CONSTANT: + for (j = 0; j < NUM_CHANNELS; j++) + const_coeff(setup, slot, j); + break; + + case INTERP_LINEAR: + for (j = 0; j < NUM_CHANNELS; j++) + line_linear_coeff(setup, slot, j); + break; + + case INTERP_PERSPECTIVE: + for (j = 0; j < NUM_CHANNELS; j++) + line_persp_coeff(setup, slot, j); + break; + } + } +} + + +/** + * Plot a pixel in a line segment. + */ +static INLINE void +plot(struct setup_stage *setup, GLint x, GLint y) +{ + const GLint iy = y & 1; + const GLint ix = x & 1; + const GLint quadX = x - ix; + const GLint quadY = y - iy; + const GLint mask = (1 << ix) << (2 * iy); + + if (quadX != setup->quad.x0 || + quadY != setup->quad.y0) + { + /* flush prev quad, start new quad */ + + if (setup->quad.x0 != -1) + quad_emit(setup->softpipe, &setup->quad); + + setup->quad.x0 = quadX; + setup->quad.y0 = quadY; + setup->quad.mask = 0x0; + } + + setup->quad.mask |= mask; +} + + +/** + * Determine whether or not to emit a line fragment by checking + * line stipple pattern. + */ +static INLINE GLuint +stipple_test(GLint counter, GLushort pattern, GLint factor) +{ + GLint b = (counter / factor) & 0xf; + return (1 << b) & pattern; +} + + +/** + * Do setup for line rasterization, then render the line. + * XXX single-pixel width, no stipple, etc + * XXX no scissoring yet. + */ +static void +setup_line(struct draw_stage *stage, struct prim_header *prim) +{ + const struct vertex_header *v0 = prim->v[0]; + const struct vertex_header *v1 = prim->v[1]; + struct setup_stage *setup = setup_stage( stage ); + struct softpipe_context *sp = setup->softpipe; + + GLint x0 = (GLint) v0->data[0][0]; + GLint x1 = (GLint) v1->data[0][0]; + GLint y0 = (GLint) v0->data[0][1]; + GLint y1 = (GLint) v1->data[0][1]; + GLint dx = x1 - x0; + GLint dy = y1 - y0; + GLint xstep, ystep; + + if (dx == 0 && dy == 0) + return; + + setup_line_coefficients(setup, prim); + + if (dx < 0) { + dx = -dx; /* make positive */ + xstep = -1; + } + else { + xstep = 1; + } + + if (dy < 0) { + dy = -dy; /* make positive */ + ystep = -1; + } + else { + ystep = 1; + } + + assert(dx >= 0); + assert(dy >= 0); + + setup->quad.x0 = setup->quad.y0 = -1; + setup->quad.mask = 0x0; + setup->quad.prim = PRIM_LINE; + + if (dx > dy) { + /*** X-major line ***/ + GLint i; + const GLint errorInc = dy + dy; + GLint error = errorInc - dx; + const GLint errorDec = error - dx; + + for (i = 0; i < dx; i++) { + if (!sp->setup.line_stipple_enable || + stipple_test(sp->line_stipple_counter, + sp->setup.line_stipple_pattern, + sp->setup.line_stipple_factor + 1)) { + plot(setup, x0, y0); + } + + x0 += xstep; + if (error < 0) { + error += errorInc; + } + else { + error += errorDec; + y0 += ystep; + } + + sp->line_stipple_counter++; + } + } + else { + /*** Y-major line ***/ + GLint i; + const GLint errorInc = dx + dx; + GLint error = errorInc - dy; + const GLint errorDec = error - dy; + + for (i = 0; i < dy; i++) { + if (!sp->setup.line_stipple_enable || + stipple_test(sp->line_stipple_counter, + sp->setup.line_stipple_pattern, + sp->setup.line_stipple_factor + 1)) { + plot(setup, x0, y0); + } + + y0 += ystep; + + if (error < 0) { + error += errorInc; + } + else { + error += errorDec; + x0 += xstep; + } + + sp->line_stipple_counter++; + } + } + + /* draw final quad */ + if (setup->quad.mask) { + quad_emit(setup->softpipe, &setup->quad); + } +} + + +/** + * Do setup for point rasterization, then render the point. + * Round or square points... + * XXX could optimize a lot for 1-pixel points. + */ +static void +setup_point(struct draw_stage *stage, struct prim_header *prim) +{ + struct setup_stage *setup = setup_stage( stage ); + /*XXX this should be a vertex attrib! */ + GLfloat halfSize = 0.5 * setup->softpipe->setup.point_size; + GLboolean round = setup->softpipe->setup.point_smooth; + const struct vertex_header *v0 = prim->v[0]; + const GLfloat x = v0->data[FRAG_ATTRIB_WPOS][0]; + const GLfloat y = v0->data[FRAG_ATTRIB_WPOS][1]; + GLuint slot, j; + + /* For points, all interpolants are constant-valued. + * However, for point sprites, we'll need to setup texcoords appropriately. + * XXX: which coefficients are the texcoords??? + * We may do point sprites as textured quads... + * + * KW: We don't know which coefficients are texcoords - ultimately + * the choice of what interpolation mode to use for each attribute + * should be determined by the fragment program, using + * per-attribute declaration statements that include interpolation + * mode as a parameter. So either the fragment program will have + * to be adjusted for pointsprite vs normal point behaviour, or + * otherwise a special interpolation mode will have to be defined + * which matches the required behaviour for point sprites. But - + * the latter is not a feature of normal hardware, and as such + * probably should be ruled out on that basis. + */ + setup->vprovoke = prim->v[0]; + const_coeff(setup, 0, 2); + const_coeff(setup, 0, 3); + for (slot = 1; slot < setup->quad.nr_attrs; slot++) { + for (j = 0; j < NUM_CHANNELS; j++) + const_coeff(setup, slot, j); + } + + setup->quad.prim = PRIM_POINT; + + /* XXX need to clip against scissor bounds too */ + + if (halfSize <= 0.5 && !round) { + /* special case for 1-pixel points */ + const GLint ix = ((GLint) x) & 1; + const GLint iy = ((GLint) y) & 1; + setup->quad.x0 = x - ix; + setup->quad.y0 = y - iy; + setup->quad.mask = (1 << ix) << (2 * iy); + quad_emit(setup->softpipe, &setup->quad); + } + else { + const GLint ixmin = block((GLint) (x - halfSize)); + const GLint ixmax = block((GLint) (x + halfSize)); + const GLint iymin = block((GLint) (y - halfSize)); + const GLint iymax = block((GLint) (y + halfSize)); + GLint ix, iy; + + if (round) { + /* rounded points */ + const GLfloat rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */ + const GLfloat rmax = halfSize + 0.7071F; + const GLfloat rmin2 = MAX2(0.0F, rmin * rmin); + const GLfloat rmax2 = rmax * rmax; + const GLfloat cscale = 1.0F / (rmax2 - rmin2); + + for (iy = iymin; iy <= iymax; iy += 2) { + for (ix = ixmin; ix <= ixmax; ix += 2) { + GLfloat dx, dy, dist2, cover; + + setup->quad.mask = 0x0; + + dx = (ix + 0.5) - x; + dy = (iy + 0.5) - y; + dist2 = dx * dx + dy * dy; + if (dist2 <= rmax2) { + cover = 1.0F - (dist2 - rmin2) * cscale; + setup->quad.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0); + setup->quad.mask |= MASK_BOTTOM_LEFT; + } + + dx = (ix + 1.5) - x; + dy = (iy + 0.5) - y; + dist2 = dx * dx + dy * dy; + if (dist2 <= rmax2) { + cover = 1.0F - (dist2 - rmin2) * cscale; + setup->quad.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0); + setup->quad.mask |= MASK_BOTTOM_RIGHT; + } + + dx = (ix + 0.5) - x; + dy = (iy + 1.5) - y; + dist2 = dx * dx + dy * dy; + if (dist2 <= rmax2) { + cover = 1.0F - (dist2 - rmin2) * cscale; + setup->quad.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0); + setup->quad.mask |= MASK_TOP_LEFT; + } + + dx = (ix + 1.5) - x; + dy = (iy + 1.5) - y; + dist2 = dx * dx + dy * dy; + if (dist2 <= rmax2) { + cover = 1.0F - (dist2 - rmin2) * cscale; + setup->quad.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0); + setup->quad.mask |= MASK_TOP_RIGHT; + } + + if (setup->quad.mask) { + setup->quad.x0 = ix; + setup->quad.y0 = iy; + quad_emit( setup->softpipe, &setup->quad ); + } + } + } + } + else { + /* square points */ + for (iy = iymin; iy <= iymax; iy += 2) { + for (ix = ixmin; ix <= ixmax; ix += 2) { + setup->quad.mask = 0xf; + + if (ix + 0.5 < x - halfSize) { + /* fragment is past left edge of point, turn off left bits */ + setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_TOP_LEFT); + } + + if (ix + 1.5 > x + halfSize) { + /* past the right edge */ + setup->quad.mask &= ~(MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT); + } + + if (iy + 0.5 < y - halfSize) { + /* below the bottom edge */ + setup->quad.mask &= ~(MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT); + } + + if (iy + 1.5 > y + halfSize) { + /* above the top edge */ + setup->quad.mask &= ~(MASK_TOP_LEFT | MASK_TOP_RIGHT); + } + + if (setup->quad.mask) { + setup->quad.x0 = ix; + setup->quad.y0 = iy; + quad_emit( setup->softpipe, &setup->quad ); + } + } + } + } + } +} + + + +static void setup_begin( struct draw_stage *stage ) +{ + struct setup_stage *setup = setup_stage(stage); + + setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs; + + /* + * XXX this is where we might map() the renderbuffers to begin + * s/w rendering. + */ +} + + +static void setup_end( struct draw_stage *stage ) +{ + /* + * XXX this is where we might unmap() the renderbuffers after + * s/w rendering. + */ +} + + +static void reset_stipple_counter( struct draw_stage *stage ) +{ + struct setup_stage *setup = setup_stage(stage); + setup->softpipe->line_stipple_counter = 0; +} + + +/** + * Create a new primitive setup/render stage. + */ +struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe ) +{ + struct setup_stage *setup = CALLOC_STRUCT(setup_stage); + + setup->softpipe = softpipe; + setup->stage.draw = softpipe->draw; + setup->stage.begin = setup_begin; + setup->stage.point = setup_point; + setup->stage.line = setup_line; + setup->stage.tri = setup_tri; + setup->stage.end = setup_end; + setup->stage.reset_stipple_counter = reset_stipple_counter; + + setup->quad.coef = setup->coef; + + return &setup->stage; +} diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.h b/src/mesa/pipe/softpipe/sp_prim_setup.h new file mode 100644 index 00000000000..e5abefcd499 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_prim_setup.h @@ -0,0 +1,122 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * 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 SP_PRIM_SETUP_H +#define SP_PRIM_SETUP_H + + +/* Vertices are just an array of floats, with all the attributes + * packed. We currently assume a layout like: + * + * attr[0][0..3] - window position + * attr[1..n][0..3] - remaining attributes. + * + * Attributes are assumed to be 4 floats wide but are packed so that + * all the enabled attributes run contiguously. + */ + +#include "glheader.h" +#include "imports.h" +#if 0 +#include "s_tri_public.h" +#endif +#include "s_context.h" + + +extern struct draw_stage *sp_draw_render_stage( struct softpipe_context *softpipe ); + + +#if 0 /* UNUSED? */ +struct tri_context; +struct fp_context; +struct be_context; + +/* Note the rasterizer does not take a GLcontext argument. This is + * deliberate. + */ +struct tri_context *tri_create_context( GLcontext *ctx ); + +void tri_destroy_context( struct tri_context *tri ); + +void tri_set_fp_context( struct tri_context *tri, + struct fp_context *fp, + void (*fp_run)( struct fp_context *fp, + const struct fp_inputs *, + struct fp_outputs * )); + + +void tri_set_be_context( struct tri_context *tri, + struct be_context *be, + void (*be_run)( struct be_context *be, + const struct fp_outputs * )); + +void tri_set_attribs( struct tri_context *tri, + const struct attr_info *info, + GLuint nr_attrib ); + +void tri_set_backface( struct tri_context *tri, + GLfloat backface ); + +void tri_set_scissor( struct tri_context *tri, + GLint x, + GLint y, + GLuint width, + GLuint height, + GLboolean enabled ); + +void tri_set_stipple( struct tri_context *tri, + const GLuint *pattern, + GLboolean enabled ); + +/* Unfilled triangles will be handled elsewhere (higher in the + * pipeline), as will things like stipple (lower in the pipeline). + */ + +void tri_triangle( struct tri_context *tri, + const struct vertex *v0, + const struct vertex *v1, + const struct vertex *v2 ); + +/* TODO: rasterize_line, rasterize_point?? + * How will linestipple work? + */ + + +#ifdef SETUP_PRIVATE + +GLboolean tri_setup( struct tri_context *tri, + const struct vertex *v0, + const struct vertex *v1, + const struct vertex *v2 ); + +void tri_rasterize( struct tri_context *tri ); +void tri_rasterize_spans( struct tri_context *tri ); + +#endif + + +#endif + +#endif /* SP_PRIM_SETUP_H */ diff --git a/src/mesa/pipe/softpipe/sp_quad.c b/src/mesa/pipe/softpipe/sp_quad.c new file mode 100644 index 00000000000..0053b16e683 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad.c @@ -0,0 +1,71 @@ + + +#include "sp_context.h" + + + +void +sp_build_quad_pipeline(struct softpipe_context *sp) +{ + /* build up the pipeline in reverse order... */ + + sp->quad.first = sp->quad.output; + + if (sp->blend.colormask != 0xf) { + sp->quad.colormask->next = sp->quad.first; + sp->quad.first = sp->quad.colormask; + } + + if (sp->blend.blend_enable) { + sp->quad.blend->next = sp->quad.first; + sp->quad.first = sp->quad.blend; + } + + if (sp->framebuffer.num_cbufs == 1) { + /* the usual case: write to exactly one colorbuf */ + sp->cbuf = sp->framebuffer.cbufs[0]; + } + else { + /* insert bufloop stage */ + sp->quad.bufloop->next = sp->quad.first; + sp->quad.first = sp->quad.bufloop; + } + + if (sp->depth_test.occlusion_count) { + sp->quad.occlusion->next = sp->quad.first; + sp->quad.first = sp->quad.occlusion; + } + + if (sp->setup.poly_smooth || + sp->setup.line_smooth || + sp->setup.point_smooth) { + sp->quad.coverage->next = sp->quad.first; + sp->quad.first = sp->quad.coverage; + } + + if ( sp->stencil.front_enabled + || sp->stencil.front_enabled) { + sp->quad.stencil_test->next = sp->quad.first; + sp->quad.first = sp->quad.stencil_test; + } + else if (sp->depth_test.enabled) { + sp->quad.depth_test->next = sp->quad.first; + sp->quad.first = sp->quad.depth_test; + } + + if (sp->alpha_test.enabled) { + sp->quad.alpha_test->next = sp->quad.first; + sp->quad.first = sp->quad.alpha_test; + } + + /* XXX always enable shader? */ + if (1) { + sp->quad.shade->next = sp->quad.first; + sp->quad.first = sp->quad.shade; + } + + if (sp->setup.poly_stipple_enable) { + sp->quad.polygon_stipple->next = sp->quad.first; + sp->quad.first = sp->quad.polygon_stipple; + } +} diff --git a/src/mesa/pipe/softpipe/sp_quad.h b/src/mesa/pipe/softpipe/sp_quad.h new file mode 100644 index 00000000000..2ee53bdecd8 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#ifndef SP_TILE_H +#define SP_TILE_H + + +struct softpipe_context; +struct quad_header; + + +struct quad_stage { + struct softpipe_context *softpipe; + + struct quad_stage *next; + + /** the stage action */ + void (*run)(struct quad_stage *qs, struct quad_header *quad); +}; + + +struct quad_stage *sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_bufloop_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe ); + +void sp_build_quad_pipeline(struct softpipe_context *sp); + +void sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad); + +#endif /* SP_TILE_H */ diff --git a/src/mesa/pipe/softpipe/sp_quad_alpha_test.c b/src/mesa/pipe/softpipe/sp_quad_alpha_test.c new file mode 100644 index 00000000000..8c28a824be5 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_alpha_test.c @@ -0,0 +1,94 @@ + +/** + * quad alpha test + */ + +#include "glheader.h" +#include "imports.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_quad.h" +#include "pipe/p_defines.h" + + +static void +alpha_test_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + const GLfloat ref = softpipe->alpha_test.ref; + GLuint passMask = 0x0, j; + + switch (softpipe->alpha_test.func) { + case PIPE_FUNC_NEVER: + quad->mask = 0x0; + break; + case PIPE_FUNC_LESS: + /* + * If mask were an array [4] we could do this SIMD-style: + * passMask = (quad->outputs.color[3] <= vec4(ref)); + */ + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->outputs.color[3][j] < ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_EQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->outputs.color[3][j] == ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_LEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->outputs.color[3][j] <= ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_GREATER: + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->outputs.color[3][j] > ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_NOTEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->outputs.color[3][j] != ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_GEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->outputs.color[3][j] >= ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_ALWAYS: + passMask = MASK_ALL; + break; + default: + abort(); + } + + quad->mask &= passMask; + + if (quad->mask) + qs->next->run(qs->next, quad); +} + + +struct quad_stage * +sp_quad_alpha_test_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = alpha_test_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_blend.c b/src/mesa/pipe/softpipe/sp_quad_blend.c new file mode 100644 index 00000000000..3d097aea65e --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_blend.c @@ -0,0 +1,395 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * quad blending + * \author Brian Paul + */ + +#include "glheader.h" +#include "imports.h" +#include "macros.h" +#include "pipe/p_defines.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" + + +#define VEC4_COPY(DST, SRC) \ +do { \ + DST[0] = SRC[0]; \ + DST[1] = SRC[1]; \ + DST[2] = SRC[2]; \ + DST[3] = SRC[3]; \ +} while(0) + +#define VEC4_SCALAR(DST, SRC) \ +do { \ + DST[0] = SRC; \ + DST[1] = SRC; \ + DST[2] = SRC; \ + DST[3] = SRC; \ +} while(0) + +#define VEC4_ADD(SUM, A, B) \ +do { \ + SUM[0] = A[0] + B[0]; \ + SUM[1] = A[1] + B[1]; \ + SUM[2] = A[2] + B[2]; \ + SUM[3] = A[3] + B[3]; \ +} while (0) + +#define VEC4_SUB(SUM, A, B) \ +do { \ + SUM[0] = A[0] - B[0]; \ + SUM[1] = A[1] - B[1]; \ + SUM[2] = A[2] - B[2]; \ + SUM[3] = A[3] - B[3]; \ +} while (0) + +#define VEC4_MUL(SUM, A, B) \ +do { \ + SUM[0] = A[0] * B[0]; \ + SUM[1] = A[1] * B[1]; \ + SUM[2] = A[2] * B[2]; \ + SUM[3] = A[3] * B[3]; \ +} while (0) + +#define VEC4_MIN(SUM, A, B) \ +do { \ + SUM[0] = (A[0] < B[0]) ? A[0] : B[0]; \ + SUM[1] = (A[1] < B[1]) ? A[1] : B[1]; \ + SUM[2] = (A[2] < B[2]) ? A[2] : B[2]; \ + SUM[3] = (A[3] < B[3]) ? A[3] : B[3]; \ +} while (0) + +#define VEC4_MAX(SUM, A, B) \ +do { \ + SUM[0] = (A[0] > B[0]) ? A[0] : B[0]; \ + SUM[1] = (A[1] > B[1]) ? A[1] : B[1]; \ + SUM[2] = (A[2] > B[2]) ? A[2] : B[2]; \ + SUM[3] = (A[3] > B[3]) ? A[3] : B[3]; \ +} while (0) + + + +static void +blend_quad(struct quad_stage *qs, struct quad_header *quad) +{ + static const GLfloat zero[4] = { 0, 0, 0, 0 }; + static const GLfloat one[4] = { 1, 1, 1, 1 }; + struct softpipe_context *softpipe = qs->softpipe; + struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf); + GLfloat source[4][QUAD_SIZE], dest[4][QUAD_SIZE]; + + /* get colors from framebuffer */ + sps->read_quad_f_swz(sps, quad->x0, quad->y0, dest); + + /* + * Compute src/first term RGB + */ + switch (softpipe->blend.rgb_src_factor) { + case PIPE_BLENDFACTOR_ONE: + VEC4_COPY(source[0], quad->outputs.color[0]); /* R */ + VEC4_COPY(source[1], quad->outputs.color[1]); /* G */ + VEC4_COPY(source[2], quad->outputs.color[2]); /* B */ + break; + case PIPE_BLENDFACTOR_SRC_COLOR: + VEC4_MUL(source[0], quad->outputs.color[0], quad->outputs.color[0]); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], quad->outputs.color[1]); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], quad->outputs.color[2]); /* B */ + break; + case PIPE_BLENDFACTOR_SRC_ALPHA: + { + const GLfloat *alpha = quad->outputs.color[3]; + VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */ + } + break; + case PIPE_BLENDFACTOR_DST_COLOR: + VEC4_MUL(source[0], quad->outputs.color[0], dest[0]); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], dest[1]); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], dest[2]); /* B */ + break; + case PIPE_BLENDFACTOR_DST_ALPHA: + { + const GLfloat *alpha = dest[3]; + VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */ + } + break; + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: + assert(0); /* to do */ + break; + case PIPE_BLENDFACTOR_CONST_COLOR: + { + GLfloat comp[4]; + VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */ + VEC4_MUL(source[0], quad->outputs.color[0], comp); /* R */ + VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */ + VEC4_MUL(source[1], quad->outputs.color[1], comp); /* G */ + VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */ + VEC4_MUL(source[2], quad->outputs.color[2], comp); /* B */ + } + break; + case PIPE_BLENDFACTOR_CONST_ALPHA: + { + GLfloat alpha[4]; + VEC4_SCALAR(alpha, softpipe->blend_color.color[3]); + VEC4_MUL(source[0], quad->outputs.color[0], alpha); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], alpha); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], alpha); /* B */ + } + break; + case PIPE_BLENDFACTOR_SRC1_COLOR: + assert(0); /* to do */ + break; + case PIPE_BLENDFACTOR_SRC1_ALPHA: + assert(0); /* to do */ + break; + case PIPE_BLENDFACTOR_ZERO: + VEC4_COPY(source[0], zero); /* R */ + VEC4_COPY(source[1], zero); /* G */ + VEC4_COPY(source[2], zero); /* B */ + break; + case PIPE_BLENDFACTOR_INV_SRC_COLOR: + { + GLfloat inv_comp[4]; + VEC4_SUB(inv_comp, one, quad->outputs.color[0]); /* R */ + VEC4_MUL(source[0], quad->outputs.color[0], inv_comp); /* R */ + VEC4_SUB(inv_comp, one, quad->outputs.color[1]); /* G */ + VEC4_MUL(source[1], quad->outputs.color[1], inv_comp); /* G */ + VEC4_SUB(inv_comp, one, quad->outputs.color[2]); /* B */ + VEC4_MUL(source[2], quad->outputs.color[2], inv_comp); /* B */ + } + break; + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: + { + GLfloat inv_alpha[4]; + VEC4_SUB(inv_alpha, one, quad->outputs.color[3]); + VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */ + } + break; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: + { + GLfloat inv_alpha[4]; + VEC4_SUB(inv_alpha, one, dest[3]); + VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */ + } + break; + case PIPE_BLENDFACTOR_INV_DST_COLOR: + { + GLfloat inv_comp[4]; + VEC4_SUB(inv_comp, one, dest[0]); /* R */ + VEC4_MUL(source[0], quad->outputs.color[0], inv_comp); /* R */ + VEC4_SUB(inv_comp, one, dest[1]); /* G */ + VEC4_MUL(source[1], quad->outputs.color[1], inv_comp); /* G */ + VEC4_SUB(inv_comp, one, dest[2]); /* B */ + VEC4_MUL(source[2], quad->outputs.color[2], inv_comp); /* B */ + } + break; + case PIPE_BLENDFACTOR_INV_CONST_COLOR: + { + GLfloat inv_comp[4]; + /* R */ + VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[0]); + VEC4_MUL(source[0], quad->outputs.color[0], inv_comp); + /* G */ + VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[1]); + VEC4_MUL(source[1], quad->outputs.color[1], inv_comp); + /* B */ + VEC4_SCALAR(inv_comp, 1.0 - softpipe->blend_color.color[2]); + VEC4_MUL(source[2], quad->outputs.color[2], inv_comp); + } + break; + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: + { + GLfloat alpha[4], inv_alpha[4]; + VEC4_SCALAR(alpha, 1.0 - softpipe->blend_color.color[3]); + VEC4_MUL(source[0], quad->outputs.color[0], inv_alpha); /* R */ + VEC4_MUL(source[1], quad->outputs.color[1], inv_alpha); /* G */ + VEC4_MUL(source[2], quad->outputs.color[2], inv_alpha); /* B */ + } + break; + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: + assert(0); /* to do */ + break; + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: + assert(0); /* to do */ + break; + default: + abort(); + } + + /* + * Compute src/first term A + */ + switch (softpipe->blend.alpha_src_factor) { + case PIPE_BLENDFACTOR_ONE: + VEC4_COPY(source[3], quad->outputs.color[3]); /* A */ + break; + case PIPE_BLENDFACTOR_SRC_ALPHA: + { + const GLfloat *alpha = quad->outputs.color[3]; + VEC4_MUL(source[3], quad->outputs.color[3], alpha); /* A */ + } + break; + case PIPE_BLENDFACTOR_ZERO: + VEC4_COPY(source[3], zero); /* A */ + break; + /* XXX fill in remaining terms */ + default: + abort(); + } + + + /* + * Compute dest/second term RGB + */ + switch (softpipe->blend.rgb_dst_factor) { + case PIPE_BLENDFACTOR_ONE: + /* dest = dest * 1 NO-OP, leave dest as-is */ + break; + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: + { + GLfloat one_minus_alpha[QUAD_SIZE]; + VEC4_SUB(one_minus_alpha, one, quad->outputs.color[3]); + VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */ + VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */ + VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */ + } + break; + case PIPE_BLENDFACTOR_ZERO: + VEC4_COPY(dest[0], zero); /* R */ + VEC4_COPY(dest[1], zero); /* G */ + VEC4_COPY(dest[2], zero); /* B */ + break; + /* XXX fill in remaining terms */ + default: + abort(); + } + + /* + * Compute dest/second term A + */ + switch (softpipe->blend.alpha_dst_factor) { + case PIPE_BLENDFACTOR_ONE: + /* dest = dest * 1 NO-OP, leave dest as-is */ + break; + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: + { + GLfloat one_minus_alpha[QUAD_SIZE]; + VEC4_SUB(one_minus_alpha, one, quad->outputs.color[3]); + VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */ + } + break; + case PIPE_BLENDFACTOR_ZERO: + VEC4_COPY(dest[3], zero); /* A */ + break; + /* XXX fill in remaining terms */ + default: + abort(); + } + + /* + * Combine RGB terms + */ + switch (softpipe->blend.rgb_func) { + case PIPE_BLEND_ADD: + VEC4_ADD(quad->outputs.color[0], source[0], dest[0]); /* R */ + VEC4_ADD(quad->outputs.color[1], source[1], dest[1]); /* G */ + VEC4_ADD(quad->outputs.color[2], source[2], dest[2]); /* B */ + break; + case PIPE_BLEND_SUBTRACT: + VEC4_SUB(quad->outputs.color[0], source[0], dest[0]); /* R */ + VEC4_SUB(quad->outputs.color[1], source[1], dest[1]); /* G */ + VEC4_SUB(quad->outputs.color[2], source[2], dest[2]); /* B */ + break; + case PIPE_BLEND_REVERSE_SUBTRACT: + VEC4_SUB(quad->outputs.color[0], dest[0], source[0]); /* R */ + VEC4_SUB(quad->outputs.color[1], dest[1], source[1]); /* G */ + VEC4_SUB(quad->outputs.color[2], dest[2], source[2]); /* B */ + break; + case PIPE_BLEND_MIN: + VEC4_MIN(quad->outputs.color[0], source[0], dest[0]); /* R */ + VEC4_MIN(quad->outputs.color[1], source[1], dest[1]); /* G */ + VEC4_MIN(quad->outputs.color[2], source[2], dest[2]); /* B */ + break; + case PIPE_BLEND_MAX: + VEC4_MAX(quad->outputs.color[0], source[0], dest[0]); /* R */ + VEC4_MAX(quad->outputs.color[1], source[1], dest[1]); /* G */ + VEC4_MAX(quad->outputs.color[2], source[2], dest[2]); /* B */ + break; + default: + abort(); + } + + /* + * Combine A terms + */ + switch (softpipe->blend.alpha_func) { + case PIPE_BLEND_ADD: + VEC4_ADD(quad->outputs.color[3], source[3], dest[3]); /* A */ + break; + case PIPE_BLEND_SUBTRACT: + VEC4_SUB(quad->outputs.color[3], source[3], dest[3]); /* A */ + break; + case PIPE_BLEND_REVERSE_SUBTRACT: + VEC4_SUB(quad->outputs.color[3], dest[3], source[3]); /* A */ + break; + case PIPE_BLEND_MIN: + VEC4_MIN(quad->outputs.color[3], source[3], dest[3]); /* A */ + break; + case PIPE_BLEND_MAX: + VEC4_MAX(quad->outputs.color[3], source[3], dest[3]); /* A */ + default: + abort(); + } + + /* pass blended quad to next stage */ + qs->next->run(qs->next, quad); +} + + + + +struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = blend_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_bufloop.c b/src/mesa/pipe/softpipe/sp_quad_bufloop.c new file mode 100644 index 00000000000..be32d02a463 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_bufloop.c @@ -0,0 +1,62 @@ + + +#include "main/glheader.h" +#include "main/imports.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" + + +/** + * Loop over colorbuffers, passing quad to next stage each time. + */ +static void +cbuf_loop_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + GLfloat tmp[4][QUAD_SIZE]; + GLuint i; + + assert(sizeof(quad->outputs.color) == sizeof(tmp)); + assert(softpipe->framebuffer.num_cbufs <= PIPE_MAX_COLOR_BUFS); + + /* make copy of original colors since they can get modified + * by blending and masking. + * XXX we won't have to do this if the fragment program actually emits + * N separate colors and we're drawing to N color buffers (MRT). + * But if we emitted one color and glDrawBuffer(GL_FRONT_AND_BACK) is + * in effect, we need to save/restore colors like this. + */ + memcpy(tmp, quad->outputs.color, sizeof(tmp)); + + for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) { + /* set current cbuffer */ + softpipe->cbuf = softpipe->framebuffer.cbufs[i]; + + /* pass blended quad to next stage */ + qs->next->run(qs->next, quad); + + /* restore quad's colors for next buffer */ + memcpy(quad->outputs.color, tmp, sizeof(tmp)); + } + + softpipe->cbuf = NULL; /* prevent accidental use */ +} + + +/** + * Create the colorbuffer loop stage. + * This is used to implement multiple render targets and GL_FRONT_AND_BACK + * rendering. + */ +struct quad_stage *sp_quad_bufloop_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = cbuf_loop_quad; + + return stage; +} + diff --git a/src/mesa/pipe/softpipe/sp_quad_colormask.c b/src/mesa/pipe/softpipe/sp_quad_colormask.c new file mode 100644 index 00000000000..fff6efa8f6a --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_colormask.c @@ -0,0 +1,84 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * \brief quad colormask stage + * \author Brian Paul + */ + +#include "main/glheader.h" +#include "main/imports.h" +#include "main/macros.h" +#include "pipe/p_defines.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" + + + +static void +colormask_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf); + GLfloat dest[4][QUAD_SIZE]; + + sps->read_quad_f_swz(sps, quad->x0, quad->y0, dest); + + /* R */ + if (!(softpipe->blend.colormask & PIPE_MASK_R)) + COPY_4FV(quad->outputs.color[0], dest[0]); + + /* G */ + if (!(softpipe->blend.colormask & PIPE_MASK_G)) + COPY_4FV(quad->outputs.color[1], dest[1]); + + /* B */ + if (!(softpipe->blend.colormask & PIPE_MASK_B)) + COPY_4FV(quad->outputs.color[2], dest[2]); + + /* A */ + if (!(softpipe->blend.colormask & PIPE_MASK_A)) + COPY_4FV(quad->outputs.color[3], dest[3]); + + /* pass quad to next stage */ + qs->next->run(qs->next, quad); +} + + + + +struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = colormask_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_coverage.c b/src/mesa/pipe/softpipe/sp_quad_coverage.c new file mode 100644 index 00000000000..cdd8890c7f3 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_coverage.c @@ -0,0 +1,74 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + +/** + * \brief Apply AA coverage to quad alpha valus + * \author Brian Paul + */ + + +#include "main/glheader.h" +#include "main/macros.h" +#include "pipe/p_defines.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_quad.h" + + +/** + * Multiply quad's alpha values by the fragment coverage. + */ +static void +coverage_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + + if ((softpipe->setup.poly_smooth && quad->prim == PRIM_TRI) || + (softpipe->setup.line_smooth && quad->prim == PRIM_LINE) || + (softpipe->setup.point_smooth && quad->prim == PRIM_POINT)) { + GLuint j; + for (j = 0; j < QUAD_SIZE; j++) { + assert(quad->coverage[j] >= 0.0); + assert(quad->coverage[j] <= 1.0); + quad->outputs.color[3][j] *= quad->coverage[j]; + } + } + + qs->next->run(qs->next, quad); +} + + +struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = coverage_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_depth_test.c b/src/mesa/pipe/softpipe/sp_quad_depth_test.c new file mode 100644 index 00000000000..d47c4c42b8f --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_depth_test.c @@ -0,0 +1,167 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * 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. + */ + +/** + * \brief Quad depth testing + */ + +#include "main/glheader.h" +#include "main/imports.h" +#include "pipe/p_defines.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" + + +/** + * Do depth testing for a quad. + * Not static since it's used by the stencil code. + */ +void +sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf); + GLuint bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */ + GLuint qzzzz[QUAD_SIZE]; /**< Z values from the quad */ + GLuint zmask = 0; + GLuint j; + GLfloat scale; + + assert(sps); /* shouldn't get here if there's no zbuffer */ + + /* + * To increase efficiency, we should probably have multiple versions + * of this function that are specifically for Z16, Z32 and FP Z buffers. + * Try to effectively do that with codegen... + */ + if (sps->surface.format == PIPE_FORMAT_U_Z16) + scale = 65535.0; + else + assert(0); /* XXX fix this someday */ + + /* + * Convert quad's float depth values to int depth values. + * If the Z buffer stores integer values, we _have_ to do the depth + * compares with integers (not floats). Otherwise, the float->int->float + * conversion of Z values (which isn't an identity function) will cause + * Z-fighting errors. + */ + for (j = 0; j < QUAD_SIZE; j++) { + qzzzz[j] = (GLuint) (quad->outputs.depth[j] * scale); + } + + /* get zquad from zbuffer */ + sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz); + + switch (softpipe->depth_test.func) { + case PIPE_FUNC_NEVER: + /* zmask = 0 */ + break; + case PIPE_FUNC_LESS: + /* Note this is pretty much a single sse or cell instruction. + * Like this: quad->mask &= (quad->outputs.depth < zzzz); + */ + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] < bzzzz[j]) + zmask |= 1 << j; + } + break; + case PIPE_FUNC_EQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] == bzzzz[j]) + zmask |= 1 << j; + } + break; + case PIPE_FUNC_LEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] <= bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_GREATER: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] > bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_NOTEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] != bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_GEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] >= bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_ALWAYS: + zmask = MASK_ALL; + break; + default: + abort(); + } + + quad->mask &= zmask; + + if (softpipe->depth_test.writemask) { + + /* This is also efficient with sse / spe instructions: + */ + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->mask & (1 << j)) { + bzzzz[j] = qzzzz[j]; + } + } + + /* write updated zquad to zbuffer */ + sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz); + } +} + + +static void +depth_test_quad(struct quad_stage *qs, struct quad_header *quad) +{ + sp_depth_test_quad(qs, quad); + + if (quad->mask) + qs->next->run(qs->next, quad); +} + + + + +struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = depth_test_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_fs.c b/src/mesa/pipe/softpipe/sp_quad_fs.c new file mode 100644 index 00000000000..301bd13aa98 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_fs.c @@ -0,0 +1,281 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * 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. + */ + +/* Vertices are just an array of floats, with all the attributes + * packed. We currently assume a layout like: + * + * attr[0][0..3] - window position + * attr[1..n][0..3] - remaining attributes. + * + * Attributes are assumed to be 4 floats wide but are packed so that + * all the enabled attributes run contiguously. + */ + +#include "glheader.h" +#include "imports.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_quad.h" +#include "core/tgsi_core.h" + +struct exec_machine { + const struct setup_coefficient *coef; /**< will point to quad->coef */ + + GLfloat attr[FRAG_ATTRIB_MAX][4][QUAD_SIZE]; +}; + + +/** + * Compute quad's attributes values, as constants (GL_FLAT shading). + */ +static INLINE void cinterp( struct exec_machine *exec, + GLuint attrib, + GLuint i ) +{ + GLuint j; + + for (j = 0; j < QUAD_SIZE; j++) { + exec->attr[attrib][i][j] = exec->coef[attrib].a0[i]; + } +} + + +/** + * Compute quad's attribute values by linear interpolation. + * + * Push into the fp: + * + * INPUT[attr] = MAD COEF_A0[attr], COEF_DADX[attr], INPUT_WPOS.xxxx + * INPUT[attr] = MAD INPUT[attr], COEF_DADY[attr], INPUT_WPOS.yyyy + */ +static INLINE void linterp( struct exec_machine *exec, + GLuint attrib, + GLuint i ) +{ + GLuint j; + + for (j = 0; j < QUAD_SIZE; j++) { + const GLfloat x = exec->attr[FRAG_ATTRIB_WPOS][0][j]; + const GLfloat y = exec->attr[FRAG_ATTRIB_WPOS][1][j]; + exec->attr[attrib][i][j] = (exec->coef[attrib].a0[i] + + exec->coef[attrib].dadx[i] * x + + exec->coef[attrib].dady[i] * y); + } +} + + +/** + * Compute quad's attribute values by linear interpolation with + * perspective correction. + * + * Push into the fp: + * + * INPUT[attr] = MAD COEF_DADX[attr], INPUT_WPOS.xxxx, COEF_A0[attr] + * INPUT[attr] = MAD COEF_DADY[attr], INPUT_WPOS.yyyy, INPUT[attr] + * TMP = RCP INPUT_WPOS.w + * INPUT[attr] = MUL INPUT[attr], TMP.xxxx + * + */ +static INLINE void pinterp( struct exec_machine *exec, + GLuint attrib, + GLuint i ) +{ + GLuint j; + + for (j = 0; j < QUAD_SIZE; j++) { + const GLfloat x = exec->attr[FRAG_ATTRIB_WPOS][0][j]; + const GLfloat y = exec->attr[FRAG_ATTRIB_WPOS][1][j]; + /* FRAG_ATTRIB_WPOS.w here is really 1/w */ + const GLfloat w = 1.0 / exec->attr[FRAG_ATTRIB_WPOS][3][j]; + exec->attr[attrib][i][j] = ((exec->coef[attrib].a0[i] + + exec->coef[attrib].dadx[i] * x + + exec->coef[attrib].dady[i] * y) * w); + } +} + + + +/* This should be done by the fragment shader execution unit (code + * generated from the decl instructions). Do it here for now. + */ +static void +shade_quad( struct quad_stage *qs, struct quad_header *quad ) +{ + const struct softpipe_context *softpipe = qs->softpipe; + struct exec_machine exec; + const GLfloat fx = quad->x0; + const GLfloat fy = quad->y0; + GLuint attr, i; + + exec.coef = quad->coef; + + /* Position: + */ + exec.attr[FRAG_ATTRIB_WPOS][0][0] = fx; + exec.attr[FRAG_ATTRIB_WPOS][0][1] = fx + 1.0; + exec.attr[FRAG_ATTRIB_WPOS][0][2] = fx; + exec.attr[FRAG_ATTRIB_WPOS][0][3] = fx + 1.0; + + exec.attr[FRAG_ATTRIB_WPOS][1][0] = fy; + exec.attr[FRAG_ATTRIB_WPOS][1][1] = fy; + exec.attr[FRAG_ATTRIB_WPOS][1][2] = fy + 1.0; + exec.attr[FRAG_ATTRIB_WPOS][1][3] = fy + 1.0; + + /* Z and W are done by linear interpolation */ + if (softpipe->need_z) { + linterp(&exec, 0, 2); /* attr[0].z */ + } + + if (softpipe->need_w) { + linterp(&exec, 0, 3); /* attr[0].w */ + /*invert(&exec, 0, 3);*/ + } + + /* Interpolate all the remaining attributes. This will get pushed + * into the fragment program's responsibilities at some point. + * Start at 1 to skip fragment position attribute (computed above). + */ + for (attr = 1; attr < quad->nr_attrs; attr++) { + switch (softpipe->interp[attr]) { + case INTERP_CONSTANT: + for (i = 0; i < NUM_CHANNELS; i++) + cinterp(&exec, attr, i); + break; + + case INTERP_LINEAR: + for (i = 0; i < NUM_CHANNELS; i++) + linterp(&exec, attr, i); + break; + + case INTERP_PERSPECTIVE: + for (i = 0; i < NUM_CHANNELS; i++) + pinterp(&exec, attr, i); + break; + } + } + +#if 1 + /*softpipe->run_fs( tri->fp, quad, &tri->outputs );*/ + + { + struct tgsi_exec_machine machine; + struct tgsi_exec_vector inputs[FRAG_ATTRIB_MAX + 1]; + struct tgsi_exec_vector outputs[FRAG_ATTRIB_MAX + 1]; + struct tgsi_exec_vector *ainputs; + struct tgsi_exec_vector *aoutputs; + GLuint i /*, total*/; + +#ifdef DEBUG + memset(&machine, 0, sizeof(machine)); +#endif + + ainputs = (struct tgsi_exec_vector *) tgsi_align_128bit( inputs ); + aoutputs = (struct tgsi_exec_vector *) tgsi_align_128bit( outputs ); + +#if 0 + for( i = total = 0; i < PIPE_ATTRIB_MAX; i++ ) { + GLuint attr; + + attr = softpipe->fp_attr_to_slot[i]; + if( attr || total == 0) { + assert( total < FRAG_ATTRIB_MAX ); + assert( attr < FRAG_ATTRIB_MAX ); + assert( sizeof( ainputs[0] ) == sizeof( exec.attr[0] ) ); + + memcpy( + &ainputs[total], + exec.attr[attr], + sizeof( ainputs[0] ) ); + total++; + } + } +#else + /* load input registers */ + /* XXX simpler than above, but might not be right... */ + for (i = 0; i < softpipe->nr_attrs; i++) { + memcpy( + &ainputs[i], + exec.attr[i], + sizeof( ainputs[0] ) ); + } +#endif + + /* init machine state */ + tgsi_exec_machine_init( + &machine, + softpipe->fs.tokens ); + + machine.Inputs = ainputs; + machine.Outputs = aoutputs; + machine.Consts = softpipe->fs.constants->constant; /* XXX alignment? */ + + /* run shader */ + tgsi_exec_machine_run( &machine ); + + /* store result color */ + memcpy(quad->outputs.color, + &aoutputs[FRAG_ATTRIB_COL0].xyzw[0].f[0], + sizeof(quad->outputs.color)); + if (softpipe->need_z) { + /* XXX temporary */ + quad->outputs.depth[0] = exec.attr[0][2][0]; + quad->outputs.depth[1] = exec.attr[0][2][1]; + quad->outputs.depth[2] = exec.attr[0][2][2]; + quad->outputs.depth[3] = exec.attr[0][2][3]; + } + } +#else + { + GLuint attr = softpipe->fp_attr_to_slot[FRAG_ATTRIB_COL0]; + assert(attr); + + memcpy(quad->outputs.color, + exec.attr[attr], + sizeof(quad->outputs.color)); + + if (softpipe->need_z) { + quad->outputs.depth[0] = exec.attr[0][2][0]; + quad->outputs.depth[1] = exec.attr[0][2][1]; + quad->outputs.depth[2] = exec.attr[0][2][2]; + quad->outputs.depth[3] = exec.attr[0][2][3]; + } + } +#endif + + /* shader may cull fragments */ + if (quad->mask) + qs->next->run(qs->next, quad); +} + + + +struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = shade_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_occlusion.c b/src/mesa/pipe/softpipe/sp_quad_occlusion.c new file mode 100644 index 00000000000..843c462d487 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_occlusion.c @@ -0,0 +1,67 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + +/** + * \brief Quad occlusion counter stage + * \author Brian Paul + */ + + +#include "main/glheader.h" +#include "main/imports.h" +#include "pipe/p_defines.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" + + +static void +occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + + softpipe->occlusion_counter += (quad->mask ) & 1; + softpipe->occlusion_counter += (quad->mask >> 1) & 1; + softpipe->occlusion_counter += (quad->mask >> 2) & 1; + softpipe->occlusion_counter += (quad->mask >> 3) & 1; + + if (quad->mask) + qs->next->run(qs->next, quad); +} + + +struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = occlusion_count_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_output.c b/src/mesa/pipe/softpipe/sp_quad_output.c new file mode 100644 index 00000000000..12ab1eca1c7 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_output.c @@ -0,0 +1,95 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * 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. + */ + +/* Vertices are just an array of floats, with all the attributes + * packed. We currently assume a layout like: + * + * attr[0][0..3] - window position + * attr[1..n][0..3] - remaining attributes. + * + * Attributes are assumed to be 4 floats wide but are packed so that + * all the enabled attributes run contiguously. + */ + +#include "glheader.h" +#include "imports.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" + + +static void mask_copy( GLfloat (*dest)[4], + GLfloat (*src)[4], + GLuint mask ) +{ + GLuint i, j; + + for (i = 0; i < 4; i++) { + if (mask & (1<<i)) { + for (j = 0; j < 4; j++) { + dest[j][i] = src[j][i]; + } + } + } +} + + +/** + * Write quad to framebuffer, taking mask into account. + * + * Note that surfaces support only full quad reads and writes. + */ +static void +output_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf); + + if (quad->mask != MASK_ALL) { + GLfloat tmp[4][QUAD_SIZE]; + + /* XXX probably add a masked-write function someday */ + + sps->read_quad_f_swz(sps, quad->x0, quad->y0, tmp); + + mask_copy( tmp, quad->outputs.color, quad->mask ); + + sps->write_quad_f_swz(sps, quad->x0, quad->y0, tmp); + } + else if (quad->mask) { + sps->write_quad_f_swz(sps, quad->x0, quad->y0, quad->outputs.color); + } +} + + +struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = output_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_stencil.c b/src/mesa/pipe/softpipe/sp_quad_stencil.c new file mode 100644 index 00000000000..0b37474c1a8 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_stencil.c @@ -0,0 +1,288 @@ + +/** + * \brief Quad stencil testing + */ + + +#include "main/glheader.h" +#include "main/imports.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" +#include "pipe/p_defines.h" + + +/** Only 8-bit stencil supported */ +#define STENCIL_MAX 0xff + + +/** + * Do the basic stencil test (compare stencil buffer values against the + * reference value. + * + * \param stencilVals the stencil values from the stencil buffer + * \param func the stencil func (PIPE_FUNC_x) + * \param ref the stencil reference value + * \param valMask the stencil value mask indicating which bits of the stencil + * values and ref value are to be used. + * \return mask indicating which pixels passed the stencil test + */ +static GLbitfield +do_stencil_test(const GLubyte stencilVals[QUAD_SIZE], GLuint func, + GLbitfield ref, GLbitfield valMask) +{ + GLbitfield passMask = 0x0; + GLuint j; + + ref &= valMask; + + switch (func) { + case PIPE_FUNC_NEVER: + /* passMask = 0x0 */ + break; + case PIPE_FUNC_LESS: + for (j = 0; j < QUAD_SIZE; j++) { + if ((stencilVals[j] & valMask) < ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_EQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if ((stencilVals[j] & valMask) == ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_LEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if ((stencilVals[j] & valMask) <= ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_GREATER: + for (j = 0; j < QUAD_SIZE; j++) { + if ((stencilVals[j] & valMask) > ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_NOTEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if ((stencilVals[j] & valMask) != ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_GEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if ((stencilVals[j] & valMask) >= ref) { + passMask |= (1 << j); + } + } + break; + case PIPE_FUNC_ALWAYS: + passMask = MASK_ALL; + break; + default: + assert(0); + } + + return passMask; +} + + +/** + * Apply the stencil operator to stencil values. + * + * \param stencilVals the stencil buffer values (read and written) + * \param mask indicates which pixels to update + * \param op the stencil operator (PIPE_STENCIL_OP_x) + * \param ref the stencil reference value + * \param wrtMask writemask controlling which bits are changed in the + * stencil values + */ +static void +apply_stencil_op(GLubyte stencilVals[QUAD_SIZE], + GLbitfield mask, GLuint op, GLubyte ref, GLubyte wrtMask) +{ + GLuint j; + GLubyte newstencil[QUAD_SIZE]; + + for (j = 0; j < QUAD_SIZE; j++) { + newstencil[j] = stencilVals[j]; + } + + switch (op) { + case PIPE_STENCIL_OP_KEEP: + /* no-op */ + break; + case PIPE_STENCIL_OP_ZERO: + for (j = 0; j < QUAD_SIZE; j++) { + if (mask & (1 << j)) { + newstencil[j] = 0; + } + } + break; + case PIPE_STENCIL_OP_REPLACE: + for (j = 0; j < QUAD_SIZE; j++) { + if (mask & (1 << j)) { + newstencil[j] = ref; + } + } + break; + case PIPE_STENCIL_OP_INCR: + for (j = 0; j < QUAD_SIZE; j++) { + if (mask & (1 << j)) { + if (stencilVals[j] < STENCIL_MAX) { + newstencil[j] = stencilVals[j] + 1; + } + } + } + break; + case PIPE_STENCIL_OP_DECR: + for (j = 0; j < QUAD_SIZE; j++) { + if (mask & (1 << j)) { + if (stencilVals[j] > 0) { + newstencil[j] = stencilVals[j] - 1; + } + } + } + break; + case PIPE_STENCIL_OP_INCR_WRAP: + for (j = 0; j < QUAD_SIZE; j++) { + if (mask & (1 << j)) { + newstencil[j] = stencilVals[j] + 1; + } + } + break; + case PIPE_STENCIL_OP_DECR_WRAP: + for (j = 0; j < QUAD_SIZE; j++) { + if (mask & (1 << j)) { + newstencil[j] = stencilVals[j] - 1; + } + } + break; + case PIPE_STENCIL_OP_INVERT: + for (j = 0; j < QUAD_SIZE; j++) { + if (mask & (1 << j)) { + newstencil[j] = ~stencilVals[j]; + } + } + break; + default: + assert(0); + } + + /* + * update the stencil values + */ + if (wrtMask != STENCIL_MAX) { + /* apply bit-wise stencil buffer writemask */ + for (j = 0; j < QUAD_SIZE; j++) { + stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]); + } + } + else { + for (j = 0; j < QUAD_SIZE; j++) { + stencilVals[j] = newstencil[j]; + } + } +} + + +/** + * Do stencil (and depth) testing. Stenciling depends on the outcome of + * depth testing. + */ +static void +stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + struct softpipe_surface *s_surf = softpipe_surface(softpipe->framebuffer.sbuf); + GLuint func, zFailOp, zPassOp, failOp; + GLubyte ref, wrtMask, valMask; + GLubyte stencilVals[QUAD_SIZE]; + + /* choose front or back face function, operator, etc */ + /* XXX we could do these initializations once per primitive */ + if (softpipe->stencil.back_enabled && quad->facing) { + func = softpipe->stencil.back_func; + failOp = softpipe->stencil.back_fail_op; + zFailOp = softpipe->stencil.back_zfail_op; + zPassOp = softpipe->stencil.back_zpass_op; + ref = softpipe->stencil.ref_value[1]; + wrtMask = softpipe->stencil.write_mask[1]; + valMask = softpipe->stencil.value_mask[1]; + } + else { + func = softpipe->stencil.front_func; + failOp = softpipe->stencil.front_fail_op; + zFailOp = softpipe->stencil.front_zfail_op; + zPassOp = softpipe->stencil.front_zpass_op; + ref = softpipe->stencil.ref_value[0]; + wrtMask = softpipe->stencil.write_mask[0]; + valMask = softpipe->stencil.value_mask[0]; + } + + assert(s_surf); /* shouldn't get here if there's no stencil buffer */ + s_surf->read_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals); + + /* do the stencil test first */ + { + GLbitfield passMask, failMask; + passMask = do_stencil_test(stencilVals, func, ref, valMask); + failMask = quad->mask & ~passMask; + quad->mask &= passMask; + + if (failOp != PIPE_STENCIL_OP_KEEP) { + apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask); + } + } + + if (quad->mask) { + + /* now the pixels that passed the stencil test are depth tested */ + if (softpipe->depth_test.enabled) { + const GLbitfield origMask = quad->mask; + + sp_depth_test_quad(qs, quad); /* quad->mask is updated */ + + /* update stencil buffer values according to z pass/fail result */ + if (zFailOp != PIPE_STENCIL_OP_KEEP) { + const GLbitfield failMask = origMask & ~quad->mask; + apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask); + } + + if (zPassOp != PIPE_STENCIL_OP_KEEP) { + const GLbitfield passMask = origMask & quad->mask; + apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask); + } + } + else { + /* no depth test, apply Zpass operator to stencil buffer values */ + apply_stencil_op(stencilVals, quad->mask, zPassOp, ref, wrtMask); + } + + } + + s_surf->write_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals); + + if (quad->mask) + qs->next->run(qs->next, quad); +} + + + + +struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = stencil_test_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_quad_stipple.c b/src/mesa/pipe/softpipe/sp_quad_stipple.c new file mode 100644 index 00000000000..cad1a1400c5 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_stipple.c @@ -0,0 +1,48 @@ + +/** + * quad polygon stipple stage + */ + +#include "glheader.h" +#include "imports.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_quad.h" +#include "pipe/p_defines.h" + + +/** + * Apply polygon stipple to quads produced by triangle rasterization + */ +static void +stipple_quad(struct quad_stage *qs, struct quad_header *quad) +{ + if (quad->prim == PRIM_TRI) { + struct softpipe_context *softpipe = qs->softpipe; + const GLint col0 = quad->x0 % 32; + const GLint row0 = quad->y0 % 32; + const GLuint stipple0 = softpipe->poly_stipple.stipple[row0]; + const GLuint stipple1 = softpipe->poly_stipple.stipple[row0 + 1]; + + /* XXX there may be a better way to lay out the stored stipple + * values to further simplify this computation. + */ + quad->mask &= (((stipple0 >> col0) & 0x3) | + (((stipple1 >> col0) & 0x3) << 2)); + + if (quad->mask) + qs->next->run(qs->next, quad); + } +} + + +struct quad_stage * +sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = stipple_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_state.h b/src/mesa/pipe/softpipe/sp_state.h new file mode 100644 index 00000000000..71c1a2d9ba0 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state.h @@ -0,0 +1,87 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#ifndef SP_STATE_H +#define SP_STATE_H + +#include "glheader.h" +#include "pipe/p_state.h" + + +void softpipe_set_framebuffer_state( struct pipe_context *, + const struct pipe_framebuffer_state * ); + +void softpipe_set_alpha_test_state( struct pipe_context *, + const struct pipe_alpha_test_state * ); + +void softpipe_set_blend_state( struct pipe_context *, + const struct pipe_blend_state * ); + +void softpipe_set_blend_color( struct pipe_context *pipe, + const struct pipe_blend_color *blend_color ); + +void softpipe_set_clear_color_state( struct pipe_context *, + const struct pipe_clear_color_state * ); + +void softpipe_set_clip_state( struct pipe_context *, + const struct pipe_clip_state * ); + +void softpipe_set_depth_test_state( struct pipe_context *, + const struct pipe_depth_state * ); + +void softpipe_set_fs_state( struct pipe_context *, + const struct pipe_fs_state * ); + +void softpipe_set_polygon_stipple( struct pipe_context *, + const struct pipe_poly_stipple * ); + +void softpipe_set_scissor_state( struct pipe_context *, + const struct pipe_scissor_state * ); + +void softpipe_set_setup_state( struct pipe_context *, + const struct pipe_setup_state * ); + +void softpipe_set_sampler_state( struct pipe_context *, + GLuint unit, + const struct pipe_sampler_state * ); + +void softpipe_set_stencil_state( struct pipe_context *, + const struct pipe_stencil_state * ); + +void softpipe_set_texture_state( struct pipe_context *, + GLuint unit, + struct pipe_texture_object * ); + +void softpipe_set_viewport_state( struct pipe_context *, + const struct pipe_viewport_state * ); + +void softpipe_update_derived( struct softpipe_context *softpipe ); + +#endif diff --git a/src/mesa/pipe/softpipe/sp_state_blend.c b/src/mesa/pipe/softpipe/sp_state_blend.c new file mode 100644 index 00000000000..8bc22b0efc0 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state_blend.c @@ -0,0 +1,93 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" + +#include "sp_context.h" +#include "sp_state.h" + + +void softpipe_set_blend_state( struct pipe_context *pipe, + const struct pipe_blend_state *blend ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->blend = *blend; + + softpipe->dirty |= SP_NEW_BLEND; +} + + +void softpipe_set_blend_color( struct pipe_context *pipe, + const struct pipe_blend_color *blend_color ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->blend_color = *blend_color; + + softpipe->dirty |= SP_NEW_BLEND; +} + + +/** XXX move someday? Or consolidate all these simple state setters + * into one file. + */ +void +softpipe_set_depth_test_state(struct pipe_context *pipe, + const struct pipe_depth_state *depth) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->depth_test = *depth; + + softpipe->dirty |= SP_NEW_DEPTH_TEST; +} + +void +softpipe_set_alpha_test_state(struct pipe_context *pipe, + const struct pipe_alpha_test_state *alpha) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->alpha_test = *alpha; + + softpipe->dirty |= SP_NEW_ALPHA_TEST; +} + +void +softpipe_set_stencil_state(struct pipe_context *pipe, + const struct pipe_stencil_state *stencil) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->stencil = *stencil; + + softpipe->dirty |= SP_NEW_STENCIL; +} + diff --git a/src/mesa/pipe/softpipe/sp_state_clip.c b/src/mesa/pipe/softpipe/sp_state_clip.c new file mode 100644 index 00000000000..8cf4383d3fa --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state_clip.c @@ -0,0 +1,85 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" + +#include "sp_context.h" +#include "sp_state.h" +#include "pipe/draw/draw_context.h" + + +void softpipe_set_clip_state( struct pipe_context *pipe, + const struct pipe_clip_state *clip ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + /* pass the clip state to the draw module */ + draw_set_clip_state(softpipe->draw, clip); +} + + + +/* Called when driver state tracker notices changes to the viewport + * matrix: + */ +void softpipe_set_viewport_state( struct pipe_context *pipe, + const struct pipe_viewport_state *viewport ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->viewport = *viewport; /* struct copy */ + softpipe->dirty |= SP_NEW_VIEWPORT; + + /* pass the viewport info to the draw module */ + draw_set_viewport_state(softpipe->draw, viewport); + + /* Using tnl/ and vf/ modules is temporary while getting started. + * Full pipe will have vertex shader, vertex fetch of its own. + */ +} + + +void softpipe_set_scissor_state( struct pipe_context *pipe, + const struct pipe_scissor_state *scissor ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + memcpy( &softpipe->scissor, scissor, sizeof(*scissor) ); + softpipe->dirty |= SP_NEW_SCISSOR; +} + + +void softpipe_set_polygon_stipple( struct pipe_context *pipe, + const struct pipe_poly_stipple *stipple ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + memcpy( &softpipe->poly_stipple, stipple, sizeof(*stipple) ); + softpipe->dirty |= SP_NEW_STIPPLE; +} diff --git a/src/mesa/pipe/softpipe/sp_state_derived.c b/src/mesa/pipe/softpipe/sp_state_derived.c new file mode 100644 index 00000000000..26083c29628 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state_derived.c @@ -0,0 +1,184 @@ +/************************************************************************** + * + * 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 "main/glheader.h" +#include "main/macros.h" +#include "main/enums.h" + +#include "vf/vf.h" +#include "pipe/draw/draw_context.h" +#include "sp_context.h" +#include "sp_state.h" + + +#define EMIT_ATTR( VF_ATTR, FRAG_ATTR, INTERP ) \ +do { \ + slot_to_vf_attr[softpipe->nr_attrs] = VF_ATTR; \ + softpipe->vf_attr_to_slot[VF_ATTR] = softpipe->nr_attrs; \ + softpipe->fp_attr_to_slot[FRAG_ATTR] = softpipe->nr_attrs; \ + softpipe->interp[softpipe->nr_attrs] = INTERP; \ + softpipe->nr_attrs++; \ + attr_mask |= (1 << (VF_ATTR)); \ +} while (0) + + +static const GLuint frag_to_vf[FRAG_ATTRIB_MAX] = +{ + VF_ATTRIB_POS, + VF_ATTRIB_COLOR0, + VF_ATTRIB_COLOR1, + VF_ATTRIB_FOG, + VF_ATTRIB_TEX0, + VF_ATTRIB_TEX1, + VF_ATTRIB_TEX2, + VF_ATTRIB_TEX3, + VF_ATTRIB_TEX4, + VF_ATTRIB_TEX5, + VF_ATTRIB_TEX6, + VF_ATTRIB_TEX7, + VF_ATTRIB_VAR0, + VF_ATTRIB_VAR1, + VF_ATTRIB_VAR2, + VF_ATTRIB_VAR3, + VF_ATTRIB_VAR4, + VF_ATTRIB_VAR5, + VF_ATTRIB_VAR6, + VF_ATTRIB_VAR7, +}; + + +/** + * Determine which post-transform / pre-rasterization vertex attributes + * we need. + * Derived from: fs, setup states. + */ +static void calculate_vertex_layout( struct softpipe_context *softpipe ) +{ + const GLbitfield inputsRead = softpipe->fs.inputs_read; + GLuint slot_to_vf_attr[VF_ATTRIB_MAX]; + GLbitfield attr_mask = 0x0; + GLuint i; + + /* Need Z if depth test is enabled or the fragment program uses the + * fragment position (XYZW). + */ + if (softpipe->depth_test.enabled || + (inputsRead & FRAG_ATTRIB_WPOS)) + softpipe->need_z = GL_TRUE; + else + softpipe->need_z = GL_FALSE; + + /* Need W if we do any perspective-corrected interpolation or the + * fragment program uses the fragment position. + */ + if (inputsRead & FRAG_ATTRIB_WPOS) + softpipe->need_w = GL_TRUE; + else + softpipe->need_w = GL_FALSE; + + + softpipe->nr_attrs = 0; + memset(slot_to_vf_attr, 0, sizeof(slot_to_vf_attr)); + + memset(softpipe->fp_attr_to_slot, 0, sizeof(softpipe->fp_attr_to_slot)); + memset(softpipe->vf_attr_to_slot, 0, sizeof(softpipe->vf_attr_to_slot)); + + /* TODO - Figure out if we need to do perspective divide, etc. + */ + EMIT_ATTR(VF_ATTRIB_POS, FRAG_ATTRIB_WPOS, INTERP_LINEAR); + + /* Pull in the rest of the attributes. They are all in float4 + * format. Future optimizations could be to keep some attributes + * as fixed point or ubyte format. + */ + for (i = 1; i < FRAG_ATTRIB_TEX0; i++) { + if (inputsRead & (1 << i)) { + assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0])); + if (softpipe->setup.flatshade + && (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1)) + EMIT_ATTR(frag_to_vf[i], i, INTERP_CONSTANT); + else + EMIT_ATTR(frag_to_vf[i], i, INTERP_LINEAR); + } + } + + for (i = FRAG_ATTRIB_TEX0; i < FRAG_ATTRIB_MAX; i++) { + if (inputsRead & (1 << i)) { + assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0])); + EMIT_ATTR(frag_to_vf[i], i, INTERP_PERSPECTIVE); + softpipe->need_w = GL_TRUE; + } + } + + softpipe->nr_frag_attrs = softpipe->nr_attrs; + + /* Additional attributes required for setup: Just twosided + * lighting. Edgeflag is dealt with specially by setting bits in + * the vertex header. + */ + if (softpipe->setup.light_twoside) { + if (inputsRead & FRAG_BIT_COL0) { + EMIT_ATTR(VF_ATTRIB_BFC0, FRAG_ATTRIB_MAX, 0); /* XXX: mark as discarded after setup */ + } + + if (inputsRead & FRAG_BIT_COL1) { + EMIT_ATTR(VF_ATTRIB_BFC1, FRAG_ATTRIB_MAX, 0); /* XXX: discard after setup */ + } + } + + /* If the attributes have changed, tell the draw module (which in turn + * tells the vf module) about the new vertex layout. + */ + if (attr_mask != softpipe->attr_mask) { + softpipe->attr_mask = attr_mask; + + draw_set_vertex_attributes( softpipe->draw, + slot_to_vf_attr, + softpipe->nr_attrs ); + } +} + + +/* Hopefully this will remain quite simple, otherwise need to pull in + * something like the state tracker mechanism. + */ +void softpipe_update_derived( struct softpipe_context *softpipe ) +{ + if (softpipe->dirty & (SP_NEW_SETUP | SP_NEW_FS)) + calculate_vertex_layout( softpipe ); + + if (softpipe->dirty & (SP_NEW_BLEND | + SP_NEW_DEPTH_TEST | + SP_NEW_ALPHA_TEST | + SP_NEW_FRAMEBUFFER | + SP_NEW_STENCIL | + SP_NEW_SETUP | + SP_NEW_FS)) + sp_build_quad_pipeline(softpipe); + + softpipe->dirty = 0; +} diff --git a/src/mesa/pipe/softpipe/sp_state_fs.c b/src/mesa/pipe/softpipe/sp_state_fs.c new file mode 100644 index 00000000000..c7ef1f1cfc9 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state_fs.c @@ -0,0 +1,50 @@ +/************************************************************************** + * + * 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 "sp_context.h" +#include "sp_state.h" + + + +void softpipe_set_fs_state( struct pipe_context *pipe, + const struct pipe_fs_state *fs ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + memcpy(&softpipe->fs, fs, sizeof(*fs)); + + softpipe->dirty |= SP_NEW_FS; +} + + + + + + + + + diff --git a/src/mesa/pipe/softpipe/sp_state_sampler.c b/src/mesa/pipe/softpipe/sp_state_sampler.c new file mode 100644 index 00000000000..9ef71f73cbb --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state_sampler.c @@ -0,0 +1,64 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: + * Brian Paul + */ + +#include "imports.h" + +#include "sp_context.h" +#include "sp_state.h" + + + +void +softpipe_set_sampler_state(struct pipe_context *pipe, + GLuint unit, + const struct pipe_sampler_state *sampler) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + assert(unit < PIPE_MAX_SAMPLERS); + softpipe->sampler[unit] = *sampler; + + softpipe->dirty |= SP_NEW_SAMPLER; +} + + +void +softpipe_set_texture_state(struct pipe_context *pipe, + GLuint unit, + struct pipe_texture_object *texture) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + assert(unit < PIPE_MAX_SAMPLERS); + softpipe->texture[unit] = texture; /* ptr, not struct */ + + softpipe->dirty |= SP_NEW_TEXTURE; +} diff --git a/src/mesa/pipe/softpipe/sp_state_setup.c b/src/mesa/pipe/softpipe/sp_state_setup.c new file mode 100644 index 00000000000..4715a26f553 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state_setup.c @@ -0,0 +1,47 @@ +/************************************************************************** + * + * 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 "sp_context.h" +#include "sp_state.h" +#include "pipe/draw/draw_context.h" + + +void softpipe_set_setup_state( struct pipe_context *pipe, + const struct pipe_setup_state *setup ) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + /* pass-through to draw module */ + draw_set_setup_state(softpipe->draw, setup); + + memcpy( &softpipe->setup, setup, sizeof(*setup) ); + + softpipe->dirty |= SP_NEW_SETUP; +} + + diff --git a/src/mesa/pipe/softpipe/sp_state_surface.c b/src/mesa/pipe/softpipe/sp_state_surface.c new file mode 100644 index 00000000000..8ce81eb2b04 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_state_surface.c @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ +#include "imports.h" + +#include "sp_context.h" +#include "sp_state.h" +#include "sp_surface.h" + + +/* + * XXX this might get moved someday + */ +void +softpipe_set_framebuffer_state(struct pipe_context *pipe, + const struct pipe_framebuffer_state *fb) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->framebuffer = *fb; /* struct copy */ + + softpipe->dirty |= SP_NEW_FRAMEBUFFER; +} + + + + +void +softpipe_set_clear_color_state(struct pipe_context *pipe, + const struct pipe_clear_color_state *clear) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->clear_color = *clear; /* struct copy */ +} diff --git a/src/mesa/pipe/softpipe/sp_surface.c b/src/mesa/pipe/softpipe/sp_surface.c new file mode 100644 index 00000000000..16bbacb12b9 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_surface.c @@ -0,0 +1,153 @@ +/************************************************************************** + * + * 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 "sp_context.h" +#include "sp_state.h" +#include "sp_surface.h" +#include "sp_headers.h" + +static void rgba8_read_quad_f( struct softpipe_surface *gs, + GLint x, GLint y, + GLfloat (*rgba)[NUM_CHANNELS] ) +{ + GLuint i, j, k = 0; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++, k++) { + GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4; + rgba[k][0] = ptr[0] * (1.0 / 255.0); + rgba[k][1] = ptr[1] * (1.0 / 255.0); + rgba[k][2] = ptr[2] * (1.0 / 255.0); + rgba[k][3] = ptr[3] * (1.0 / 255.0); + } + } +} + +static void rgba8_read_quad_f_swz( struct softpipe_surface *gs, + GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE] ) +{ + GLuint i, j, k = 0; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++, k++) { + GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4; + rrrr[0][k] = ptr[0] * (1.0 / 255.0); + rrrr[1][k] = ptr[1] * (1.0 / 255.0); + rrrr[2][k] = ptr[2] * (1.0 / 255.0); + rrrr[3][k] = ptr[3] * (1.0 / 255.0); + } + } +} + +static void rgba8_write_quad_f( struct softpipe_surface *gs, + GLint x, GLint y, + GLfloat (*rgba)[NUM_CHANNELS] ) +{ + GLuint i, j, k = 0; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++, k++) { + GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4; + ptr[0] = rgba[k][0] * 255.0; + ptr[1] = rgba[k][1] * 255.0; + ptr[2] = rgba[k][2] * 255.0; + ptr[3] = rgba[k][3] * 255.0; + } + } +} + +static void rgba8_write_quad_f_swz( struct softpipe_surface *gs, + GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE] ) +{ + GLuint i, j, k = 0; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++, k++) { + GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4; + ptr[0] = rrrr[0][k] * 255.0; + ptr[1] = rrrr[1][k] * 255.0; + ptr[2] = rrrr[2][k] * 255.0; + ptr[3] = rrrr[3][k] * 255.0; + } + } +} + + + + +static void rgba8_read_quad_ub( struct softpipe_surface *gs, + GLint x, GLint y, + GLubyte (*rgba)[NUM_CHANNELS] ) +{ + GLuint i, j, k = 0; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++, k++) { + GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4; + rgba[k][0] = ptr[0]; + rgba[k][1] = ptr[1]; + rgba[k][2] = ptr[2]; + rgba[k][3] = ptr[3]; + } + } +} + + +static void rgba8_write_quad_ub( struct softpipe_surface *gs, + GLint x, GLint y, + GLubyte (*rgba)[NUM_CHANNELS] ) +{ + GLuint i, j, k = 0; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++, k++) { + GLubyte *ptr = gs->surface.ptr + (y+i) * gs->surface.stride + (x+j) * 4; + ptr[0] = rgba[k][0]; + ptr[1] = rgba[k][1]; + ptr[2] = rgba[k][2]; + ptr[3] = rgba[k][3]; + } + } +} + + + + +struct softpipe_surface_type gs_rgba8 = { + G_SURFACE_RGBA_8888, + rgba8_read_quad_f, + rgba8_read_quad_f_swz, + rgba8_read_quad_ub, + rgba8_write_quad_f, + rgba8_write_quad_f_swz, + rgba8_write_quad_ub, +}; + + + diff --git a/src/mesa/pipe/softpipe/sp_surface.h b/src/mesa/pipe/softpipe/sp_surface.h new file mode 100644 index 00000000000..3ba732cebe4 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_surface.h @@ -0,0 +1,101 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <[email protected]> + */ + +#ifndef SP_SURFACE_H +#define SP_SURFACE_H + +#include "glheader.h" +#include "sp_headers.h" + +struct softpipe_surface; + +#define G_SURFACE_RGBA_8888 0x1 + + +/** + * Softpipe surface is derived from pipe_surface. + */ +struct softpipe_surface { + struct pipe_surface surface; + + /** + * Functions for read/writing surface data + */ + void (*read_quad_f)( struct softpipe_surface *, + GLint x, GLint y, + GLfloat (*rgba)[NUM_CHANNELS] ); + + void (*read_quad_f_swz)( struct softpipe_surface *, + GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE] ); + + void (*read_quad_ub)( struct softpipe_surface *, + GLint x, GLint y, + GLubyte (*rgba)[NUM_CHANNELS] ); + + + void (*write_quad_f)( struct softpipe_surface *, + GLint x, GLint y, + GLfloat (*rgba)[NUM_CHANNELS] ); + + void (*write_quad_f_swz)( struct softpipe_surface *, + GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE] ); + + + void (*write_quad_ub)( struct softpipe_surface *, + GLint x, GLint y, + GLubyte (*rgba)[NUM_CHANNELS] ); + + void (*write_mono_row_ub)( struct softpipe_surface *, + GLuint count, GLint x, GLint y, + GLubyte rgba[NUM_CHANNELS] ); + + void (*read_quad_z)(struct softpipe_surface *, + GLint x, GLint y, GLuint zzzz[QUAD_SIZE]); + void (*write_quad_z)(struct softpipe_surface *, + GLint x, GLint y, const GLuint zzzz[QUAD_SIZE]); + + void (*read_quad_stencil)(struct softpipe_surface *, + GLint x, GLint y, GLubyte ssss[QUAD_SIZE]); + void (*write_quad_stencil)(struct softpipe_surface *, + GLint x, GLint y, const GLubyte ssss[QUAD_SIZE]); +}; + + +/** Cast wrapper */ +static INLINE struct softpipe_surface * +softpipe_surface(struct pipe_surface *ps) +{ + return (struct softpipe_surface *) ps; +} + + +#endif /* SP_SURFACE_H */ diff --git a/src/mesa/pipe/tgsi/Makefile b/src/mesa/pipe/tgsi/Makefile new file mode 100644 index 00000000000..12a8bd0409e --- /dev/null +++ b/src/mesa/pipe/tgsi/Makefile @@ -0,0 +1,3 @@ +default: + cd ../.. ; make + diff --git a/src/mesa/pipe/tgsi/core/Makefile b/src/mesa/pipe/tgsi/core/Makefile new file mode 100644 index 00000000000..eb8b14e0e89 --- /dev/null +++ b/src/mesa/pipe/tgsi/core/Makefile @@ -0,0 +1,3 @@ +default: + cd ../../.. ; make + diff --git a/src/mesa/pipe/tgsi/core/tgsi_build.c b/src/mesa/pipe/tgsi/core/tgsi_build.c new file mode 100644 index 00000000000..2a482a78dc3 --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_build.c @@ -0,0 +1,1315 @@ +#include "tgsi_platform.h" +#include "tgsi_core.h" + +/* + * version + */ + +struct tgsi_version +tgsi_build_version( void ) +{ + struct tgsi_version version; + + version.MajorVersion = 1; + version.MinorVersion = 1; + version.Padding = 0; + + return version; +} + +/* + * header + */ + +struct tgsi_header +tgsi_build_header( void ) +{ + struct tgsi_header header; + + header.HeaderSize = 1; + header.BodySize = 0; + + return header; +} + +static void +header_headersize_grow( struct tgsi_header *header ) +{ + assert (header->HeaderSize < 0xFF); + assert (header->BodySize == 0); + + header->HeaderSize++; +} + +static void +header_bodysize_grow( struct tgsi_header *header ) +{ + assert (header->BodySize < 0xFFFFFF); + + header->BodySize++; +} + +struct tgsi_processor +tgsi_default_processor( void ) +{ + struct tgsi_processor processor; + + processor.Processor = TGSI_PROCESSOR_FRAGMENT; + processor.Padding = 0; + + return processor; +} + +struct tgsi_processor +tgsi_build_processor( + GLuint type, + struct tgsi_header *header ) +{ + struct tgsi_processor processor; + + processor = tgsi_default_processor(); + processor.Processor = type; + + header_headersize_grow( header ); + + return processor; +} + +/* + * declaration + */ + +struct tgsi_declaration +tgsi_default_declaration( void ) +{ + struct tgsi_declaration declaration; + + declaration.Type = TGSI_TOKEN_TYPE_DECLARATION; + declaration.Size = 1; + declaration.File = TGSI_FILE_NULL; + declaration.Declare = TGSI_DECLARE_RANGE; + declaration.Interpolate = 0; + declaration.Padding = 0; + declaration.Extended = 0; + + return declaration; +} + +struct tgsi_declaration +tgsi_build_declaration( + GLuint file, + GLuint declare, + GLuint interpolate, + struct tgsi_header *header ) +{ + struct tgsi_declaration declaration; + + assert (file <= TGSI_FILE_IMMEDIATE); + assert (declare <= TGSI_DECLARE_MASK); + + declaration = tgsi_default_declaration(); + declaration.File = file; + declaration.Declare = declare; + declaration.Interpolate = interpolate; + + header_bodysize_grow( header ); + + return declaration; +} + +static void +declaration_grow( + struct tgsi_declaration *declaration, + struct tgsi_header *header ) +{ + assert (declaration->Size < 0xFF); + + declaration->Size++; + + header_bodysize_grow( header ); +} + +struct tgsi_full_declaration +tgsi_default_full_declaration( void ) +{ + struct tgsi_full_declaration full_declaration; + + full_declaration.Declaration = tgsi_default_declaration(); + full_declaration.Interpolation = tgsi_default_declaration_interpolation(); + + return full_declaration; +} + +GLuint +tgsi_build_full_declaration( + const struct tgsi_full_declaration *full_decl, + struct tgsi_token *tokens, + struct tgsi_header *header, + GLuint maxsize ) +{ + GLuint size = 0; + struct tgsi_declaration *declaration; + + if( maxsize <= size ) + return 0; + declaration = (struct tgsi_declaration *) &tokens[size]; + size++; + + *declaration = tgsi_build_declaration( + full_decl->Declaration.File, + full_decl->Declaration.Declare, + full_decl->Declaration.Interpolate, + header ); + + switch( full_decl->Declaration.Declare ) { + case TGSI_DECLARE_RANGE: + { + struct tgsi_declaration_range *dr; + + if( maxsize <= size ) + return 0; + dr = (struct tgsi_declaration_range *) &tokens[size]; + size++; + + *dr = tgsi_build_declaration_range( + full_decl->u.DeclarationRange.First, + full_decl->u.DeclarationRange.Last, + declaration, + header ); + break; + } + + case TGSI_DECLARE_MASK: + { + struct tgsi_declaration_mask *dm; + + if( maxsize <= size ) + return 0; + dm = (struct tgsi_declaration_mask *) &tokens[size]; + size++; + + *dm = tgsi_build_declaration_mask( + full_decl->u.DeclarationMask.Mask, + declaration, + header ); + break; + } + + default: + assert( 0 ); + } + + if( full_decl->Declaration.Interpolate ) { + struct tgsi_declaration_interpolation *di; + + if( maxsize <= size ) + return 0; + di = (struct tgsi_declaration_interpolation *) &tokens[size]; + size++; + + *di = tgsi_build_declaration_interpolation( + full_decl->Interpolation.Interpolate, + declaration, + header ); + } + + return size; +} + +struct tgsi_declaration_range +tgsi_build_declaration_range( + GLuint first, + GLuint last, + struct tgsi_declaration *declaration, + struct tgsi_header *header ) +{ + struct tgsi_declaration_range declaration_range; + + assert (last >= first); + assert (last <= 0xFFFF); + + declaration_range.First = first; + declaration_range.Last = last; + + declaration_grow( declaration, header ); + + return declaration_range; +} + +struct tgsi_declaration_mask +tgsi_build_declaration_mask( + GLuint mask, + struct tgsi_declaration *declaration, + struct tgsi_header *header ) +{ + struct tgsi_declaration_mask declaration_mask; + + declaration_mask.Mask = mask; + + declaration_grow( declaration, header ); + + return declaration_mask; +} + +struct tgsi_declaration_interpolation +tgsi_default_declaration_interpolation( void ) +{ + struct tgsi_declaration_interpolation di; + + di.Interpolate = TGSI_INTERPOLATE_CONSTANT; + di.Padding = 0; + + return di; +} + +struct tgsi_declaration_interpolation +tgsi_build_declaration_interpolation( + GLuint interpolate, + struct tgsi_declaration *declaration, + struct tgsi_header *header ) +{ + struct tgsi_declaration_interpolation di; + + assert( interpolate <= TGSI_INTERPOLATE_PERSPECTIVE ); + + di = tgsi_default_declaration_interpolation(); + di.Interpolate = interpolate; + + declaration_grow( declaration, header ); + + return di; +} + +/* + * immediate + */ + +struct tgsi_immediate +tgsi_default_immediate( void ) +{ + struct tgsi_immediate immediate; + + immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE; + immediate.Size = 1; + immediate.DataType = TGSI_IMM_FLOAT32; + immediate.Padding = 0; + immediate.Extended = 0; + + return immediate; +} + +struct tgsi_immediate +tgsi_build_immediate( + struct tgsi_header *header ) +{ + struct tgsi_immediate immediate; + + immediate = tgsi_default_immediate(); + + header_bodysize_grow( header ); + + return immediate; +} + +struct tgsi_full_immediate +tgsi_default_full_immediate( void ) +{ + struct tgsi_full_immediate fullimm; + + fullimm.Immediate = tgsi_default_immediate(); + fullimm.u.Pointer = (void *) 0; + + return fullimm; +} + +static void +immediate_grow( + struct tgsi_immediate *immediate, + struct tgsi_header *header ) +{ + assert( immediate->Size < 0xFF ); + + immediate->Size++; + + header_bodysize_grow( header ); +} + +struct tgsi_immediate_float32 +tgsi_build_immediate_float32( + GLfloat value, + struct tgsi_immediate *immediate, + struct tgsi_header *header ) +{ + struct tgsi_immediate_float32 immediate_float32; + + immediate_float32.Float = value; + + immediate_grow( immediate, header ); + + return immediate_float32; +} + +GLuint +tgsi_build_full_immediate( + const struct tgsi_full_immediate *full_imm, + struct tgsi_token *tokens, + struct tgsi_header *header, + GLuint maxsize ) +{ + GLuint size = 0, i; + struct tgsi_immediate *immediate; + + if( maxsize <= size ) + return 0; + immediate = (struct tgsi_immediate *) &tokens[size]; + size++; + + *immediate = tgsi_build_immediate( header ); + + for( i = 0; i < full_imm->Immediate.Size - 1; i++ ) { + struct tgsi_immediate_float32 *if32; + + if( maxsize <= size ) + return 0; + if32 = (struct tgsi_immediate_float32 *) &tokens[size]; + size++; + + *if32 = tgsi_build_immediate_float32( + full_imm->u.ImmediateFloat32[i].Float, + immediate, + header ); + } + + return size; +} + +/* + * instruction + */ + +struct tgsi_instruction +tgsi_default_instruction( void ) +{ + struct tgsi_instruction instruction; + + instruction.Type = TGSI_TOKEN_TYPE_INSTRUCTION; + instruction.Size = 1; + instruction.Opcode = TGSI_OPCODE_MOV; + instruction.Saturate = TGSI_SAT_NONE; + instruction.NumDstRegs = 1; + instruction.NumSrcRegs = 1; + instruction.Padding = 0; + instruction.Extended = 0; + + return instruction; +} + +struct tgsi_instruction +tgsi_build_instruction( + GLuint opcode, + GLuint saturate, + GLuint num_dst_regs, + GLuint num_src_regs, + struct tgsi_header *header ) +{ + struct tgsi_instruction instruction; + + assert (opcode <= TGSI_OPCODE_LAST); + assert (saturate <= TGSI_SAT_MINUS_PLUS_ONE); + assert (num_dst_regs <= 3); + assert (num_src_regs <= 15); + + instruction = tgsi_default_instruction(); + instruction.Opcode = opcode; + instruction.Saturate = saturate; + instruction.NumDstRegs = num_dst_regs; + instruction.NumSrcRegs = num_src_regs; + + header_bodysize_grow( header ); + + return instruction; +} + +static void +instruction_grow( + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + assert (instruction->Size < 0xFF); + + instruction->Size++; + + header_bodysize_grow( header ); +} + +struct tgsi_full_instruction +tgsi_default_full_instruction( void ) +{ + struct tgsi_full_instruction full_instruction; + GLuint i; + + full_instruction.Instruction = tgsi_default_instruction(); + full_instruction.InstructionExtNv = tgsi_default_instruction_ext_nv(); + full_instruction.InstructionExtLabel = tgsi_default_instruction_ext_label(); + full_instruction.InstructionExtTexture = tgsi_default_instruction_ext_texture(); + for( i = 0; i < TGSI_FULL_MAX_DST_REGISTERS; i++ ) { + full_instruction.FullDstRegisters[i] = tgsi_default_full_dst_register(); + } + for( i = 0; i < TGSI_FULL_MAX_SRC_REGISTERS; i++ ) { + full_instruction.FullSrcRegisters[i] = tgsi_default_full_src_register(); + } + + return full_instruction; +} + +GLuint +tgsi_build_full_instruction( + const struct tgsi_full_instruction *full_inst, + struct tgsi_token *tokens, + struct tgsi_header *header, + GLuint maxsize ) +{ + GLuint size = 0; + GLuint i; + struct tgsi_instruction *instruction; + struct tgsi_token *prev_token; + + if( maxsize <= size ) + return 0; + instruction = (struct tgsi_instruction *) &tokens[size]; + size++; + + *instruction = tgsi_build_instruction( + full_inst->Instruction.Opcode, + full_inst->Instruction.Saturate, + full_inst->Instruction.NumDstRegs, + full_inst->Instruction.NumSrcRegs, + header ); + prev_token = (struct tgsi_token *) instruction; + + if( tgsi_compare_instruction_ext_nv( + full_inst->InstructionExtNv, + tgsi_default_instruction_ext_nv() ) ) { + struct tgsi_instruction_ext_nv *instruction_ext_nv; + + if( maxsize <= size ) + return 0; + instruction_ext_nv = + (struct tgsi_instruction_ext_nv *) &tokens[size]; + size++; + + *instruction_ext_nv = tgsi_build_instruction_ext_nv( + full_inst->InstructionExtNv.Precision, + full_inst->InstructionExtNv.CondDstIndex, + full_inst->InstructionExtNv.CondFlowIndex, + full_inst->InstructionExtNv.CondMask, + full_inst->InstructionExtNv.CondSwizzleX, + full_inst->InstructionExtNv.CondSwizzleY, + full_inst->InstructionExtNv.CondSwizzleZ, + full_inst->InstructionExtNv.CondSwizzleW, + full_inst->InstructionExtNv.CondDstUpdate, + full_inst->InstructionExtNv.CondFlowEnable, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) instruction_ext_nv; + } + + if( tgsi_compare_instruction_ext_label( + full_inst->InstructionExtLabel, + tgsi_default_instruction_ext_label() ) ) { + struct tgsi_instruction_ext_label *instruction_ext_label; + + if( maxsize <= size ) + return 0; + instruction_ext_label = + (struct tgsi_instruction_ext_label *) &tokens[size]; + size++; + + *instruction_ext_label = tgsi_build_instruction_ext_label( + full_inst->InstructionExtLabel.Label, + full_inst->InstructionExtLabel.Target, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) instruction_ext_label; + } + + if( tgsi_compare_instruction_ext_texture( + full_inst->InstructionExtTexture, + tgsi_default_instruction_ext_texture() ) ) { + struct tgsi_instruction_ext_texture *instruction_ext_texture; + + if( maxsize <= size ) + return 0; + instruction_ext_texture = + (struct tgsi_instruction_ext_texture *) &tokens[size]; + size++; + + *instruction_ext_texture = tgsi_build_instruction_ext_texture( + full_inst->InstructionExtTexture.Texture, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) instruction_ext_texture; + } + + for( i = 0; i < full_inst->Instruction.NumDstRegs; i++ ) { + const struct tgsi_full_dst_register *reg = &full_inst->FullDstRegisters[i]; + struct tgsi_dst_register *dst_register; + struct tgsi_token *prev_token; + + if( maxsize <= size ) + return 0; + dst_register = (struct tgsi_dst_register *) &tokens[size]; + size++; + + *dst_register = tgsi_build_dst_register( + reg->DstRegister.File, + reg->DstRegister.WriteMask, + reg->DstRegister.Index, + instruction, + header ); + prev_token = (struct tgsi_token *) dst_register; + + if( tgsi_compare_dst_register_ext_concode( + reg->DstRegisterExtConcode, + tgsi_default_dst_register_ext_concode() ) ) { + struct tgsi_dst_register_ext_concode *dst_register_ext_concode; + + if( maxsize <= size ) + return 0; + dst_register_ext_concode = + (struct tgsi_dst_register_ext_concode *) &tokens[size]; + size++; + + *dst_register_ext_concode = tgsi_build_dst_register_ext_concode( + reg->DstRegisterExtConcode.CondMask, + reg->DstRegisterExtConcode.CondSwizzleX, + reg->DstRegisterExtConcode.CondSwizzleY, + reg->DstRegisterExtConcode.CondSwizzleZ, + reg->DstRegisterExtConcode.CondSwizzleW, + reg->DstRegisterExtConcode.CondSrcIndex, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) dst_register_ext_concode; + } + + if( tgsi_compare_dst_register_ext_modulate( + reg->DstRegisterExtModulate, + tgsi_default_dst_register_ext_modulate() ) ) { + struct tgsi_dst_register_ext_modulate *dst_register_ext_modulate; + + if( maxsize <= size ) + return 0; + dst_register_ext_modulate = + (struct tgsi_dst_register_ext_modulate *) &tokens[size]; + size++; + + *dst_register_ext_modulate = tgsi_build_dst_register_ext_modulate( + reg->DstRegisterExtModulate.Modulate, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) dst_register_ext_modulate; + } + } + + for( i = 0; i < full_inst->Instruction.NumSrcRegs; i++ ) { + const struct tgsi_full_src_register *reg = &full_inst->FullSrcRegisters[i]; + struct tgsi_src_register *src_register; + struct tgsi_token *prev_token; + + if( maxsize <= size ) + return 0; + src_register = (struct tgsi_src_register *) &tokens[size]; + size++; + + *src_register = tgsi_build_src_register( + reg->SrcRegister.File, + reg->SrcRegister.SwizzleX, + reg->SrcRegister.SwizzleY, + reg->SrcRegister.SwizzleZ, + reg->SrcRegister.SwizzleW, + reg->SrcRegister.Negate, + reg->SrcRegister.Indirect, + reg->SrcRegister.Dimension, + reg->SrcRegister.Index, + instruction, + header ); + prev_token = (struct tgsi_token *) src_register; + + if( tgsi_compare_src_register_ext_swz( + reg->SrcRegisterExtSwz, + tgsi_default_src_register_ext_swz() ) ) { + struct tgsi_src_register_ext_swz *src_register_ext_swz; + + if( maxsize <= size ) + return 0; + src_register_ext_swz = + (struct tgsi_src_register_ext_swz *) &tokens[size]; + size++; + + *src_register_ext_swz = tgsi_build_src_register_ext_swz( + reg->SrcRegisterExtSwz.ExtSwizzleX, + reg->SrcRegisterExtSwz.ExtSwizzleY, + reg->SrcRegisterExtSwz.ExtSwizzleZ, + reg->SrcRegisterExtSwz.ExtSwizzleW, + reg->SrcRegisterExtSwz.NegateX, + reg->SrcRegisterExtSwz.NegateY, + reg->SrcRegisterExtSwz.NegateZ, + reg->SrcRegisterExtSwz.NegateW, + reg->SrcRegisterExtSwz.ExtDivide, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) src_register_ext_swz; + } + + if( tgsi_compare_src_register_ext_mod( + reg->SrcRegisterExtMod, + tgsi_default_src_register_ext_mod() ) ) { + struct tgsi_src_register_ext_mod *src_register_ext_mod; + + if( maxsize <= size ) + return 0; + src_register_ext_mod = + (struct tgsi_src_register_ext_mod *) &tokens[size]; + size++; + + *src_register_ext_mod = tgsi_build_src_register_ext_mod( + reg->SrcRegisterExtMod.Complement, + reg->SrcRegisterExtMod.Bias, + reg->SrcRegisterExtMod.Scale2X, + reg->SrcRegisterExtMod.Absolute, + reg->SrcRegisterExtMod.Negate, + prev_token, + instruction, + header ); + prev_token = (struct tgsi_token *) src_register_ext_mod; + } + + if( reg->SrcRegister.Indirect ) { + struct tgsi_src_register *ind; + + if( maxsize <= size ) + return 0; + ind = (struct tgsi_src_register *) &tokens[size]; + size++; + + *ind = tgsi_build_src_register( + reg->SrcRegisterInd.File, + reg->SrcRegisterInd.SwizzleX, + reg->SrcRegisterInd.SwizzleY, + reg->SrcRegisterInd.SwizzleZ, + reg->SrcRegisterInd.SwizzleW, + reg->SrcRegisterInd.Negate, + reg->SrcRegisterInd.Indirect, + reg->SrcRegisterInd.Dimension, + reg->SrcRegisterInd.Index, + instruction, + header ); + } + + if( reg->SrcRegister.Dimension ) { + struct tgsi_dimension *dim; + + assert( !reg->SrcRegisterDim.Dimension ); + + if( maxsize <= size ) + return 0; + dim = (struct tgsi_dimension *) &tokens[size]; + size++; + + *dim = tgsi_build_dimension( + reg->SrcRegisterDim.Indirect, + reg->SrcRegisterDim.Index, + instruction, + header ); + + if( reg->SrcRegisterDim.Indirect ) { + struct tgsi_src_register *ind; + + if( maxsize <= size ) + return 0; + ind = (struct tgsi_src_register *) &tokens[size]; + size++; + + *ind = tgsi_build_src_register( + reg->SrcRegisterDimInd.File, + reg->SrcRegisterDimInd.SwizzleX, + reg->SrcRegisterDimInd.SwizzleY, + reg->SrcRegisterDimInd.SwizzleZ, + reg->SrcRegisterDimInd.SwizzleW, + reg->SrcRegisterDimInd.Negate, + reg->SrcRegisterDimInd.Indirect, + reg->SrcRegisterDimInd.Dimension, + reg->SrcRegisterDimInd.Index, + instruction, + header ); + } + } + } + + return size; +} + +struct tgsi_instruction_ext_nv +tgsi_default_instruction_ext_nv( void ) +{ + struct tgsi_instruction_ext_nv instruction_ext_nv; + + instruction_ext_nv.Type = TGSI_INSTRUCTION_EXT_TYPE_NV; + instruction_ext_nv.Precision = TGSI_PRECISION_DEFAULT; + instruction_ext_nv.CondDstIndex = 0; + instruction_ext_nv.CondFlowIndex = 0; + instruction_ext_nv.CondMask = TGSI_CC_TR; + instruction_ext_nv.CondSwizzleX = TGSI_SWIZZLE_X; + instruction_ext_nv.CondSwizzleY = TGSI_SWIZZLE_Y; + instruction_ext_nv.CondSwizzleZ = TGSI_SWIZZLE_Z; + instruction_ext_nv.CondSwizzleW = TGSI_SWIZZLE_W; + instruction_ext_nv.CondDstUpdate = 0; + instruction_ext_nv.CondFlowEnable = 0; + instruction_ext_nv.Padding = 0; + instruction_ext_nv.Extended = 0; + + return instruction_ext_nv; +} + +union token_u32 +{ + GLuint u32; +}; + +GLuint +tgsi_compare_instruction_ext_nv( + struct tgsi_instruction_ext_nv a, + struct tgsi_instruction_ext_nv b ) +{ + a.Padding = b.Padding = 0; + a.Extended = b.Extended = 0; + return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; +} + +struct tgsi_instruction_ext_nv +tgsi_build_instruction_ext_nv( + GLuint precision, + GLuint cond_dst_index, + GLuint cond_flow_index, + GLuint cond_mask, + GLuint cond_swizzle_x, + GLuint cond_swizzle_y, + GLuint cond_swizzle_z, + GLuint cond_swizzle_w, + GLuint cond_dst_update, + GLuint cond_flow_update, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_instruction_ext_nv instruction_ext_nv; + + instruction_ext_nv = tgsi_default_instruction_ext_nv(); + instruction_ext_nv.Precision = precision; + instruction_ext_nv.CondDstIndex = cond_dst_index; + instruction_ext_nv.CondFlowIndex = cond_flow_index; + instruction_ext_nv.CondMask = cond_mask; + instruction_ext_nv.CondSwizzleX = cond_swizzle_x; + instruction_ext_nv.CondSwizzleY = cond_swizzle_y; + instruction_ext_nv.CondSwizzleZ = cond_swizzle_z; + instruction_ext_nv.CondSwizzleW = cond_swizzle_w; + instruction_ext_nv.CondDstUpdate = cond_dst_update; + instruction_ext_nv.CondFlowEnable = cond_flow_update; + + prev_token->Extended = 1; + instruction_grow( instruction, header ); + + return instruction_ext_nv; +} + +struct tgsi_instruction_ext_label +tgsi_default_instruction_ext_label( void ) +{ + struct tgsi_instruction_ext_label instruction_ext_label; + + instruction_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL; + instruction_ext_label.Label = 0; + instruction_ext_label.Target = 0; + instruction_ext_label.Padding = 0; + instruction_ext_label.Extended = 0; + + return instruction_ext_label; +} + +GLuint +tgsi_compare_instruction_ext_label( + struct tgsi_instruction_ext_label a, + struct tgsi_instruction_ext_label b ) +{ + a.Padding = b.Padding = 0; + a.Extended = b.Extended = 0; + return *(GLuint *) &a != *(GLuint *) &b; +} + +struct tgsi_instruction_ext_label +tgsi_build_instruction_ext_label( + GLuint label, + GLuint target, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_instruction_ext_label instruction_ext_label; + + instruction_ext_label = tgsi_default_instruction_ext_label(); + instruction_ext_label.Label = label; + instruction_ext_label.Target = target; + + prev_token->Extended = 1; + instruction_grow( instruction, header ); + + return instruction_ext_label; +} + +struct tgsi_instruction_ext_texture +tgsi_default_instruction_ext_texture( void ) +{ + struct tgsi_instruction_ext_texture instruction_ext_texture; + + instruction_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE; + instruction_ext_texture.Texture = TGSI_TEXTURE_UNKNOWN; + instruction_ext_texture.Padding = 0; + instruction_ext_texture.Extended = 0; + + return instruction_ext_texture; +} + +GLuint +tgsi_compare_instruction_ext_texture( + struct tgsi_instruction_ext_texture a, + struct tgsi_instruction_ext_texture b ) +{ + a.Padding = b.Padding = 0; + a.Extended = b.Extended = 0; + return *(GLuint *) &a != *(GLuint *) &b; +} + +struct tgsi_instruction_ext_texture +tgsi_build_instruction_ext_texture( + GLuint texture, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_instruction_ext_texture instruction_ext_texture; + + instruction_ext_texture = tgsi_default_instruction_ext_texture(); + instruction_ext_texture.Texture = texture; + + prev_token->Extended = 1; + instruction_grow( instruction, header ); + + return instruction_ext_texture; +} + +struct tgsi_src_register +tgsi_default_src_register( void ) +{ + struct tgsi_src_register src_register; + + src_register.File = TGSI_FILE_NULL; + src_register.SwizzleX = TGSI_SWIZZLE_X; + src_register.SwizzleY = TGSI_SWIZZLE_Y; + src_register.SwizzleZ = TGSI_SWIZZLE_Z; + src_register.SwizzleW = TGSI_SWIZZLE_W; + src_register.Negate = 0; + src_register.Indirect = 0; + src_register.Dimension = 0; + src_register.Index = 0; + src_register.Extended = 0; + + return src_register; +} + +struct tgsi_src_register +tgsi_build_src_register( + GLuint file, + GLuint swizzle_x, + GLuint swizzle_y, + GLuint swizzle_z, + GLuint swizzle_w, + GLuint negate, + GLuint indirect, + GLuint dimension, + GLint index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_src_register src_register; + + assert( file <= TGSI_FILE_IMMEDIATE ); + assert( swizzle_x <= TGSI_SWIZZLE_W ); + assert( swizzle_y <= TGSI_SWIZZLE_W ); + assert( swizzle_z <= TGSI_SWIZZLE_W ); + assert( swizzle_w <= TGSI_SWIZZLE_W ); + assert( negate <= 1 ); + assert( index >= -0x8000 && index <= 0x7FFF ); + + src_register = tgsi_default_src_register(); + src_register.File = file; + src_register.SwizzleX = swizzle_x; + src_register.SwizzleY = swizzle_y; + src_register.SwizzleZ = swizzle_z; + src_register.SwizzleW = swizzle_w; + src_register.Negate = negate; + src_register.Indirect = indirect; + src_register.Dimension = dimension; + src_register.Index = index; + + instruction_grow( instruction, header ); + + return src_register; +} + +struct tgsi_full_src_register +tgsi_default_full_src_register( void ) +{ + struct tgsi_full_src_register full_src_register; + + full_src_register.SrcRegister = tgsi_default_src_register(); + full_src_register.SrcRegisterExtSwz = tgsi_default_src_register_ext_swz(); + full_src_register.SrcRegisterExtMod = tgsi_default_src_register_ext_mod(); + full_src_register.SrcRegisterInd = tgsi_default_src_register(); + full_src_register.SrcRegisterDim = tgsi_default_dimension(); + full_src_register.SrcRegisterDimInd = tgsi_default_src_register(); + + return full_src_register; +} + +struct tgsi_src_register_ext_swz +tgsi_default_src_register_ext_swz( void ) +{ + struct tgsi_src_register_ext_swz src_register_ext_swz; + + src_register_ext_swz.Type = TGSI_SRC_REGISTER_EXT_TYPE_SWZ; + src_register_ext_swz.ExtSwizzleX = TGSI_EXTSWIZZLE_X; + src_register_ext_swz.ExtSwizzleY = TGSI_EXTSWIZZLE_Y; + src_register_ext_swz.ExtSwizzleZ = TGSI_EXTSWIZZLE_Z; + src_register_ext_swz.ExtSwizzleW = TGSI_EXTSWIZZLE_W; + src_register_ext_swz.NegateX = 0; + src_register_ext_swz.NegateY = 0; + src_register_ext_swz.NegateZ = 0; + src_register_ext_swz.NegateW = 0; + src_register_ext_swz.ExtDivide = TGSI_EXTSWIZZLE_ONE; + src_register_ext_swz.Padding = 0; + src_register_ext_swz.Extended = 0; + + return src_register_ext_swz; +} + +GLuint +tgsi_compare_src_register_ext_swz( + struct tgsi_src_register_ext_swz a, + struct tgsi_src_register_ext_swz b ) +{ + a.Padding = b.Padding = 0; + a.Extended = b.Extended = 0; + return *(GLuint *) &a != *(GLuint *) &b; +} + +struct tgsi_src_register_ext_swz +tgsi_build_src_register_ext_swz( + GLuint ext_swizzle_x, + GLuint ext_swizzle_y, + GLuint ext_swizzle_z, + GLuint ext_swizzle_w, + GLuint negate_x, + GLuint negate_y, + GLuint negate_z, + GLuint negate_w, + GLuint ext_divide, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_src_register_ext_swz src_register_ext_swz; + + assert (ext_swizzle_x <= TGSI_EXTSWIZZLE_ONE); + assert (ext_swizzle_y <= TGSI_EXTSWIZZLE_ONE); + assert (ext_swizzle_z <= TGSI_EXTSWIZZLE_ONE); + assert (ext_swizzle_w <= TGSI_EXTSWIZZLE_ONE); + assert (negate_x <= 1); + assert (negate_y <= 1); + assert (negate_z <= 1); + assert (negate_w <= 1); + assert (ext_divide <= TGSI_EXTSWIZZLE_ONE); + + src_register_ext_swz = tgsi_default_src_register_ext_swz(); + src_register_ext_swz.ExtSwizzleX = ext_swizzle_x; + src_register_ext_swz.ExtSwizzleY = ext_swizzle_y; + src_register_ext_swz.ExtSwizzleZ = ext_swizzle_z; + src_register_ext_swz.ExtSwizzleW = ext_swizzle_w; + src_register_ext_swz.NegateX = negate_x; + src_register_ext_swz.NegateY = negate_y; + src_register_ext_swz.NegateZ = negate_z; + src_register_ext_swz.NegateW = negate_w; + src_register_ext_swz.ExtDivide = ext_divide; + + prev_token->Extended = 1; + instruction_grow( instruction, header ); + + return src_register_ext_swz; +} + +struct tgsi_src_register_ext_mod +tgsi_default_src_register_ext_mod( void ) +{ + struct tgsi_src_register_ext_mod src_register_ext_mod; + + src_register_ext_mod.Type = TGSI_SRC_REGISTER_EXT_TYPE_MOD; + src_register_ext_mod.Complement = 0; + src_register_ext_mod.Bias = 0; + src_register_ext_mod.Scale2X = 0; + src_register_ext_mod.Absolute = 0; + src_register_ext_mod.Negate = 0; + src_register_ext_mod.Padding = 0; + src_register_ext_mod.Extended = 0; + + return src_register_ext_mod; +} + +GLuint +tgsi_compare_src_register_ext_mod( + struct tgsi_src_register_ext_mod a, + struct tgsi_src_register_ext_mod b ) +{ + a.Padding = b.Padding = 0; + a.Extended = b.Extended = 0; + return *(GLuint *) &a != *(GLuint *) &b; +} + +struct tgsi_src_register_ext_mod +tgsi_build_src_register_ext_mod( + GLuint complement, + GLuint bias, + GLuint scale_2x, + GLuint absolute, + GLuint negate, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_src_register_ext_mod src_register_ext_mod; + + assert (complement <= 1); + assert (bias <= 1); + assert (scale_2x <= 1); + assert (absolute <= 1); + assert (negate <= 1); + + src_register_ext_mod = tgsi_default_src_register_ext_mod(); + src_register_ext_mod.Complement = complement; + src_register_ext_mod.Bias = bias; + src_register_ext_mod.Scale2X = scale_2x; + src_register_ext_mod.Absolute = absolute; + src_register_ext_mod.Negate = negate; + + prev_token->Extended = 1; + instruction_grow( instruction, header ); + + return src_register_ext_mod; +} + +struct tgsi_dimension +tgsi_default_dimension( void ) +{ + struct tgsi_dimension dimension; + + dimension.Indirect = 0; + dimension.Dimension = 0; + dimension.Padding = 0; + dimension.Index = 0; + dimension.Extended = 0; + + return dimension; +} + +struct tgsi_dimension +tgsi_build_dimension( + GLuint indirect, + GLuint index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_dimension dimension; + + dimension = tgsi_default_dimension(); + dimension.Indirect = indirect; + dimension.Index = index; + + instruction_grow( instruction, header ); + + return dimension; +} + +struct tgsi_dst_register +tgsi_default_dst_register( void ) +{ + struct tgsi_dst_register dst_register; + + dst_register.File = TGSI_FILE_NULL; + dst_register.WriteMask = TGSI_WRITEMASK_XYZW; + dst_register.Indirect = 0; + dst_register.Dimension = 0; + dst_register.Index = 0; + dst_register.Padding = 0; + dst_register.Extended = 0; + + return dst_register; +} + +struct tgsi_dst_register +tgsi_build_dst_register( + GLuint file, + GLuint mask, + GLint index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_dst_register dst_register; + + assert (file <= TGSI_FILE_IMMEDIATE); + assert (mask <= TGSI_WRITEMASK_XYZW); + assert (index >= -32768 && index <= 32767); + + dst_register = tgsi_default_dst_register(); + dst_register.File = file; + dst_register.WriteMask = mask; + dst_register.Index = index; + + instruction_grow( instruction, header ); + + return dst_register; +} + +struct tgsi_full_dst_register +tgsi_default_full_dst_register( void ) +{ + struct tgsi_full_dst_register full_dst_register; + + full_dst_register.DstRegister = tgsi_default_dst_register(); + full_dst_register.DstRegisterExtConcode = + tgsi_default_dst_register_ext_concode(); + full_dst_register.DstRegisterExtModulate = + tgsi_default_dst_register_ext_modulate(); + + return full_dst_register; +} + +struct tgsi_dst_register_ext_concode +tgsi_default_dst_register_ext_concode( void ) +{ + struct tgsi_dst_register_ext_concode dst_register_ext_concode; + + dst_register_ext_concode.Type = TGSI_DST_REGISTER_EXT_TYPE_CONDCODE; + dst_register_ext_concode.CondMask = TGSI_CC_TR; + dst_register_ext_concode.CondSwizzleX = TGSI_SWIZZLE_X; + dst_register_ext_concode.CondSwizzleY = TGSI_SWIZZLE_Y; + dst_register_ext_concode.CondSwizzleZ = TGSI_SWIZZLE_Z; + dst_register_ext_concode.CondSwizzleW = TGSI_SWIZZLE_W; + dst_register_ext_concode.CondSrcIndex = 0; + dst_register_ext_concode.Padding = 0; + dst_register_ext_concode.Extended = 0; + + return dst_register_ext_concode; +} + +GLuint +tgsi_compare_dst_register_ext_concode( + struct tgsi_dst_register_ext_concode a, + struct tgsi_dst_register_ext_concode b ) +{ + a.Padding = b.Padding = 0; + a.Extended = b.Extended = 0; + return *(GLuint *) &a != *(GLuint *) &b; +} + +struct tgsi_dst_register_ext_concode +tgsi_build_dst_register_ext_concode( + GLuint cc, + GLuint swizzle_x, + GLuint swizzle_y, + GLuint swizzle_z, + GLuint swizzle_w, + GLint index, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_dst_register_ext_concode dst_register_ext_concode; + + assert (cc <= TGSI_CC_FL); + assert (swizzle_x <= TGSI_SWIZZLE_W); + assert (swizzle_y <= TGSI_SWIZZLE_W); + assert (swizzle_z <= TGSI_SWIZZLE_W); + assert (swizzle_w <= TGSI_SWIZZLE_W); + assert (index >= -32768 && index <= 32767); + + dst_register_ext_concode = tgsi_default_dst_register_ext_concode(); + dst_register_ext_concode.CondMask = cc; + dst_register_ext_concode.CondSwizzleX = swizzle_x; + dst_register_ext_concode.CondSwizzleY = swizzle_y; + dst_register_ext_concode.CondSwizzleZ = swizzle_z; + dst_register_ext_concode.CondSwizzleW = swizzle_w; + dst_register_ext_concode.CondSrcIndex = index; + + prev_token->Extended = 1; + instruction_grow( instruction, header ); + + return dst_register_ext_concode; +} + +struct tgsi_dst_register_ext_modulate +tgsi_default_dst_register_ext_modulate( void ) +{ + struct tgsi_dst_register_ext_modulate dst_register_ext_modulate; + + dst_register_ext_modulate.Type = TGSI_DST_REGISTER_EXT_TYPE_MODULATE; + dst_register_ext_modulate.Modulate = TGSI_MODULATE_1X; + dst_register_ext_modulate.Padding = 0; + dst_register_ext_modulate.Extended = 0; + + return dst_register_ext_modulate; +} + +GLuint +tgsi_compare_dst_register_ext_modulate( + struct tgsi_dst_register_ext_modulate a, + struct tgsi_dst_register_ext_modulate b ) +{ + a.Padding = b.Padding = 0; + a.Extended = b.Extended = 0; + return *(GLuint *) &a != *(GLuint *) &b; +} + +struct tgsi_dst_register_ext_modulate +tgsi_build_dst_register_ext_modulate( + GLuint modulate, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ) +{ + struct tgsi_dst_register_ext_modulate dst_register_ext_modulate; + + assert (modulate <= TGSI_MODULATE_EIGHTH); + + dst_register_ext_modulate = tgsi_default_dst_register_ext_modulate(); + dst_register_ext_modulate.Modulate = modulate; + + prev_token->Extended = 1; + instruction_grow( instruction, header ); + + return dst_register_ext_modulate; +} + diff --git a/src/mesa/pipe/tgsi/core/tgsi_build.h b/src/mesa/pipe/tgsi/core/tgsi_build.h new file mode 100644 index 00000000000..db259565193 --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_build.h @@ -0,0 +1,309 @@ +#if !defined TGSI_BUILD_H +#define TGSI_BUILD_H + +#if defined __cplusplus +extern "C" { +#endif // defined __cplusplus + +/* + * version + */ + +struct tgsi_version +tgsi_build_version( void ); + +/* + * header + */ + +struct tgsi_header +tgsi_build_header( void ); + +struct tgsi_processor +tgsi_default_processor( void ); + +struct tgsi_processor +tgsi_build_processor( + GLuint processor, + struct tgsi_header *header ); + +/* + * declaration + */ + +struct tgsi_declaration +tgsi_default_declaration( void ); + +struct tgsi_declaration +tgsi_build_declaration( + GLuint file, + GLuint declare, + GLuint interpolate, + struct tgsi_header *header ); + +struct tgsi_full_declaration +tgsi_default_full_declaration( void ); + +GLuint +tgsi_build_full_declaration( + const struct tgsi_full_declaration *full_decl, + struct tgsi_token *tokens, + struct tgsi_header *header, + GLuint maxsize ); + +struct tgsi_declaration_range +tgsi_build_declaration_range( + GLuint first, + GLuint last, + struct tgsi_declaration *declaration, + struct tgsi_header *header ); + +struct tgsi_declaration_mask +tgsi_build_declaration_mask( + GLuint mask, + struct tgsi_declaration *declaration, + struct tgsi_header *header ); + +struct tgsi_declaration_interpolation +tgsi_default_declaration_interpolation( void ); + +struct tgsi_declaration_interpolation +tgsi_build_declaration_interpolation( + GLuint interpolate, + struct tgsi_declaration *declaration, + struct tgsi_header *header ); + +/* + * immediate + */ + +struct tgsi_immediate +tgsi_default_immediate( void ); + +struct tgsi_immediate +tgsi_build_immediate( + struct tgsi_header *header ); + +struct tgsi_full_immediate +tgsi_default_full_immediate( void ); + +struct tgsi_immediate_float32 +tgsi_build_immediate_float32( + GLfloat value, + struct tgsi_immediate *immediate, + struct tgsi_header *header ); + +GLuint +tgsi_build_full_immediate( + const struct tgsi_full_immediate *full_imm, + struct tgsi_token *tokens, + struct tgsi_header *header, + GLuint maxsize ); + +/* + * instruction + */ + +struct tgsi_instruction +tgsi_default_instruction( void ); + +struct tgsi_instruction +tgsi_build_instruction( + GLuint opcode, + GLuint saturate, + GLuint num_dst_regs, + GLuint num_src_regs, + struct tgsi_header *header ); + +struct tgsi_full_instruction +tgsi_default_full_instruction( void ); + +GLuint +tgsi_build_full_instruction( + const struct tgsi_full_instruction *full_inst, + struct tgsi_token *tokens, + struct tgsi_header *header, + GLuint maxsize ); + +struct tgsi_instruction_ext_nv +tgsi_default_instruction_ext_nv( void ); + +GLuint +tgsi_compare_instruction_ext_nv( + struct tgsi_instruction_ext_nv a, + struct tgsi_instruction_ext_nv b ); + +struct tgsi_instruction_ext_nv +tgsi_build_instruction_ext_nv( + GLuint precision, + GLuint cond_dst_index, + GLuint cond_flow_index, + GLuint cond_mask, + GLuint cond_swizzle_x, + GLuint cond_swizzle_y, + GLuint cond_swizzle_z, + GLuint cond_swizzle_w, + GLuint cond_dst_update, + GLuint cond_flow_update, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_instruction_ext_label +tgsi_default_instruction_ext_label( void ); + +GLuint +tgsi_compare_instruction_ext_label( + struct tgsi_instruction_ext_label a, + struct tgsi_instruction_ext_label b ); + +struct tgsi_instruction_ext_label +tgsi_build_instruction_ext_label( + GLuint label, + GLuint target, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_instruction_ext_texture +tgsi_default_instruction_ext_texture( void ); + +GLuint +tgsi_compare_instruction_ext_texture( + struct tgsi_instruction_ext_texture a, + struct tgsi_instruction_ext_texture b ); + +struct tgsi_instruction_ext_texture +tgsi_build_instruction_ext_texture( + GLuint texture, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_src_register +tgsi_default_src_register( void ); + +struct tgsi_src_register +tgsi_build_src_register( + GLuint file, + GLuint swizzle_x, + GLuint swizzle_y, + GLuint swizzle_z, + GLuint swizzle_w, + GLuint negate, + GLuint indirect, + GLuint dimension, + GLint index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_full_src_register +tgsi_default_full_src_register( void ); + +struct tgsi_src_register_ext_swz +tgsi_default_src_register_ext_swz( void ); + +GLuint +tgsi_compare_src_register_ext_swz( + struct tgsi_src_register_ext_swz a, + struct tgsi_src_register_ext_swz b ); + +struct tgsi_src_register_ext_swz +tgsi_build_src_register_ext_swz( + GLuint ext_swizzle_x, + GLuint ext_swizzle_y, + GLuint ext_swizzle_z, + GLuint ext_swizzle_w, + GLuint negate_x, + GLuint negate_y, + GLuint negate_z, + GLuint negate_w, + GLuint ext_divide, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_src_register_ext_mod +tgsi_default_src_register_ext_mod( void ); + +GLuint +tgsi_compare_src_register_ext_mod( + struct tgsi_src_register_ext_mod a, + struct tgsi_src_register_ext_mod b ); + +struct tgsi_src_register_ext_mod +tgsi_build_src_register_ext_mod( + GLuint complement, + GLuint bias, + GLuint scale_2x, + GLuint absolute, + GLuint negate, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_dimension +tgsi_default_dimension( void ); + +struct tgsi_dimension +tgsi_build_dimension( + GLuint indirect, + GLuint index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_dst_register +tgsi_default_dst_register( void ); + +struct tgsi_dst_register +tgsi_build_dst_register( + GLuint file, + GLuint mask, + GLint index, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_full_dst_register +tgsi_default_full_dst_register( void ); + +struct tgsi_dst_register_ext_concode +tgsi_default_dst_register_ext_concode( void ); + +GLuint +tgsi_compare_dst_register_ext_concode( + struct tgsi_dst_register_ext_concode a, + struct tgsi_dst_register_ext_concode b ); + +struct tgsi_dst_register_ext_concode +tgsi_build_dst_register_ext_concode( + GLuint cc, + GLuint swizzle_x, + GLuint swizzle_y, + GLuint swizzle_z, + GLuint swizzle_w, + GLint index, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +struct tgsi_dst_register_ext_modulate +tgsi_default_dst_register_ext_modulate( void ); + +GLuint +tgsi_compare_dst_register_ext_modulate( + struct tgsi_dst_register_ext_modulate a, + struct tgsi_dst_register_ext_modulate b ); + +struct tgsi_dst_register_ext_modulate +tgsi_build_dst_register_ext_modulate( + GLuint modulate, + struct tgsi_token *prev_token, + struct tgsi_instruction *instruction, + struct tgsi_header *header ); + +#if defined __cplusplus +} // extern "C" +#endif // defined __cplusplus + +#endif // !defined TGSI_BUILD_H + diff --git a/src/mesa/pipe/tgsi/core/tgsi_core.h b/src/mesa/pipe/tgsi/core/tgsi_core.h new file mode 100644 index 00000000000..1f5f00a38ea --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_core.h @@ -0,0 +1,12 @@ +#if !defined TGSI_CORE_H +#define TGSI_CORE_H + +#include "tgsi_token.h" +#include "tgsi_parse.h" +#include "tgsi_build.h" +#include "tgsi_exec.h" +#include "tgsi_dump.h" +#include "tgsi_util.h" + +#endif // !defined TGSI_CORE_H + diff --git a/src/mesa/pipe/tgsi/core/tgsi_dump.c b/src/mesa/pipe/tgsi/core/tgsi_dump.c new file mode 100644 index 00000000000..33a898ea042 --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_dump.c @@ -0,0 +1,881 @@ +#include "tgsi_platform.h" +#include "tgsi_core.h" + +struct text_dump +{ + FILE *file; + GLuint tabs; +}; + +static void +text_dump_write( + struct text_dump *dump, + const void *buffer, + GLuint size ) +{ + fwrite( buffer, size, 1, dump->file ); +} + +static void +text_dump_str( + struct text_dump *dump, + const char *str ) +{ + GLuint i; + GLuint len = strlen( str ); + + for( i = 0; i < len; i++ ) { + text_dump_write( dump, &str[i], 1 ); + + if( str[i] == '\n' ) { + GLuint i; + + for( i = 0; i < dump->tabs; i++ ) { + text_dump_write( dump, " ", 4 ); + } + } + } +} + +static void +text_dump_chr( + struct text_dump *dump, + const char chr ) +{ + char str[2]; + + str[0] = chr; + str[1] = '\0'; + text_dump_str( dump, str ); +} + +static void +text_dump_uix( + struct text_dump *dump, + const GLuint ui) +{ + char str[36]; + + sprintf( str, "0x%x", ui ); + text_dump_str( dump, str ); +} + +static void +text_dump_uid( + struct text_dump *dump, + const GLuint ui ) +{ + char str[16]; + + sprintf( str, "%u", ui ); + text_dump_str( dump, str ); +} + +static void +text_dump_sid( + struct text_dump *dump, + const GLint si ) +{ + char str[16]; + + sprintf( str, "%d", si ); + text_dump_str( dump, str ); +} + +static void +text_dump_flt( + struct text_dump *dump, + const GLfloat f ) +{ + char str[48]; + + sprintf( str, "%40.6f", f ); + text_dump_str( dump, str ); +} + +static void +text_dump_enum( + struct text_dump *dump, + const GLuint e, + const char **enums, + const GLuint enums_count ) +{ + if( e >= enums_count ) { + text_dump_uid( dump, e ); + } + else { + text_dump_str( dump, enums[e] ); + } +} + +static void +text_dump_tab( + struct text_dump *dump ) +{ + dump->tabs++; +} + +static void +text_dump_untab( + struct text_dump *dump ) +{ + assert( dump->tabs > 0 ); + + --dump->tabs; +} + +#define TXT(S) text_dump_str( &dump, S ) +#define CHR(C) text_dump_chr( &dump, C ) +#define UIX(I) text_dump_uix( &dump, I ) +#define UID(I) text_dump_uid( &dump, I ) +#define SID(I) text_dump_sid( &dump, I ) +#define FLT(F) text_dump_flt( &dump, F ) +#define TAB() text_dump_tab( &dump ) +#define UNT() text_dump_untab( &dump ) +#define ENM(E,ENUMS) text_dump_enum( &dump, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) + +static const char *TGSI_PROCESSOR_TYPES[] = +{ + "PROCESSOR_FRAGMENT", + "PROCESSOR_VERTEX" +}; + +static const char *TGSI_TOKEN_TYPES[] = +{ + "TOKEN_TYPE_DECLARATION", + "TOKEN_TYPE_IMMEDIATE", + "TOKEN_TYPE_INSTRUCTION" +}; + +static const char *TGSI_FILES[] = +{ + "FILE_NULL", + "FILE_CONSTANT", + "FILE_INPUT", + "FILE_OUTPUT", + "FILE_TEMPORARY", + "FILE_SAMPLER", + "FILE_ADDRESS", + "FILE_IMMEDIATE" +}; + +static const char *TGSI_DECLARES[] = +{ + "DECLARE_RANGE", + "DECLARE_MASK" +}; + +static const char *TGSI_INTERPOLATES[] = +{ + "INTERPOLATE_CONSTANT", + "INTERPOLATE_LINEAR", + "INTERPOLATE_PERSPECTIVE" +}; + +static const char *TGSI_IMMS[] = +{ + "IMM_FLOAT32" +}; + +static const char *TGSI_OPCODES[] = +{ + "OPCODE_ARL", + "OPCODE_MOV", + "OPCODE_LIT", + "OPCODE_RCP", + "OPCODE_RSQ", + "OPCODE_EXP", + "OPCODE_LOG", + "OPCODE_MUL", + "OPCODE_ADD", + "OPCODE_DP3", + "OPCODE_DP4", + "OPCODE_DST", + "OPCODE_MIN", + "OPCODE_MAX", + "OPCODE_SLT", + "OPCODE_SGE", + "OPCODE_MAD", + "OPCODE_SUB", + "OPCODE_LERP", + "OPCODE_CND", + "OPCODE_CND0", + "OPCODE_DOT2ADD", + "OPCODE_INDEX", + "OPCODE_NEGATE", + "OPCODE_FRAC", + "OPCODE_CLAMP", + "OPCODE_FLOOR", + "OPCODE_ROUND", + "OPCODE_EXPBASE2", + "OPCODE_LOGBASE2", + "OPCODE_POWER", + "OPCODE_CROSSPRODUCT", + "OPCODE_MULTIPLYMATRIX", + "OPCODE_ABS", + "OPCODE_RCC", + "OPCODE_DPH", + "OPCODE_COS", + "OPCODE_DDX", + "OPCODE_DDY", + "OPCODE_KIL", + "OPCODE_PK2H", + "OPCODE_PK2US", + "OPCODE_PK4B", + "OPCODE_PK4UB", + "OPCODE_RFL", + "OPCODE_SEQ", + "OPCODE_SFL", + "OPCODE_SGT", + "OPCODE_SIN", + "OPCODE_SLE", + "OPCODE_SNE", + "OPCODE_STR", + "OPCODE_TEX", + "OPCODE_TXD", + "OPCODE_UP2H", + "OPCODE_UP2US", + "OPCODE_UP4B", + "OPCODE_UP4UB", + "OPCODE_X2D", + "OPCODE_ARA", + "OPCODE_ARR", + "OPCODE_BRA", + "OPCODE_CAL", + "OPCODE_RET", + "OPCODE_SSG", + "OPCODE_CMP", + "OPCODE_SCS", + "OPCODE_TXB", + "OPCODE_NRM", + "OPCODE_DIV", + "OPCODE_DP2", + "OPCODE_TXL", + "OPCODE_BRK", + "OPCODE_IF", + "OPCODE_LOOP", + "OPCODE_REP", + "OPCODE_ELSE", + "OPCODE_ENDIF", + "OPCODE_ENDLOOP", + "OPCODE_ENDREP", + "OPCODE_PUSHA", + "OPCODE_POPA", + "OPCODE_CEIL", + "OPCODE_I2F", + "OPCODE_NOT", + "OPCODE_TRUNC", + "OPCODE_SHL", + "OPCODE_SHR", + "OPCODE_AND", + "OPCODE_OR", + "OPCODE_MOD", + "OPCODE_XOR", + "OPCODE_SAD", + "OPCODE_TXF", + "OPCODE_TXQ", + "OPCODE_CONT", + "OPCODE_EMIT", + "OPCODE_ENDPRIM" +}; + +static const char *TGSI_SATS[] = +{ + "SAT_NONE", + "SAT_ZERO_ONE", + "SAT_MINUS_PLUS_ONE" +}; + +static const char *TGSI_INSTRUCTION_EXTS[] = +{ + "INSTRUCTION_EXT_TYPE_NV", + "INSTRUCTION_EXT_TYPE_LABEL", + "INSTRUCTION_EXT_TYPE_TEXTURE" +}; + +static const char *TGSI_PRECISIONS[] = +{ + "PRECISION_DEFAULT", + "TGSI_PRECISION_FLOAT32", + "TGSI_PRECISION_FLOAT16", + "TGSI_PRECISION_FIXED12" +}; + +static const char *TGSI_CCS[] = +{ + "CC_GT", + "CC_EQ", + "CC_LT", + "CC_UN", + "CC_GE", + "CC_LE", + "CC_NE", + "CC_TR", + "CC_FL" +}; + +static const char *TGSI_SWIZZLES[] = +{ + "SWIZZLE_X", + "SWIZZLE_Y", + "SWIZZLE_Z", + "SWIZZLE_W" +}; + +static const char *TGSI_TEXTURES[] = +{ + "TEXTURE_UNKNOWN", + "TEXTURE_1D", + "TEXTURE_2D", + "TEXTURE_3D", + "TEXTURE_CUBE", + "TEXTURE_RECT", + "TEXTURE_SHADOW1D", + "TEXTURE_SHADOW2D", + "TEXTURE_SHADOWRECT" +}; + +static const char *TGSI_SRC_REGISTER_EXTS[] = +{ + "SRC_REGISTER_EXT_TYPE_SWZ", + "SRC_REGISTER_EXT_TYPE_MOD" +}; + +static const char *TGSI_EXTSWIZZLES[] = +{ + "EXTSWIZZLE_X", + "EXTSWIZZLE_Y", + "EXTSWIZZLE_Z", + "EXTSWIZZLE_W", + "EXTSWIZZLE_ZERO", + "EXTSWIZZLE_ONE" +}; + +static const char *TGSI_WRITEMASKS[] = +{ + "0", + "WRITEMASK_X", + "WRITEMASK_Y", + "WRITEMASK_XY", + "WRITEMASK_Z", + "WRITEMASK_XZ", + "WRITEMASK_YZ", + "WRITEMASK_XYZ", + "WRITEMASK_W", + "WRITEMASK_XW", + "WRITEMASK_YW", + "WRITEMASK_XYW", + "WRITEMASK_ZW", + "WRITEMASK_XZW", + "WRITEMASK_YZW", + "WRITEMASK_XYZW" +}; + +static const char *TGSI_DST_REGISTER_EXTS[] = +{ + "DST_REGISTER_EXT_TYPE_CONDCODE", + "DST_REGISTER_EXT_TYPE_MODULATE" +}; + +static const char *TGSI_MODULATES[] = +{ + "MODULATE_1X", + "MODULATE_2X", + "MODULATE_4X", + "MODULATE_8X", + "MODULATE_HALF", + "MODULATE_QUARTER", + "MODULATE_EIGHTH" +}; + +void +tgsi_dump( + const struct tgsi_token *tokens, + GLuint flags ) +{ + struct text_dump dump; + struct tgsi_parse_context parse; + struct tgsi_full_instruction fi; + struct tgsi_full_declaration fd; + GLuint ignored = !(flags & TGSI_DUMP_NO_IGNORED); + GLuint deflt = !(flags & TGSI_DUMP_NO_DEFAULT); + + { +#if 0 + static GLuint counter = 0; + char buffer[64]; + + sprintf( buffer, "tgsi-dump-%.4u.txt", counter++ ); + dump.file = fopen( buffer, "wt" ); +#else + dump.file = stderr; + dump.tabs = 0; +#endif + } + + /* sanity check */ + assert(strcmp(TGSI_OPCODES[TGSI_OPCODE_CONT], "OPCODE_CONT") == 0); + + tgsi_parse_init( &parse, tokens ); + + TXT( "tgsi-dump begin" ); + + CHR( '\n' ); + TXT( "\nMajorVersion: " ); + UID( parse.FullVersion.Version.MajorVersion ); + TXT( "\nMinorVersion: " ); + UID( parse.FullVersion.Version.MinorVersion ); + + CHR( '\n' ); + TXT( "\nHeaderSize: " ); + UID( parse.FullHeader.Header.HeaderSize ); + TXT( "\nBodySize : " ); + UID( parse.FullHeader.Header.BodySize ); + TXT( "\nProcessor : " ); + ENM( parse.FullHeader.Processor.Processor, TGSI_PROCESSOR_TYPES ); + + fi = tgsi_default_full_instruction(); + fd = tgsi_default_full_declaration(); + + while( !tgsi_parse_end_of_tokens( &parse ) ) { + GLuint i; + + tgsi_parse_token( &parse ); + + CHR( '\n' ); + TXT( "\nType : " ); + ENM( parse.FullToken.Token.Type, TGSI_TOKEN_TYPES ); + if( ignored ) { + TXT( "\nSize : " ); + UID( parse.FullToken.Token.Size ); + if( deflt || parse.FullToken.Token.Extended ) { + TXT( "\nExtended : " ); + UID( parse.FullToken.Token.Extended ); + } + } + + switch( parse.FullToken.Token.Type ) { + case TGSI_TOKEN_TYPE_DECLARATION: + { + struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration; + + TXT( "\nFile : " ); + ENM( decl->Declaration.File, TGSI_FILES ); + TXT( "\nDeclare : " ); + ENM( decl->Declaration.Declare, TGSI_DECLARES ); + if( deflt || fd.Declaration.Interpolate != decl->Declaration.Interpolate ) { + TXT( "\nInterpolate: " ); + UID( decl->Declaration.Interpolate ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( decl->Declaration.Padding ); + } + + CHR( '\n' ); + switch( decl->Declaration.Declare ) { + case TGSI_DECLARE_RANGE: + TXT( "\nFirst: " ); + UID( decl->u.DeclarationRange.First ); + TXT( "\nLast : " ); + UID( decl->u.DeclarationRange.Last ); + break; + + case TGSI_DECLARE_MASK: + TXT( "\nMask: " ); + UIX( decl->u.DeclarationMask.Mask ); + break; + + default: + assert( 0 ); + } + + if( decl->Declaration.Interpolate ) { + CHR( '\n' ); + TXT( "\nInterpolate: " ); + ENM( decl->Interpolation.Interpolate, TGSI_INTERPOLATES ); + if( ignored ) { + TXT( "\nPadding : " ); + UIX( decl->Interpolation.Padding ); + } + } + } + break; + + case TGSI_TOKEN_TYPE_IMMEDIATE: + TXT( "\nDataType : " ); + ENM( parse.FullToken.FullImmediate.Immediate.DataType, TGSI_IMMS ); + if( ignored ) { + TXT( "\nPadding : " ); + UIX( parse.FullToken.FullImmediate.Immediate.Padding ); + } + + for( i = 0; i < parse.FullToken.FullImmediate.Immediate.Size - 1; i++ ) { + CHR( '\n' ); + switch( parse.FullToken.FullImmediate.Immediate.DataType ) { + case TGSI_IMM_FLOAT32: + TXT( "\nFloat: " ); + FLT( parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float ); + break; + + default: + assert( 0 ); + } + } + break; + + case TGSI_TOKEN_TYPE_INSTRUCTION: + { + struct tgsi_full_instruction *inst = &parse.FullToken.FullInstruction; + + TXT( "\nOpcode : " ); + ENM( inst->Instruction.Opcode, TGSI_OPCODES ); + if( deflt || fi.Instruction.Saturate != inst->Instruction.Saturate ) { + TXT( "\nSaturate : " ); + ENM( inst->Instruction.Saturate, TGSI_SATS ); + } + if( deflt || fi.Instruction.NumDstRegs != inst->Instruction.NumDstRegs ) { + TXT( "\nNumDstRegs : " ); + UID( inst->Instruction.NumDstRegs ); + } + if( deflt || fi.Instruction.NumSrcRegs != inst->Instruction.NumSrcRegs ) { + TXT( "\nNumSrcRegs : " ); + UID( inst->Instruction.NumSrcRegs ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( inst->Instruction.Padding ); + } + + if( deflt || tgsi_compare_instruction_ext_nv( inst->InstructionExtNv, fi.InstructionExtNv)) { + CHR( '\n' ); + TXT( "\nType : " ); + ENM( inst->InstructionExtNv.Type, TGSI_INSTRUCTION_EXTS ); + if( deflt || fi.InstructionExtNv.Precision != inst->InstructionExtNv.Precision ) { + TXT( "\nPrecision : " ); + ENM( inst->InstructionExtNv.Precision, TGSI_PRECISIONS ); + } + if( deflt || fi.InstructionExtNv.CondDstIndex != inst->InstructionExtNv.CondDstIndex ) { + TXT( "\nCondDstIndex : " ); + UID( inst->InstructionExtNv.CondDstIndex ); + } + if( deflt || fi.InstructionExtNv.CondFlowIndex != inst->InstructionExtNv.CondFlowIndex ) { + TXT( "\nCondFlowIndex : " ); + UID( inst->InstructionExtNv.CondFlowIndex ); + } + if( deflt || fi.InstructionExtNv.CondMask != inst->InstructionExtNv.CondMask ) { + TXT( "\nCondMask : " ); + ENM( inst->InstructionExtNv.CondMask, TGSI_CCS ); + } + if( deflt || fi.InstructionExtNv.CondSwizzleX != inst->InstructionExtNv.CondSwizzleX ) { + TXT( "\nCondSwizzleX : " ); + ENM( inst->InstructionExtNv.CondSwizzleX, TGSI_SWIZZLES ); + } + if( deflt || fi.InstructionExtNv.CondSwizzleY != inst->InstructionExtNv.CondSwizzleY ) { + TXT( "\nCondSwizzleY : " ); + ENM( inst->InstructionExtNv.CondSwizzleY, TGSI_SWIZZLES ); + } + if( deflt || fi.InstructionExtNv.CondSwizzleZ != inst->InstructionExtNv.CondSwizzleZ ) { + TXT( "\nCondSwizzleZ : " ); + ENM( inst->InstructionExtNv.CondSwizzleZ, TGSI_SWIZZLES ); + } + if( deflt || fi.InstructionExtNv.CondSwizzleW != inst->InstructionExtNv.CondSwizzleW ) { + TXT( "\nCondSwizzleW : " ); + ENM( inst->InstructionExtNv.CondSwizzleW, TGSI_SWIZZLES ); + } + if( deflt || fi.InstructionExtNv.CondDstUpdate != inst->InstructionExtNv.CondDstUpdate ) { + TXT( "\nCondDstUpdate : " ); + UID( inst->InstructionExtNv.CondDstUpdate ); + } + if( deflt || fi.InstructionExtNv.CondFlowEnable != inst->InstructionExtNv.CondFlowEnable ) { + TXT( "\nCondFlowEnable: " ); + UID( inst->InstructionExtNv.CondFlowEnable ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( inst->InstructionExtNv.Padding ); + if( deflt || fi.InstructionExtNv.Extended != inst->InstructionExtNv.Extended ) { + TXT( "\nExtended : " ); + UID( inst->InstructionExtNv.Extended ); + } + } + } + + if( deflt || tgsi_compare_instruction_ext_label( inst->InstructionExtLabel, fi.InstructionExtLabel ) ) { + CHR( '\n' ); + TXT( "\nType : " ); + ENM( inst->InstructionExtLabel.Type, TGSI_INSTRUCTION_EXTS ); + if( deflt || fi.InstructionExtLabel.Label != inst->InstructionExtLabel.Label ) { + TXT( "\nLabel : " ); + UID( inst->InstructionExtLabel.Label ); + } + if( deflt || fi.InstructionExtLabel.Target != inst->InstructionExtLabel.Target ) { + TXT( "\nTarget : " ); + UID( inst->InstructionExtLabel.Target ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( inst->InstructionExtLabel.Padding ); + if( deflt || fi.InstructionExtLabel.Extended != inst->InstructionExtLabel.Extended ) { + TXT( "\nExtended: " ); + UID( inst->InstructionExtLabel.Extended ); + } + } + } + + if( deflt || tgsi_compare_instruction_ext_texture( inst->InstructionExtTexture, fi.InstructionExtTexture ) ) { + CHR( '\n' ); + TXT( "\nType : " ); + ENM( inst->InstructionExtTexture.Type, TGSI_INSTRUCTION_EXTS ); + if( deflt || fi.InstructionExtTexture.Texture != inst->InstructionExtTexture.Texture ) { + TXT( "\nTexture : " ); + ENM( inst->InstructionExtTexture.Texture, TGSI_TEXTURES ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( inst->InstructionExtTexture.Padding ); + if( deflt || fi.InstructionExtTexture.Extended != inst->InstructionExtTexture.Extended ) { + TXT( "\nExtended: " ); + UID( inst->InstructionExtTexture.Extended ); + } + } + } + + for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) { + struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i]; + struct tgsi_full_dst_register *fd = &fi.FullDstRegisters[i]; + + CHR( '\n' ); + TXT( "\nFile : " ); + ENM( dst->DstRegister.File, TGSI_FILES ); + if( deflt || fd->DstRegister.WriteMask != dst->DstRegister.WriteMask ) { + TXT( "\nWriteMask: " ); + ENM( dst->DstRegister.WriteMask, TGSI_WRITEMASKS ); + } + if( ignored ) { + if( deflt || fd->DstRegister.Indirect != dst->DstRegister.Indirect ) { + TXT( "\nIndirect : " ); + UID( dst->DstRegister.Indirect ); + } + if( deflt || fd->DstRegister.Dimension != dst->DstRegister.Dimension ) { + TXT( "\nDimension: " ); + UID( dst->DstRegister.Dimension ); + } + } + if( deflt || fd->DstRegister.Index != dst->DstRegister.Index ) { + TXT( "\nIndex : " ); + SID( dst->DstRegister.Index ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( dst->DstRegister.Padding ); + if( deflt || fd->DstRegister.Extended != dst->DstRegister.Extended ) { + TXT( "\nExtended : " ); + UID( dst->DstRegister.Extended ); + } + } + + if( deflt || tgsi_compare_dst_register_ext_concode( dst->DstRegisterExtConcode, fd->DstRegisterExtConcode ) ) { + CHR( '\n' ); + TXT( "\nType : " ); + ENM( dst->DstRegisterExtConcode.Type, TGSI_DST_REGISTER_EXTS ); + if( deflt || fd->DstRegisterExtConcode.CondMask != dst->DstRegisterExtConcode.CondMask ) { + TXT( "\nCondMask : " ); + ENM( dst->DstRegisterExtConcode.CondMask, TGSI_CCS ); + } + if( deflt || fd->DstRegisterExtConcode.CondSwizzleX != dst->DstRegisterExtConcode.CondSwizzleX ) { + TXT( "\nCondSwizzleX: " ); + ENM( dst->DstRegisterExtConcode.CondSwizzleX, TGSI_SWIZZLES ); + } + if( deflt || fd->DstRegisterExtConcode.CondSwizzleY != dst->DstRegisterExtConcode.CondSwizzleY ) { + TXT( "\nCondSwizzleY: " ); + ENM( dst->DstRegisterExtConcode.CondSwizzleY, TGSI_SWIZZLES ); + } + if( deflt || fd->DstRegisterExtConcode.CondSwizzleZ != dst->DstRegisterExtConcode.CondSwizzleZ ) { + TXT( "\nCondSwizzleZ: " ); + ENM( dst->DstRegisterExtConcode.CondSwizzleZ, TGSI_SWIZZLES ); + } + if( deflt || fd->DstRegisterExtConcode.CondSwizzleW != dst->DstRegisterExtConcode.CondSwizzleW ) { + TXT( "\nCondSwizzleW: " ); + ENM( dst->DstRegisterExtConcode.CondSwizzleW, TGSI_SWIZZLES ); + } + if( deflt || fd->DstRegisterExtConcode.CondSrcIndex != dst->DstRegisterExtConcode.CondSrcIndex ) { + TXT( "\nCondSrcIndex: " ); + UID( dst->DstRegisterExtConcode.CondSrcIndex ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( dst->DstRegisterExtConcode.Padding ); + if( deflt || fd->DstRegisterExtConcode.Extended != dst->DstRegisterExtConcode.Extended ) { + TXT( "\nExtended : " ); + UID( dst->DstRegisterExtConcode.Extended ); + } + } + } + + if( deflt || tgsi_compare_dst_register_ext_modulate( dst->DstRegisterExtModulate, fd->DstRegisterExtModulate ) ) { + CHR( '\n' ); + TXT( "\nType : " ); + ENM( dst->DstRegisterExtModulate.Type, TGSI_DST_REGISTER_EXTS ); + if( deflt || fd->DstRegisterExtModulate.Modulate != dst->DstRegisterExtModulate.Modulate ) { + TXT( "\nModulate: " ); + ENM( dst->DstRegisterExtModulate.Modulate, TGSI_MODULATES ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( dst->DstRegisterExtModulate.Padding ); + if( deflt || fd->DstRegisterExtModulate.Extended != dst->DstRegisterExtModulate.Extended ) { + TXT( "\nExtended: " ); + UID( dst->DstRegisterExtModulate.Extended ); + } + } + } + } + + for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) { + struct tgsi_full_src_register *src = &inst->FullSrcRegisters[i]; + struct tgsi_full_src_register *fs = &fi.FullSrcRegisters[i]; + + CHR( '\n' ); + TXT( "\nFile : "); + ENM( src->SrcRegister.File, TGSI_FILES ); + if( deflt || fs->SrcRegister.SwizzleX != src->SrcRegister.SwizzleX ) { + TXT( "\nSwizzleX : " ); + ENM( src->SrcRegister.SwizzleX, TGSI_SWIZZLES ); + } + if( deflt || fs->SrcRegister.SwizzleY != src->SrcRegister.SwizzleY ) { + TXT( "\nSwizzleY : " ); + ENM( src->SrcRegister.SwizzleY, TGSI_SWIZZLES ); + } + if( deflt || fs->SrcRegister.SwizzleZ != src->SrcRegister.SwizzleZ ) { + TXT( "\nSwizzleZ : " ); + ENM( src->SrcRegister.SwizzleZ, TGSI_SWIZZLES ); + } + if( deflt || fs->SrcRegister.SwizzleW != src->SrcRegister.SwizzleW ) { + TXT( "\nSwizzleW : " ); + ENM( src->SrcRegister.SwizzleW, TGSI_SWIZZLES ); + } + if( deflt || fs->SrcRegister.Negate != src->SrcRegister.Negate ) { + TXT( "\nNegate : " ); + UID( src->SrcRegister.Negate ); + } + if( ignored ) { + if( deflt || fs->SrcRegister.Indirect != src->SrcRegister.Indirect ) { + TXT( "\nIndirect : " ); + UID( src->SrcRegister.Indirect ); + } + if( deflt || fs->SrcRegister.Dimension != src->SrcRegister.Dimension ) { + TXT( "\nDimension: " ); + UID( src->SrcRegister.Dimension ); + } + } + if( deflt || fs->SrcRegister.Index != src->SrcRegister.Index ) { + TXT( "\nIndex : " ); + SID( src->SrcRegister.Index ); + } + if( ignored ) { + if( deflt || fs->SrcRegister.Extended != src->SrcRegister.Extended ) { + TXT( "\nExtended : " ); + UID( src->SrcRegister.Extended ); + } + } + + if( deflt || tgsi_compare_src_register_ext_swz( src->SrcRegisterExtSwz, fs->SrcRegisterExtSwz ) ) { + CHR( '\n' ); + TXT( "\nType : " ); + ENM( src->SrcRegisterExtSwz.Type, TGSI_SRC_REGISTER_EXTS ); + if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleX != src->SrcRegisterExtSwz.ExtSwizzleX ) { + TXT( "\nExtSwizzleX: " ); + ENM( src->SrcRegisterExtSwz.ExtSwizzleX, TGSI_EXTSWIZZLES ); + } + if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleY != src->SrcRegisterExtSwz.ExtSwizzleY ) { + TXT( "\nExtSwizzleY: " ); + ENM( src->SrcRegisterExtSwz.ExtSwizzleY, TGSI_EXTSWIZZLES ); + } + if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleZ != src->SrcRegisterExtSwz.ExtSwizzleZ ) { + TXT( "\nExtSwizzleZ: " ); + ENM( src->SrcRegisterExtSwz.ExtSwizzleZ, TGSI_EXTSWIZZLES ); + } + if( deflt || fs->SrcRegisterExtSwz.ExtSwizzleW != src->SrcRegisterExtSwz.ExtSwizzleW ) { + TXT( "\nExtSwizzleW: " ); + ENM( src->SrcRegisterExtSwz.ExtSwizzleW, TGSI_EXTSWIZZLES ); + } + if( deflt || fs->SrcRegisterExtSwz.NegateX != src->SrcRegisterExtSwz.NegateX ) { + TXT( "\nNegateX : " ); + UID( src->SrcRegisterExtSwz.NegateX ); + } + if( deflt || fs->SrcRegisterExtSwz.NegateY != src->SrcRegisterExtSwz.NegateY ) { + TXT( "\nNegateY : " ); + UID( src->SrcRegisterExtSwz.NegateY ); + } + if( deflt || fs->SrcRegisterExtSwz.NegateZ != src->SrcRegisterExtSwz.NegateZ ) { + TXT( "\nNegateZ : " ); + UID( src->SrcRegisterExtSwz.NegateZ ); + } + if( deflt || fs->SrcRegisterExtSwz.NegateW != src->SrcRegisterExtSwz.NegateW ) { + TXT( "\nNegateW : " ); + UID( src->SrcRegisterExtSwz.NegateW ); + } + if( deflt || fs->SrcRegisterExtSwz.ExtDivide != src->SrcRegisterExtSwz.ExtDivide ) { + TXT( "\nExtDivide : " ); + ENM( src->SrcRegisterExtSwz.ExtDivide, TGSI_EXTSWIZZLES ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( src->SrcRegisterExtSwz.Padding ); + if( deflt || fs->SrcRegisterExtSwz.Extended != src->SrcRegisterExtSwz.Extended ) { + TXT( "\nExtended : " ); + UID( src->SrcRegisterExtSwz.Extended ); + } + } + } + + if( deflt || tgsi_compare_src_register_ext_mod( src->SrcRegisterExtMod, fs->SrcRegisterExtMod ) ) { + CHR( '\n' ); + TXT( "\nType : " ); + ENM( src->SrcRegisterExtMod.Type, TGSI_SRC_REGISTER_EXTS ); + if( deflt || fs->SrcRegisterExtMod.Complement != src->SrcRegisterExtMod.Complement ) { + TXT( "\nComplement: " ); + UID( src->SrcRegisterExtMod.Complement ); + } + if( deflt || fs->SrcRegisterExtMod.Bias != src->SrcRegisterExtMod.Bias ) { + TXT( "\nBias : " ); + UID( src->SrcRegisterExtMod.Bias ); + } + if( deflt || fs->SrcRegisterExtMod.Scale2X != src->SrcRegisterExtMod.Scale2X ) { + TXT( "\nScale2X : " ); + UID( src->SrcRegisterExtMod.Scale2X ); + } + if( deflt || fs->SrcRegisterExtMod.Absolute != src->SrcRegisterExtMod.Absolute ) { + TXT( "\nAbsolute : " ); + UID( src->SrcRegisterExtMod.Absolute ); + } + if( deflt || fs->SrcRegisterExtMod.Negate != src->SrcRegisterExtMod.Negate ) { + TXT( "\nNegate : " ); + UID( src->SrcRegisterExtMod.Negate ); + } + if( ignored ) { + TXT( "\nPadding : " ); + UIX( src->SrcRegisterExtMod.Padding ); + if( deflt || fs->SrcRegisterExtMod.Extended != src->SrcRegisterExtMod.Extended ) { + TXT( "\nExtended : " ); + UID( src->SrcRegisterExtMod.Extended ); + } + } + } + } + } + break; + + default: + assert( 0 ); + } + } + + TXT( "\ntgsi-dump end\n" ); + + tgsi_parse_free( &parse ); + + fclose( dump.file ); +} + diff --git a/src/mesa/pipe/tgsi/core/tgsi_dump.h b/src/mesa/pipe/tgsi/core/tgsi_dump.h new file mode 100644 index 00000000000..dc34a840de6 --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_dump.h @@ -0,0 +1,22 @@ +#if !defined TGSI_DUMP_H +#define TGSI_DUMP_H + +#if defined __cplusplus +extern "C" { +#endif // defined __cplusplus + +#define TGSI_DUMP_VERBOSE 0 +#define TGSI_DUMP_NO_IGNORED 1 +#define TGSI_DUMP_NO_DEFAULT 2 + +void +tgsi_dump( + const struct tgsi_token *tokens, + GLuint flags ); + +#if defined __cplusplus +} // extern "C" +#endif // defined __cplusplus + +#endif // !defined TGSI_DUMP_H + diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.c b/src/mesa/pipe/tgsi/core/tgsi_exec.c new file mode 100644 index 00000000000..6aaaef98a83 --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.c @@ -0,0 +1,2249 @@ +#include "tgsi_platform.h" +#include "tgsi_core.h" + +#define MESA 1 +#if MESA +#include "main/context.h" +#include "main/macros.h" +#include "main/colormac.h" +#include "swrast/swrast.h" +#include "swrast/s_context.h" +#endif + +#define TILE_BOTTOM_LEFT 0 +#define TILE_BOTTOM_RIGHT 1 +#define TILE_TOP_LEFT 2 +#define TILE_TOP_RIGHT 3 + +#define TEMP_0_I TGSI_EXEC_TEMP_00000000_I +#define TEMP_0_C TGSI_EXEC_TEMP_00000000_C +#define TEMP_7F_I TGSI_EXEC_TEMP_7FFFFFFF_I +#define TEMP_7F_C TGSI_EXEC_TEMP_7FFFFFFF_C +#define TEMP_80_I TGSI_EXEC_TEMP_80000000_I +#define TEMP_80_C TGSI_EXEC_TEMP_80000000_C +#define TEMP_FF_I TGSI_EXEC_TEMP_FFFFFFFF_I +#define TEMP_FF_C TGSI_EXEC_TEMP_FFFFFFFF_C +#define TEMP_1_I TGSI_EXEC_TEMP_ONE_I +#define TEMP_1_C TGSI_EXEC_TEMP_ONE_C +#define TEMP_2_I TGSI_EXEC_TEMP_TWO_I +#define TEMP_2_C TGSI_EXEC_TEMP_TWO_C +#define TEMP_128_I TGSI_EXEC_TEMP_128_I +#define TEMP_128_C TGSI_EXEC_TEMP_128_C +#define TEMP_M128_I TGSI_EXEC_TEMP_MINUS_128_I +#define TEMP_M128_C TGSI_EXEC_TEMP_MINUS_128_C +#define TEMP_KILMASK_I TGSI_EXEC_TEMP_KILMASK_I +#define TEMP_KILMASK_C TGSI_EXEC_TEMP_KILMASK_C +#define TEMP_OUTPUT_I TGSI_EXEC_TEMP_OUTPUT_I +#define TEMP_OUTPUT_C TGSI_EXEC_TEMP_OUTPUT_C +#define TEMP_PRIMITIVE_I TGSI_EXEC_TEMP_PRIMITIVE_I +#define TEMP_PRIMITIVE_C TGSI_EXEC_TEMP_PRIMITIVE_C +#define TEMP_R0 TGSI_EXEC_TEMP_R0 + +#define FOR_EACH_CHANNEL(CHAN)\ + for (CHAN = 0; CHAN < 4; CHAN++) + +#define IS_CHANNEL_ENABLED(INST, CHAN)\ + ((INST).FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN))) + +#define IS_CHANNEL_ENABLED2(INST, CHAN)\ + ((INST).FullDstRegisters[1].DstRegister.WriteMask & (1 << (CHAN))) + +#define FOR_EACH_ENABLED_CHANNEL(INST, CHAN)\ + FOR_EACH_CHANNEL( CHAN )\ + if (IS_CHANNEL_ENABLED( INST, CHAN )) + +#define FOR_EACH_ENABLED_CHANNEL2(INST, CHAN)\ + FOR_EACH_CHANNEL( CHAN )\ + if (IS_CHANNEL_ENABLED2( INST, CHAN )) + +#define CHAN_X 0 +#define CHAN_Y 1 +#define CHAN_Z 2 +#define CHAN_W 3 + +void +tgsi_exec_machine_init( + struct tgsi_exec_machine *mach, + struct tgsi_token *tokens ) +{ + GLuint i, k; + struct tgsi_parse_context parse; + + mach->Tokens = tokens; + + k = tgsi_parse_init (&parse, mach->Tokens); + if (k != TGSI_PARSE_OK) { + printf("Problem parsing!\n"); + return; + } + + mach->Processor = parse.FullHeader.Processor.Processor; + tgsi_parse_free (&parse); + + mach->Temps = (struct tgsi_exec_vector *) tgsi_align_128bit( mach->_Temps); + mach->Addrs = &mach->Temps[TGSI_EXEC_NUM_TEMPS]; + +#if XXX_SSE + tgsi_emit_sse (tokens, + &mach->Function); +#endif + + /* Setup constants. */ + for( i = 0; i < 4; i++ ) { + mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].u[i] = 0x00000000; + mach->Temps[TEMP_7F_I].xyzw[TEMP_7F_C].u[i] = 0x7FFFFFFF; + mach->Temps[TEMP_80_I].xyzw[TEMP_80_C].u[i] = 0x80000000; + mach->Temps[TEMP_FF_I].xyzw[TEMP_FF_C].u[i] = 0xFFFFFFFF; + mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].f[i] = 1.0f; + mach->Temps[TEMP_2_I].xyzw[TEMP_2_C].f[i] = 2.0f; + mach->Temps[TEMP_128_I].xyzw[TEMP_128_C].f[i] = 128.0f; + mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C].f[i] = -128.0f; + } +} + +void +tgsi_exec_prepare( + struct tgsi_exec_machine *mach, + struct tgsi_exec_labels *labels ) +{ + struct tgsi_parse_context parse; + GLuint k; + + mach->ImmLimit = 0; + labels->count = 0; + + k = tgsi_parse_init( &parse, mach->Tokens ); + if (k != TGSI_PARSE_OK) { + printf("Problem parsing!\n"); + return; + } + + while( !tgsi_parse_end_of_tokens( &parse ) ) { + GLuint pointer = parse.Position; + GLuint i; + tgsi_parse_token( &parse ); + switch( parse.FullToken.Token.Type ) { + case TGSI_TOKEN_TYPE_DECLARATION: + break; + case TGSI_TOKEN_TYPE_IMMEDIATE: + assert( (parse.FullToken.FullImmediate.Immediate.Size - 1) % 4 == 0 ); + assert( mach->ImmLimit + (parse.FullToken.FullImmediate.Immediate.Size - 1) / 4 <= 256 ); + for( i = 0; i < parse.FullToken.FullImmediate.Immediate.Size - 1; i++ ) { + mach->Imms[mach->ImmLimit + i / 4][i % 4] = parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float; + } + mach->ImmLimit += (parse.FullToken.FullImmediate.Immediate.Size - 1) / 4; + break; + case TGSI_TOKEN_TYPE_INSTRUCTION: + if( parse.FullToken.FullInstruction.InstructionExtLabel.Label && + parse.FullToken.FullInstruction.InstructionExtLabel.Target ) { + assert( labels->count < 128 ); + labels->labels[labels->count][0] = parse.FullToken.FullInstruction.InstructionExtLabel.Label; + labels->labels[labels->count][1] = pointer; + labels->count++; + } + break; + default: + assert( 0 ); + } + } + tgsi_parse_free (&parse); +} + +void +tgsi_exec_machine_run( + struct tgsi_exec_machine *mach ) +{ + struct tgsi_exec_labels labels; + + tgsi_exec_prepare( mach, &labels ); + tgsi_exec_machine_run2( mach, &labels ); +} + +static void +micro_abs( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) fabs( (GLdouble) src->f[0] ); + dst->f[1] = (GLfloat) fabs( (GLdouble) src->f[1] ); + dst->f[2] = (GLfloat) fabs( (GLdouble) src->f[2] ); + dst->f[3] = (GLfloat) fabs( (GLdouble) src->f[3] ); +} + +static void +micro_add( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->f[0] = src0->f[0] + src1->f[0]; + dst->f[1] = src0->f[1] + src1->f[1]; + dst->f[2] = src0->f[2] + src1->f[2]; + dst->f[3] = src0->f[3] + src1->f[3]; +} + +static void +micro_iadd( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->i[0] = src0->i[0] + src1->i[0]; + dst->i[1] = src0->i[1] + src1->i[1]; + dst->i[2] = src0->i[2] + src1->i[2]; + dst->i[3] = src0->i[3] + src1->i[3]; +} + +static void +micro_and( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] & src1->u[0]; + dst->u[1] = src0->u[1] & src1->u[1]; + dst->u[2] = src0->u[2] & src1->u[2]; + dst->u[3] = src0->u[3] & src1->u[3]; +} + +static void +micro_ceil( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) ceil( (GLdouble) src->f[0] ); + dst->f[1] = (GLfloat) ceil( (GLdouble) src->f[1] ); + dst->f[2] = (GLfloat) ceil( (GLdouble) src->f[2] ); + dst->f[3] = (GLfloat) ceil( (GLdouble) src->f[3] ); +} + +static void +micro_cos( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) cos( (GLdouble) src->f[0] ); + dst->f[1] = (GLfloat) cos( (GLdouble) src->f[1] ); + dst->f[2] = (GLfloat) cos( (GLdouble) src->f[2] ); + dst->f[3] = (GLfloat) cos( (GLdouble) src->f[3] ); +} + +static void +micro_ddx( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = + dst->f[1] = + dst->f[2] = + dst->f[3] = src->f[TILE_BOTTOM_RIGHT] - src->f[TILE_BOTTOM_LEFT]; +} + +static void +micro_ddy( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = + dst->f[1] = + dst->f[2] = + dst->f[3] = src->f[TILE_TOP_LEFT] - src->f[TILE_BOTTOM_LEFT]; +} + +static void +micro_div( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->f[0] = src0->f[0] / src1->f[0]; + dst->f[1] = src0->f[1] / src1->f[1]; + dst->f[2] = src0->f[2] / src1->f[2]; + dst->f[3] = src0->f[3] / src1->f[3]; +} + +static void +micro_udiv( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] / src1->u[0]; + dst->u[1] = src0->u[1] / src1->u[1]; + dst->u[2] = src0->u[2] / src1->u[2]; + dst->u[3] = src0->u[3] / src1->u[3]; +} + +static void +micro_eq( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2, + const union tgsi_exec_channel *src3 ) +{ + dst->f[0] = src0->f[0] == src1->f[0] ? src2->f[0] : src3->f[0]; + dst->f[1] = src0->f[1] == src1->f[1] ? src2->f[1] : src3->f[1]; + dst->f[2] = src0->f[2] == src1->f[2] ? src2->f[2] : src3->f[2]; + dst->f[3] = src0->f[3] == src1->f[3] ? src2->f[3] : src3->f[3]; +} + +static void +micro_ieq( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2, + const union tgsi_exec_channel *src3 ) +{ + dst->i[0] = src0->i[0] == src1->i[0] ? src2->i[0] : src3->i[0]; + dst->i[1] = src0->i[1] == src1->i[1] ? src2->i[1] : src3->i[1]; + dst->i[2] = src0->i[2] == src1->i[2] ? src2->i[2] : src3->i[2]; + dst->i[3] = src0->i[3] == src1->i[3] ? src2->i[3] : src3->i[3]; +} + +static void +micro_exp2( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) pow( 2.0, (GLdouble) src->f[0] ); + dst->f[1] = (GLfloat) pow( 2.0, (GLdouble) src->f[1] ); + dst->f[2] = (GLfloat) pow( 2.0, (GLdouble) src->f[2] ); + dst->f[3] = (GLfloat) pow( 2.0, (GLdouble) src->f[3] ); +} + +static void +micro_f2it( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->i[0] = (GLint) src->f[0]; + dst->i[1] = (GLint) src->f[1]; + dst->i[2] = (GLint) src->f[2]; + dst->i[3] = (GLint) src->f[3]; +} + +static void +micro_f2ut( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->u[0] = (GLuint) src->f[0]; + dst->u[1] = (GLuint) src->f[1]; + dst->u[2] = (GLuint) src->f[2]; + dst->u[3] = (GLuint) src->f[3]; +} + +static void +micro_flr( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) floor( (GLdouble) src->f[0] ); + dst->f[1] = (GLfloat) floor( (GLdouble) src->f[1] ); + dst->f[2] = (GLfloat) floor( (GLdouble) src->f[2] ); + dst->f[3] = (GLfloat) floor( (GLdouble) src->f[3] ); +} + +static void +micro_frc( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = src->f[0] - (GLfloat) floor( (GLdouble) src->f[0] ); + dst->f[1] = src->f[1] - (GLfloat) floor( (GLdouble) src->f[1] ); + dst->f[2] = src->f[2] - (GLfloat) floor( (GLdouble) src->f[2] ); + dst->f[3] = src->f[3] - (GLfloat) floor( (GLdouble) src->f[3] ); +} + +static void +micro_i2f( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) src->i[0]; + dst->f[1] = (GLfloat) src->i[1]; + dst->f[2] = (GLfloat) src->i[2]; + dst->f[3] = (GLfloat) src->i[3]; +} + +static void +micro_lg2( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) log( (GLdouble) src->f[0] ) * 1.442695f; + dst->f[1] = (GLfloat) log( (GLdouble) src->f[1] ) * 1.442695f; + dst->f[2] = (GLfloat) log( (GLdouble) src->f[2] ) * 1.442695f; + dst->f[3] = (GLfloat) log( (GLdouble) src->f[3] ) * 1.442695f; +} + +static void +micro_lt( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2, + const union tgsi_exec_channel *src3 ) +{ + dst->f[0] = src0->f[0] < src1->f[0] ? src2->f[0] : src3->f[0]; + dst->f[1] = src0->f[1] < src1->f[1] ? src2->f[1] : src3->f[1]; + dst->f[2] = src0->f[2] < src1->f[2] ? src2->f[2] : src3->f[2]; + dst->f[3] = src0->f[3] < src1->f[3] ? src2->f[3] : src3->f[3]; +} + +static void +micro_ilt( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2, + const union tgsi_exec_channel *src3 ) +{ + dst->i[0] = src0->i[0] < src1->i[0] ? src2->i[0] : src3->i[0]; + dst->i[1] = src0->i[1] < src1->i[1] ? src2->i[1] : src3->i[1]; + dst->i[2] = src0->i[2] < src1->i[2] ? src2->i[2] : src3->i[2]; + dst->i[3] = src0->i[3] < src1->i[3] ? src2->i[3] : src3->i[3]; +} + +static void +micro_ult( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2, + const union tgsi_exec_channel *src3 ) +{ + dst->u[0] = src0->u[0] < src1->u[0] ? src2->u[0] : src3->u[0]; + dst->u[1] = src0->u[1] < src1->u[1] ? src2->u[1] : src3->u[1]; + dst->u[2] = src0->u[2] < src1->u[2] ? src2->u[2] : src3->u[2]; + dst->u[3] = src0->u[3] < src1->u[3] ? src2->u[3] : src3->u[3]; +} + +static void +micro_max( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->f[0] = src0->f[0] > src1->f[0] ? src0->f[0] : src1->f[0]; + dst->f[1] = src0->f[1] > src1->f[1] ? src0->f[1] : src1->f[1]; + dst->f[2] = src0->f[2] > src1->f[2] ? src0->f[2] : src1->f[2]; + dst->f[3] = src0->f[3] > src1->f[3] ? src0->f[3] : src1->f[3]; +} + +static void +micro_imax( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->i[0] = src0->i[0] > src1->i[0] ? src0->i[0] : src1->i[0]; + dst->i[1] = src0->i[1] > src1->i[1] ? src0->i[1] : src1->i[1]; + dst->i[2] = src0->i[2] > src1->i[2] ? src0->i[2] : src1->i[2]; + dst->i[3] = src0->i[3] > src1->i[3] ? src0->i[3] : src1->i[3]; +} + +static void +micro_umax( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] > src1->u[0] ? src0->u[0] : src1->u[0]; + dst->u[1] = src0->u[1] > src1->u[1] ? src0->u[1] : src1->u[1]; + dst->u[2] = src0->u[2] > src1->u[2] ? src0->u[2] : src1->u[2]; + dst->u[3] = src0->u[3] > src1->u[3] ? src0->u[3] : src1->u[3]; +} + +static void +micro_min( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->f[0] = src0->f[0] < src1->f[0] ? src0->f[0] : src1->f[0]; + dst->f[1] = src0->f[1] < src1->f[1] ? src0->f[1] : src1->f[1]; + dst->f[2] = src0->f[2] < src1->f[2] ? src0->f[2] : src1->f[2]; + dst->f[3] = src0->f[3] < src1->f[3] ? src0->f[3] : src1->f[3]; +} + +static void +micro_imin( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->i[0] = src0->i[0] < src1->i[0] ? src0->i[0] : src1->i[0]; + dst->i[1] = src0->i[1] < src1->i[1] ? src0->i[1] : src1->i[1]; + dst->i[2] = src0->i[2] < src1->i[2] ? src0->i[2] : src1->i[2]; + dst->i[3] = src0->i[3] < src1->i[3] ? src0->i[3] : src1->i[3]; +} + +static void +micro_umin( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] < src1->u[0] ? src0->u[0] : src1->u[0]; + dst->u[1] = src0->u[1] < src1->u[1] ? src0->u[1] : src1->u[1]; + dst->u[2] = src0->u[2] < src1->u[2] ? src0->u[2] : src1->u[2]; + dst->u[3] = src0->u[3] < src1->u[3] ? src0->u[3] : src1->u[3]; +} + +static void +micro_umod( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] % src1->u[0]; + dst->u[1] = src0->u[1] % src1->u[1]; + dst->u[2] = src0->u[2] % src1->u[2]; + dst->u[3] = src0->u[3] % src1->u[3]; +} + +static void +micro_mul( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->f[0] = src0->f[0] * src1->f[0]; + dst->f[1] = src0->f[1] * src1->f[1]; + dst->f[2] = src0->f[2] * src1->f[2]; + dst->f[3] = src0->f[3] * src1->f[3]; +} + +static void +micro_imul( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->i[0] = src0->i[0] * src1->i[0]; + dst->i[1] = src0->i[1] * src1->i[1]; + dst->i[2] = src0->i[2] * src1->i[2]; + dst->i[3] = src0->i[3] * src1->i[3]; +} + +static void +micro_imul64( + union tgsi_exec_channel *dst0, + union tgsi_exec_channel *dst1, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst1->i[0] = src0->i[0] * src1->i[0]; + dst1->i[1] = src0->i[1] * src1->i[1]; + dst1->i[2] = src0->i[2] * src1->i[2]; + dst1->i[3] = src0->i[3] * src1->i[3]; + dst0->i[0] = 0; + dst0->i[1] = 0; + dst0->i[2] = 0; + dst0->i[3] = 0; +} + +static void +micro_umul64( + union tgsi_exec_channel *dst0, + union tgsi_exec_channel *dst1, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst1->u[0] = src0->u[0] * src1->u[0]; + dst1->u[1] = src0->u[1] * src1->u[1]; + dst1->u[2] = src0->u[2] * src1->u[2]; + dst1->u[3] = src0->u[3] * src1->u[3]; + dst0->u[0] = 0; + dst0->u[1] = 0; + dst0->u[2] = 0; + dst0->u[3] = 0; +} + +static void +micro_movc( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1, + const union tgsi_exec_channel *src2 ) +{ + dst->u[0] = src0->u[0] ? src1->u[0] : src2->u[0]; + dst->u[1] = src0->u[1] ? src1->u[1] : src2->u[1]; + dst->u[2] = src0->u[2] ? src1->u[2] : src2->u[2]; + dst->u[3] = src0->u[3] ? src1->u[3] : src2->u[3]; +} + +static void +micro_neg( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = -src->f[0]; + dst->f[1] = -src->f[1]; + dst->f[2] = -src->f[2]; + dst->f[3] = -src->f[3]; +} + +static void +micro_ineg( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->i[0] = -src->i[0]; + dst->i[1] = -src->i[1]; + dst->i[2] = -src->i[2]; + dst->i[3] = -src->i[3]; +} + +static void +micro_not( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->u[0] = ~src->u[0]; + dst->u[1] = ~src->u[1]; + dst->u[2] = ~src->u[2]; + dst->u[3] = ~src->u[3]; +} + +static void +micro_or( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] | src1->u[0]; + dst->u[1] = src0->u[1] | src1->u[1]; + dst->u[2] = src0->u[2] | src1->u[2]; + dst->u[3] = src0->u[3] | src1->u[3]; +} + +static void +micro_pow( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->f[0] = (GLfloat) pow( (GLdouble) src0->f[0], (GLdouble) src1->f[0] ); + dst->f[1] = (GLfloat) pow( (GLdouble) src0->f[1], (GLdouble) src1->f[1] ); + dst->f[2] = (GLfloat) pow( (GLdouble) src0->f[2], (GLdouble) src1->f[2] ); + dst->f[3] = (GLfloat) pow( (GLdouble) src0->f[3], (GLdouble) src1->f[3] ); +} + +static void +micro_rnd( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) floor( (GLdouble) (src->f[0] + 0.5f) ); + dst->f[1] = (GLfloat) floor( (GLdouble) (src->f[1] + 0.5f) ); + dst->f[2] = (GLfloat) floor( (GLdouble) (src->f[2] + 0.5f) ); + dst->f[3] = (GLfloat) floor( (GLdouble) (src->f[3] + 0.5f) ); +} + +static void +micro_shl( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->i[0] = src0->i[0] << src1->i[0]; + dst->i[1] = src0->i[1] << src1->i[1]; + dst->i[2] = src0->i[2] << src1->i[2]; + dst->i[3] = src0->i[3] << src1->i[3]; +} + +static void +micro_ishr( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->i[0] = src0->i[0] >> src1->i[0]; + dst->i[1] = src0->i[1] >> src1->i[1]; + dst->i[2] = src0->i[2] >> src1->i[2]; + dst->i[3] = src0->i[3] >> src1->i[3]; +} + +static void +micro_ushr( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] >> src1->u[0]; + dst->u[1] = src0->u[1] >> src1->u[1]; + dst->u[2] = src0->u[2] >> src1->u[2]; + dst->u[3] = src0->u[3] >> src1->u[3]; +} + +static void +micro_sin( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) sin( (GLdouble) src->f[0] ); + dst->f[1] = (GLfloat) sin( (GLdouble) src->f[1] ); + dst->f[2] = (GLfloat) sin( (GLdouble) src->f[2] ); + dst->f[3] = (GLfloat) sin( (GLdouble) src->f[3] ); +} + +static void +micro_sqrt( union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) sqrt( (GLdouble) src->f[0] ); + dst->f[1] = (GLfloat) sqrt( (GLdouble) src->f[1] ); + dst->f[2] = (GLfloat) sqrt( (GLdouble) src->f[2] ); + dst->f[3] = (GLfloat) sqrt( (GLdouble) src->f[3] ); +} + +static void +micro_sub( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->f[0] = src0->f[0] - src1->f[0]; + dst->f[1] = src0->f[1] - src1->f[1]; + dst->f[2] = src0->f[2] - src1->f[2]; + dst->f[3] = src0->f[3] - src1->f[3]; +} + +static void +micro_u2f( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src ) +{ + dst->f[0] = (GLfloat) src->u[0]; + dst->f[1] = (GLfloat) src->u[1]; + dst->f[2] = (GLfloat) src->u[2]; + dst->f[3] = (GLfloat) src->u[3]; +} + +static void +micro_xor( + union tgsi_exec_channel *dst, + const union tgsi_exec_channel *src0, + const union tgsi_exec_channel *src1 ) +{ + dst->u[0] = src0->u[0] ^ src1->u[0]; + dst->u[1] = src0->u[1] ^ src1->u[1]; + dst->u[2] = src0->u[2] ^ src1->u[2]; + dst->u[3] = src0->u[3] ^ src1->u[3]; +} + +static void +fetch_src_file_channel( + const struct tgsi_exec_machine *mach, + const GLuint file, + const GLuint swizzle, + const union tgsi_exec_channel *index, + union tgsi_exec_channel *chan ) +{ + switch( swizzle ) { + case TGSI_EXTSWIZZLE_X: + case TGSI_EXTSWIZZLE_Y: + case TGSI_EXTSWIZZLE_Z: + case TGSI_EXTSWIZZLE_W: + switch( file ) { + case TGSI_FILE_CONSTANT: + chan->f[0] = mach->Consts[index->i[0]][swizzle]; + chan->f[1] = mach->Consts[index->i[1]][swizzle]; + chan->f[2] = mach->Consts[index->i[2]][swizzle]; + chan->f[3] = mach->Consts[index->i[3]][swizzle]; + break; + + case TGSI_FILE_INPUT: + chan->u[0] = mach->Inputs[index->i[0]].xyzw[swizzle].u[0]; + chan->u[1] = mach->Inputs[index->i[1]].xyzw[swizzle].u[1]; + chan->u[2] = mach->Inputs[index->i[2]].xyzw[swizzle].u[2]; + chan->u[3] = mach->Inputs[index->i[3]].xyzw[swizzle].u[3]; + break; + + case TGSI_FILE_TEMPORARY: + chan->u[0] = mach->Temps[index->i[0]].xyzw[swizzle].u[0]; + chan->u[1] = mach->Temps[index->i[1]].xyzw[swizzle].u[1]; + chan->u[2] = mach->Temps[index->i[2]].xyzw[swizzle].u[2]; + chan->u[3] = mach->Temps[index->i[3]].xyzw[swizzle].u[3]; + break; + + case TGSI_FILE_IMMEDIATE: + assert( index->i[0] < (GLint) mach->ImmLimit ); + chan->f[0] = mach->Imms[index->i[0]][swizzle]; + assert( index->i[1] < (GLint) mach->ImmLimit ); + chan->f[1] = mach->Imms[index->i[1]][swizzle]; + assert( index->i[2] < (GLint) mach->ImmLimit ); + chan->f[2] = mach->Imms[index->i[2]][swizzle]; + assert( index->i[3] < (GLint) mach->ImmLimit ); + chan->f[3] = mach->Imms[index->i[3]][swizzle]; + break; + + case TGSI_FILE_ADDRESS: + chan->u[0] = mach->Addrs[index->i[0]].xyzw[swizzle].u[0]; + chan->u[1] = mach->Addrs[index->i[1]].xyzw[swizzle].u[1]; + chan->u[2] = mach->Addrs[index->i[2]].xyzw[swizzle].u[2]; + chan->u[3] = mach->Addrs[index->i[3]].xyzw[swizzle].u[3]; + break; + + default: + assert( 0 ); + } + break; + + case TGSI_EXTSWIZZLE_ZERO: + *chan = mach->Temps[TEMP_0_I].xyzw[TEMP_0_C]; + break; + + case TGSI_EXTSWIZZLE_ONE: + *chan = mach->Temps[TEMP_1_I].xyzw[TEMP_1_C]; + break; + + default: + assert( 0 ); + } +} + +static void +fetch_source( + const struct tgsi_exec_machine *mach, + union tgsi_exec_channel *chan, + const struct tgsi_full_src_register *reg, + const GLuint chan_index ) +{ + union tgsi_exec_channel index; + GLuint swizzle; + + index.i[0] = + index.i[1] = + index.i[2] = + index.i[3] = reg->SrcRegister.Index; + + if (reg->SrcRegister.Indirect) { + union tgsi_exec_channel index2; + union tgsi_exec_channel indir_index; + + index2.i[0] = + index2.i[1] = + index2.i[2] = + index2.i[3] = reg->SrcRegisterInd.Index; + + swizzle = tgsi_util_get_src_register_swizzle( ®->SrcRegisterInd, CHAN_X ); + fetch_src_file_channel( + mach, + reg->SrcRegisterInd.File, + swizzle, + &index2, + &indir_index ); + + index.i[0] += indir_index.i[0]; + index.i[1] += indir_index.i[1]; + index.i[2] += indir_index.i[2]; + index.i[3] += indir_index.i[3]; + } + + if( reg->SrcRegister.Dimension ) { + switch( reg->SrcRegister.File ) { + case TGSI_FILE_INPUT: + index.i[0] *= 17; + index.i[1] *= 17; + index.i[2] *= 17; + index.i[3] *= 17; + break; + case TGSI_FILE_CONSTANT: + index.i[0] *= 4096; + index.i[1] *= 4096; + index.i[2] *= 4096; + index.i[3] *= 4096; + break; + default: + assert( 0 ); + } + + index.i[0] += reg->SrcRegisterDim.Index; + index.i[1] += reg->SrcRegisterDim.Index; + index.i[2] += reg->SrcRegisterDim.Index; + index.i[3] += reg->SrcRegisterDim.Index; + + if (reg->SrcRegisterDim.Indirect) { + union tgsi_exec_channel index2; + union tgsi_exec_channel indir_index; + + index2.i[0] = + index2.i[1] = + index2.i[2] = + index2.i[3] = reg->SrcRegisterDimInd.Index; + + swizzle = tgsi_util_get_src_register_swizzle( ®->SrcRegisterDimInd, CHAN_X ); + fetch_src_file_channel( + mach, + reg->SrcRegisterDimInd.File, + swizzle, + &index2, + &indir_index ); + + index.i[0] += indir_index.i[0]; + index.i[1] += indir_index.i[1]; + index.i[2] += indir_index.i[2]; + index.i[3] += indir_index.i[3]; + } + } + + swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index ); + fetch_src_file_channel( + mach, + reg->SrcRegister.File, + swizzle, + &index, + chan ); + + switch (tgsi_util_get_full_src_register_sign_mode( reg, chan_index )) { + case TGSI_UTIL_SIGN_CLEAR: + micro_abs( chan, chan ); + break; + + case TGSI_UTIL_SIGN_SET: + micro_abs( chan, chan ); + micro_neg( chan, chan ); + break; + + case TGSI_UTIL_SIGN_TOGGLE: + micro_neg( chan, chan ); + break; + + case TGSI_UTIL_SIGN_KEEP: + break; + } +} + +static void +store_dest( + struct tgsi_exec_machine *mach, + const union tgsi_exec_channel *chan, + const struct tgsi_full_dst_register *reg, + const struct tgsi_full_instruction *inst, + GLuint chan_index ) +{ + union tgsi_exec_channel *dst; + + switch( reg->DstRegister.File ) { + case TGSI_FILE_NULL: + return; + + case TGSI_FILE_OUTPUT: + dst = &mach->Outputs[mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] + reg->DstRegister.Index].xyzw[chan_index]; + break; + + case TGSI_FILE_TEMPORARY: + dst = &mach->Temps[reg->DstRegister.Index].xyzw[chan_index]; + break; + + case TGSI_FILE_ADDRESS: + dst = &mach->Addrs[reg->DstRegister.Index].xyzw[chan_index]; + break; + + default: + assert( 0 ); + } + + switch (inst->Instruction.Saturate) + { + case TGSI_SAT_NONE: + *dst = *chan; + break; + + case TGSI_SAT_ZERO_ONE: + micro_lt( dst, chan, &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], chan ); + micro_lt( dst, chan, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], chan, &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] ); + break; + + case TGSI_SAT_MINUS_PLUS_ONE: + assert( 0 ); + break; + + default: + assert( 0 ); + } +} + +#define FETCH(VAL,INDEX,CHAN)\ + fetch_source (mach, VAL, &inst->FullSrcRegisters[INDEX], CHAN) + +#define STORE(VAL,INDEX,CHAN)\ + store_dest (mach, VAL, &inst->FullDstRegisters[INDEX], inst, CHAN) + +static void +exec_kil (struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst) +{ + GLuint uniquemask; + GLuint chan_index; + GLuint kilmask = 0; + union tgsi_exec_channel r[1]; + + /* This mask stores component bits that were already tested. Note that + * we test if the value is less than zero, so 1.0 and 0.0 need not to be + * tested. */ + uniquemask = (1 << TGSI_EXTSWIZZLE_ZERO) | (1 << TGSI_EXTSWIZZLE_ONE); + + for (chan_index = 0; chan_index < 4; chan_index++) + { + GLuint swizzle; + GLuint i; + + /* unswizzle channel */ + swizzle = tgsi_util_get_full_src_register_extswizzle ( + &inst->FullSrcRegisters[0], + chan_index); + + /* check if the component has not been already tested */ + if (uniquemask & (1 << swizzle)) + continue; + uniquemask |= 1 << swizzle; + + FETCH(&r[0], 0, chan_index); + for (i = 0; i < 4; i++) + if (r[0].f[i] < 0.0f) + kilmask |= 1 << (i * 4); + } + + mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask; +} + +#if MESA +/* + * Fetch a texel using S texture coordinate. + */ +static void +fetch_texel_1d( GLcontext *ctx, + struct tgsi_sampler_state *sampler, + const union tgsi_exec_channel *s, + GLuint unit, + union tgsi_exec_channel *r, + union tgsi_exec_channel *g, + union tgsi_exec_channel *b, + union tgsi_exec_channel *a ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint fragment_index; + GLfloat stpq[4][4]; + GLfloat lambdas[4]; + GLchan rgba[4][4]; + + for (fragment_index = 0; fragment_index < 4; fragment_index++) + { + stpq[fragment_index][0] = s->f[fragment_index]; + } + + if (sampler->NeedLambda) + { + GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT]; + GLfloat dsdy = s->f[TILE_TOP_LEFT] - s->f[TILE_BOTTOM_LEFT]; + + GLfloat rho, lambda; + + dsdx = FABSF(dsdx); + dsdy = FABSF(dsdy); + + rho = MAX2(dsdx, dsdy) * sampler->ImageWidth; + + lambda = LOG2(rho); + + if (sampler->NeedLodBias) + lambda += sampler->LodBias; + + if (sampler->NeedLambdaClamp) + lambda = CLAMP(lambda, sampler->MinLod, sampler->MaxLod); + + /* XXX: Use the same lambda value throughout the tile. Could + * end up with four unique values by recalculating partial + * derivs in the other row and column, and calculating lambda + * using the dx and dy values appropriate for each fragment in + * the tile. + */ + lambdas[0] = + lambdas[1] = + lambdas[2] = + lambdas[3] = lambda; + } + + if (!swrast->TextureSample[unit]) { + _swrast_update_texture_samplers(ctx); + } + + /* XXX use a float-valued TextureSample routine here!!! */ + swrast->TextureSample[unit] (ctx, + ctx->Texture.Unit[unit]._Current, + 4, + (const GLfloat (*)[4])stpq, + lambdas, + rgba); + + for (fragment_index = 0; fragment_index < 4; fragment_index++) + { + r->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][0]); + g->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][1]); + b->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][2]); + a->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][3]); + } +} + +/* + * Fetch a texel using ST texture coordinates. + */ +static void +fetch_texel_2d( GLcontext *ctx, + struct tgsi_sampler_state *sampler, + const union tgsi_exec_channel *s, + const union tgsi_exec_channel *t, + GLuint unit, + union tgsi_exec_channel *r, + union tgsi_exec_channel *g, + union tgsi_exec_channel *b, + union tgsi_exec_channel *a ) +{ + SWcontext *swrast = SWRAST_CONTEXT( ctx ); + GLuint fragment_index; + GLfloat stpq[4][4]; + GLfloat lambdas[4]; + GLchan rgba[4][4]; + + for (fragment_index = 0; fragment_index < 4; fragment_index++) { + stpq[fragment_index][0] = s->f[fragment_index]; + stpq[fragment_index][1] = t->f[fragment_index]; + } + + if (sampler->NeedLambda) { + GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT]; + GLfloat dsdy = s->f[TILE_TOP_LEFT] - s->f[TILE_BOTTOM_LEFT]; + + GLfloat dtdx = t->f[TILE_BOTTOM_RIGHT] - t->f[TILE_BOTTOM_LEFT]; + GLfloat dtdy = t->f[TILE_TOP_LEFT] - t->f[TILE_BOTTOM_LEFT]; + + GLfloat maxU, maxV, rho, lambda; + + dsdx = FABSF( dsdx ); + dsdy = FABSF( dsdy ); + dtdx = FABSF( dtdx ); + dtdy = FABSF( dtdy ); + + maxU = MAX2( dsdx, dsdy ) * sampler->ImageWidth; + maxV = MAX2( dtdx, dtdy ) * sampler->ImageHeight; + + rho = MAX2( maxU, maxV ); + + lambda = LOG2( rho ); + + if (sampler->NeedLodBias) + lambda += sampler->LodBias; + + if (sampler->NeedLambdaClamp) + lambda = CLAMP( + lambda, + sampler->MinLod, + sampler->MaxLod ); + + /* XXX: Use the same lambda value throughout the tile. Could + * end up with four unique values by recalculating partial + * derivs in the other row and column, and calculating lambda + * using the dx and dy values appropriate for each fragment in + * the tile. + */ + lambdas[0] = + lambdas[1] = + lambdas[2] = + lambdas[3] = lambda; + } + + if (!swrast->TextureSample[unit]) { + _swrast_update_texture_samplers(ctx); + } + + /* XXX use a float-valued TextureSample routine here!!! */ + swrast->TextureSample[unit]( + ctx, + ctx->Texture.Unit[unit]._Current, + 4, + (const GLfloat (*)[4]) stpq, + lambdas, + rgba ); + + for (fragment_index = 0; fragment_index < 4; fragment_index++) { + r->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][0] ); + g->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][1] ); + b->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][2] ); + a->f[fragment_index] = CHAN_TO_FLOAT( rgba[fragment_index][3] ); + } +} + +/* + * Fetch a texel using STR texture coordinates. + */ +static void +fetch_texel_3d( GLcontext *ctx, + struct tgsi_sampler_state *sampler, + const union tgsi_exec_channel *s, + const union tgsi_exec_channel *t, + const union tgsi_exec_channel *p, + GLuint unit, + union tgsi_exec_channel *r, + union tgsi_exec_channel *g, + union tgsi_exec_channel *b, + union tgsi_exec_channel *a ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLuint fragment_index; + GLfloat stpq[4][4]; + GLfloat lambdas[4]; + GLchan rgba[4][4]; + + for (fragment_index = 0; fragment_index < 4; fragment_index++) + { + stpq[fragment_index][0] = s->f[fragment_index]; + stpq[fragment_index][1] = t->f[fragment_index]; + stpq[fragment_index][2] = p->f[fragment_index]; + } + + if (sampler->NeedLambda) + { + GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT]; + GLfloat dsdy = s->f[TILE_TOP_LEFT] - s->f[TILE_BOTTOM_LEFT]; + + GLfloat dtdx = t->f[TILE_BOTTOM_RIGHT] - t->f[TILE_BOTTOM_LEFT]; + GLfloat dtdy = t->f[TILE_TOP_LEFT] - t->f[TILE_BOTTOM_LEFT]; + + GLfloat dpdx = p->f[TILE_BOTTOM_RIGHT] - p->f[TILE_BOTTOM_LEFT]; + GLfloat dpdy = p->f[TILE_TOP_LEFT] - p->f[TILE_BOTTOM_LEFT]; + + GLfloat maxU, maxV, maxW, rho, lambda; + + dsdx = FABSF(dsdx); + dsdy = FABSF(dsdy); + dtdx = FABSF(dtdx); + dtdy = FABSF(dtdy); + dpdx = FABSF(dpdx); + dpdy = FABSF(dpdy); + + maxU = MAX2(dsdx, dsdy) * sampler->ImageWidth; + maxV = MAX2(dtdx, dtdy) * sampler->ImageHeight; + maxW = MAX2(dpdx, dpdy) * sampler->ImageDepth; + + rho = MAX2(maxU, MAX2(maxV, maxW)); + + lambda = LOG2(rho); + + if (sampler->NeedLodBias) + lambda += sampler->LodBias; + + if (sampler->NeedLambdaClamp) + lambda = CLAMP(lambda, sampler->MinLod, sampler->MaxLod); + + /* XXX: Use the same lambda value throughout the tile. Could + * end up with four unique values by recalculating partial + * derivs in the other row and column, and calculating lambda + * using the dx and dy values appropriate for each fragment in + * the tile. + */ + lambdas[0] = + lambdas[1] = + lambdas[2] = + lambdas[3] = lambda; + } + + if (!swrast->TextureSample[unit]) { + _swrast_update_texture_samplers(ctx); + } + + /* XXX use a float-valued TextureSample routine here!!! */ + swrast->TextureSample[unit] (ctx, + ctx->Texture.Unit[unit]._Current, + 4, + (const GLfloat (*)[4])stpq, + lambdas, + rgba); + + for (fragment_index = 0; fragment_index < 4; fragment_index++) + { + r->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][0]); + g->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][1]); + b->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][2]); + a->f[fragment_index] = CHAN_TO_FLOAT(rgba[fragment_index][3]); + } +} +#endif + +static GLuint +map_label( + GLuint label, + struct tgsi_exec_labels *labels ) +{ + GLuint i; + + for( i = 0; i < labels->count; i++ ) { + if( labels->labels[i][0] == label ) { + return labels->labels[i][1]; + } + } + assert( 0 ); + return 0; +} + +static void +exec_instruction( + struct tgsi_exec_machine *mach, + const struct tgsi_full_instruction *inst, + struct tgsi_exec_labels *labels, + GLuint *programCounter ) +{ +#if MESA + GET_CURRENT_CONTEXT(ctx); +#endif + GLuint chan_index; + union tgsi_exec_channel r[8]; + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_ARL: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_f2it( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_MOV: + /* TGSI_OPCODE_SWZ */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_LIT: + if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) { + STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X ); + } + + if (IS_CHANNEL_ENABLED( *inst, CHAN_Y ) || IS_CHANNEL_ENABLED( *inst, CHAN_Z )) { + FETCH( &r[0], 0, CHAN_X ); + if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) { + micro_max( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] ); + STORE( &r[0], 0, CHAN_Y ); + } + + if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) { + FETCH( &r[1], 0, CHAN_Y ); + micro_max( &r[1], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] ); + + FETCH( &r[2], 0, CHAN_W ); + micro_min( &r[2], &r[2], &mach->Temps[TEMP_128_I].xyzw[TEMP_128_C] ); + micro_max( &r[2], &r[2], &mach->Temps[TEMP_M128_I].xyzw[TEMP_M128_C] ); + micro_pow( &r[1], &r[1], &r[2] ); + micro_lt( &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[0], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] ); + STORE( &r[0], 0, CHAN_Z ); + } + } + + if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) { + STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W ); + } + break; + + case TGSI_OPCODE_RCP: + /* TGSI_OPCODE_RECIP */ + FETCH( &r[0], 0, CHAN_X ); + micro_div( &r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &r[0] ); + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_RSQ: + /* TGSI_OPCODE_RECIPSQRT */ + FETCH( &r[0], 0, CHAN_X ); + micro_sqrt( &r[0], &r[0] ); + micro_div( &r[0], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &r[0] ); + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_EXP: + assert (0); + break; + + case TGSI_OPCODE_LOG: + assert (0); + break; + + case TGSI_OPCODE_MUL: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) + { + FETCH(&r[0], 0, chan_index); + FETCH(&r[1], 1, chan_index); + + micro_mul( &r[0], &r[0], &r[1] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_ADD: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_add( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_DP3: + /* TGSI_OPCODE_DOT3 */ + FETCH( &r[0], 0, CHAN_X ); + FETCH( &r[1], 1, CHAN_X ); + micro_mul( &r[0], &r[0], &r[1] ); + + FETCH( &r[1], 0, CHAN_Y ); + FETCH( &r[2], 1, CHAN_Y ); + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FETCH( &r[1], 0, CHAN_Z ); + FETCH( &r[2], 1, CHAN_Z ); + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_DP4: + /* TGSI_OPCODE_DOT4 */ + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 1, CHAN_X); + + micro_mul( &r[0], &r[0], &r[1] ); + + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 1, CHAN_Y); + + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FETCH(&r[1], 0, CHAN_Z); + FETCH(&r[2], 1, CHAN_Z); + + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FETCH(&r[1], 0, CHAN_W); + FETCH(&r[2], 1, CHAN_W); + + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_DST: + if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) { + STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_X ); + } + + if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) { + FETCH( &r[0], 0, CHAN_Y ); + FETCH( &r[1], 1, CHAN_Y); + micro_mul( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, CHAN_Y ); + } + + if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) { + FETCH( &r[0], 0, CHAN_Z ); + STORE( &r[0], 0, CHAN_Z ); + } + + if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) { + FETCH( &r[0], 1, CHAN_W ); + STORE( &r[0], 0, CHAN_W ); + } + break; + + case TGSI_OPCODE_MIN: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH(&r[0], 0, chan_index); + FETCH(&r[1], 1, chan_index); + + micro_lt( &r[0], &r[0], &r[1], &r[0], &r[1] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_MAX: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH(&r[0], 0, chan_index); + FETCH(&r[1], 1, chan_index); + + micro_lt( &r[0], &r[0], &r[1], &r[1], &r[0] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_SLT: + /* TGSI_OPCODE_SETLT */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_lt( &r[0], &r[0], &r[1], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_SGE: + /* TGSI_OPCODE_SETGE */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH(&r[0], 0, chan_index); + FETCH(&r[1], 1, chan_index); + + micro_lt( &r[0], &r[0], &r[1], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_MAD: + /* TGSI_OPCODE_MADD */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_mul( &r[0], &r[0], &r[1] ); + FETCH( &r[1], 2, chan_index ); + micro_add( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_SUB: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH(&r[0], 0, chan_index); + FETCH(&r[1], 1, chan_index); + + micro_sub( &r[0], &r[0], &r[1] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_LERP: + /* TGSI_OPCODE_LRP */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH(&r[0], 0, chan_index); + FETCH(&r[1], 1, chan_index); + FETCH(&r[2], 2, chan_index); + + micro_sub( &r[1], &r[1], &r[2] ); + micro_mul( &r[0], &r[0], &r[1] ); + micro_add( &r[0], &r[0], &r[2] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_CND: + assert (0); + break; + + case TGSI_OPCODE_CND0: + assert (0); + break; + + case TGSI_OPCODE_DOT2ADD: + /* TGSI_OPCODE_DP2A */ + assert (0); + break; + + case TGSI_OPCODE_INDEX: + assert (0); + break; + + case TGSI_OPCODE_NEGATE: + assert (0); + break; + + case TGSI_OPCODE_FRAC: + /* TGSI_OPCODE_FRC */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_frc( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_CLAMP: + assert (0); + break; + + case TGSI_OPCODE_FLOOR: + /* TGSI_OPCODE_FLR */ + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_flr( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_ROUND: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_rnd( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_EXPBASE2: + /* TGSI_OPCODE_EX2 */ + FETCH(&r[0], 0, CHAN_X); + + micro_pow( &r[0], &mach->Temps[TEMP_2_I].xyzw[TEMP_2_C], &r[0] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_LOGBASE2: + /* TGSI_OPCODE_LG2 */ + FETCH( &r[0], 0, CHAN_X ); + micro_lg2( &r[0], &r[0] ); + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_POWER: + /* TGSI_OPCODE_POW */ + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 1, CHAN_X); + + micro_pow( &r[0], &r[0], &r[1] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_CROSSPRODUCT: + /* TGSI_OPCODE_XPD */ + FETCH(&r[0], 0, CHAN_Y); + FETCH(&r[1], 1, CHAN_Z); + + micro_mul( &r[2], &r[0], &r[1] ); + + FETCH(&r[3], 0, CHAN_Z); + FETCH(&r[4], 1, CHAN_Y); + + micro_mul( &r[5], &r[3], &r[4] ); + micro_sub( &r[2], &r[2], &r[5] ); + + if (IS_CHANNEL_ENABLED( *inst, CHAN_X )) { + STORE( &r[2], 0, CHAN_X ); + } + + FETCH(&r[2], 1, CHAN_X); + + micro_mul( &r[3], &r[3], &r[2] ); + + FETCH(&r[5], 0, CHAN_X); + + micro_mul( &r[1], &r[1], &r[5] ); + micro_sub( &r[3], &r[3], &r[1] ); + + if (IS_CHANNEL_ENABLED( *inst, CHAN_Y )) { + STORE( &r[3], 0, CHAN_Y ); + } + + micro_mul( &r[5], &r[5], &r[4] ); + micro_mul( &r[0], &r[0], &r[2] ); + micro_sub( &r[5], &r[5], &r[0] ); + + if (IS_CHANNEL_ENABLED( *inst, CHAN_Z )) { + STORE( &r[5], 0, CHAN_Z ); + } + + if (IS_CHANNEL_ENABLED( *inst, CHAN_W )) { + STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W ); + } + break; + + case TGSI_OPCODE_MULTIPLYMATRIX: + assert (0); + break; + + case TGSI_OPCODE_ABS: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH(&r[0], 0, chan_index); + + micro_abs( &r[0], &r[0] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_RCC: + assert (0); + break; + + case TGSI_OPCODE_DPH: + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 1, CHAN_X); + + micro_mul( &r[0], &r[0], &r[1] ); + + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 1, CHAN_Y); + + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FETCH(&r[1], 0, CHAN_Z); + FETCH(&r[2], 1, CHAN_Z); + + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FETCH(&r[1], 1, CHAN_W); + + micro_add( &r[0], &r[0], &r[1] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_COS: + FETCH(&r[0], 0, CHAN_X); + + micro_cos( &r[0], &r[0] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_DDX: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_ddx( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_DDY: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_ddy( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_KIL: + exec_kil (mach, inst); + break; + + case TGSI_OPCODE_PK2H: + assert (0); + break; + + case TGSI_OPCODE_PK2US: + assert (0); + break; + + case TGSI_OPCODE_PK4B: + assert (0); + break; + + case TGSI_OPCODE_PK4UB: + assert (0); + break; + + case TGSI_OPCODE_RFL: + assert (0); + break; + + case TGSI_OPCODE_SEQ: + assert (0); + break; + + case TGSI_OPCODE_SFL: + assert (0); + break; + + case TGSI_OPCODE_SGT: + assert (0); + break; + + case TGSI_OPCODE_SIN: + FETCH(&r[0], 0, CHAN_X); + + micro_sin( &r[0], &r[0] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_SLE: + assert (0); + break; + + case TGSI_OPCODE_SNE: + assert (0); + break; + + case TGSI_OPCODE_STR: + assert (0); + break; + + case TGSI_OPCODE_TEX: + switch (inst->InstructionExtTexture.Texture) { + case TGSI_TEXTURE_1D: + + FETCH(&r[0], 0, CHAN_X); + + switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) { + case TGSI_EXTSWIZZLE_W: + FETCH(&r[1], 0, CHAN_W); + micro_div( &r[0], &r[0], &r[1] ); + break; + + case TGSI_EXTSWIZZLE_ONE: + break; + + default: + assert (0); + } +#if MESA + fetch_texel_1d (ctx, + &mach->Samplers[inst->FullSrcRegisters[1].SrcRegister.Index], + &r[0], + inst->FullSrcRegisters[1].SrcRegister.Index, + &r[0], &r[1], &r[2], &r[3]); +#endif + break; + + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + + switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) { + case TGSI_EXTSWIZZLE_W: + FETCH(&r[2], 0, CHAN_W); + micro_div( &r[0], &r[0], &r[2] ); + micro_div( &r[1], &r[1], &r[2] ); + break; + + case TGSI_EXTSWIZZLE_ONE: + break; + + default: + assert (0); + } + +#if MESA + fetch_texel_2d (ctx, + &mach->Samplers[inst->FullSrcRegisters[1].SrcRegister.Index], + &r[0], &r[1], + inst->FullSrcRegisters[1].SrcRegister.Index, + &r[0], &r[1], &r[2], &r[3]); +#endif + break; + + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + + FETCH(&r[0], 0, CHAN_X); + FETCH(&r[1], 0, CHAN_Y); + FETCH(&r[2], 0, CHAN_Z); + + switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) { + case TGSI_EXTSWIZZLE_W: + FETCH(&r[3], 0, CHAN_W); + micro_div( &r[0], &r[0], &r[3] ); + micro_div( &r[1], &r[1], &r[3] ); + micro_div( &r[2], &r[2], &r[3] ); + break; + + case TGSI_EXTSWIZZLE_ONE: + break; + + default: + assert (0); + } + +#if MESA + fetch_texel_3d (ctx, + &mach->Samplers[inst->FullSrcRegisters[1].SrcRegister.Index], + &r[0], &r[1], &r[2], + inst->FullSrcRegisters[1].SrcRegister.Index, + &r[0], &r[1], &r[2], &r[3]); +#endif + break; + + default: + assert (0); + } + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[chan_index], 0, chan_index ); + } + break; + + case TGSI_OPCODE_TXD: + assert (0); + break; + + case TGSI_OPCODE_UP2H: + assert (0); + break; + + case TGSI_OPCODE_UP2US: + assert (0); + break; + + case TGSI_OPCODE_UP4B: + assert (0); + break; + + case TGSI_OPCODE_UP4UB: + assert (0); + break; + + case TGSI_OPCODE_X2D: + assert (0); + break; + + case TGSI_OPCODE_ARA: + assert (0); + break; + + case TGSI_OPCODE_ARR: + assert (0); + break; + + case TGSI_OPCODE_BRA: + assert (0); + break; + + case TGSI_OPCODE_CAL: + assert (0); + break; + + case TGSI_OPCODE_RET: + /* XXX: end of shader! */ + /*assert (0);*/ + break; + + case TGSI_OPCODE_SSG: + assert (0); + break; + + case TGSI_OPCODE_CMP: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH(&r[0], 0, chan_index); + FETCH(&r[1], 1, chan_index); + FETCH(&r[2], 2, chan_index); + + micro_lt( &r[0], &r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[1], &r[2] ); + + STORE(&r[0], 0, chan_index); + } + break; + + case TGSI_OPCODE_SCS: + if( IS_CHANNEL_ENABLED( *inst, CHAN_X ) || IS_CHANNEL_ENABLED( *inst, CHAN_Y ) ) { + FETCH( &r[0], 0, CHAN_X ); + } + if( IS_CHANNEL_ENABLED( *inst, CHAN_X ) ) { + micro_cos( &r[1], &r[0] ); + STORE( &r[1], 0, CHAN_X ); + } + if( IS_CHANNEL_ENABLED( *inst, CHAN_Y ) ) { + micro_sin( &r[1], &r[0] ); + STORE( &r[1], 0, CHAN_Y ); + } + if( IS_CHANNEL_ENABLED( *inst, CHAN_Z ) ) { + STORE( &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], 0, CHAN_Z ); + } + if( IS_CHANNEL_ENABLED( *inst, CHAN_W ) ) { + STORE( &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C], 0, CHAN_W ); + } + break; + + case TGSI_OPCODE_TXB: + assert (0); + break; + + case TGSI_OPCODE_NRM: + assert (0); + break; + + case TGSI_OPCODE_DIV: + assert( 0 ); + break; + + case TGSI_OPCODE_DP2: + FETCH( &r[0], 0, CHAN_X ); + FETCH( &r[1], 1, CHAN_X ); + micro_mul( &r[0], &r[0], &r[1] ); + + FETCH( &r[1], 0, CHAN_Y ); + FETCH( &r[2], 1, CHAN_Y ); + micro_mul( &r[1], &r[1], &r[2] ); + micro_add( &r[0], &r[0], &r[1] ); + + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_TXL: + assert (0); + break; + + case TGSI_OPCODE_BRK: + assert (0); + break; + + case TGSI_OPCODE_IF: + assert (0); + break; + + case TGSI_OPCODE_LOOP: + assert (0); + break; + + case TGSI_OPCODE_REP: + assert (0); + break; + + case TGSI_OPCODE_ELSE: + assert (0); + break; + + case TGSI_OPCODE_ENDIF: + assert (0); + break; + + case TGSI_OPCODE_ENDLOOP: + assert (0); + break; + + case TGSI_OPCODE_ENDREP: + assert (0); + break; + + case TGSI_OPCODE_PUSHA: + assert (0); + break; + + case TGSI_OPCODE_POPA: + assert (0); + break; + + case TGSI_OPCODE_CEIL: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_ceil( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_I2F: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_i2f( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_NOT: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + micro_not( &r[0], &r[0] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_TRUNC: + assert (0); + break; + + case TGSI_OPCODE_SHL: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_shl( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_SHR: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_ishr( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_AND: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_and( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_OR: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_or( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_MOD: + assert (0); + break; + + case TGSI_OPCODE_XOR: + FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { + FETCH( &r[0], 0, chan_index ); + FETCH( &r[1], 1, chan_index ); + micro_xor( &r[0], &r[0], &r[1] ); + STORE( &r[0], 0, chan_index ); + } + break; + + case TGSI_OPCODE_SAD: + assert (0); + break; + + case TGSI_OPCODE_TXF: + assert (0); + break; + + case TGSI_OPCODE_TXQ: + assert (0); + break; + + case TGSI_OPCODE_CONT: + assert (0); + break; + + case TGSI_OPCODE_EMIT: + mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += 16; + mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++; + break; + + case TGSI_OPCODE_ENDPRIM: + mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]++; + mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0; + break; + + default: + assert( 0 ); + } +} + + +#if !defined(XSTDCALL) +#if defined(WIN32) +#define XSTDCALL __stdcall +#else +#define XSTDCALL +#endif +#endif + +typedef void (XSTDCALL *fp_function) (const struct tgsi_exec_vector *input, + struct tgsi_exec_vector *output, + GLfloat (*constant)[4], + struct tgsi_exec_vector *temporary); + +void +tgsi_exec_machine_run2( + struct tgsi_exec_machine *mach, + struct tgsi_exec_labels *labels ) +{ +#if MESA + GET_CURRENT_CONTEXT(ctx); + GLuint i; +#endif + +#if XXX_SSE + fp_function function; + + mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0; + + function = (fp_function) x86_get_func (&mach->Function); + + function (mach->Inputs, + mach->Outputs, + mach->Consts, + mach->Temps); +#else + struct tgsi_parse_context parse; + GLuint k; + + mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0; + mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0; + + if( mach->Processor == TGSI_PROCESSOR_GEOMETRY ) { + mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0; + mach->Primitives[0] = 0; + } + + k = tgsi_parse_init( &parse, mach->Tokens ); + if (k != TGSI_PARSE_OK) { + printf("Problem parsing!\n"); + return; + } + + while( !tgsi_parse_end_of_tokens( &parse ) ) { + tgsi_parse_token( &parse ); + switch( parse.FullToken.Token.Type ) { + case TGSI_TOKEN_TYPE_DECLARATION: + break; + case TGSI_TOKEN_TYPE_IMMEDIATE: + break; + case TGSI_TOKEN_TYPE_INSTRUCTION: + exec_instruction( mach, &parse.FullToken.FullInstruction, labels, &parse.Position ); + break; + default: + assert( 0 ); + } + } + tgsi_parse_free (&parse); +#endif + +#if MESA + if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) { + /* + * Scale back depth component. + */ + for (i = 0; i < 4; i++) + mach->Outputs[0].xyzw[2].f[i] *= ctx->DrawBuffer->_DepthMaxF; + } +#endif +} + diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.h b/src/mesa/pipe/tgsi/core/tgsi_exec.h new file mode 100644 index 00000000000..abce6ee924a --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.h @@ -0,0 +1,137 @@ +#if !defined TGSI_EXEC_H +#define TGSI_EXEC_H + +#if 0 +#include "x86/rtasm/x86sse.h" +#endif + +#if defined __cplusplus +extern "C" { +#endif // defined __cplusplus + +union tgsi_exec_channel +{ + GLfloat f[4]; + GLint i[4]; + GLuint u[4]; +}; + +struct tgsi_exec_vector +{ + union tgsi_exec_channel xyzw[4]; +}; + +struct tgsi_sampler_state +{ + GLboolean NeedLambda; + GLboolean NeedLodBias; /* if NeedLambda */ + GLboolean NeedLambdaClamp; /* if NeedLambda */ + GLfloat LodBias; /* if NeedLodBias */ + GLfloat MinLod; /* if NeedLambdaClamp */ + GLfloat MaxLod; /* if NeedLambdaClamp */ + GLfloat ImageWidth; + GLfloat ImageHeight; + GLfloat ImageDepth; +}; + +struct tgsi_exec_labels +{ + GLuint labels[128][2]; + GLuint count; +}; + +#define TGSI_EXEC_TEMP_00000000_I 32 +#define TGSI_EXEC_TEMP_00000000_C 0 + +#define TGSI_EXEC_TEMP_7FFFFFFF_I 32 +#define TGSI_EXEC_TEMP_7FFFFFFF_C 1 + +#define TGSI_EXEC_TEMP_80000000_I 32 +#define TGSI_EXEC_TEMP_80000000_C 2 + +#define TGSI_EXEC_TEMP_FFFFFFFF_I 32 +#define TGSI_EXEC_TEMP_FFFFFFFF_C 3 + +#define TGSI_EXEC_TEMP_ONE_I 33 +#define TGSI_EXEC_TEMP_ONE_C 0 + +#define TGSI_EXEC_TEMP_TWO_I 33 +#define TGSI_EXEC_TEMP_TWO_C 1 + +#define TGSI_EXEC_TEMP_128_I 33 +#define TGSI_EXEC_TEMP_128_C 2 + +#define TGSI_EXEC_TEMP_MINUS_128_I 33 +#define TGSI_EXEC_TEMP_MINUS_128_C 3 + +#define TGSI_EXEC_TEMP_KILMASK_I 34 +#define TGSI_EXEC_TEMP_KILMASK_C 0 + +#define TGSI_EXEC_TEMP_OUTPUT_I 34 +#define TGSI_EXEC_TEMP_OUTPUT_C 1 + +#define TGSI_EXEC_TEMP_PRIMITIVE_I 34 +#define TGSI_EXEC_TEMP_PRIMITIVE_C 2 + +#define TGSI_EXEC_TEMP_R0 35 + +#define TGSI_EXEC_NUM_TEMPS (32 + 4) +#define TGSI_EXEC_NUM_ADDRS 1 + +struct tgsi_exec_machine +{ + /* + * 32 program temporaries + * 4 internal temporaries + * 1 address + * 1 temporary of padding to align to 16 bytes + */ + struct tgsi_exec_vector _Temps[TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_ADDRS + 1]; + + /* + * This will point to _Temps after aligning to 16B boundary. + */ + struct tgsi_exec_vector *Temps; + struct tgsi_exec_vector *Addrs; + + struct tgsi_sampler_state Samplers[16]; + + GLfloat Imms[256][4]; + GLuint ImmLimit; + GLfloat (*Consts)[4]; + const struct tgsi_exec_vector *Inputs; + struct tgsi_exec_vector *Outputs; + struct tgsi_token *Tokens; + GLuint Processor; + + GLuint *Primitives; +#if XXX_SSE + struct x86_function Function; +#endif +}; + +void +tgsi_exec_machine_init( + struct tgsi_exec_machine *mach, + struct tgsi_token *tokens ); + +void +tgsi_exec_prepare( + struct tgsi_exec_machine *mach, + struct tgsi_exec_labels *labels ); + +void +tgsi_exec_machine_run( + struct tgsi_exec_machine *mach ); + +void +tgsi_exec_machine_run2( + struct tgsi_exec_machine *mach, + struct tgsi_exec_labels *labels ); + +#if defined __cplusplus +} // extern "C" +#endif // defined __cplusplus + +#endif // !defined TGSI_EXEC_H + diff --git a/src/mesa/pipe/tgsi/core/tgsi_parse.c b/src/mesa/pipe/tgsi/core/tgsi_parse.c new file mode 100644 index 00000000000..df34fa7d7ef --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_parse.c @@ -0,0 +1,284 @@ +#include "tgsi_platform.h" +#include "tgsi_core.h" + +void +tgsi_full_token_init( + union tgsi_full_token *full_token ) +{ + full_token->Token.Type = TGSI_TOKEN_TYPE_DECLARATION; +} + +void +tgsi_full_token_free( + union tgsi_full_token *full_token ) +{ + if( full_token->Token.Type == TGSI_TOKEN_TYPE_IMMEDIATE ) + free( full_token->FullImmediate.u.Pointer ); +} + +GLuint +tgsi_parse_init( + struct tgsi_parse_context *ctx, + const struct tgsi_token *tokens ) +{ + ctx->FullVersion.Version = *(struct tgsi_version *) &tokens[0]; + if( ctx->FullVersion.Version.MajorVersion > 1 ) { + return TGSI_PARSE_ERROR; + } + + ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[1]; + if( ctx->FullHeader.Header.HeaderSize >= 2 ) { + ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[2]; + } + else { + ctx->FullHeader.Processor = tgsi_default_processor(); + } + + ctx->Tokens = tokens; + ctx->Position = 1 + ctx->FullHeader.Header.HeaderSize; + + tgsi_full_token_init( &ctx->FullToken ); + + return TGSI_PARSE_OK; +} + +void +tgsi_parse_free( + struct tgsi_parse_context *ctx ) +{ + tgsi_full_token_free( &ctx->FullToken ); +} + +GLuint +tgsi_parse_end_of_tokens( + struct tgsi_parse_context *ctx ) +{ + return ctx->Position >= + 1 + ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize; +} + +static void +next_token( + struct tgsi_parse_context *ctx, + void *token ) +{ + assert( !tgsi_parse_end_of_tokens( ctx ) ); + + *(struct tgsi_token *) token = ctx->Tokens[ctx->Position++]; +} + +void +tgsi_parse_token( + struct tgsi_parse_context *ctx ) +{ + struct tgsi_token token; + GLuint i; + + tgsi_full_token_free( &ctx->FullToken ); + tgsi_full_token_init( &ctx->FullToken ); + + next_token( ctx, &token ); + + switch( token.Type ) { + case TGSI_TOKEN_TYPE_DECLARATION: + { + struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; + + *decl = tgsi_default_full_declaration(); + decl->Declaration = *(struct tgsi_declaration *) &token; + + switch( decl->Declaration.Type ) { + case TGSI_DECLARE_RANGE: + next_token( ctx, &decl->u.DeclarationRange ); + break; + + case TGSI_DECLARE_MASK: + next_token( ctx, &decl->u.DeclarationMask ); + break; + + default: + assert (0); + } + + if( decl->Declaration.Interpolate ) { + next_token( ctx, &decl->Interpolation ); + } + + break; + } + + case TGSI_TOKEN_TYPE_IMMEDIATE: + { + struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; + + *imm = tgsi_default_full_immediate(); + imm->Immediate = *(struct tgsi_immediate *) &token; + + assert( !imm->Immediate.Extended ); + + switch (imm->Immediate.DataType) { + case TGSI_IMM_FLOAT32: + imm->u.Pointer = malloc( + sizeof( struct tgsi_immediate_float32 ) * (imm->Immediate.Size - 1) ); + for( i = 0; i < imm->Immediate.Size - 1; i++ ) { + next_token( ctx, &imm->u.ImmediateFloat32[i] ); + } + break; + + default: + assert( 0 ); + } + + break; + } + + case TGSI_TOKEN_TYPE_INSTRUCTION: + { + struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction; + GLuint extended; + + *inst = tgsi_default_full_instruction(); + inst->Instruction = *(struct tgsi_instruction *) &token; + + extended = inst->Instruction.Extended; + + while( extended ) { + struct tgsi_src_register_ext token; + + next_token( ctx, &token ); + + switch( token.Type ) { + case TGSI_INSTRUCTION_EXT_TYPE_NV: + inst->InstructionExtNv = + *(struct tgsi_instruction_ext_nv *) &token; + break; + + case TGSI_INSTRUCTION_EXT_TYPE_LABEL: + inst->InstructionExtLabel = + *(struct tgsi_instruction_ext_label *) &token; + break; + + case TGSI_INSTRUCTION_EXT_TYPE_TEXTURE: + inst->InstructionExtTexture = + *(struct tgsi_instruction_ext_texture *) &token; + break; + + default: + assert( 0 ); + } + + extended = token.Extended; + } + + assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS ); + + for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) { + GLuint extended; + + next_token( ctx, &inst->FullDstRegisters[i].DstRegister ); + + /* + * No support for indirect or multi-dimensional addressing. + */ + assert( !inst->FullDstRegisters[i].DstRegister.Indirect ); + assert( !inst->FullDstRegisters[i].DstRegister.Dimension ); + + extended = inst->FullDstRegisters[i].DstRegister.Extended; + + while( extended ) { + struct tgsi_src_register_ext token; + + next_token( ctx, &token ); + + switch( token.Type ) { + case TGSI_DST_REGISTER_EXT_TYPE_CONDCODE: + inst->FullDstRegisters[i].DstRegisterExtConcode = + *(struct tgsi_dst_register_ext_concode *) &token; + break; + + case TGSI_DST_REGISTER_EXT_TYPE_MODULATE: + inst->FullDstRegisters[i].DstRegisterExtModulate = + *(struct tgsi_dst_register_ext_modulate *) &token; + break; + + default: + assert( 0 ); + } + + extended = token.Extended; + } + } + + assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); + + for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) { + GLuint extended; + + next_token( ctx, &inst->FullSrcRegisters[i].SrcRegister ); + + extended = inst->FullSrcRegisters[i].SrcRegister.Extended; + + while( extended ) { + struct tgsi_src_register_ext token; + + next_token( ctx, &token ); + + switch( token.Type ) { + case TGSI_SRC_REGISTER_EXT_TYPE_SWZ: + inst->FullSrcRegisters[i].SrcRegisterExtSwz = + *(struct tgsi_src_register_ext_swz *) &token; + break; + + case TGSI_SRC_REGISTER_EXT_TYPE_MOD: + inst->FullSrcRegisters[i].SrcRegisterExtMod = + *(struct tgsi_src_register_ext_mod *) &token; + break; + + default: + assert( 0 ); + } + + extended = token.Extended; + } + + if( inst->FullSrcRegisters[i].SrcRegister.Indirect ) { + next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterInd ); + + /* + * No support for indirect or multi-dimensional addressing. + */ + assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect ); + assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension ); + assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended ); + } + + if( inst->FullSrcRegisters[i].SrcRegister.Dimension ) { + next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDim ); + + /* + * No support for multi-dimensional addressing. + */ + assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Dimension ); + assert( !inst->FullSrcRegisters[i].SrcRegisterDim.Extended ); + + if( inst->FullSrcRegisters[i].SrcRegisterDim.Indirect ) { + next_token( ctx, &inst->FullSrcRegisters[i].SrcRegisterDimInd ); + + /* + * No support for indirect or multi-dimensional addressing. + */ + assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Indirect ); + assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Dimension ); + assert( !inst->FullSrcRegisters[i].SrcRegisterInd.Extended ); + } + } + } + + break; + } + + default: + assert( 0 ); + } +} + diff --git a/src/mesa/pipe/tgsi/core/tgsi_parse.h b/src/mesa/pipe/tgsi/core/tgsi_parse.h new file mode 100644 index 00000000000..61ad0669b17 --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_parse.h @@ -0,0 +1,120 @@ +#if !defined TGSI_PARSE_H +#define TGSI_PARSE_H + +#if defined __cplusplus +extern "C" { +#endif // defined __cplusplus + +struct tgsi_full_version +{ + struct tgsi_version Version; +}; + +struct tgsi_full_header +{ + struct tgsi_header Header; + struct tgsi_processor Processor; +}; + +struct tgsi_full_dst_register +{ + struct tgsi_dst_register DstRegister; + struct tgsi_dst_register_ext_concode DstRegisterExtConcode; + struct tgsi_dst_register_ext_modulate DstRegisterExtModulate; +}; + +struct tgsi_full_src_register +{ + struct tgsi_src_register SrcRegister; + struct tgsi_src_register_ext_swz SrcRegisterExtSwz; + struct tgsi_src_register_ext_mod SrcRegisterExtMod; + struct tgsi_src_register SrcRegisterInd; + struct tgsi_dimension SrcRegisterDim; + struct tgsi_src_register SrcRegisterDimInd; +}; + +struct tgsi_full_declaration +{ + struct tgsi_declaration Declaration; + union + { + struct tgsi_declaration_range DeclarationRange; + struct tgsi_declaration_mask DeclarationMask; + } u; + struct tgsi_declaration_interpolation Interpolation; +}; + +struct tgsi_full_immediate +{ + struct tgsi_immediate Immediate; + union + { + void *Pointer; + struct tgsi_immediate_float32 *ImmediateFloat32; + } u; +}; + +#define TGSI_FULL_MAX_DST_REGISTERS 2 +#define TGSI_FULL_MAX_SRC_REGISTERS 3 + +struct tgsi_full_instruction +{ + struct tgsi_instruction Instruction; + struct tgsi_instruction_ext_nv InstructionExtNv; + struct tgsi_instruction_ext_label InstructionExtLabel; + struct tgsi_instruction_ext_texture InstructionExtTexture; + struct tgsi_full_dst_register FullDstRegisters[TGSI_FULL_MAX_DST_REGISTERS]; + struct tgsi_full_src_register FullSrcRegisters[TGSI_FULL_MAX_SRC_REGISTERS]; +}; + +union tgsi_full_token +{ + struct tgsi_token Token; + struct tgsi_full_declaration FullDeclaration; + struct tgsi_full_immediate FullImmediate; + struct tgsi_full_instruction FullInstruction; +}; + +void +tgsi_full_token_init( + union tgsi_full_token *full_token ); + +void +tgsi_full_token_free( + union tgsi_full_token *full_token ); + +struct tgsi_parse_context +{ + const struct tgsi_token *Tokens; + GLuint Position; + struct tgsi_full_version FullVersion; + struct tgsi_full_header FullHeader; + union tgsi_full_token FullToken; +}; + +#define TGSI_PARSE_OK 0 +#define TGSI_PARSE_ERROR 1 + +GLuint +tgsi_parse_init( + struct tgsi_parse_context *ctx, + const struct tgsi_token *tokens ); + +void +tgsi_parse_free( + struct tgsi_parse_context *ctx ); + +GLuint +tgsi_parse_end_of_tokens( + struct tgsi_parse_context *ctx ); + +void +tgsi_parse_token( + struct tgsi_parse_context *ctx ); + +#if defined __cplusplus +} // extern "C" +#endif // defined __cplusplus + +#endif // !defined TGSI_PARSE_H + diff --git a/src/mesa/pipe/tgsi/core/tgsi_token.h b/src/mesa/pipe/tgsi/core/tgsi_token.h new file mode 100644 index 00000000000..becdd480fbd --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_token.h @@ -0,0 +1,1045 @@ +#if !defined TGSI_TOKEN_H +#define TGSI_TOKEN_H + +#if defined __cplusplus +extern "C" { +#endif // defined __cplusplus + +struct tgsi_version +{ + GLuint MajorVersion : 8; + GLuint MinorVersion : 8; + GLuint Padding : 16; +}; + +struct tgsi_header +{ + GLuint HeaderSize : 8; + GLuint BodySize : 24; +}; + +#define TGSI_PROCESSOR_FRAGMENT 0 +#define TGSI_PROCESSOR_VERTEX 1 +#define TGSI_PROCESSOR_GEOMETRY 2 + +struct tgsi_processor +{ + GLuint Processor : 4; /* TGSI_PROCESSOR_ */ + GLuint Padding : 28; +}; + +#define TGSI_TOKEN_TYPE_DECLARATION 0 +#define TGSI_TOKEN_TYPE_IMMEDIATE 1 +#define TGSI_TOKEN_TYPE_INSTRUCTION 2 + +struct tgsi_token +{ + GLuint Type : 4; /* TGSI_TOKEN_TYPE_ */ + GLuint Size : 8; /* UINT */ + GLuint Padding : 19; + GLuint Extended : 1; /* BOOL */ +}; + +#define TGSI_FILE_NULL 0 +#define TGSI_FILE_CONSTANT 1 +#define TGSI_FILE_INPUT 2 +#define TGSI_FILE_OUTPUT 3 +#define TGSI_FILE_TEMPORARY 4 +#define TGSI_FILE_SAMPLER 5 +#define TGSI_FILE_ADDRESS 6 +#define TGSI_FILE_IMMEDIATE 7 + +#define TGSI_DECLARE_RANGE 0 +#define TGSI_DECLARE_MASK 1 + +struct tgsi_declaration +{ + GLuint Type : 4; /* TGSI_TOKEN_TYPE_DECLARATION */ + GLuint Size : 8; /* UINT */ + GLuint File : 4; /* TGSI_FILE_ */ + GLuint Declare : 4; /* TGSI_DECLARE_ */ + GLuint Interpolate : 1; /* BOOL */ + GLuint Padding : 10; + GLuint Extended : 1; /* BOOL */ +}; + +struct tgsi_declaration_range +{ + GLuint First : 16; /* UINT */ + GLuint Last : 16; /* UINT */ +}; + +struct tgsi_declaration_mask +{ + GLuint Mask : 32; /* UINT */ +}; + +#define TGSI_INTERPOLATE_CONSTANT 0 +#define TGSI_INTERPOLATE_LINEAR 1 +#define TGSI_INTERPOLATE_PERSPECTIVE 2 + +struct tgsi_declaration_interpolation +{ + GLuint Interpolate : 4; /* TGSI_INTERPOLATE_ */ + GLuint Padding : 28; +}; + +#define TGSI_IMM_FLOAT32 0 + +struct tgsi_immediate +{ + GLuint Type : 4; /* TGSI_TOKEN_TYPE_IMMEDIATE */ + GLuint Size : 8; /* UINT */ + GLuint DataType : 4; /* TGSI_IMM_ */ + GLuint Padding : 15; + GLuint Extended : 1; /* BOOL */ +}; + +struct tgsi_immediate_float32 +{ + GLfloat Float; +}; + +/* + * GL_NV_vertex_program + */ +#define TGSI_OPCODE_ARL 0 +#define TGSI_OPCODE_MOV 1 +#define TGSI_OPCODE_LIT 2 +#define TGSI_OPCODE_RCP 3 +#define TGSI_OPCODE_RSQ 4 +#define TGSI_OPCODE_EXP 5 +#define TGSI_OPCODE_LOG 6 +#define TGSI_OPCODE_MUL 7 +#define TGSI_OPCODE_ADD 8 +#define TGSI_OPCODE_DP3 9 +#define TGSI_OPCODE_DP4 10 +#define TGSI_OPCODE_DST 11 +#define TGSI_OPCODE_MIN 12 +#define TGSI_OPCODE_MAX 13 +#define TGSI_OPCODE_SLT 14 +#define TGSI_OPCODE_SGE 15 +#define TGSI_OPCODE_MAD 16 + +/* + * GL_ATI_fragment_shader + */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_ADD */ +/* TGSI_OPCODE_MUL */ +#define TGSI_OPCODE_SUB 17 +#define TGSI_OPCODE_DOT3 TGSI_OPCODE_DP3 +#define TGSI_OPCODE_DOT4 TGSI_OPCODE_DP4 +/* TGSI_OPCODE_MAD */ +#define TGSI_OPCODE_LERP 18 +#define TGSI_OPCODE_CND 19 +#define TGSI_OPCODE_CND0 20 +#define TGSI_OPCODE_DOT2ADD 21 + +/* + * GL_EXT_vertex_shader + */ +#define TGSI_OPCODE_INDEX 22 +#define TGSI_OPCODE_NEGATE 23 +/* TGSI_OPCODE_DOT3 */ +/* TGSI_OPCODE_DOT4 */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_ADD */ +#define TGSI_OPCODE_MADD TGSI_OPCODE_MAD +#define TGSI_OPCODE_FRAC 24 +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +#define TGSI_OPCODE_SETGE TGSI_OPCODE_SGE +#define TGSI_OPCODE_SETLT TGSI_OPCODE_SLT +#define TGSI_OPCODE_CLAMP 25 +#define TGSI_OPCODE_FLOOR 26 +#define TGSI_OPCODE_ROUND 27 +#define TGSI_OPCODE_EXPBASE2 28 +#define TGSI_OPCODE_LOGBASE2 29 +#define TGSI_OPCODE_POWER 30 +#define TGSI_OPCODE_RECIP TGSI_OPCODE_RCP +#define TGSI_OPCODE_RECIPSQRT TGSI_OPCODE_RSQ +/* TGSI_OPCODE_SUB */ +#define TGSI_OPCODE_CROSSPRODUCT 31 +#define TGSI_OPCODE_MULTIPLYMATRIX 32 +/* TGSI_OPCODE_MOV */ + +/* + * GL_NV_vertex_program1_1 + */ +/* TGSI_OPCODE_ARL */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_LIT */ +#define TGSI_OPCODE_ABS 33 +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +/* TGSI_OPCODE_EXP */ +/* TGSI_OPCODE_LOG */ +#define TGSI_OPCODE_RCC 34 +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_ADD */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SGE */ +#define TGSI_OPCODE_DPH 35 +/* TGSI_OPCODE_SUB */ +/* TGSI_OPCODE_MAD */ + +/* + * GL_NV_fragment_program + */ +/* TGSI_OPCODE_ADD */ +#define TGSI_OPCODE_COS 36 +#define TGSI_OPCODE_DDX 37 +#define TGSI_OPCODE_DDY 38 +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DST */ +#define TGSI_OPCODE_EX2 TGSI_OPCODE_EXPBASE2 +#define TGSI_OPCODE_FLR TGSI_OPCODE_FLOOR +#define TGSI_OPCODE_FRC TGSI_OPCODE_FRAC +#define TGSI_OPCODE_KIL 39 +#define TGSI_OPCODE_LG2 TGSI_OPCODE_LOGBASE2 +/* TGSI_OPCODE_LIT */ +#define TGSI_OPCODE_LRP TGSI_OPCODE_LERP +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_MUL */ +#define TGSI_OPCODE_PK2H 40 +#define TGSI_OPCODE_PK2US 41 +#define TGSI_OPCODE_PK4B 42 +#define TGSI_OPCODE_PK4UB 43 +#define TGSI_OPCODE_POW TGSI_OPCODE_POWER +/* TGSI_OPCODE_RCP */ +#define TGSI_OPCODE_RFL 44 +/* TGSI_OPCODE_RSQ */ +#define TGSI_OPCODE_SEQ 45 +#define TGSI_OPCODE_SFL 46 +/* TGSI_OPCODE_SGE */ +#define TGSI_OPCODE_SGT 47 +#define TGSI_OPCODE_SIN 48 +#define TGSI_OPCODE_SLE 49 +/* TGSI_OPCODE_SLT */ +#define TGSI_OPCODE_SNE 50 +#define TGSI_OPCODE_STR 51 +/* TGSI_OPCODE_SUB */ +#define TGSI_OPCODE_TEX 52 +#define TGSI_OPCODE_TXD 53 +/* TGSI_OPCODE_TXP - use TGSI_OPCODE_TEX */ +#define TGSI_OPCODE_UP2H 54 +#define TGSI_OPCODE_UP2US 55 +#define TGSI_OPCODE_UP4B 56 +#define TGSI_OPCODE_UP4UB 57 +#define TGSI_OPCODE_X2D 58 + +/* + * GL_NV_vertex_program2 + */ +/* TGSI_OPCODE_ABS */ +/* TGSI_OPCODE_ADD */ +#define TGSI_OPCODE_ARA 59 +/* TGSI_OPCODE_ARL */ +#define TGSI_OPCODE_ARR 60 +#define TGSI_OPCODE_BRA 61 +#define TGSI_OPCODE_CAL 62 +/* TGSI_OPCODE_COS */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_EXP */ +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_LOG */ +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_RCC */ +/* TGSI_OPCODE_RCP */ +#define TGSI_OPCODE_RET 63 +/* TGSI_OPCODE_RSQNV */ +/* TGSI_OPCODE_SEQ */ +/* TGSI_OPCODE_SFL */ +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SGT */ +/* TGSI_OPCODE_SIN */ +/* TGSI_OPCODE_SLE */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SNE */ +#define TGSI_OPCODE_SSG 64 +/* TGSI_OPCODE_STR */ +/* TGSI_OPCODE_SUB */ + +/* + * GL_ARB_vertex_program + */ +/* TGSI_OPCODE_ABS */ +/* TGSI_OPCODE_ADD */ +/* TGSI_OPCODE_ARL */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_EXP */ +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_LOG */ +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_POW */ +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SUB */ +#define TGSI_OPCODE_SWZ TGSI_OPCODE_MOV +#define TGSI_OPCODE_XPD TGSI_OPCODE_CROSSPRODUCT + +/* + * GL_ARB_fragment_program + */ +/* TGSI_OPCODE_ABS */ +/* TGSI_OPCODE_ADD */ +#define TGSI_OPCODE_CMP 65 +/* TGSI_OPCODE_COS */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_LRP */ +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_POW */ +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +#define TGSI_OPCODE_SCS 66 +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SIN */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SUB */ +/* TGSI_OPCODE_SWZ */ +/* TGSI_OPCODE_XPD */ +/* TGSI_OPCODE_TEX */ +/* TGSI_OPCODE_TXP */ +#define TGSI_OPCODE_TXB 67 +/* TGSI_OPCODE_KIL */ + +/* + * GL_NV_fragment_program_option + */ +/* TGSI_OPCODE_ABS */ +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_DDX */ +/* TGSI_OPCODE_DDY */ +/* TGSI_OPCODE_PK2H */ +/* TGSI_OPCODE_PK2US */ +/* TGSI_OPCODE_PK4B */ +/* TGSI_OPCODE_PK4UB */ +/* TGSI_OPCODE_COS */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +/* TGSI_OPCODE_SIN */ +/* TGSI_OPCODE_SCS */ +/* TGSI_OPCODE_UP2H */ +/* TGSI_OPCODE_UP2US */ +/* TGSI_OPCODE_UP4B */ +/* TGSI_OPCODE_UP4UB */ +/* TGSI_OPCODE_POW */ +/* TGSI_OPCODE_ADD */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SUB */ +/* TGSI_OPCODE_XPD */ +/* TGSI_OPCODE_RFL */ +/* TGSI_OPCODE_SEQ */ +/* TGSI_OPCODE_SFL */ +/* TGSI_OPCODE_SGT */ +/* TGSI_OPCODE_SLE */ +/* TGSI_OPCODE_SNE */ +/* TGSI_OPCODE_STR */ +/* TGSI_OPCODE_CMP */ +/* TGSI_OPCODE_LRP */ +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_X2D */ +/* TGSI_OPCODE_SWZ */ +/* TGSI_OPCODE_TEX */ +/* TGSI_OPCODE_TXP */ +/* TGSI_OPCODE_TXB */ +/* TGSI_OPCODE_KIL */ +/* TGSI_OPCODE_TXD */ + +/* + * GL_NV_fragment_program2 + */ +/* TGSI_OPCODE_ABS */ +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_DDX */ +/* TGSI_OPCODE_DDY */ +/* TGSI_OPCODE_PK2H */ +/* TGSI_OPCODE_PK2US */ +/* TGSI_OPCODE_PK4B */ +/* TGSI_OPCODE_PK4UB */ +#define TGSI_OPCODE_NRM 68 +#define TGSI_OPCODE_DIV 69 +/* TGSI_OPCODE_COS */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +/* TGSI_OPCODE_SIN */ +/* TGSI_OPCODE_SCS */ +/* TGSI_OPCODE_UP2H */ +/* TGSI_OPCODE_UP2US */ +/* TGSI_OPCODE_UP4B */ +/* TGSI_OPCODE_UP4UB */ +/* TGSI_OPCODE_POW */ +/* TGSI_OPCODE_ADD */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SUB */ +/* TGSI_OPCODE_XPD */ +/* TGSI_OPCODE_RFL */ +/* TGSI_OPCODE_SEQ */ +/* TGSI_OPCODE_SFL */ +/* TGSI_OPCODE_SGT */ +/* TGSI_OPCODE_SLE */ +/* TGSI_OPCODE_SNE */ +/* TGSI_OPCODE_STR */ +#define TGSI_OPCODE_DP2 70 +/* TGSI_OPCODE_CMP */ +/* TGSI_OPCODE_LRP */ +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_X2D */ +#define TGSI_OPCODE_DP2A TGSI_OPCODE_DOT2ADD +/* TGSI_OPCODE_SWZ */ +/* TGSI_OPCODE_TEX */ +/* TGSI_OPCODE_TXP */ +/* TGSI_OPCODE_TXB */ +#define TGSI_OPCODE_TXL 71 +/* TGSI_OPCODE_KIL */ +/* TGSI_OPCODE_TXD */ +/* TGSI_OPCODE_CAL */ +/* TGSI_OPCODE_RET */ +#define TGSI_OPCODE_BRK 72 +#define TGSI_OPCODE_IF 73 +#define TGSI_OPCODE_LOOP 74 +#define TGSI_OPCODE_REP 75 +#define TGSI_OPCODE_ELSE 76 +#define TGSI_OPCODE_ENDIF 77 +#define TGSI_OPCODE_ENDLOOP 78 +#define TGSI_OPCODE_ENDREP 79 + +/* + * GL_NV_vertex_program2_option + */ +/* TGSI_OPCODE_ARL */ +/* TGSI_OPCODE_ABS */ +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_SSG */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_EXP */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_LOG */ +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +/* TGSI_OPCODE_COS */ +/* TGSI_OPCODE_RCC */ +/* TGSI_OPCODE_SIN */ +/* TGSI_OPCODE_POW */ +/* TGSI_OPCODE_ADD */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SUB */ +/* TGSI_OPCODE_XPD */ +/* TGSI_OPCODE_SEQ */ +/* TGSI_OPCODE_SFL */ +/* TGSI_OPCODE_SGT */ +/* TGSI_OPCODE_SLE */ +/* TGSI_OPCODE_SNE */ +/* TGSI_OPCODE_STR */ +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_SWZ */ +/* TGSI_OPCODE_ARR */ +/* TGSI_OPCODE_ARA */ +/* TGSI_OPCODE_BRA */ +/* TGSI_OPCODE_CAL */ +/* TGSI_OPCODE_RET */ + +/* + * GL_NV_vertex_program3 + */ +/* TGSI_OPCODE_ARL */ +/* TGSI_OPCODE_ABS */ +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_MOV */ +/* TGSI_OPCODE_SSG */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_EXP */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_LOG */ +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +/* TGSI_OPCODE_COS */ +/* TGSI_OPCODE_RCC */ +/* TGSI_OPCODE_SIN */ +/* TGSI_OPCODE_POW */ +/* TGSI_OPCODE_ADD */ +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MUL */ +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SUB */ +/* TGSI_OPCODE_XPD */ +/* TGSI_OPCODE_SEQ */ +/* TGSI_OPCODE_SFL */ +/* TGSI_OPCODE_SGT */ +/* TGSI_OPCODE_SLE */ +/* TGSI_OPCODE_SNE */ +/* TGSI_OPCODE_STR */ +/* TGSI_OPCODE_MAD */ +/* TGSI_OPCODE_SWZ */ +/* TGSI_OPCODE_ARR */ +/* TGSI_OPCODE_ARA */ +/* TGSI_OPCODE_BRA */ +/* TGSI_OPCODE_CAL */ +/* TGSI_OPCODE_RET */ +#define TGSI_OPCODE_PUSHA 80 +#define TGSI_OPCODE_POPA 81 +/* TGSI_OPCODE_TEX */ +/* TGSI_OPCODE_TXP */ +/* TGSI_OPCODE_TXB */ +/* TGSI_OPCODE_TXL */ + +/* + * GL_NV_gpu_program4 + */ +/* TGSI_OPCODE_ABS */ +#define TGSI_OPCODE_CEIL 82 +/* TGSI_OPCODE_FLR */ +/* TGSI_OPCODE_FRC */ +#define TGSI_OPCODE_I2F 83 +/* TGSI_OPCODE_LIT */ +/* TGSI_OPCODE_MOV */ +#define TGSI_OPCODE_NOT 84 +/* TGSI_OPCODE_NRM */ +/* TGSI_OPCODE_PK2H */ +/* TGSI_OPCODE_PK2US */ +/* TGSI_OPCODE_PK4B */ +/* TGSI_OPCODE_PK4UB */ +/* TGSI_OPCODE_ROUND */ +/* TGSI_OPCODE_SSG */ +#define TGSI_OPCODE_TRUNC 85 +/* TGSI_OPCODE_COS */ +/* TGSI_OPCODE_EX2 */ +/* TGSI_OPCODE_LG2 */ +/* TGSI_OPCODE_RCC */ +/* TGSI_OPCODE_RCP */ +/* TGSI_OPCODE_RSQ */ +/* TGSI_OPCODE_SCS */ +/* TGSI_OPCODE_SIN */ +/* TGSI_OPCODE_UP2H */ +/* TGSI_OPCODE_UP2US */ +/* TGSI_OPCODE_UP4B */ +/* TGSI_OPCODE_UP4UB */ +/* TGSI_OPCODE_POW */ +/* TGSI_OPCODE_DIV */ +#define TGSI_OPCODE_SHL 86 +#define TGSI_OPCODE_SHR 87 +/* TGSI_OPCODE_ADD */ +#define TGSI_OPCODE_AND 88 +/* TGSI_OPCODE_DP3 */ +/* TGSI_OPCODE_DP4 */ +/* TGSI_OPCODE_DPH */ +/* TGSI_OPCODE_DST */ +/* TGSI_OPCODE_MAX */ +/* TGSI_OPCODE_MIN */ +/* TGSI_OPCODE_MUL */ +#define TGSI_OPCODE_OR 89 +/* TGSI_OPCODE_RFL */ +/* TGSI_OPCODE_SEQ */ +/* TGSI_OPCODE_SFL */ +/* TGSI_OPCODE_SGE */ +/* TGSI_OPCODE_SGT */ +/* TGSI_OPCODE_SLE */ +/* TGSI_OPCODE_SLT */ +/* TGSI_OPCODE_SNE */ +/* TGSI_OPCODE_STR */ +/* TGSI_OPCODE_SUB */ +/* TGSI_OPCODE_XPD */ +/* TGSI_OPCODE_DP2 */ +#define TGSI_OPCODE_MOD 90 +#define TGSI_OPCODE_XOR 91 +/* TGSI_OPCODE_CMP */ +/* TGSI_OPCODE_DP2A */ +/* TGSI_OPCODE_LRP */ +/* TGSI_OPCODE_MAD */ +#define TGSI_OPCODE_SAD 92 +/* TGSI_OPCODE_X2D */ +/* TGSI_OPCODE_SWZ */ +/* TGSI_OPCODE_TEX */ +/* TGSI_OPCODE_TXB */ +#define TGSI_OPCODE_TXF 93 +/* TGSI_OPCODE_TXL */ +/* TGSI_OPCODE_TXP */ +#define TGSI_OPCODE_TXQ 94 +/* TGSI_OPCODE_TXD */ +/* TGSI_OPCODE_CAL */ +/* TGSI_OPCODE_RET */ +/* TGSI_OPCODE_BRK */ +#define TGSI_OPCODE_CONT 95 +/* TGSI_OPCODE_IF */ +/* TGSI_OPCODE_REP */ +/* TGSI_OPCODE_ELSE */ +/* TGSI_OPCODE_ENDIF */ +/* TGSI_OPCODE_ENDREP */ + +/* + * GL_NV_vertex_program4 + */ +/* Same as GL_NV_gpu_program4 */ + +/* + * GL_NV_fragment_program4 + */ +/* Same as GL_NV_gpu_program4 */ +/* TGSI_OPCODE_KIL */ +/* TGSI_OPCODE_DDX */ +/* TGSI_OPCODE_DDY */ + +/* + * GL_NV_geometry_program4 + */ +/* Same as GL_NV_gpu_program4 */ +#define TGSI_OPCODE_EMIT 96 +#define TGSI_OPCODE_ENDPRIM 97 + +#define TGSI_OPCODE_LAST 98 + +#define TGSI_SAT_NONE 0 /* do not saturate */ +#define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */ +#define TGSI_SAT_MINUS_PLUS_ONE 2 /* clamp to [-1,1] */ + +/* + * Opcode is the operation code to execute. A given operation defines the + * semantics how the source registers (if any) are interpreted and what is + * written to the destination registers (if any) as a result of execution. + * + * NumDstRegs and NumSrcRegs is the number of destination and source registers, + * respectively. For a given operation code, those numbers are fixed and are + * present here only for convenience. + * + * If Extended is TRUE, it is now executed. + * + * Saturate controls how are final results in destination registers modified. + */ + +struct tgsi_instruction +{ + GLuint Type : 4; /* TGSI_TOKEN_TYPE_INSTRUCTION */ + GLuint Size : 8; /* UINT */ + GLuint Opcode : 8; /* TGSI_OPCODE_ */ + GLuint Saturate : 2; /* TGSI_SAT_ */ + GLuint NumDstRegs : 2; /* UINT */ + GLuint NumSrcRegs : 4; /* UINT */ + GLuint Padding : 3; + GLuint Extended : 1; /* BOOL */ +}; + +/* + * If tgsi_instruction::Extended is TRUE, tgsi_instruction_ext follows. + * + * Then, tgsi_instruction::NumDstRegs of tgsi_dst_register follow. + * + * Then, tgsi_instruction::NumSrcRegs of tgsi_src_register follow. + * + * tgsi_instruction::Size contains the total number of words that make the + * instruction, including the instruction word. + */ + +#define TGSI_INSTRUCTION_EXT_TYPE_NV 0 +#define TGSI_INSTRUCTION_EXT_TYPE_LABEL 1 +#define TGSI_INSTRUCTION_EXT_TYPE_TEXTURE 2 + +struct tgsi_instruction_ext +{ + GLuint Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_ */ + GLuint Padding : 27; + GLuint Extended : 1; /* BOOL */ +}; + +/* + * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_NV, it should + * be cast to tgsi_instruction_ext_nv. + * + * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_LABEL, it + * should be cast to tgsi_instruction_ext_label. + * + * If tgsi_instruction_ext::Type is TGSI_INSTRUCTION_EXT_TYPE_TEXTURE, it + * should be cast to tgsi_instruction_ext_texture. + * + * If tgsi_instruction_ext::Extended is TRUE, another tgsi_instruction_ext + * follows. + */ + +#define TGSI_PRECISION_DEFAULT 0 +#define TGSI_PRECISION_FLOAT32 1 +#define TGSI_PRECISION_FLOAT16 2 +#define TGSI_PRECISION_FIXED12 3 + +#define TGSI_CC_GT 0 +#define TGSI_CC_EQ 1 +#define TGSI_CC_LT 2 +#define TGSI_CC_UN 3 +#define TGSI_CC_GE 4 +#define TGSI_CC_LE 5 +#define TGSI_CC_NE 6 +#define TGSI_CC_TR 7 +#define TGSI_CC_FL 8 + +#define TGSI_SWIZZLE_X 0 +#define TGSI_SWIZZLE_Y 1 +#define TGSI_SWIZZLE_Z 2 +#define TGSI_SWIZZLE_W 3 + +/* + * Precision controls the precision at which the operation should be executed. + * + * CondDstUpdate enables condition code register writes. When this field is + * TRUE, CondDstIndex specifies the index of the condition code register to + * update. + * + * CondFlowEnable enables conditional execution of the operation. When this + * field is TRUE, CondFlowIndex specifies the index of the condition code + * register to test against CondMask with component swizzle controled by + * CondSwizzleX, CondSwizzleY, CondSwizzleZ and CondSwizzleW. If the test fails, + * the operation is not executed. + */ + +struct tgsi_instruction_ext_nv +{ + GLuint Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_NV */ + GLuint Precision : 4; /* TGSI_PRECISION_ */ + GLuint CondDstIndex : 4; /* UINT */ + GLuint CondFlowIndex : 4; /* UINT */ + GLuint CondMask : 4; /* TGSI_CC_ */ + GLuint CondSwizzleX : 2; /* TGSI_SWIZZLE_ */ + GLuint CondSwizzleY : 2; /* TGSI_SWIZZLE_ */ + GLuint CondSwizzleZ : 2; /* TGSI_SWIZZLE_ */ + GLuint CondSwizzleW : 2; /* TGSI_SWIZZLE_ */ + GLuint CondDstUpdate : 1; /* BOOL */ + GLuint CondFlowEnable : 1; /* BOOL */ + GLuint Padding : 1; + GLuint Extended : 1; /* BOOL */ +}; + +struct tgsi_instruction_ext_label +{ + GLuint Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_LABEL */ + GLuint Label : 24; /* UINT */ + GLuint Target : 1; /* BOOL */ + GLuint Padding : 2; + GLuint Extended : 1; /* BOOL */ +}; + +#define TGSI_TEXTURE_UNKNOWN 0 +#define TGSI_TEXTURE_1D 1 +#define TGSI_TEXTURE_2D 2 +#define TGSI_TEXTURE_3D 3 +#define TGSI_TEXTURE_CUBE 4 +#define TGSI_TEXTURE_RECT 5 +#define TGSI_TEXTURE_SHADOW1D 6 +#define TGSI_TEXTURE_SHADOW2D 7 +#define TGSI_TEXTURE_SHADOWRECT 8 + +struct tgsi_instruction_ext_texture +{ + GLuint Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_TEXTURE */ + GLuint Texture : 8; /* TGSI_TEXTURE_ */ + GLuint Padding : 19; + GLuint Extended : 1; /* BOOL */ +}; + +/* + * File specifies the register array to access. + * + * Index specifies the element number of a register in the register file. + * + * If Indirect is TRUE, Index should be offset by the X component of a source + * register that follows. The register can be now fetched into local storage + * for further processing. + * + * If Negate is TRUE, all components of the fetched register are negated. + * + * The fetched register components are swizzled according to SwizzleX, SwizzleY, + * SwizzleZ and SwizzleW. + * + * If Extended is TRUE, any further modifications to the source register are + * made to this temporary storage. + */ + +struct tgsi_src_register +{ + GLuint File : 4; /* TGSI_FILE_ */ + GLuint SwizzleX : 2; /* TGSI_SWIZZLE_ */ + GLuint SwizzleY : 2; /* TGSI_SWIZZLE_ */ + GLuint SwizzleZ : 2; /* TGSI_SWIZZLE_ */ + GLuint SwizzleW : 2; /* TGSI_SWIZZLE_ */ + GLuint Negate : 1; /* BOOL */ + GLuint Indirect : 1; /* BOOL */ + GLuint Dimension : 1; /* BOOL */ + GLint Index : 16; /* SINT */ + GLuint Extended : 1; /* BOOL */ +}; + +/* + * If tgsi_src_register::Extended is TRUE, tgsi_src_register_ext follows. + * + * Then, if tgsi_src_register::Indirect is TRUE, another tgsi_src_register + * follows. + * + * Then, if tgsi_src_register::Dimension is TRUE, tgsi_dimension follows. + */ + +#define TGSI_SRC_REGISTER_EXT_TYPE_SWZ 0 +#define TGSI_SRC_REGISTER_EXT_TYPE_MOD 1 + +struct tgsi_src_register_ext +{ + GLuint Type : 4; /* TGSI_SRC_REGISTER_EXT_TYPE_ */ + GLuint Padding : 27; + GLuint Extended : 1; /* BOOL */ +}; + +/* + * If tgsi_src_register_ext::Type is TGSI_SRC_REGISTER_EXT_TYPE_SWZ, + * it should be cast to tgsi_src_register_ext_extswz. + * + * If tgsi_src_register_ext::Type is TGSI_SRC_REGISTER_EXT_TYPE_MOD, + * it should be cast to tgsi_src_register_ext_mod. + * + * If tgsi_dst_register_ext::Extended is TRUE, another tgsi_dst_register_ext + * follows. + */ + +#define TGSI_EXTSWIZZLE_X TGSI_SWIZZLE_X +#define TGSI_EXTSWIZZLE_Y TGSI_SWIZZLE_Y +#define TGSI_EXTSWIZZLE_Z TGSI_SWIZZLE_Z +#define TGSI_EXTSWIZZLE_W TGSI_SWIZZLE_W +#define TGSI_EXTSWIZZLE_ZERO 4 +#define TGSI_EXTSWIZZLE_ONE 5 + +/* + * ExtSwizzleX, ExtSwizzleY, ExtSwizzleZ and ExtSwizzleW swizzle the source + * register in an extended manner. + * + * NegateX, NegateY, NegateZ and NegateW negate individual components of the + * source register. + * + * ExtDivide specifies which component is used to divide all components of the + * source register. + */ + +struct tgsi_src_register_ext_swz +{ + GLuint Type : 4; /* TGSI_SRC_REGISTER_EXT_TYPE_SWZ */ + GLuint ExtSwizzleX : 4; /* TGSI_EXTSWIZZLE_ */ + GLuint ExtSwizzleY : 4; /* TGSI_EXTSWIZZLE_ */ + GLuint ExtSwizzleZ : 4; /* TGSI_EXTSWIZZLE_ */ + GLuint ExtSwizzleW : 4; /* TGSI_EXTSWIZZLE_ */ + GLuint NegateX : 1; /* BOOL */ + GLuint NegateY : 1; /* BOOL */ + GLuint NegateZ : 1; /* BOOL */ + GLuint NegateW : 1; /* BOOL */ + GLuint ExtDivide : 4; /* TGSI_EXTSWIZZLE_ */ + GLuint Padding : 3; + GLuint Extended : 1; /* BOOL */ +}; + +/* + * If Complement is TRUE, the source register is modified by subtracting it + * from 1.0. + * + * If Bias is TRUE, the source register is modified by subtracting 0.5 from it. + * + * If Scale2X is TRUE, the source register is modified by multiplying it by 2.0. + * + * If Absolute is TRUE, the source register is modified by removing the sign. + * + * If Negate is TRUE, the source register is modified by negating it. + */ + +struct tgsi_src_register_ext_mod +{ + GLuint Type : 4; /* TGSI_SRC_REGISTER_EXT_TYPE_MOD */ + GLuint Complement : 1; /* BOOL */ + GLuint Bias : 1; /* BOOL */ + GLuint Scale2X : 1; /* BOOL */ + GLuint Absolute : 1; /* BOOL */ + GLuint Negate : 1; /* BOOL */ + GLuint Padding : 22; + GLuint Extended : 1; /* BOOL */ +}; + +struct tgsi_dimension +{ + GLuint Indirect : 1; /* BOOL */ + GLuint Dimension : 1; /* BOOL */ + GLuint Padding : 13; + GLint Index : 16; /* SINT */ + GLuint Extended : 1; /* BOOL */ +}; + +#define TGSI_WRITEMASK_NONE 0x00 +#define TGSI_WRITEMASK_X 0x01 +#define TGSI_WRITEMASK_Y 0x02 +#define TGSI_WRITEMASK_XY 0x03 +#define TGSI_WRITEMASK_Z 0x04 +#define TGSI_WRITEMASK_XZ 0x05 +#define TGSI_WRITEMASK_YZ 0x06 +#define TGSI_WRITEMASK_XYZ 0x07 +#define TGSI_WRITEMASK_W 0x08 +#define TGSI_WRITEMASK_XW 0x09 +#define TGSI_WRITEMASK_YW 0x0A +#define TGSI_WRITEMASK_XYW 0x0B +#define TGSI_WRITEMASK_ZW 0x0C +#define TGSI_WRITEMASK_XZW 0x0D +#define TGSI_WRITEMASK_YZW 0x0E +#define TGSI_WRITEMASK_XYZW 0x0F + +struct tgsi_dst_register +{ + GLuint File : 4; /* TGSI_FILE_ */ + GLuint WriteMask : 4; /* TGSI_WRITEMASK_ */ + GLuint Indirect : 1; /* BOOL */ + GLuint Dimension : 1; /* BOOL */ + GLint Index : 16; /* SINT */ + GLuint Padding : 5; + GLuint Extended : 1; /* BOOL */ +}; + +/* + * If tgsi_dst_register::Extended is TRUE, tgsi_dst_register_ext follows. + * + * Then, if tgsi_dst_register::Indirect is TRUE, tgsi_src_register follows. + */ + +#define TGSI_DST_REGISTER_EXT_TYPE_CONDCODE 0 +#define TGSI_DST_REGISTER_EXT_TYPE_MODULATE 1 + +struct tgsi_dst_register_ext +{ + GLuint Type : 4; /* TGSI_DST_REGISTER_EXT_TYPE_ */ + GLuint Padding : 27; + GLuint Extended : 1; /* BOOL */ +}; + +/* + * If tgsi_dst_register_ext::Type is TGSI_DST_REGISTER_EXT_TYPE_CONDCODE, + * it should be cast to tgsi_dst_register_ext_condcode. + * + * If tgsi_dst_register_ext::Type is TGSI_DST_REGISTER_EXT_TYPE_MODULATE, + * it should be cast to tgsi_dst_register_ext_modulate. + * + * If tgsi_dst_register_ext::Extended is TRUE, another tgsi_dst_register_ext + * follows. + */ + +struct tgsi_dst_register_ext_concode +{ + GLuint Type : 4; /* TGSI_DST_REGISTER_EXT_TYPE_CONDCODE */ + GLuint CondMask : 4; /* TGSI_CC_ */ + GLuint CondSwizzleX : 2; /* TGSI_SWIZZLE_ */ + GLuint CondSwizzleY : 2; /* TGSI_SWIZZLE_ */ + GLuint CondSwizzleZ : 2; /* TGSI_SWIZZLE_ */ + GLuint CondSwizzleW : 2; /* TGSI_SWIZZLE_ */ + GLuint CondSrcIndex : 4; /* UINT */ + GLuint Padding : 11; + GLuint Extended : 1; /* BOOL */ +}; + +#define TGSI_MODULATE_1X 0 +#define TGSI_MODULATE_2X 1 +#define TGSI_MODULATE_4X 2 +#define TGSI_MODULATE_8X 3 +#define TGSI_MODULATE_HALF 4 +#define TGSI_MODULATE_QUARTER 5 +#define TGSI_MODULATE_EIGHTH 6 + +struct tgsi_dst_register_ext_modulate +{ + GLuint Type : 4; /* TGSI_DST_REGISTER_EXT_TYPE_MODULATE */ + GLuint Modulate : 4; /* TGSI_MODULATE_ */ + GLuint Padding : 23; + GLuint Extended : 1; /* BOOL */ +}; + +#if defined __cplusplus +} // extern "C" +#endif // defined __cplusplus + +#endif // !defined TGSI_TOKEN_H + diff --git a/src/mesa/pipe/tgsi/core/tgsi_util.c b/src/mesa/pipe/tgsi/core/tgsi_util.c new file mode 100644 index 00000000000..38d6d6e6bcd --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_util.c @@ -0,0 +1,270 @@ +#include "tgsi_platform.h" +#include "tgsi_core.h" + +union pointer_hack +{ + void *pointer; + unsigned long long uint64; +}; + +void * +tgsi_align_128bit( + void *unaligned ) +{ + union pointer_hack ph; + + ph.uint64 = 0; + ph.pointer = unaligned; + ph.uint64 = (ph.uint64 + 15) & ~15; + return ph.pointer; +} + +GLuint +tgsi_util_get_src_register_swizzle( + const struct tgsi_src_register *reg, + GLuint component ) +{ + switch( component ) { + case 0: + return reg->SwizzleX; + case 1: + return reg->SwizzleY; + case 2: + return reg->SwizzleZ; + case 3: + return reg->SwizzleW; + default: + assert( 0 ); + } + return 0; +} + +GLuint +tgsi_util_get_src_register_extswizzle( + const struct tgsi_src_register_ext_swz *reg, + GLuint component ) +{ + switch( component ) { + case 0: + return reg->ExtSwizzleX; + case 1: + return reg->ExtSwizzleY; + case 2: + return reg->ExtSwizzleZ; + case 3: + return reg->ExtSwizzleW; + default: + assert( 0 ); + } + return 0; +} + +GLuint +tgsi_util_get_full_src_register_extswizzle( + const struct tgsi_full_src_register *reg, + GLuint component ) +{ + GLuint swizzle; + + /* + * First, calculate the extended swizzle for a given channel. This will give + * us either a channel index into the simple swizzle or a constant 1 or 0. + */ + swizzle = tgsi_util_get_src_register_extswizzle( + ®->SrcRegisterExtSwz, + component ); + + assert (TGSI_SWIZZLE_X == TGSI_EXTSWIZZLE_X); + assert (TGSI_SWIZZLE_Y == TGSI_EXTSWIZZLE_Y); + assert (TGSI_SWIZZLE_Z == TGSI_EXTSWIZZLE_Z); + assert (TGSI_SWIZZLE_W == TGSI_EXTSWIZZLE_W); + assert (TGSI_EXTSWIZZLE_ZERO > TGSI_SWIZZLE_W); + assert (TGSI_EXTSWIZZLE_ONE > TGSI_SWIZZLE_W); + + /* + * Second, calculate the simple swizzle for the unswizzled channel index. + * Leave the constants intact, they are not affected by the simple swizzle. + */ + if( swizzle <= TGSI_SWIZZLE_W ) { + swizzle = tgsi_util_get_src_register_swizzle( + ®->SrcRegister, + swizzle ); + } + + return swizzle; +} + +void +tgsi_util_set_src_register_swizzle( + struct tgsi_src_register *reg, + GLuint swizzle, + GLuint component ) +{ + switch( component ) { + case 0: + reg->SwizzleX = swizzle; + break; + case 1: + reg->SwizzleY = swizzle; + break; + case 2: + reg->SwizzleZ = swizzle; + break; + case 3: + reg->SwizzleW = swizzle; + break; + default: + assert( 0 ); + } +} + +void +tgsi_util_set_src_register_extswizzle( + struct tgsi_src_register_ext_swz *reg, + GLuint swizzle, + GLuint component ) +{ + switch( component ) { + case 0: + reg->ExtSwizzleX = swizzle; + break; + case 1: + reg->ExtSwizzleY = swizzle; + break; + case 2: + reg->ExtSwizzleZ = swizzle; + break; + case 3: + reg->ExtSwizzleW = swizzle; + break; + default: + assert( 0 ); + } +} + +GLuint +tgsi_util_get_src_register_extnegate( + const struct tgsi_src_register_ext_swz *reg, + GLuint component ) +{ + switch( component ) { + case 0: + return reg->NegateX; + case 1: + return reg->NegateY; + case 2: + return reg->NegateZ; + case 3: + return reg->NegateW; + default: + assert( 0 ); + } + return 0; +} + +void +tgsi_util_set_src_register_extnegate( + struct tgsi_src_register_ext_swz *reg, + GLuint negate, + GLuint component ) +{ + switch( component ) { + case 0: + reg->NegateX = negate; + break; + case 1: + reg->NegateY = negate; + break; + case 2: + reg->NegateZ = negate; + break; + case 3: + reg->NegateW = negate; + break; + default: + assert( 0 ); + } +} + +GLuint +tgsi_util_get_full_src_register_sign_mode( + const struct tgsi_full_src_register *reg, + GLuint component ) +{ + GLuint sign_mode; + + if( reg->SrcRegisterExtMod.Absolute ) { + /* Consider only the post-abs negation. */ + + if( reg->SrcRegisterExtMod.Negate ) { + sign_mode = TGSI_UTIL_SIGN_SET; + } + else { + sign_mode = TGSI_UTIL_SIGN_CLEAR; + } + } + else { + /* Accumulate the three negations. */ + + GLuint negate; + + negate = reg->SrcRegister.Negate; + if( tgsi_util_get_src_register_extnegate( ®->SrcRegisterExtSwz, component ) ) { + negate = !negate; + } + if( reg->SrcRegisterExtMod.Negate ) { + negate = !negate; + } + + if( negate ) { + sign_mode = TGSI_UTIL_SIGN_TOGGLE; + } + else { + sign_mode = TGSI_UTIL_SIGN_KEEP; + } + } + + return sign_mode; +} + +void +tgsi_util_set_full_src_register_sign_mode( + struct tgsi_full_src_register *reg, + GLuint sign_mode ) +{ + reg->SrcRegisterExtSwz.NegateX = 0; + reg->SrcRegisterExtSwz.NegateY = 0; + reg->SrcRegisterExtSwz.NegateZ = 0; + reg->SrcRegisterExtSwz.NegateW = 0; + + switch (sign_mode) + { + case TGSI_UTIL_SIGN_CLEAR: + reg->SrcRegister.Negate = 0; + reg->SrcRegisterExtMod.Absolute = 1; + reg->SrcRegisterExtMod.Negate = 0; + break; + + case TGSI_UTIL_SIGN_SET: + reg->SrcRegister.Negate = 0; + reg->SrcRegisterExtMod.Absolute = 1; + reg->SrcRegisterExtMod.Negate = 1; + break; + + case TGSI_UTIL_SIGN_TOGGLE: + reg->SrcRegister.Negate = 1; + reg->SrcRegisterExtMod.Absolute = 0; + reg->SrcRegisterExtMod.Negate = 0; + break; + + case TGSI_UTIL_SIGN_KEEP: + reg->SrcRegister.Negate = 0; + reg->SrcRegisterExtMod.Absolute = 0; + reg->SrcRegisterExtMod.Negate = 0; + break; + + default: + assert( 0 ); + } +} + diff --git a/src/mesa/pipe/tgsi/core/tgsi_util.h b/src/mesa/pipe/tgsi/core/tgsi_util.h new file mode 100644 index 00000000000..70c48690c5b --- /dev/null +++ b/src/mesa/pipe/tgsi/core/tgsi_util.h @@ -0,0 +1,70 @@ +#if !defined TGSI_UTIL_H +#define TGSI_UTIL_H + +#if defined __cplusplus +extern "C" { +#endif // defined __cplusplus + +void * +tgsi_align_128bit( + void *unaligned ); + +GLuint +tgsi_util_get_src_register_swizzle( + const struct tgsi_src_register *reg, + GLuint component ); + +GLuint +tgsi_util_get_src_register_extswizzle( + const struct tgsi_src_register_ext_swz *reg, + GLuint component); + +GLuint +tgsi_util_get_full_src_register_extswizzle( + const struct tgsi_full_src_register *reg, + GLuint component ); + +void +tgsi_util_set_src_register_swizzle( + struct tgsi_src_register *reg, + GLuint swizzle, + GLuint component ); + +void +tgsi_util_set_src_register_extswizzle( + struct tgsi_src_register_ext_swz *reg, + GLuint swizzle, + GLuint component ); + +GLuint +tgsi_util_get_src_register_extnegate( + const struct tgsi_src_register_ext_swz *reg, + GLuint component ); + +void +tgsi_util_set_src_register_extnegate( + struct tgsi_src_register_ext_swz *reg, + GLuint negate, + GLuint component ); + +#define TGSI_UTIL_SIGN_CLEAR 0 /* Force positive */ +#define TGSI_UTIL_SIGN_SET 1 /* Force negative */ +#define TGSI_UTIL_SIGN_TOGGLE 2 /* Negate */ +#define TGSI_UTIL_SIGN_KEEP 3 /* No change */ + +GLuint +tgsi_util_get_full_src_register_sign_mode( + const struct tgsi_full_src_register *reg, + GLuint component ); + +void +tgsi_util_set_full_src_register_sign_mode( + struct tgsi_full_src_register *reg, + GLuint sign_mode ); + +#if defined __cplusplus +} // extern "C" +#endif // defined __cplusplus + +#endif // !defined TGSI_UTIL_H + diff --git a/src/mesa/pipe/tgsi/mesa/Makefile b/src/mesa/pipe/tgsi/mesa/Makefile new file mode 100644 index 00000000000..eb8b14e0e89 --- /dev/null +++ b/src/mesa/pipe/tgsi/mesa/Makefile @@ -0,0 +1,3 @@ +default: + cd ../../.. ; make + diff --git a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c new file mode 100644 index 00000000000..a9415ac15bc --- /dev/null +++ b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c @@ -0,0 +1,546 @@ +#include "tgsi_platform.h"
+#include "tgsi_mesa.h"
+
+/*
+ * Map mesa register file to SBIR register file.
+ */
+static GLuint
+map_register_file(
+ enum register_file file )
+{
+ switch( file ) {
+ case PROGRAM_UNDEFINED:
+ return TGSI_FILE_NULL;
+ case PROGRAM_TEMPORARY:
+ return TGSI_FILE_TEMPORARY;
+ //case PROGRAM_LOCAL_PARAM:
+ //case PROGRAM_ENV_PARAM:
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_CONSTANT:
+ case PROGRAM_UNIFORM:
+ return TGSI_FILE_CONSTANT;
+ case PROGRAM_INPUT:
+ return TGSI_FILE_INPUT;
+ case PROGRAM_OUTPUT:
+ return TGSI_FILE_OUTPUT;
+ case PROGRAM_ADDRESS:
+ return TGSI_FILE_ADDRESS;
+ default:
+ assert( 0 );
+ return TGSI_FILE_NULL;
+ }
+}
+
+/**
+ * Map mesa register file index to SBIR index.
+ * Take special care when processing input and output indices.
+ * \param processor either TGSI_PROCESSOR_FRAGMENT or TGSI_PROCESSOR_VERTEX
+ * \param file one of TGSI_FILE_x
+ * \param index the mesa register file index
+ * \param usage_bitmask ???
+ */
+static GLuint
+map_register_file_index(
+ GLuint processor,
+ GLuint file,
+ GLuint index,
+ GLbitfield usage_bitmask )
+{
+ GLuint mapped_index;
+ GLuint i;
+
+ switch( file ) {
+ case TGSI_FILE_INPUT:
+ /*
+ * The fragment/vertex program input indexes (FRAG/VERT_ATTRIB_x) get
+ * mapped to a packed sequence of integers.
+ * If a program uses one input attribute, the mapped index will be 1.
+ * If a program uses two input attribs, the mapped indexes will be 1,2.
+ * If a program uses 3 input attribs, the mapped indexes will be 1,2,3.
+ * etc.
+ */
+ assert( index < 32 );
+ assert( usage_bitmask & (1 << index) );
+ mapped_index = 0;
+ for( i = 0; i < index; i++ ) {
+ if( usage_bitmask & (1 << i) ) {
+ mapped_index++;
+ }
+ }
+ printf("Map input %d to %d\n", index, mapped_index);
+ break;
+
+ case TGSI_FILE_OUTPUT:
+ assert( usage_bitmask == 0x0 );
+ if( processor == TGSI_PROCESSOR_FRAGMENT ) {
+ /* depth result -> index 0
+ * color results -> index 1, 2, ...
+ */
+ if( index == FRAG_RESULT_DEPR ) {
+ mapped_index = 0;
+ }
+ else {
+ assert( index == FRAG_RESULT_COLR );
+ mapped_index = index + 1;
+ }
+ }
+ else {
+ /* mapped_index = VERT_RESULT_x */
+ mapped_index = index;
+ }
+ break;
+
+ default:
+ mapped_index = index;
+ }
+
+ return mapped_index;
+}
+
+/*
+ * Map mesa texture target to SBIR texture target.
+ */
+static GLuint
+map_texture_target(
+ GLuint textarget )
+{
+ switch( textarget ) {
+ case TEXTURE_1D_INDEX:
+ return TGSI_TEXTURE_1D;
+ case TEXTURE_2D_INDEX:
+ return TGSI_TEXTURE_2D;
+ case TEXTURE_3D_INDEX:
+ return TGSI_TEXTURE_3D;
+ case TEXTURE_CUBE_INDEX:
+ return TGSI_TEXTURE_CUBE;
+ case TEXTURE_RECT_INDEX:
+ return TGSI_TEXTURE_RECT;
+ default:
+ assert( 0 );
+ }
+
+ return TGSI_TEXTURE_1D;
+}
+
+static GLuint
+convert_sat(
+ GLuint sat )
+{
+ switch( sat ) {
+ case SATURATE_OFF:
+ return TGSI_SAT_NONE;
+ case SATURATE_ZERO_ONE:
+ return TGSI_SAT_ZERO_ONE;
+ case SATURATE_PLUS_MINUS_ONE:
+ return TGSI_SAT_MINUS_PLUS_ONE;
+ default:
+ assert( 0 );
+ return TGSI_SAT_NONE;
+ }
+}
+
+static GLuint
+convert_writemask(
+ GLuint writemask )
+{
+ assert( WRITEMASK_X == TGSI_WRITEMASK_X );
+ assert( WRITEMASK_Y == TGSI_WRITEMASK_Y );
+ assert( WRITEMASK_Z == TGSI_WRITEMASK_Z );
+ assert( WRITEMASK_W == TGSI_WRITEMASK_W );
+ assert( (writemask & ~TGSI_WRITEMASK_XYZW) == 0 );
+
+ return writemask;
+}
+
+static GLboolean
+compile_instruction(
+ const struct prog_instruction *inst,
+ struct tgsi_full_instruction *fullinst,
+ GLuint inputs_read,
+ GLuint processor )
+{
+ GLuint i;
+ struct tgsi_full_dst_register *fulldst;
+ struct tgsi_full_src_register *fullsrc;
+
+ *fullinst = tgsi_default_full_instruction();
+
+ fullinst->Instruction.Saturate = convert_sat( inst->SaturateMode );
+ fullinst->Instruction.NumDstRegs = 1;
+ fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
+
+ fulldst = &fullinst->FullDstRegisters[0];
+ fulldst->DstRegister.File = map_register_file( inst->DstReg.File );
+ fulldst->DstRegister.Index = map_register_file_index(
+ processor,
+ fulldst->DstRegister.File,
+ inst->DstReg.Index,
+ 0x0 );
+ fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
+
+ for( i = 0; i < fullinst->Instruction.NumSrcRegs; i++ ) {
+ GLuint j;
+
+ fullsrc = &fullinst->FullSrcRegisters[i];
+ fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File );
+ fullsrc->SrcRegister.Index = map_register_file_index(
+ processor,
+ fullsrc->SrcRegister.File,
+ inst->SrcReg[i].Index,
+ inputs_read );
+
+ for( j = 0; j < 4; j++ ) {
+ GLuint swz;
+
+ swz = GET_SWZ( inst->SrcReg[i].Swizzle, j );
+ if( swz > SWIZZLE_W ) {
+ tgsi_util_set_src_register_extswizzle(
+ &fullsrc->SrcRegisterExtSwz,
+ swz,
+ j );
+ }
+ else {
+ tgsi_util_set_src_register_swizzle(
+ &fullsrc->SrcRegister,
+ swz,
+ j );
+ }
+ }
+
+ if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) {
+ fullsrc->SrcRegister.Negate = 1;
+ }
+ else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) {
+ if( inst->SrcReg[i].NegateBase & NEGATE_X ) {
+ fullsrc->SrcRegisterExtSwz.NegateX = 1;
+ }
+ if( inst->SrcReg[i].NegateBase & NEGATE_Y ) {
+ fullsrc->SrcRegisterExtSwz.NegateY = 1;
+ }
+ if( inst->SrcReg[i].NegateBase & NEGATE_Z ) {
+ fullsrc->SrcRegisterExtSwz.NegateZ = 1;
+ }
+ if( inst->SrcReg[i].NegateBase & NEGATE_W ) {
+ fullsrc->SrcRegisterExtSwz.NegateW = 1;
+ }
+ }
+
+ if( inst->SrcReg[i].Abs ) {
+ fullsrc->SrcRegisterExtMod.Absolute = 1;
+ }
+
+ if( inst->SrcReg[i].NegateAbs ) {
+ fullsrc->SrcRegisterExtMod.Negate = 1;
+ }
+
+ if( inst->SrcReg[i].RelAddr ) {
+ fullsrc->SrcRegister.Indirect = 1;
+
+ fullsrc->SrcRegisterInd.File = TGSI_FILE_ADDRESS;
+ fullsrc->SrcRegisterInd.Index = 0;
+ }
+ }
+
+ switch( inst->Opcode ) {
+ case OPCODE_ARL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ARL;
+ break;
+ case OPCODE_ABS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ABS;
+ break;
+ case OPCODE_ADD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_ADD;
+ break;
+ case OPCODE_CMP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_CMP;
+ break;
+ case OPCODE_COS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_COS;
+ break;
+ case OPCODE_DP3:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP3;
+ break;
+ case OPCODE_DDX:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DDX;
+ break;
+ case OPCODE_DDY:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DDY;
+ break;
+ case OPCODE_DP4:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DP4;
+ break;
+ case OPCODE_DPH:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DPH;
+ break;
+ case OPCODE_DST:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_DST;
+ break;
+ case OPCODE_EX2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
+ break;
+ case OPCODE_FLR:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_FLR;
+ break;
+ case OPCODE_FRC:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_FRC;
+ break;
+ case OPCODE_KIL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
+ break;
+ case OPCODE_LG2:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
+ break;
+ case OPCODE_LIT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LIT;
+ break;
+ case OPCODE_LRP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_LRP;
+ break;
+ case OPCODE_MAD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MAD;
+ break;
+ case OPCODE_MAX:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MAX;
+ break;
+ case OPCODE_MIN:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MIN;
+ break;
+ case OPCODE_MOV:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MOV;
+ break;
+ case OPCODE_MUL:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_MUL;
+ break;
+ case OPCODE_POW:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_POW;
+ break;
+ case OPCODE_RCP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
+ break;
+ case OPCODE_RSQ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
+ tgsi_util_set_full_src_register_sign_mode(
+ &fullinst->FullSrcRegisters[0],
+ TGSI_UTIL_SIGN_CLEAR );
+ break;
+ case OPCODE_SCS:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SCS;
+ fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XY;
+ break;
+ case OPCODE_SGE:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SGE;
+ break;
+ case OPCODE_SIN:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SIN;
+ break;
+ case OPCODE_SLT:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SLT;
+ break;
+ case OPCODE_SUB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SUB;
+ break;
+ case OPCODE_SWZ:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_SWZ;
+ break;
+ case OPCODE_TEX:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXB:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXB;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_TXP:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
+ fullinst->Instruction.NumSrcRegs = 2;
+ fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
+ fullinst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide = TGSI_EXTSWIZZLE_W;
+ fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
+ fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
+ break;
+ case OPCODE_XPD:
+ fullinst->Instruction.Opcode = TGSI_OPCODE_XPD;
+ fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
+ break;
+ case OPCODE_END:
+ return GL_TRUE;
+ default:
+ assert( 0 );
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean
+tgsi_mesa_compile_fp_program(
+ const struct gl_fragment_program *program,
+ struct tgsi_token *tokens,
+ GLuint maxTokens )
+{
+ GLuint i, ti;
+ struct tgsi_header *header;
+ struct tgsi_full_declaration fulldecl;
+ struct tgsi_full_instruction fullinst;
+ struct tgsi_full_dst_register *fulldst;
+ struct tgsi_full_src_register *fullsrc;
+ GLuint inputs_read;
+
+ *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+
+ header = (struct tgsi_header *) &tokens[1];
+ *header = tgsi_build_header();
+
+ ti = 2;
+
+ /*
+ * Input 0 is always read, at least implicitly by the instruction generated
+ * above, so mark it as used.
+ */
+ inputs_read = program->Base.InputsRead | 1;
+
+ /*
+ * Declare input attributes.
+ */
+ fulldecl = tgsi_default_full_declaration();
+
+ fulldecl.Declaration.File = TGSI_FILE_INPUT;
+ fulldecl.Declaration.Declare = TGSI_DECLARE_RANGE;
+ fulldecl.Declaration.Interpolate = 1;
+
+ /*
+ * Do not interpolate fragment position.
+ */
+ fulldecl.u.DeclarationRange.First = 0;
+ fulldecl.u.DeclarationRange.Last = 0;
+
+ fulldecl.Interpolation.Interpolate = TGSI_INTERPOLATE_CONSTANT;
+
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ /*
+ * Interpolate generic attributes.
+ */
+ fulldecl.u.DeclarationRange.First = 1;
+ fulldecl.u.DeclarationRange.Last = 1;
+ for( i = 1; i < 32; i++ ) {
+ if( inputs_read & (1 << i) ) {
+ fulldecl.u.DeclarationRange.Last++;
+ }
+ }
+
+ fulldecl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR;
+
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ /*
+ * Copy input fragment xyz to output xyz.
+ * If the shader writes depth, do not copy the z component.
+ */
+
+ fullinst = tgsi_default_full_instruction();
+
+ fullinst.Instruction.Opcode = TGSI_OPCODE_MOV;
+ fullinst.Instruction.NumDstRegs = 1;
+ fullinst.Instruction.NumSrcRegs = 1;
+
+ fulldst = &fullinst.FullDstRegisters[0];
+ fulldst->DstRegister.File = TGSI_FILE_OUTPUT;
+ fulldst->DstRegister.Index = 0;
+ if( program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR) ) {
+ fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XY;
+ }
+ else {
+ fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
+ }
+
+ fullsrc = &fullinst.FullSrcRegisters[0];
+ fullsrc->SrcRegister.File = TGSI_FILE_INPUT;
+ fullsrc->SrcRegister.Index = 0;
+
+ ti += tgsi_build_full_instruction(
+ &fullinst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ for( i = 0; i < program->Base.NumInstructions; i++ ) {
+ if( compile_instruction(
+ &program->Base.Instructions[i],
+ &fullinst,
+ inputs_read,
+ TGSI_PROCESSOR_FRAGMENT ) ) {
+ assert( i == program->Base.NumInstructions - 1 );
+ tgsi_dump(
+ tokens,
+ TGSI_DUMP_NO_IGNORED | TGSI_DUMP_NO_DEFAULT );
+ break;
+ }
+
+ ti += tgsi_build_full_instruction(
+ &fullinst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+
+ return GL_TRUE;
+}
+
+GLboolean
+tgsi_mesa_compile_vp_program(
+ const struct gl_vertex_program *program,
+ struct tgsi_token *tokens,
+ GLuint maxTokens )
+{
+ GLuint ii, ti;
+ struct tgsi_header *header;
+ struct tgsi_processor *processor;
+ struct tgsi_full_instruction fullinst;
+ GLuint inputs_read = ~0;
+
+ *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
+
+ header = (struct tgsi_header *) &tokens[1];
+ *header = tgsi_build_header();
+
+ processor = (struct tgsi_processor *) &tokens[2];
+ *processor = tgsi_build_processor( TGSI_PROCESSOR_VERTEX, header );
+
+ ti = 3;
+
+ for( ii = 0; ii < program->Base.NumInstructions; ii++ ) {
+ if( compile_instruction(
+ &program->Base.Instructions[ii],
+ &fullinst,
+ inputs_read,
+ TGSI_PROCESSOR_VERTEX ) ) {
+ assert( ii == program->Base.NumInstructions - 1 );
+ tgsi_dump( tokens, TGSI_DUMP_NO_IGNORED | TGSI_DUMP_NO_DEFAULT );
+ break;
+ }
+
+ ti += tgsi_build_full_instruction(
+ &fullinst,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ }
+
+ return GL_TRUE;
+}
+
diff --git a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.h b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.h new file mode 100644 index 00000000000..9256318997a --- /dev/null +++ b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.h @@ -0,0 +1,27 @@ +#if !defined MESA_TO_TGSI_H
+#define MESA_TO_TGSI_H
+
+#if defined __cplusplus
+extern "C" {
+#endif // defined __cplusplus
+
+struct tgsi_token;
+
+GLboolean
+tgsi_mesa_compile_fp_program(
+ const struct gl_fragment_program *program,
+ struct tgsi_token *tokens,
+ GLuint maxTokens );
+
+GLboolean
+tgsi_mesa_compile_vp_program(
+ const struct gl_vertex_program *program,
+ struct tgsi_token *tokens,
+ GLuint maxTokens );
+
+#if defined __cplusplus
+} // extern "C"
+#endif // defined __cplusplus
+
+#endif // !defined MESA_TO_TGSI_H
+
diff --git a/src/mesa/pipe/tgsi/mesa/tgsi_mesa.h b/src/mesa/pipe/tgsi/mesa/tgsi_mesa.h new file mode 100644 index 00000000000..0053748fdef --- /dev/null +++ b/src/mesa/pipe/tgsi/mesa/tgsi_mesa.h @@ -0,0 +1,8 @@ +#if !defined TGSI_MESA_H
+#define TGSI_MESA_H
+
+#include "../core/tgsi_core.h"
+#include "mesa_to_tgsi.h"
+
+#endif // !defined TGSI_MESA_H
+
diff --git a/src/mesa/pipe/tgsi/tgsi_platform.h b/src/mesa/pipe/tgsi/tgsi_platform.h new file mode 100644 index 00000000000..553f0b26a89 --- /dev/null +++ b/src/mesa/pipe/tgsi/tgsi_platform.h @@ -0,0 +1,18 @@ +#if !defined TGSI_PLATFORM_H +#define TGSI_PLATFORM_H + +#if defined __cplusplus +extern "C" { +#endif // defined __cplusplus + +#include "imports.h" +#include "mtypes.h" +#include "prog_instruction.h" +#include "program.h" + +#if defined __cplusplus +} // extern "C" +#endif // defined __cplusplus + +#endif // !defined TGSI_PLATFORM_H + diff --git a/src/mesa/sources b/src/mesa/sources index dbfc01d0edf..a589ae4373b 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -149,6 +149,75 @@ VBO_SOURCES = \ vbo/vbo_save_draw.c \ vbo/vbo_save_loopback.c +VF_SOURCES = \ + vf/vf.c \ + vf/vf_generic.c \ + vf/vf_sse.c + +SOFTPIPE_SOURCES = \ + pipe/softpipe/sp_clear.c \ + pipe/softpipe/sp_context.c \ + pipe/softpipe/sp_quad.c \ + pipe/softpipe/sp_quad_alpha_test.c \ + pipe/softpipe/sp_quad_blend.c \ + pipe/softpipe/sp_quad_bufloop.c \ + pipe/softpipe/sp_quad_colormask.c \ + pipe/softpipe/sp_quad_coverage.c \ + pipe/softpipe/sp_quad_depth_test.c \ + pipe/softpipe/sp_quad_fs.c \ + pipe/softpipe/sp_quad_occlusion.c \ + pipe/softpipe/sp_quad_output.c \ + pipe/softpipe/sp_quad_stipple.c \ + pipe/softpipe/sp_quad_stencil.c \ + pipe/softpipe/sp_state_blend.c \ + pipe/softpipe/sp_state_clip.c \ + pipe/softpipe/sp_state_derived.c \ + pipe/softpipe/sp_state_fs.c \ + pipe/softpipe/sp_state_sampler.c \ + pipe/softpipe/sp_state_setup.c \ + pipe/softpipe/sp_state_surface.c \ + pipe/softpipe/sp_prim_setup.c + +DRAW_SOURCES = \ + pipe/draw/draw_clip.c \ + pipe/draw/draw_context.c\ + pipe/draw/draw_cull.c \ + pipe/draw/draw_flatshade.c \ + pipe/draw/draw_offset.c \ + pipe/draw/draw_twoside.c \ + pipe/draw/draw_unfilled.c \ + pipe/draw/draw_vb.c + +TGSICORE_SOURCES = \ + pipe/tgsi/core/tgsi_build.c \ + pipe/tgsi/core/tgsi_dump.c \ + pipe/tgsi/core/tgsi_exec.c \ + pipe/tgsi/core/tgsi_parse.c \ + pipe/tgsi/core/tgsi_util.c + +TGSIMESA_SOURCES = \ + pipe/tgsi/mesa/mesa_to_tgsi.c + +STATETRACKER_SOURCES = \ + state_tracker/st_atom.c \ + state_tracker/st_atom_alphatest.c \ + state_tracker/st_atom_blend.c \ + state_tracker/st_atom_clear_color.c \ + state_tracker/st_atom_clip.c \ + state_tracker/st_atom_depth.c \ + state_tracker/st_atom_fs.c \ + state_tracker/st_atom_vs.c \ + state_tracker/st_atom_framebuffer.c \ + state_tracker/st_atom_sampler.c \ + state_tracker/st_atom_scissor.c \ + state_tracker/st_atom_setup.c \ + state_tracker/st_atom_stencil.c \ + state_tracker/st_atom_stipple.c \ + state_tracker/st_atom_viewport.c \ + state_tracker/st_cb_program.c \ + state_tracker/st_draw.c \ + state_tracker/st_context.c \ + state_tracker/st_texobj.c SHADER_SOURCES = \ shader/arbprogparse.c \ @@ -250,6 +319,7 @@ X11_DRIVER_SOURCES = \ drivers/x11/xm_glide.c \ drivers/x11/xm_line.c \ drivers/x11/xm_span.c \ + drivers/x11/xm_surface.c \ drivers/x11/xm_tri.c OSMESA_DRIVER_SOURCES = \ @@ -294,6 +364,12 @@ SOLO_SOURCES = \ $(MAIN_SOURCES) \ $(MATH_SOURCES) \ $(VBO_SOURCES) \ + $(VF_SOURCES) \ + $(SOFTPIPE_SOURCES) \ + $(DRAW_SOURCES) \ + $(TGSICORE_SOURCES) \ + $(TGSIMESA_SOURCES) \ + $(STATETRACKER_SOURCES) \ $(TNL_SOURCES) \ $(SHADER_SOURCES) \ $(SWRAST_SOURCES) \ @@ -339,4 +415,5 @@ INCLUDE_DIRS = \ -I$(TOP)/src/mesa/shader/grammar \ -I$(TOP)/src/mesa/shader/slang \ -I$(TOP)/src/mesa/swrast \ - -I$(TOP)/src/mesa/swrast_setup + -I$(TOP)/src/mesa/swrast_setup \ + -I$(TOP)/src/mesa/pipe/tgsi diff --git a/src/mesa/state_tracker/Makefile b/src/mesa/state_tracker/Makefile new file mode 100644 index 00000000000..0ab1dc6e6bd --- /dev/null +++ b/src/mesa/state_tracker/Makefile @@ -0,0 +1,2 @@ +default: + cd ../.. ; make
\ No newline at end of file diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c new file mode 100644 index 00000000000..85c99bc1822 --- /dev/null +++ b/src/mesa/state_tracker/st_atom.c @@ -0,0 +1,175 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "glheader.h" +#include "context.h" + +#include "st_context.h" +#include "st_atom.h" + + + +/* This is used to initialize st->atoms[]. We could use this list + * directly except for a single atom, st_update_constants, which has a + * .dirty value which changes according to the parameters of the + * current fragment and vertex programs, and so cannot be a static + * value. + */ +static const struct st_tracked_state *atoms[] = +{ + &st_update_framebuffer, + &st_update_clear_color, + &st_update_depth, + &st_update_clip, + &st_update_vs, + &st_update_fs, + &st_update_setup, + &st_update_polygon_stipple, + &st_update_viewport, + &st_update_scissor, + &st_update_blend, + &st_update_stencil, + /* will be patched out at runtime */ +/* &st_update_constants */ +}; + + +void st_init_atoms( struct st_context *st ) +{ + GLuint i; + + st->atoms = malloc(sizeof(atoms)); + st->nr_atoms = sizeof(atoms)/sizeof(*atoms); + memcpy(st->atoms, atoms, sizeof(atoms)); + + /* Patch in a pointer to the dynamic state atom: + */ + for (i = 0; i < st->nr_atoms; i++) + if (st->atoms[i] == &st_update_constants) + st->atoms[i] = &st->constants.tracked_state; + + memcpy(&st->constants.tracked_state, + &st_update_constants, + sizeof(st_update_constants)); +} + + +void st_destroy_atoms( struct st_context *st ) +{ + if (st->atoms) { + free(st->atoms); + st->atoms = NULL; + } +} + + +/*********************************************************************** + */ + +static GLboolean check_state( const struct st_state_flags *a, + const struct st_state_flags *b ) +{ + return ((a->mesa & b->mesa) || + (a->st & b->st)); +} + +static void accumulate_state( struct st_state_flags *a, + const struct st_state_flags *b ) +{ + a->mesa |= b->mesa; + a->st |= b->st; +} + + +static void xor_states( struct st_state_flags *result, + const struct st_state_flags *a, + const struct st_state_flags *b ) +{ + result->mesa = a->mesa ^ b->mesa; + result->st = a->st ^ b->st; +} + + +/*********************************************************************** + * Update all derived state: + */ + +void st_validate_state( struct st_context *st ) +{ + struct st_state_flags *state = &st->dirty; + GLuint i; + + if (state->st == 0) + return; + + if (1) { + /* Debug version which enforces various sanity checks on the + * state flags which are generated and checked to help ensure + * state atoms are ordered correctly in the list. + */ + struct st_state_flags examined, prev; + memset(&examined, 0, sizeof(examined)); + prev = *state; + + for (i = 0; i < st->nr_atoms; i++) { + const struct st_tracked_state *atom = st->atoms[i]; + struct st_state_flags generated; + + assert(atom->dirty.mesa || + atom->dirty.st); + assert(atom->update); + + if (check_state(state, &atom->dirty)) { + st->atoms[i]->update( st ); + } + + accumulate_state(&examined, &atom->dirty); + + /* generated = (prev ^ state) + * if (examined & generated) + * fail; + */ + xor_states(&generated, &prev, state); + assert(!check_state(&examined, &generated)); + prev = *state; + } + } + else { + const GLuint nr = st->nr_atoms; + + for (i = 0; i < nr; i++) { + if (check_state(state, &st->atoms[i]->dirty)) + st->atoms[i]->update( st ); + } + } + + memset(state, 0, sizeof(*state)); +} + + + diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h new file mode 100644 index 00000000000..1b70e279339 --- /dev/null +++ b/src/mesa/state_tracker/st_atom.h @@ -0,0 +1,62 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + + +#ifndef ST_ATOM_H +#define ST_ATOM_H + +struct st_context; +struct st_tracked_state; + +void st_init_atoms( struct st_context *st ); +void st_destroy_atoms( struct st_context *st ); + + +void st_validate_state( struct st_context *st ); + + +const struct st_tracked_state st_update_framebuffer; +const struct st_tracked_state st_update_clip; +const struct st_tracked_state st_update_clear_color; +const struct st_tracked_state st_update_depth; +const struct st_tracked_state st_update_fs; +const struct st_tracked_state st_update_vs; +const struct st_tracked_state st_update_setup; +const struct st_tracked_state st_update_polygon_stipple; +const struct st_tracked_state st_update_viewport; +const struct st_tracked_state st_update_constants; +const struct st_tracked_state st_update_scissor; +const struct st_tracked_state st_update_blend; +const struct st_tracked_state st_update_stencil; + + +#endif diff --git a/src/mesa/state_tracker/st_atom_alphatest.c b/src/mesa/state_tracker/st_atom_alphatest.c new file mode 100644 index 00000000000..1e2e4497951 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_alphatest.c @@ -0,0 +1,94 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + + +/** + * Convert GLenum stencil func tokens to pipe tokens. + */ +static GLuint +gl_alpha_func_to_sp(GLenum func) +{ + /* Same values, just biased */ + assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER); + assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER); + assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER); + assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER); + assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER); + assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER); + assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER); + assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER); + assert(func >= GL_NEVER); + assert(func <= GL_ALWAYS); + return func - GL_NEVER; +} + + +static void +update_alpha_test( struct st_context *st ) +{ + struct pipe_alpha_test_state alpha; + + memset(&alpha, 0, sizeof(alpha)); + + if (st->ctx->Color.AlphaEnabled) { + alpha.enabled = 1; + alpha.func = gl_alpha_func_to_sp(st->ctx->Color.AlphaFunc); + alpha.ref = st->ctx->Color.AlphaRef; + } + + if (memcmp(&alpha, &st->state.alpha_test, sizeof(alpha)) != 0) { + /* state has changed */ + st->state.alpha_test = alpha; /* struct copy */ + st->pipe->set_alpha_test_state(st->pipe, &alpha); /* set new state */ + } +} + + +const struct st_tracked_state st_update_alpha_test = { + .dirty = { + .mesa = (_NEW_COLOR), + .st = 0, + }, + .update = update_alpha_test +}; + + + + + diff --git a/src/mesa/state_tracker/st_atom_blend.c b/src/mesa/state_tracker/st_atom_blend.c new file mode 100644 index 00000000000..256f13471a2 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_blend.c @@ -0,0 +1,240 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + + +/** + * Convert GLenum blend tokens to pipe tokens. + * Both blend factors and blend funcs are accepted. + */ +static GLuint +gl_blend_to_sp(GLenum blend) +{ + switch (blend) { + /* blend functions */ + case GL_FUNC_ADD: + return PIPE_BLEND_ADD; + case GL_FUNC_SUBTRACT: + return PIPE_BLEND_SUBTRACT; + case GL_FUNC_REVERSE_SUBTRACT: + return PIPE_BLEND_REVERSE_SUBTRACT; + case GL_MIN: + return PIPE_BLEND_MIN; + case GL_MAX: + return PIPE_BLEND_MAX; + + /* blend factors */ + case GL_ONE: + return PIPE_BLENDFACTOR_ONE; + case GL_SRC_COLOR: + return PIPE_BLENDFACTOR_SRC_COLOR; + case GL_SRC_ALPHA: + return PIPE_BLENDFACTOR_SRC_ALPHA; + case GL_DST_ALPHA: + return PIPE_BLENDFACTOR_DST_ALPHA; + case GL_DST_COLOR: + return PIPE_BLENDFACTOR_DST_COLOR; + case GL_SRC_ALPHA_SATURATE: + return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; + case GL_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_CONST_COLOR; + case GL_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_CONST_ALPHA; + /* + return PIPE_BLENDFACTOR_SRC1_COLOR; + return PIPE_BLENDFACTOR_SRC1_ALPHA; + */ + case GL_ZERO: + return PIPE_BLENDFACTOR_ZERO; + case GL_ONE_MINUS_SRC_COLOR: + return PIPE_BLENDFACTOR_INV_SRC_COLOR; + case GL_ONE_MINUS_SRC_ALPHA: + return PIPE_BLENDFACTOR_INV_SRC_ALPHA; + case GL_ONE_MINUS_DST_COLOR: + return PIPE_BLENDFACTOR_INV_DST_ALPHA; + case GL_ONE_MINUS_DST_ALPHA: + return PIPE_BLENDFACTOR_INV_DST_COLOR; + case GL_ONE_MINUS_CONSTANT_COLOR: + return PIPE_BLENDFACTOR_INV_CONST_COLOR; + case GL_ONE_MINUS_CONSTANT_ALPHA: + return PIPE_BLENDFACTOR_INV_CONST_ALPHA; + /* + return PIPE_BLENDFACTOR_INV_SRC1_COLOR; + return PIPE_BLENDFACTOR_INV_SRC1_ALPHA; + */ + default: + assert("invalid GL token in gl_blend_to_sp()" == NULL); + return 0; + } +} + + +/** + * Convert GLenum logicop tokens to pipe tokens. + */ +static GLuint +gl_logicop_to_sp(GLenum logicop) +{ + switch (logicop) { + case GL_CLEAR: + return PIPE_LOGICOP_CLEAR; + case GL_NOR: + return PIPE_LOGICOP_NOR; + case GL_AND_INVERTED: + return PIPE_LOGICOP_AND_INVERTED; + case GL_COPY_INVERTED: + return PIPE_LOGICOP_COPY_INVERTED; + case GL_AND_REVERSE: + return PIPE_LOGICOP_AND_REVERSE; + case GL_INVERT: + return PIPE_LOGICOP_INVERT; + case GL_XOR: + return PIPE_LOGICOP_XOR; + case GL_NAND: + return PIPE_LOGICOP_NAND; + case GL_AND: + return PIPE_LOGICOP_AND; + case GL_EQUIV: + return PIPE_LOGICOP_EQUIV; + case GL_NOOP: + return PIPE_LOGICOP_NOOP; + case GL_OR_INVERTED: + return PIPE_LOGICOP_OR_INVERTED; + case GL_COPY: + return PIPE_LOGICOP_COPY; + case GL_OR_REVERSE: + return PIPE_LOGICOP_OR_REVERSE; + case GL_OR: + return PIPE_LOGICOP_OR; + case GL_SET: + return PIPE_LOGICOP_SET; + default: + assert("invalid GL token in gl_logicop_to_sp()" == NULL); + return 0; + } +} + + +static void +update_blend( struct st_context *st ) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(blend)); + + if (st->ctx->Color.ColorLogicOpEnabled || + (st->ctx->Color.BlendEnabled && + st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) { + /* logicop enabled */ + blend.logicop_enable = 1; + blend.logicop_func = gl_logicop_to_sp(st->ctx->Color.LogicOp); + } + else if (st->ctx->Color.BlendEnabled) { + /* blending enabled */ + blend.blend_enable = 1; + + blend.rgb_func = gl_blend_to_sp(st->ctx->Color.BlendEquationRGB); + if (st->ctx->Color.BlendEquationRGB == GL_MIN || + st->ctx->Color.BlendEquationRGB == GL_MAX) { + /* Min/max are special */ + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + } + else { + blend.rgb_src_factor = gl_blend_to_sp(st->ctx->Color.BlendSrcRGB); + blend.rgb_dst_factor = gl_blend_to_sp(st->ctx->Color.BlendDstRGB); + } + + blend.alpha_func = gl_blend_to_sp(st->ctx->Color.BlendEquationA); + if (st->ctx->Color.BlendEquationA == GL_MIN || + st->ctx->Color.BlendEquationA == GL_MAX) { + /* Min/max are special */ + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + } + else { + blend.alpha_src_factor = gl_blend_to_sp(st->ctx->Color.BlendSrcA); + blend.alpha_dst_factor = gl_blend_to_sp(st->ctx->Color.BlendDstA); + } + } + else { + /* no blending / logicop */ + } + + /* Colormask - maybe reverse these bits? */ + if (st->ctx->Color.ColorMask[0]) + blend.colormask |= PIPE_MASK_R; + if (st->ctx->Color.ColorMask[1]) + blend.colormask |= PIPE_MASK_G; + if (st->ctx->Color.ColorMask[2]) + blend.colormask |= PIPE_MASK_B; + if (st->ctx->Color.ColorMask[3]) + blend.colormask |= PIPE_MASK_A; + + if (st->ctx->Color.DitherFlag) + blend.dither = 1; + + if (memcmp(&blend, &st->state.blend, sizeof(blend)) != 0) { + /* state has changed */ + st->state.blend = blend; /* struct copy */ + st->pipe->set_blend_state(st->pipe, &blend); /* set new state */ + } + + if (memcmp(st->ctx->Color.BlendColor, &st->state.blend_color, 4 * sizeof(GLfloat)) != 0) { + /* state has changed */ + st->state.blend_color.color[0] = st->ctx->Color.BlendColor[0]; + st->state.blend_color.color[1] = st->ctx->Color.BlendColor[1]; + st->state.blend_color.color[2] = st->ctx->Color.BlendColor[2]; + st->state.blend_color.color[3] = st->ctx->Color.BlendColor[3]; + st->pipe->set_blend_color(st->pipe, (struct pipe_blend_color *) st->ctx->Color.BlendColor); + } +} + + +const struct st_tracked_state st_update_blend = { + .dirty = { + .mesa = (_NEW_COLOR), /* XXX _NEW_BLEND someday? */ + .st = 0, + }, + .update = update_blend +}; + + + + + diff --git a/src/mesa/state_tracker/st_atom_cbuf.c b/src/mesa/state_tracker/st_atom_cbuf.c new file mode 100644 index 00000000000..0f90aa76463 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_cbuf.c @@ -0,0 +1,72 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" + +extern GLboolean xmesa_get_cbuf_details( GLcontext *ctx, + void **ptr, + GLuint *cpp, + GLint *stride, + GLuint *format ); + + +/* This is a hack to work with the X11 driver as a test harness + */ +static void update_cbuf_state( struct st_context *st ) +{ + struct pipe_surface cbuf; + GLboolean ok; + + ok = xmesa_get_cbuf_details( st->ctx, + (void **)&cbuf.ptr, + &cbuf.cpp, + &cbuf.stride, + &cbuf.format ); + + assert(ok); + + if (memcmp(&cbuf, &st->state.cbuf, sizeof(cbuf)) != 0) { + st->state.cbuf = cbuf; + st->pipe->set_cbuf_state( st->pipe, &cbuf ); + } +} + +const struct st_tracked_state st_update_cbuf = { + .dirty = { + .mesa = _NEW_BUFFERS, + .st = 0, + }, + .update = update_cbuf_state +}; + diff --git a/src/mesa/state_tracker/st_atom_clear_color.c b/src/mesa/state_tracker/st_atom_clear_color.c new file mode 100644 index 00000000000..adf730cd8cc --- /dev/null +++ b/src/mesa/state_tracker/st_atom_clear_color.c @@ -0,0 +1,62 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" + + +static void +update_clear_color_state( struct st_context *st ) +{ + struct pipe_clear_color_state clear; + + clear.color[0] = st->ctx->Color.ClearColor[0]; + clear.color[1] = st->ctx->Color.ClearColor[1]; + clear.color[2] = st->ctx->Color.ClearColor[2]; + clear.color[3] = st->ctx->Color.ClearColor[3]; + + if (memcmp(&clear, &st->state.clear_color, sizeof(clear)) != 0) { + st->state.clear_color = clear; + st->pipe->set_clear_color_state( st->pipe, &clear ); + } +} + + +const struct st_tracked_state st_update_clear_color = { + .dirty = { + .mesa = _NEW_COLOR, + .st = 0, + }, + .update = update_clear_color_state +}; diff --git a/src/mesa/state_tracker/st_atom_clip.c b/src/mesa/state_tracker/st_atom_clip.c new file mode 100644 index 00000000000..8ccad637d5f --- /dev/null +++ b/src/mesa/state_tracker/st_atom_clip.c @@ -0,0 +1,75 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + + +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" + + +/* Second state atom for user clip planes: + */ +static void update_clip( struct st_context *st ) +{ + struct pipe_clip_state clip; + GLuint i; + + memset(&clip, 0, sizeof(clip)); + + for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) { + if (st->ctx->Transform.ClipPlanesEnabled & (1 << i)) { + memcpy(clip.ucp[clip.nr], + st->ctx->Transform._ClipUserPlane[i], + sizeof(clip.ucp[0])); + clip.nr++; + } + } + + if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) { + st->state.clip = clip; + st->pipe->set_clip_state(st->pipe, &clip); + } +} + + +const struct st_tracked_state st_update_clip = { + .dirty = { + .mesa = (_NEW_TRANSFORM), + .st = 0, + }, + .update = update_clip +}; + + + + + diff --git a/src/mesa/state_tracker/st_atom_depth.c b/src/mesa/state_tracker/st_atom_depth.c new file mode 100644 index 00000000000..7fc51953dc6 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_depth.c @@ -0,0 +1,92 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + + +/** + * Convert GLenum depth func tokens to pipe tokens. + */ +static GLuint +gl_depth_func_to_sp(GLenum func) +{ + /* Same values, just biased */ + assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER); + assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER); + assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER); + assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER); + assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER); + assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER); + assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER); + assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER); + assert(func >= GL_NEVER); + assert(func <= GL_ALWAYS); + return func - GL_NEVER; +} + + +static void +update_depth( struct st_context *st ) +{ + struct pipe_depth_state depth; + + memset(&depth, 0, sizeof(depth)); + + depth.enabled = st->ctx->Depth.Test; + depth.writemask = st->ctx->Depth.Mask; + depth.func = gl_depth_func_to_sp(st->ctx->Depth.Func); + depth.clear = st->ctx->Depth.Clear; + + if (st->ctx->Query.CurrentOcclusionObject && + st->ctx->Query.CurrentOcclusionObject->Active) + depth.occlusion_count = 1; + + if (memcmp(&depth, &st->state.depth, sizeof(depth)) != 0) { + /* state has changed */ + st->state.depth = depth; /* struct copy */ + st->pipe->set_depth_state(st->pipe, &depth); /* set new state */ + } +} + + +const struct st_tracked_state st_update_depth = { + .dirty = { + .mesa = (_NEW_DEPTH), + .st = 0, + }, + .update = update_depth +}; diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c new file mode 100644 index 00000000000..595f390b28d --- /dev/null +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -0,0 +1,89 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" + + +extern struct pipe_surface * +xmesa_get_color_surface(GLcontext *ctx, GLuint i); + +extern struct pipe_surface * +xmesa_get_z_surface(GLcontext *ctx); + +extern struct pipe_surface * +xmesa_get_stencil_surface(GLcontext *ctx); + + +/** + * Update framebuffer state (color, depth, stencil, etc. buffers) + * XXX someday: separate draw/read buffers. + */ +static void +update_framebuffer_state( struct st_context *st ) +{ + struct pipe_framebuffer_state framebuffer; + GLuint i; + + /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state + * to determine which surfaces to draw to + */ + framebuffer.num_cbufs = st->ctx->DrawBuffer->_NumColorDrawBuffers[0]; + for (i = 0; i < framebuffer.num_cbufs; i++) { + framebuffer.cbufs[i] = xmesa_get_color_surface(st->ctx, i); + } + + if (st->ctx->DrawBuffer->_DepthBuffer/*Attachment[BUFFER_DEPTH].Renderbuffer*/) { + framebuffer.zbuf = xmesa_get_z_surface(st->ctx); + } + + if (st->ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer) { + framebuffer.sbuf = xmesa_get_stencil_surface(st->ctx); + } + + if (memcmp(&framebuffer, &st->state.framebuffer, sizeof(framebuffer)) != 0) { + st->state.framebuffer = framebuffer; + st->pipe->set_framebuffer_state( st->pipe, &framebuffer ); + } +} + + +const struct st_tracked_state st_update_framebuffer = { + .dirty = { + .mesa = _NEW_BUFFERS, + .st = 0, + }, + .update = update_framebuffer_state +}; + diff --git a/src/mesa/state_tracker/st_atom_fs.c b/src/mesa/state_tracker/st_atom_fs.c new file mode 100644 index 00000000000..9ca1807913c --- /dev/null +++ b/src/mesa/state_tracker/st_atom_fs.c @@ -0,0 +1,102 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "shader/prog_parameter.h" +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" +#include "st_program.h" +#include "pipe/tgsi/mesa/mesa_to_tgsi.h" +#include "pipe/tgsi/core/tgsi_dump.h" + +static void compile_fs( struct st_context *st, + struct st_fragment_program *fs ) +{ + /* XXX: fix static allocation of tokens: + */ + tgsi_mesa_compile_fp_program( &fs->Base, fs->tokens, ST_FP_MAX_TOKENS ); + + tgsi_dump( fs->tokens, TGSI_DUMP_VERBOSE ); +} + + +static void update_fs( struct st_context *st ) +{ + struct pipe_fs_state fs; + struct st_fragment_program *fp = NULL; + struct gl_program_parameter_list *params = NULL; + + if (st->ctx->Shader.CurrentProgram && + st->ctx->Shader.CurrentProgram->LinkStatus && + st->ctx->Shader.CurrentProgram->FragmentProgram) { + struct gl_fragment_program *f + = st->ctx->Shader.CurrentProgram->FragmentProgram; + fp = st_fragment_program(f); + params = f->Base.Parameters; + } + else if (st->ctx->FragmentProgram._Current) { + fp = st_fragment_program(st->ctx->FragmentProgram._Current); + params = st->ctx->FragmentProgram._Current->Base.Parameters; + } + + if (fp && params) { + /* load program's constants array */ + fp->constants.nr_constants = params->NumParameters; + memcpy(fp->constants.constant, + params->ParameterValues, + params->NumParameters * sizeof(GLfloat) * 4); + } + + if (fp->dirty) + compile_fs( st, fp ); + + memset( &fs, 0, sizeof(fs) ); + fs.inputs_read = fp->Base.Base.InputsRead; + fs.tokens = &fp->tokens[0]; + fs.constants = &fp->constants; + + if (memcmp(&fs, &st->state.fs, sizeof(fs)) != 0 || + fp->dirty) + { + fp->dirty = 0; + st->state.fs = fs; + st->pipe->set_fs_state(st->pipe, &fs); + } +} + + +const struct st_tracked_state st_update_fs = { + .dirty = { + .mesa = _NEW_PROGRAM, + .st = ST_NEW_FRAGMENT_PROGRAM, + }, + .update = update_fs +}; diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c new file mode 100644 index 00000000000..1aa9da84847 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -0,0 +1,135 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + + +/** + * Convert GLenum texcoord wrap tokens to pipe tokens. + */ +static GLuint +gl_wrap_to_sp(GLenum wrap) +{ + switch (wrap) { + case GL_REPEAT: + return PIPE_TEX_WRAP_REPEAT; + case GL_CLAMP: + return PIPE_TEX_WRAP_CLAMP; + case GL_CLAMP_TO_EDGE: + return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + case GL_CLAMP_TO_BORDER: + return PIPE_TEX_WRAP_CLAMP_TO_BORDER; + case GL_MIRRORED_REPEAT: + return PIPE_TEX_WRAP_MIRROR_REPEAT; + case GL_MIRROR_CLAMP_EXT: + return PIPE_TEX_WRAP_MIRROR_CLAMP; + case GL_MIRROR_CLAMP_TO_EDGE_EXT: + return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + case GL_MIRROR_CLAMP_TO_BORDER_EXT: + return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER; + default: + abort(); + return 0; + } +} + + +static GLuint +gl_filter_to_sp(GLenum filter) +{ + switch (filter) { + case GL_NEAREST: + return PIPE_TEX_FILTER_NEAREST; + case GL_LINEAR: + return PIPE_TEX_FILTER_LINEAR; + case GL_NEAREST_MIPMAP_NEAREST: + return PIPE_TEX_FILTER_NEAREST_MIPMAP_NEAREST; + case GL_NEAREST_MIPMAP_LINEAR: + return PIPE_TEX_FILTER_NEAREST_MIPMAP_LINEAR; + case GL_LINEAR_MIPMAP_NEAREST: + return PIPE_TEX_FILTER_LINEAR_MIPMAP_NEAREST; + case GL_LINEAR_MIPMAP_LINEAR: + return PIPE_TEX_FILTER_LINEAR_MIPMAP_LINEAR; + default: + abort(); + return 0; + } +} + + +static void +update_samplers(struct st_context *st) +{ + GLuint u; + + for (u = 0; u < st->ctx->Const.MaxTextureImageUnits; u++) { + const struct gl_texture_object *texobj + = st->ctx->Texture.Unit[u]._Current; + struct pipe_sampler_state sampler; + + memset(&sampler, 0, sizeof(sampler)); + + sampler.wrap_s = gl_wrap_to_sp(texobj->WrapS); + sampler.wrap_t = gl_wrap_to_sp(texobj->WrapT); + sampler.wrap_r = gl_wrap_to_sp(texobj->WrapR); + + sampler.min_filter = gl_filter_to_sp(texobj->MinFilter); + sampler.mag_filter = gl_filter_to_sp(texobj->MagFilter); + + /* XXX more sampler state here */ + + if (memcmp(&sampler, &st->state.sampler[u], sizeof(sampler)) != 0) { + /* state has changed */ + st->state.sampler[u] = sampler; + st->pipe->set_sampler_state(st->pipe, u, &sampler); + } + } +} + + +const struct st_tracked_state st_update_sampler = { + .dirty = { + .mesa = _NEW_TEXTURE, + .st = 0, + }, + .update = update_samplers +}; + + + + + diff --git a/src/mesa/state_tracker/st_atom_scissor.c b/src/mesa/state_tracker/st_atom_scissor.c new file mode 100644 index 00000000000..05a9f3eed18 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_scissor.c @@ -0,0 +1,88 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + + +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" + + +/** + * Scissor depends on the scissor box, and the framebuffer dimensions. + */ +static void +update_scissor( struct st_context *st ) +{ + struct pipe_scissor_state scissor; + const struct gl_framebuffer *fb = st->ctx->DrawBuffer; + + scissor.minx = 0; + scissor.miny = 0; + scissor.maxx = fb->Width; + scissor.maxy = fb->Height; + + if (st->ctx->Scissor.Enabled) { + if (st->ctx->Scissor.X > scissor.minx) + scissor.minx = st->ctx->Scissor.X; + if (st->ctx->Scissor.Y > scissor.miny) + scissor.miny = st->ctx->Scissor.Y; + + if (st->ctx->Scissor.X + st->ctx->Scissor.Width < scissor.maxx) + scissor.maxx = st->ctx->Scissor.X + st->ctx->Scissor.Width; + if (st->ctx->Scissor.Y + st->ctx->Scissor.Height < scissor.maxy) + scissor.maxy = st->ctx->Scissor.Y + st->ctx->Scissor.Height; + + /* check for null space */ + if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy) + scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0; + } + + if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) { + /* state has changed */ + st->state.scissor = scissor; /* struct copy */ + st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */ + } +} + + +const struct st_tracked_state st_update_scissor = { + .dirty = { + .mesa = (_NEW_SCISSOR | _NEW_BUFFERS), + .st = 0, + }, + .update = update_scissor +}; + + + + + diff --git a/src/mesa/state_tracker/st_atom_setup.c b/src/mesa/state_tracker/st_atom_setup.c new file mode 100644 index 00000000000..6ee96f61784 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_setup.c @@ -0,0 +1,216 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + + +#include "st_context.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "st_atom.h" + +static GLuint translate_fill( GLenum mode ) +{ + switch (mode) { + case GL_POINT: + return PIPE_POLYGON_MODE_POINT; + case GL_LINE: + return PIPE_POLYGON_MODE_LINE; + case GL_FILL: + return PIPE_POLYGON_MODE_FILL; + default: + assert(0); + return 0; + } +} + +static GLboolean get_offset_flag( GLuint fill_mode, + const struct gl_polygon_attrib *p ) +{ + switch (fill_mode) { + case PIPE_POLYGON_MODE_POINT: + return p->OffsetPoint; + case PIPE_POLYGON_MODE_LINE: + return p->OffsetLine; + case PIPE_POLYGON_MODE_FILL: + return p->OffsetFill; + default: + assert(0); + return 0; + } +} + + +static void update_setup_state( struct st_context *st ) +{ + GLcontext *ctx = st->ctx; + struct pipe_setup_state setup; + + memset(&setup, 0, sizeof(setup)); + + /* _NEW_POLYGON, _NEW_BUFFERS + */ + { + if (ctx->Polygon.FrontFace == GL_CCW) + setup.front_winding = PIPE_WINDING_CCW; + else + setup.front_winding = PIPE_WINDING_CW; + + /* XXX + * I think the intention here is that user-created framebuffer objects + * use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout. + * Flipping Y changes CW to CCW and vice-versa. + * But this is an implementation/driver-specific artifact - remove... + */ + if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0) + setup.front_winding ^= PIPE_WINDING_BOTH; + } + + /* _NEW_LIGHT + */ + if (ctx->Light.ShadeModel == GL_FLAT) + setup.flatshade = 1; + + /* _NEW_LIGHT | _NEW_PROGRAM + * + * Back-face colors can come from traditional lighting (when + * GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs (when + * GL_VERTEX_PROGRAM_TWO_SIDE is set). Note the logic here. + */ + if (ctx->VertexProgram._Enabled) { + setup.light_twoside = ctx->VertexProgram.TwoSideEnabled; + } + else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { + setup.light_twoside = 1; + } + + /* _NEW_POLYGON + */ + if (ctx->Polygon.CullFlag) { + if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) { + setup.cull_mode = PIPE_WINDING_BOTH; + } + else if (ctx->Polygon.CullFaceMode == GL_FRONT) { + setup.cull_mode = setup.front_winding; + } + else { + setup.cull_mode = setup.front_winding ^ PIPE_WINDING_BOTH; + } + } + + /* _NEW_POLYGON + */ + { + GLuint fill_front = translate_fill( ctx->Polygon.FrontMode ); + GLuint fill_back = translate_fill( ctx->Polygon.BackMode ); + + if (setup.front_winding == PIPE_WINDING_CW) { + setup.fill_cw = fill_front; + setup.fill_ccw = fill_back; + } + else { + setup.fill_cw = fill_back; + setup.fill_ccw = fill_front; + } + + /* Simplify when culling is active: + */ + if (setup.cull_mode & PIPE_WINDING_CW) { + setup.fill_cw = setup.fill_ccw; + } + + if (setup.cull_mode & PIPE_WINDING_CCW) { + setup.fill_ccw = setup.fill_cw; + } + } + + /* _NEW_POLYGON + */ + if (ctx->Polygon.OffsetUnits != 0.0 || + ctx->Polygon.OffsetFactor != 0.0) { + setup.offset_cw = get_offset_flag( setup.fill_cw, &ctx->Polygon ); + setup.offset_ccw = get_offset_flag( setup.fill_ccw, &ctx->Polygon ); + setup.offset_units = ctx->Polygon.OffsetUnits; + setup.offset_scale = ctx->Polygon.OffsetFactor; + } + + if (ctx->Polygon.SmoothFlag) + setup.poly_smooth = 1; + + if (ctx->Polygon.StippleFlag) + setup.poly_stipple_enable = 1; + + + /* _NEW_BUFFERS, _NEW_POLYGON + */ + if (setup.fill_cw != PIPE_POLYGON_MODE_FILL || + setup.fill_ccw != PIPE_POLYGON_MODE_FILL) + { + GLfloat mrd = (ctx->DrawBuffer ? + ctx->DrawBuffer->_MRD : + 1.0); + + setup.offset_units = ctx->Polygon.OffsetFactor * mrd; + setup.offset_scale = (ctx->Polygon.OffsetUnits * mrd * + st->polygon_offset_scale); + } + + /* _NEW_POINT + */ + setup.point_size = ctx->Point.Size; + setup.point_smooth = ctx->Point.SmoothFlag; + + /* _NEW_LINE + */ + setup.line_width = ctx->Line.Width; + setup.line_smooth = ctx->Line.SmoothFlag; + setup.line_stipple_enable = ctx->Line.StippleFlag; + setup.line_stipple_pattern = ctx->Line.StipplePattern; + /* GL stipple factor is in [1,256], remap to [0, 255] here */ + setup.line_stipple_factor = ctx->Line.StippleFactor - 1; + + /* _NEW_MULTISAMPLE */ + if (ctx->Multisample.Enabled) + setup.multisample = 1; + + if (memcmp(&setup, &st->state.setup, sizeof(setup)) != 0) { + st->state.setup = setup; + st->pipe->set_setup_state( st->pipe, &setup ); + } +} + +const struct st_tracked_state st_update_setup = { + .dirty = { + .mesa = (_NEW_LIGHT | _NEW_POLYGON | _NEW_LINE | + _NEW_POINT | _NEW_BUFFERS | _NEW_MULTISAMPLE), + .st = 0, + }, + .update = update_setup_state +}; diff --git a/src/mesa/state_tracker/st_atom_stencil.c b/src/mesa/state_tracker/st_atom_stencil.c new file mode 100644 index 00000000000..d037335e9e2 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_stencil.c @@ -0,0 +1,140 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + * Brian Paul + */ + + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + + +/** + * Convert GLenum stencil func tokens to pipe tokens. + */ +static GLuint +gl_stencil_func_to_sp(GLenum func) +{ + /* Same values, just biased */ + assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER); + assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER); + assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER); + assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER); + assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER); + assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER); + assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER); + assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER); + assert(func >= GL_NEVER); + assert(func <= GL_ALWAYS); + return func - GL_NEVER; +} + + +/** + * Convert GLenum stencil op tokens to pipe tokens. + */ +static GLuint +gl_stencil_op_to_sp(GLenum func) +{ + switch (func) { + case GL_KEEP: + return PIPE_STENCIL_OP_KEEP; + case GL_ZERO: + return PIPE_STENCIL_OP_ZERO; + case GL_REPLACE: + return PIPE_STENCIL_OP_REPLACE; + case GL_INCR: + return PIPE_STENCIL_OP_INCR; + case GL_DECR: + return PIPE_STENCIL_OP_DECR; + case GL_INCR_WRAP: + return PIPE_STENCIL_OP_INCR_WRAP; + case GL_DECR_WRAP: + return PIPE_STENCIL_OP_DECR_WRAP; + case GL_INVERT: + return PIPE_STENCIL_OP_INVERT; + default: + assert("invalid GL token in gl_stencil_op_to_sp()" == NULL); + return 0; + } +} + + +static void +update_stencil( struct st_context *st ) +{ + struct pipe_stencil_state stencil; + + memset(&stencil, 0, sizeof(stencil)); + + if (st->ctx->Stencil.Enabled) { + stencil.front_enabled = 1; + stencil.front_func = gl_stencil_func_to_sp(st->ctx->Stencil.Function[0]); + stencil.front_fail_op = gl_stencil_op_to_sp(st->ctx->Stencil.FailFunc[0]); + stencil.front_zfail_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZFailFunc[0]); + stencil.front_zpass_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZPassFunc[0]); + stencil.ref_value[0] = st->ctx->Stencil.Ref[0] & 0xff; + stencil.value_mask[0] = st->ctx->Stencil.ValueMask[0] & 0xff; + stencil.write_mask[0] = st->ctx->Stencil.WriteMask[0] & 0xff; + if (st->ctx->Stencil.TestTwoSide) { + stencil.back_enabled = 1; + stencil.back_func = gl_stencil_func_to_sp(st->ctx->Stencil.Function[1]); + stencil.back_fail_op = gl_stencil_op_to_sp(st->ctx->Stencil.FailFunc[1]); + stencil.back_zfail_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZFailFunc[1]); + stencil.back_zpass_op = gl_stencil_op_to_sp(st->ctx->Stencil.ZPassFunc[1]); + stencil.ref_value[1] = st->ctx->Stencil.Ref[1] & 0xff; + stencil.value_mask[1] = st->ctx->Stencil.ValueMask[1] & 0xff; + stencil.write_mask[1] = st->ctx->Stencil.WriteMask[1] & 0xff; + } + stencil.clear_value = st->ctx->Stencil.Clear & 0xff; + } + + if (memcmp(&stencil, &st->state.stencil, sizeof(stencil)) != 0) { + /* state has changed */ + st->state.stencil = stencil; /* struct copy */ + st->pipe->set_stencil_state(st->pipe, &stencil); /* set new state */ + } +} + + +const struct st_tracked_state st_update_stencil = { + .dirty = { + .mesa = (_NEW_STENCIL), + .st = 0, + }, + .update = update_stencil +}; + + + + + diff --git a/src/mesa/state_tracker/st_atom_stipple.c b/src/mesa/state_tracker/st_atom_stipple.c new file mode 100644 index 00000000000..dd04d2158c7 --- /dev/null +++ b/src/mesa/state_tracker/st_atom_stipple.c @@ -0,0 +1,62 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * \brief polygon stipple state + * + * Authors: + * Brian Paul + */ + + +#include "st_context.h" +#include "st_atom.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" + + +static void +update_stipple( struct st_context *st ) +{ + const GLuint sz = sizeof(st->state.poly_stipple.stipple); + assert(sz == sizeof(st->ctx->PolygonStipple)); + + if (memcmp(&st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz)) { + /* state has changed */ + memcpy(st->state.poly_stipple.stipple, st->ctx->PolygonStipple, sz); + st->pipe->set_polygon_stipple(st->pipe, &st->state.poly_stipple); + } +} + + +const struct st_tracked_state st_update_polygon_stipple = { + .dirty = { + .mesa = (_NEW_POLYGONSTIPPLE), + .st = 0, + }, + .update = update_stipple +}; diff --git a/src/mesa/state_tracker/st_atom_viewport.c b/src/mesa/state_tracker/st_atom_viewport.c new file mode 100644 index 00000000000..ac91f628aab --- /dev/null +++ b/src/mesa/state_tracker/st_atom_viewport.c @@ -0,0 +1,117 @@ +/************************************************************************** + * + * Copyright 2007 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 "context.h" +#include "colormac.h" +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" + + + + + +/** + * Update the viewport transformation matrix. Depends on: + * - viewport pos/size + * - depthrange + * - window pos/size or FBO size + */ +static void update_viewport( struct st_context *st ) +{ + GLcontext *ctx = st->ctx; + const GLframebuffer *DrawBuffer = ctx->DrawBuffer; + GLfloat yScale = 1.0; + GLfloat yBias = 0.0; + + /* _NEW_BUFFERS + */ + if (DrawBuffer) { + +#if 0 + if (DrawBuffer->Name) { + /* User created FBO */ + struct st_renderbuffer *irb + = st_renderbuffer(DrawBuffer->_ColorDrawBuffers[0][0]); + if (irb && !irb->RenderToTexture) { + /* y=0=top */ + yScale = -1.0; + yBias = irb->Base.Height; + } + else { + /* y=0=bottom */ + yScale = 1.0; + yBias = 0.0; + } + } + else + { + /* window buffer, y=0=top */ + yScale = -1.0; + yBias = DrawBuffer->Height; + } +#endif + } + + { + /* _NEW_VIEWPORT + */ + GLfloat x = ctx->Viewport.X; + GLfloat y = ctx->Viewport.Y; + GLfloat z = ctx->Viewport.Near; + GLfloat half_width = ctx->Viewport.Width / 2.0; + GLfloat half_height = ctx->Viewport.Height / 2.0; + GLfloat half_depth = (ctx->Viewport.Far - ctx->Viewport.Near) / 2.0; + + struct pipe_viewport_state vp; + + vp.scale[0] = half_width; + vp.scale[1] = half_height * yScale; + vp.scale[2] = half_depth; + vp.scale[3] = 1.0; + + vp.translate[0] = (half_width + x); + vp.translate[1] = (half_height + y) * yScale + yBias; + vp.translate[2] = (half_depth + z); + vp.translate[3] = 0.0; + + if (memcmp(&vp, &st->state.viewport, sizeof(vp)) != 0) { + st->state.viewport = vp; + st->pipe->set_viewport_state(st->pipe, &vp); + } + } +} + + +const struct st_tracked_state st_update_viewport = { + .dirty = { + .mesa = _NEW_BUFFERS | _NEW_VIEWPORT, + .st = 0, + }, + .update = update_viewport +}; diff --git a/src/mesa/state_tracker/st_atom_vs.c b/src/mesa/state_tracker/st_atom_vs.c new file mode 100644 index 00000000000..6a26bfdd19f --- /dev/null +++ b/src/mesa/state_tracker/st_atom_vs.c @@ -0,0 +1,49 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "st_context.h" +#include "pipe/p_context.h" +#include "st_atom.h" + + + +static void update_vs( struct st_context *st ) +{ +} + + +const struct st_tracked_state st_update_vs = { + .dirty = { + .mesa = 0, + .st = ST_NEW_VERTEX_PROGRAM, + }, + .update = update_vs +}; diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c new file mode 100644 index 00000000000..fa9eaf446e6 --- /dev/null +++ b/src/mesa/state_tracker/st_cb_program.c @@ -0,0 +1,168 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "st_context.h" +#include "st_program.h" + +#include "glheader.h" +#include "macros.h" +#include "enums.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "program.h" +#include "programopt.h" +#include "tnl/tnl.h" +#include "pipe/tgsi/mesa/tgsi_mesa.h" + + +static void st_bind_program( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) +{ + struct st_context *st = st_context(ctx); + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: + st->dirty.st |= ST_NEW_VERTEX_PROGRAM; + break; + case GL_FRAGMENT_PROGRAM_ARB: + st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; + break; + } +} + +static struct gl_program *st_new_program( GLcontext *ctx, + GLenum target, + GLuint id ) +{ + struct st_context *st = st_context(ctx); + + switch (target) { + case GL_VERTEX_PROGRAM_ARB: { + struct st_vertex_program *prog = CALLOC_STRUCT(st_vertex_program); + + prog->id = st->program_id++; + prog->dirty = 1; + + return _mesa_init_vertex_program( ctx, + &prog->Base, + target, + id ); + } + + case GL_FRAGMENT_PROGRAM_ARB: + case GL_FRAGMENT_PROGRAM_NV: + { + struct st_fragment_program *prog = CALLOC_STRUCT(st_fragment_program); + + prog->id = st->program_id++; + prog->dirty = 1; + + return _mesa_init_fragment_program( ctx, + &prog->Base, + target, + id ); + } + + default: + return _mesa_new_program(ctx, target, id); + } +} + +static void st_delete_program( GLcontext *ctx, + struct gl_program *prog ) +{ + _mesa_delete_program( ctx, prog ); +} + + +static GLboolean st_is_program_native( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) +{ + return GL_TRUE; +} + +static void st_program_string_notify( GLcontext *ctx, + GLenum target, + struct gl_program *prog ) +{ + struct st_context *st = st_context(ctx); + + if (target == GL_FRAGMENT_PROGRAM_ARB) { + struct st_fragment_program *p = (struct st_fragment_program *)prog; + + if (prog == &ctx->FragmentProgram._Current->Base) + st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; + + p->id = st->program_id++; + p->param_state = p->Base.Base.Parameters->StateFlags; + } + else if (target == GL_VERTEX_PROGRAM_ARB) { + struct st_vertex_program *p = (struct st_vertex_program *)prog; + + if (prog == &ctx->VertexProgram._Current->Base) + st->dirty.st |= ST_NEW_VERTEX_PROGRAM; + + p->id = st->program_id++; + p->param_state = p->Base.Base.Parameters->StateFlags; + + /* Also tell tnl about it: + */ + _tnl_program_string(ctx, target, prog); + } +} + + + +void st_init_cb_program( struct st_context *st ) +{ + struct dd_function_table *functions = &st->ctx->Driver; + + /* Need these flags: + */ + st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE; + st->ctx->FragmentProgram._UseTexEnvProgram = GL_TRUE; + + assert(functions->ProgramStringNotify == _tnl_program_string); + functions->BindProgram = st_bind_program; + functions->NewProgram = st_new_program; + functions->DeleteProgram = st_delete_program; + functions->IsProgramNative = st_is_program_native; + functions->ProgramStringNotify = st_program_string_notify; +} + + +void st_destroy_cb_program( struct st_context *st ) +{ +} + diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c new file mode 100644 index 00000000000..6308e81a619 --- /dev/null +++ b/src/mesa/state_tracker/st_context.c @@ -0,0 +1,76 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "imports.h" +#include "st_public.h" +#include "st_context.h" +#include "st_atom.h" +#include "st_draw.h" +#include "st_program.h" +#include "pipe/p_context.h" + +void st_invalidate_state(GLcontext * ctx, GLuint new_state) +{ + struct st_context *st = st_context(ctx); + + st->dirty.mesa |= new_state; + st->dirty.st |= ST_NEW_MESA; +} + + +struct st_context *st_create_context( GLcontext *ctx, + struct pipe_context *pipe ) +{ + struct st_context *st = CALLOC_STRUCT( st_context ); + + ctx->st = st; + + st->ctx = ctx; + st->pipe = pipe; + + st->dirty.mesa = ~0; + st->dirty.st = ~0; + + st_init_atoms( st ); + st_init_draw( st ); + st_init_cb_program( st ); + + return st; +} + + +void st_destroy_context( struct st_context *st ) +{ + st_destroy_atoms( st ); + st_destroy_draw( st ); + st_destroy_cb_program( st ); + st->pipe->destroy( st->pipe ); + FREE( st ); +} + + + diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h new file mode 100644 index 00000000000..ef3cdb3b091 --- /dev/null +++ b/src/mesa/state_tracker/st_context.h @@ -0,0 +1,116 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef ST_CONTEXT_H +#define ST_CONTEXT_H + +#include "mtypes.h" +#include "pipe/p_state.h" + + +struct st_context; +struct st_region; +struct st_texture_object; +struct st_texture_image; +struct st_fragment_program; + +#define ST_NEW_MESA 0x1 /* Mesa state has changed */ +#define ST_NEW_FRAGMENT_PROGRAM 0x2 +#define ST_NEW_VERTEX_PROGRAM 0x4 + +struct st_state_flags { + GLuint mesa; + GLuint st; +}; + +struct st_tracked_state { + struct st_state_flags dirty; + void (*update)( struct st_context *st ); +}; + + + + +struct st_context +{ + GLcontext *ctx; + + struct pipe_context *pipe; + + /* Eventually will use a cache to feed the pipe with + * create/bind/delete calls to constant state objects. Not yet + * though, we just shove random objects across the interface. + */ + struct { + struct pipe_alpha_test_state alpha_test; + struct pipe_blend_state blend; + struct pipe_blend_color blend_color; + struct pipe_clear_color_state clear_color; + struct pipe_clip_state clip; + struct pipe_depth_state depth; + struct pipe_framebuffer_state framebuffer; + struct pipe_fs_state fs; + struct pipe_poly_stipple poly_stipple; + struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS]; + struct pipe_scissor_state scissor; + struct pipe_setup_state setup; + struct pipe_stencil_state stencil; + struct pipe_viewport_state viewport; + } state; + + struct { + struct st_tracked_state tracked_state; + } constants; + + struct { + struct gl_fragment_program *fragment_program; + } cb; + + /* State to be validated: + */ + struct st_tracked_state **atoms; + GLuint nr_atoms; + + struct st_state_flags dirty; + + /* Counter to track program string changes: + */ + GLuint program_id; + + GLfloat polygon_offset_scale; /* ?? */ +}; + + +/* Need this so that we can implement Mesa callbacks in this module. + */ +static INLINE struct st_context *st_context(GLcontext *ctx) +{ + return ctx->st; +} + + +#endif diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c new file mode 100644 index 00000000000..a424d1dd050 --- /dev/null +++ b/src/mesa/state_tracker/st_draw.c @@ -0,0 +1,120 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "imports.h" + +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "st_context.h" +#include "st_atom.h" +#include "st_draw.h" +#include "pipe/p_context.h" + +/* + * TNL stage which feeds into the above. + * + * XXX: this needs to go into each driver using this code, because we + * cannot make the leap from ctx->draw_context in this file. The + * driver needs to customize tnl anyway, so this isn't a big deal. + */ +static GLboolean draw( GLcontext * ctx, struct tnl_pipeline_stage *stage ) +{ + struct st_context *st = st_context(ctx); + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + /* Validate driver and pipe state: + */ + st_validate_state( st ); + + /* Call into the new draw code to handle the VB: + */ + st->pipe->draw_vb( st->pipe, VB ); + + /* Finished + */ + return GL_FALSE; +} + +const struct tnl_pipeline_stage st_draw = { + "check state and draw", + NULL, + NULL, + NULL, + NULL, + draw +}; + +static const struct tnl_pipeline_stage *st_pipeline[] = { + &_tnl_vertex_transform_stage, + &_tnl_vertex_cull_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_tnl_point_attenuation_stage, + &_tnl_vertex_program_stage, + &st_draw, /* ADD: escape to pipe */ + 0, +}; + +/* This is all a hack to keep using tnl until we have vertex programs + * up and running. + */ +void st_init_draw( struct st_context *st ) +{ + GLcontext *ctx = st->ctx; + + _tnl_destroy_pipeline( ctx ); + _tnl_install_pipeline( ctx, st_pipeline ); +} + + +void st_destroy_draw( struct st_context *st ) +{ + /* Nothing to do. + */ +} + + +/** XXX temporary here */ +void +st_clear(struct st_context *st, GLboolean color, GLboolean depth, + GLboolean stencil, GLboolean accum) +{ + /* This makes sure the softpipe has the latest scissor, etc values */ + st_validate_state( st ); + + st->pipe->clear(st->pipe, color, depth, stencil, accum); +} + diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h new file mode 100644 index 00000000000..7a3ba521300 --- /dev/null +++ b/src/mesa/state_tracker/st_draw.h @@ -0,0 +1,44 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + + +#ifndef ST_DRAW_H +#define ST_DRAW_H + +void st_init_draw( struct st_context *st ); +void st_destroy_draw( struct st_context *st ); + +/** XXX temporary here */ +void st_clear(struct st_context *st, GLboolean color, GLboolean depth, + GLboolean stencil, GLboolean accum); + +#endif diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h new file mode 100644 index 00000000000..f6d5f6d76ce --- /dev/null +++ b/src/mesa/state_tracker/st_program.h @@ -0,0 +1,105 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + + +#ifndef ST_PROGRAM_H +#define ST_PROGRAM_H + +#include "mtypes.h" +#include "pipe/tgsi/core/tgsi_token.h" + +#define ST_FP_MAX_TOKENS 1024 + + +struct st_fragment_program +{ + struct gl_fragment_program Base; + GLboolean error; /* If program is malformed for any reason. */ + + GLuint id; /* String id, for tracking + * ProgramStringNotify changes. + */ + + + struct tgsi_token tokens[ST_FP_MAX_TOKENS]; + GLboolean dirty; + + struct pipe_constant_buffer constants; + +#if 0 + GLfloat (*cbuffer)[4]; + GLuint nr_constants; + + /* Translate all the parameters, etc, into a constant buffer which + * we update on state changes. + */ + struct + { + GLuint reg; /* Constant idx */ + const GLfloat *values; /* Pointer to tracked values */ + } *param; + GLuint nr_params; +#endif + + GLuint param_state; +}; + + +struct st_vertex_program +{ + struct gl_vertex_program Base; + GLboolean error; /* If program is malformed for any reason. */ + + GLuint id; /* String id, for tracking + * ProgramStringNotify changes. + */ + + GLboolean dirty; + GLuint param_state; +}; + +void st_init_cb_program( struct st_context *st ); +void st_destroy_cb_program( struct st_context *st ); + +static inline struct st_fragment_program * +st_fragment_program( struct gl_fragment_program *fp ) +{ + return (struct st_fragment_program *)fp; +} + +static inline struct st_vertex_program * +st_vertex_program( struct gl_vertex_program *vp ) +{ + return (struct st_vertex_program *)vp; +} + +#endif diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h new file mode 100644 index 00000000000..3191549a2f8 --- /dev/null +++ b/src/mesa/state_tracker/st_public.h @@ -0,0 +1,43 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef ST_PUBLIC_H +#define ST_PUBLIC_H + +#include "mtypes.h" + +struct st_context; +struct pipe_context; + +struct st_context *st_create_context( GLcontext *ctx, + struct pipe_context *pipe); + +void st_destroy_context( struct st_context *st ); + +void st_invalidate_state(GLcontext * ctx, GLuint new_state); + +#endif diff --git a/src/mesa/state_tracker/st_texobj.c b/src/mesa/state_tracker/st_texobj.c new file mode 100644 index 00000000000..eb5bdb2d08f --- /dev/null +++ b/src/mesa/state_tracker/st_texobj.c @@ -0,0 +1,102 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* + * Authors: + * Brian Paul + */ + +#include "imports.h" +#include "texformat.h" + +#include "st_context.h" +#include "st_texobj.h" +#include "pipe/p_defines.h" + + +/** + * Create a pipe_texture_object from a Mesa texture object. + * Eventually, gl_texture_object may be derived from this... + */ +struct pipe_texture_object * +create_texture_object(struct gl_texture_object *texObj) +{ + struct pipe_texture_object *pto; + const struct gl_texture_image *texImage; + + pto = calloc(1, sizeof(*pto)); + if (!pto) + return NULL; + + /* XXX: Member not defined. Comment-out to get it compile. */ + /*assert(texObj->Complete);*/ + + switch (texObj->Target) { + case GL_TEXTURE_1D: + pto->type = PIPE_TEXTURE_1D; + break; + case GL_TEXTURE_2D: + pto->type = PIPE_TEXTURE_2D; + break; + case GL_TEXTURE_3D: + pto->type = PIPE_TEXTURE_3D; + break; + case GL_TEXTURE_CUBE_MAP: + pto->type = PIPE_TEXTURE_CUBE; + break; + default: + assert(0); + return NULL; + } + + texImage = texObj->Image[0][texObj->BaseLevel]; + assert(texImage); + + switch (texImage->TexFormat->MesaFormat) { + case MESA_FORMAT_RGBA8888: + pto->format = PIPE_FORMAT_U_R8_G8_B8_A8; + break; + case MESA_FORMAT_RGB565: + pto->format = PIPE_FORMAT_U_R5_G6_B5; + break; + + /* XXX fill in more formats */ + + default: + assert(0); + return NULL; + } + + pto->width = texImage->Width; + pto->height = texImage->Height; + pto->depth = texImage->Depth; + + /* XXX verify this */ + pto->mipmapped = texObj->Image[0][texObj->BaseLevel + 1] != NULL; + + return pto; +} diff --git a/src/mesa/state_tracker/st_texobj.h b/src/mesa/state_tracker/st_texobj.h new file mode 100644 index 00000000000..3c660310187 --- /dev/null +++ b/src/mesa/state_tracker/st_texobj.h @@ -0,0 +1,41 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* + * Authors: + * Brian Paul + */ + +#ifndef ST_TEXOBJ_H +#define ST_TEXOBJ_H 1 + + +extern struct pipe_texture_object * +create_texture_object(struct gl_texture_object *texObj); + + +#endif /* ST_TEXOBJ_H */ diff --git a/src/mesa/vf/vf.c b/src/mesa/vf/vf.c new file mode 100644 index 00000000000..cb25f2e1131 --- /dev/null +++ b/src/mesa/vf/vf.c @@ -0,0 +1,372 @@ +/* + * Copyright 2003 Tungsten Graphics, 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 + * 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 + * TUNGSTEN GRAPHICS 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: + * Keith Whitwell <[email protected]> + */ + +#include "glheader.h" +#include "context.h" +#include "colormac.h" + +#include "vf.h" + +#define DBG 0 + + + +static GLboolean match_fastpath( struct vertex_fetch *vf, + const struct vf_fastpath *fp) +{ + GLuint j; + + if (vf->attr_count != fp->attr_count) + return GL_FALSE; + + for (j = 0; j < vf->attr_count; j++) + if (vf->attr[j].format != fp->attr[j].format || + vf->attr[j].inputsize != fp->attr[j].size || + vf->attr[j].vertoffset != fp->attr[j].offset) + return GL_FALSE; + + if (fp->match_strides) { + if (vf->vertex_stride != fp->vertex_stride) + return GL_FALSE; + + for (j = 0; j < vf->attr_count; j++) + if (vf->attr[j].inputstride != fp->attr[j].stride) + return GL_FALSE; + } + + return GL_TRUE; +} + +static GLboolean search_fastpath_emit( struct vertex_fetch *vf ) +{ + struct vf_fastpath *fp = vf->fastpath; + + for ( ; fp ; fp = fp->next) { + if (match_fastpath(vf, fp)) { + vf->emit = fp->func; + return GL_TRUE; + } + } + + return GL_FALSE; +} + +void vf_register_fastpath( struct vertex_fetch *vf, + GLboolean match_strides ) +{ + struct vf_fastpath *fastpath = CALLOC_STRUCT(vf_fastpath); + GLuint i; + + fastpath->vertex_stride = vf->vertex_stride; + fastpath->attr_count = vf->attr_count; + fastpath->match_strides = match_strides; + fastpath->func = vf->emit; + fastpath->attr = (struct vf_attr_type *) + _mesa_malloc(vf->attr_count * sizeof(fastpath->attr[0])); + + for (i = 0; i < vf->attr_count; i++) { + fastpath->attr[i].format = vf->attr[i].format; + fastpath->attr[i].stride = vf->attr[i].inputstride; + fastpath->attr[i].size = vf->attr[i].inputsize; + fastpath->attr[i].offset = vf->attr[i].vertoffset; + } + + fastpath->next = vf->fastpath; + vf->fastpath = fastpath; +} + + + + +/*********************************************************************** + * Build codegen functions or return generic ones: + */ +static void choose_emit_func( struct vertex_fetch *vf, + GLuint count, + GLubyte *dest) +{ + vf->emit = NULL; + + /* Does this match an existing (hardwired, codegen or known-bad) + * fastpath? + */ + if (search_fastpath_emit(vf)) { + /* Use this result. If it is null, then it is already known + * that the current state will fail for codegen and there is no + * point trying again. + */ + } + else if (vf->codegen_emit) { + vf->codegen_emit( vf ); + } + + if (!vf->emit) { + vf_generate_hardwired_emit(vf); + } + + /* Otherwise use the generic version: + */ + if (!vf->emit) + vf->emit = vf_generic_emit; + + vf->emit( vf, count, dest ); +} + + + + + +/*********************************************************************** + * Public entrypoints, mostly dispatch to the above: + */ + + + +GLuint vf_set_vertex_attributes( struct vertex_fetch *vf, + const struct vf_attr_map *map, + GLuint nr, + GLuint vertex_stride ) +{ + GLuint offset = 0; + GLuint i, j; + + assert(nr < VF_ATTRIB_MAX); + + memset(vf->lookup, 0, sizeof(vf->lookup)); + + for (j = 0, i = 0; i < nr; i++) { + const GLuint format = map[i].format; + if (format == EMIT_PAD) { + if (DBG) + _mesa_printf("%d: pad %d, offset %d\n", i, + map[i].offset, offset); + + offset += map[i].offset; + + } + else { + assert(vf->lookup[map[i].attrib] == 0); + vf->lookup[map[i].attrib] = &vf->attr[j]; + + vf->attr[j].attrib = map[i].attrib; + vf->attr[j].format = format; + vf->attr[j].insert = vf_format_info[format].insert; + vf->attr[j].extract = vf_format_info[format].extract; + vf->attr[j].vertattrsize = vf_format_info[format].attrsize; + vf->attr[j].vertoffset = offset; + + if (DBG) + _mesa_printf("%d: %s, offset %d\n", i, + vf_format_info[format].name, + vf->attr[j].vertoffset); + + offset += vf_format_info[format].attrsize; + j++; + } + } + + vf->attr_count = j; + vf->vertex_stride = vertex_stride ? vertex_stride : offset; + vf->emit = choose_emit_func; + + assert(vf->vertex_stride >= offset); + return vf->vertex_stride; +} + + + +void vf_set_vp_matrix( struct vertex_fetch *vf, + const GLfloat *viewport ) +{ + assert(vf->allow_viewport_emits); + + /* scale */ + vf->vp[0] = viewport[MAT_SX]; + vf->vp[1] = viewport[MAT_SY]; + vf->vp[2] = viewport[MAT_SZ]; + vf->vp[3] = 1.0; + + /* translate */ + vf->vp[4] = viewport[MAT_TX]; + vf->vp[5] = viewport[MAT_TY]; + vf->vp[6] = viewport[MAT_TZ]; + vf->vp[7] = 0.0; +} + +void vf_set_vp_scale_translate( struct vertex_fetch *vf, + const GLfloat *scale, + const GLfloat *translate ) +{ + assert(vf->allow_viewport_emits); + + vf->vp[0] = scale[0]; + vf->vp[1] = scale[1]; + vf->vp[2] = scale[2]; + vf->vp[3] = scale[3]; + + vf->vp[4] = translate[0]; + vf->vp[5] = translate[1]; + vf->vp[6] = translate[2]; + vf->vp[7] = translate[3]; +} + + +/* Set attribute pointers, adjusted for start position: + */ +void vf_set_sources( struct vertex_fetch *vf, + GLvector4f * const sources[], + GLuint start ) +{ + struct vf_attr *a = vf->attr; + GLuint j; + + for (j = 0; j < vf->attr_count; j++) { + const GLvector4f *vptr = sources[a[j].attrib]; + + if ((a[j].inputstride != vptr->stride) || + (a[j].inputsize != vptr->size)) + vf->emit = choose_emit_func; + + a[j].inputstride = vptr->stride; + a[j].inputsize = vptr->size; + a[j].do_insert = a[j].insert[vptr->size - 1]; + a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride; + } +} + + + +/* Emit count VB vertices to dest. + */ +void vf_emit_vertices( struct vertex_fetch *vf, + GLuint count, + void *dest ) +{ + vf->emit( vf, count, (GLubyte*) dest ); +} + + +/* Extract a named attribute from a hardware vertex. Will have to + * reverse any viewport transformation, swizzling or other conversions + * which may have been applied. + * + * This is mainly required for on-the-fly vertex translations to + * swrast format. + */ +void vf_get_attr( struct vertex_fetch *vf, + const void *vertex, + GLenum attr, + const GLfloat *dflt, + GLfloat *dest ) +{ + const struct vf_attr *a = vf->attr; + const GLuint attr_count = vf->attr_count; + GLuint j; + + for (j = 0; j < attr_count; j++) { + if (a[j].attrib == attr) { + a[j].extract( &a[j], dest, (GLubyte *)vertex + a[j].vertoffset ); + return; + } + } + + /* Else return the value from ctx->Current. + */ + _mesa_memcpy( dest, dflt, 4*sizeof(GLfloat)); +} + + + + +struct vertex_fetch *vf_create( GLboolean allow_viewport_emits ) +{ + struct vertex_fetch *vf = CALLOC_STRUCT(vertex_fetch); + GLuint i; + + for (i = 0; i < VF_ATTRIB_MAX; i++) + vf->attr[i].vf = vf; + + vf->allow_viewport_emits = allow_viewport_emits; + + switch(CHAN_TYPE) { + case GL_UNSIGNED_BYTE: + vf->chan_scale[0] = 255.0; + vf->chan_scale[1] = 255.0; + vf->chan_scale[2] = 255.0; + vf->chan_scale[3] = 255.0; + break; + case GL_UNSIGNED_SHORT: + vf->chan_scale[0] = 65535.0; + vf->chan_scale[1] = 65535.0; + vf->chan_scale[2] = 65535.0; + vf->chan_scale[3] = 65535.0; + break; + default: + vf->chan_scale[0] = 1.0; + vf->chan_scale[1] = 1.0; + vf->chan_scale[2] = 1.0; + vf->chan_scale[3] = 1.0; + break; + } + + vf->identity[0] = 0.0; + vf->identity[1] = 0.0; + vf->identity[2] = 0.0; + vf->identity[3] = 1.0; + + vf->codegen_emit = NULL; + +#ifdef USE_SSE_ASM + if (!_mesa_getenv("MESA_NO_CODEGEN")) + vf->codegen_emit = vf_generate_sse_emit; +#endif + + return vf; +} + + +void vf_destroy( struct vertex_fetch *vf ) +{ + struct vf_fastpath *fp, *tmp; + + for (fp = vf->fastpath ; fp ; fp = tmp) { + tmp = fp->next; + FREE(fp->attr); + + /* KW: At the moment, fp->func is constrained to be allocated by + * _mesa_exec_alloc(), as the hardwired fastpaths in + * t_vertex_generic.c are handled specially. It would be nice + * to unify them, but this probably won't change until this + * module gets another overhaul. + */ + _mesa_exec_free((void *) fp->func); + FREE(fp); + } + + vf->fastpath = NULL; + FREE(vf); +} diff --git a/src/mesa/vf/vf.h b/src/mesa/vf/vf.h new file mode 100644 index 00000000000..fc988b9fb9a --- /dev/null +++ b/src/mesa/vf/vf.h @@ -0,0 +1,234 @@ +/* + * Copyright 2003 Tungsten Graphics, 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 + * 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 + * TUNGSTEN GRAPHICS 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: + * Keith Whitwell <[email protected]> + */ + +#ifndef VF_VERTEX_H +#define VF_VERTEX_H + +#include "mtypes.h" +#include "m_vector.h" + +enum { + VF_ATTRIB_POS = 0, + VF_ATTRIB_WEIGHT = 1, + VF_ATTRIB_NORMAL = 2, + VF_ATTRIB_COLOR0 = 3, + VF_ATTRIB_COLOR1 = 4, + VF_ATTRIB_FOG = 5, + VF_ATTRIB_COLOR_INDEX = 6, + VF_ATTRIB_EDGEFLAG = 7, + VF_ATTRIB_TEX0 = 8, + VF_ATTRIB_TEX1 = 9, + VF_ATTRIB_TEX2 = 10, + VF_ATTRIB_TEX3 = 11, + VF_ATTRIB_TEX4 = 12, + VF_ATTRIB_TEX5 = 13, + VF_ATTRIB_TEX6 = 14, + VF_ATTRIB_TEX7 = 15, + VF_ATTRIB_VAR0 = 16, + VF_ATTRIB_VAR1 = 17, + VF_ATTRIB_VAR2 = 18, + VF_ATTRIB_VAR3 = 19, + VF_ATTRIB_VAR4 = 20, + VF_ATTRIB_VAR5 = 21, + VF_ATTRIB_VAR6 = 22, + VF_ATTRIB_VAR7 = 23, + VF_ATTRIB_POINTSIZE = 24, + VF_ATTRIB_BFC0 = 25, + VF_ATTRIB_BFC1 = 26, + VF_ATTRIB_CLIP_POS = 27, + VF_ATTRIB_VERTEX_HEADER = 28, + VF_ATTRIB_MAX = 29 +}; + + +enum vf_attr_format { + EMIT_1F, + EMIT_2F, + EMIT_3F, + EMIT_4F, + EMIT_2F_VIEWPORT, /* do viewport transform and emit */ + EMIT_3F_VIEWPORT, /* do viewport transform and emit */ + EMIT_4F_VIEWPORT, /* do viewport transform and emit */ + EMIT_3F_XYW, /* for projective texture */ + EMIT_1UB_1F, /* for fog coordinate */ + EMIT_3UB_3F_RGB, /* for specular color */ + EMIT_3UB_3F_BGR, /* for specular color */ + EMIT_4UB_4F_RGBA, /* for color */ + EMIT_4UB_4F_BGRA, /* for color */ + EMIT_4UB_4F_ARGB, /* for color */ + EMIT_4UB_4F_ABGR, /* for color */ + EMIT_4CHAN_4F_RGBA, /* for swrast color */ + EMIT_PAD, /* leave a hole of 'offset' bytes */ + EMIT_MAX +}; + +struct vf_attr_map { + GLuint attrib; + enum vf_attr_format format; + GLuint offset; +}; + +struct vertex_fetch; + +void vf_set_vp_matrix( struct vertex_fetch *vf, + const GLfloat *viewport ); + +void vf_set_vp_scale_translate( struct vertex_fetch *vf, + const GLfloat *scale, + const GLfloat *translate ); + +GLuint vf_set_vertex_attributes( struct vertex_fetch *vf, + const struct vf_attr_map *map, + GLuint nr, + GLuint vertex_stride ); + +void vf_set_sources( struct vertex_fetch *vf, + GLvector4f * const attrib[], + GLuint start ); + +void vf_emit_vertices( struct vertex_fetch *vf, + GLuint count, + void *dest ); + +void vf_get_attr( struct vertex_fetch *vf, + const void *vertex, + GLenum attr, + const GLfloat *dflt, + GLfloat *dest ); + +struct vertex_fetch *vf_create( GLboolean allow_viewport_emits ); + +void vf_destroy( struct vertex_fetch *vf ); + + + +/*********************************************************************** + * Internal functions and structs: + */ + +struct vf_attr; + +typedef void (*vf_extract_func)( const struct vf_attr *a, + GLfloat *out, + const GLubyte *v ); + +typedef void (*vf_insert_func)( const struct vf_attr *a, + GLubyte *v, + const GLfloat *in ); + +typedef void (*vf_emit_func)( struct vertex_fetch *vf, + GLuint count, + GLubyte *dest ); + + + +/* Describes how to convert/move a vertex attribute from a vertex + * array to a vertex structure. + */ +struct vf_attr +{ + struct vertex_fetch *vf; + + GLuint format; + GLuint inputsize; + GLuint inputstride; + GLuint vertoffset; /* position of the attrib in the vertex struct */ + + GLuint attrib; /* which vertex attrib (0=position, etc) */ + GLuint vertattrsize; /* size of the attribute in bytes */ + + GLubyte *inputptr; + const vf_insert_func *insert; + vf_insert_func do_insert; + vf_extract_func extract; +}; + +struct vertex_fetch +{ + struct vf_attr attr[VF_ATTRIB_MAX]; + GLuint attr_count; + GLuint vertex_stride; + + struct vf_attr *lookup[VF_ATTRIB_MAX]; + + vf_emit_func emit; + + /* Parameters and constants for codegen: + */ + GLboolean allow_viewport_emits; + GLfloat vp[8]; + GLfloat chan_scale[4]; + GLfloat identity[4]; + + struct vf_fastpath *fastpath; + + void (*codegen_emit)( struct vertex_fetch *vf ); +}; + + +struct vf_attr_type { + GLuint format; + GLuint size; + GLuint stride; + GLuint offset; +}; + +struct vf_fastpath { + GLuint vertex_stride; + GLuint attr_count; + GLboolean match_strides; + + struct vf_attr_type *attr; + + vf_emit_func func; + struct vf_fastpath *next; +}; + + +void vf_register_fastpath( struct vertex_fetch *vtx, + GLboolean match_strides ); + +void vf_generic_emit( struct vertex_fetch *vf, + GLuint count, + GLubyte *v ); + +void vf_generate_hardwired_emit( struct vertex_fetch *vf ); + +void vf_generate_sse_emit( struct vertex_fetch *vf ); + + +struct vf_format_info { + const char *name; + vf_extract_func extract; + vf_insert_func insert[4]; + const GLuint attrsize; +}; + +const struct vf_format_info vf_format_info[EMIT_MAX]; + + +#endif diff --git a/src/mesa/vf/vf_generic.c b/src/mesa/vf/vf_generic.c new file mode 100644 index 00000000000..68d8d0897b8 --- /dev/null +++ b/src/mesa/vf/vf_generic.c @@ -0,0 +1,981 @@ + +/* + * Copyright 2003 Tungsten Graphics, 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 + * 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 + * TUNGSTEN GRAPHICS 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: + * Keith Whitwell <[email protected]> + */ + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "simple_list.h" + +#include "vf/vf.h" + + +/* + * These functions take the NDC coordinates pointed to by 'in', apply the + * NDC->Viewport mapping and store the results at 'v'. + */ + +static INLINE void insert_4f_viewport_4( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = scale[1] * in[1] + trans[1]; + out[2] = scale[2] * in[2] + trans[2]; + out[3] = in[3]; +} + +static INLINE void insert_4f_viewport_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = scale[1] * in[1] + trans[1]; + out[2] = scale[2] * in[2] + trans[2]; + out[3] = 1; +} + +static INLINE void insert_4f_viewport_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = scale[1] * in[1] + trans[1]; + out[2] = trans[2]; + out[3] = 1; +} + +static INLINE void insert_4f_viewport_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = trans[1]; + out[2] = trans[2]; + out[3] = 1; +} + +static INLINE void insert_3f_viewport_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = scale[1] * in[1] + trans[1]; + out[2] = scale[2] * in[2] + trans[2]; +} + +static INLINE void insert_3f_viewport_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = scale[1] * in[1] + trans[1]; + out[2] = scale[2] * in[2] + trans[2]; +} + +static INLINE void insert_3f_viewport_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = trans[1]; + out[2] = trans[2]; +} + +static INLINE void insert_2f_viewport_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = scale[1] * in[1] + trans[1]; +} + +static INLINE void insert_2f_viewport_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = scale[0] * in[0] + trans[0]; + out[1] = trans[1]; +} + + +/* + * These functions do the same as above, except for the viewport mapping. + */ + +static INLINE void insert_4f_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +static INLINE void insert_4f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = 1; +} + +static INLINE void insert_4f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = 0; + out[3] = 1; +} + +static INLINE void insert_4f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = 0; + out[2] = 0; + out[3] = 1; +} + +static INLINE void insert_3f_xyw_4( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[3]; +} + +static INLINE void insert_3f_xyw_err( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + (void) a; (void) v; (void) in; + _mesa_exit(1); +} + +static INLINE void insert_3f_3( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +static INLINE void insert_3f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = 0; +} + +static INLINE void insert_3f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = 0; + out[2] = 0; +} + + +static INLINE void insert_2f_2( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = in[1]; +} + +static INLINE void insert_2f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; + out[1] = 0; +} + +static INLINE void insert_1f_1( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + GLfloat *out = (GLfloat *)(v); + (void) a; + + out[0] = in[0]; +} + +static INLINE void insert_null( const struct vf_attr *a, GLubyte *v, const GLfloat *in ) +{ + (void) a; (void) v; (void) in; +} + +static INLINE void insert_4chan_4f_rgba_4( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLchan *c = (GLchan *)v; + (void) a; + UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); + UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); + UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]); + UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]); +} + +static INLINE void insert_4chan_4f_rgba_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLchan *c = (GLchan *)v; + (void) a; + UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); + UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); + UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]); + c[3] = CHAN_MAX; +} + +static INLINE void insert_4chan_4f_rgba_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLchan *c = (GLchan *)v; + (void) a; + UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); + UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); + c[2] = 0; + c[3] = CHAN_MAX; +} + +static INLINE void insert_4chan_4f_rgba_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + GLchan *c = (GLchan *)v; + (void) a; + UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); + c[1] = 0; + c[2] = 0; + c[3] = CHAN_MAX; +} + +static INLINE void insert_4ub_4f_rgba_4( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]); + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]); +} + +static INLINE void insert_4ub_4f_rgba_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]); + v[3] = 0xff; +} + +static INLINE void insert_4ub_4f_rgba_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + v[2] = 0; + v[3] = 0xff; +} + +static INLINE void insert_4ub_4f_rgba_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); + v[1] = 0; + v[2] = 0; + v[3] = 0xff; +} + +static INLINE void insert_4ub_4f_bgra_4( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]); + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]); +} + +static INLINE void insert_4ub_4f_bgra_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]); + v[3] = 0xff; +} + +static INLINE void insert_4ub_4f_bgra_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + v[0] = 0; + v[3] = 0xff; +} + +static INLINE void insert_4ub_4f_bgra_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); + v[1] = 0; + v[0] = 0; + v[3] = 0xff; +} + +static INLINE void insert_4ub_4f_argb_4( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]); + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]); +} + +static INLINE void insert_4ub_4f_argb_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]); + v[0] = 0xff; +} + +static INLINE void insert_4ub_4f_argb_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); + v[3] = 0x00; + v[0] = 0xff; +} + +static INLINE void insert_4ub_4f_argb_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); + v[2] = 0x00; + v[3] = 0x00; + v[0] = 0xff; +} + +static INLINE void insert_4ub_4f_abgr_4( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]); + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]); +} + +static INLINE void insert_4ub_4f_abgr_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]); + v[0] = 0xff; +} + +static INLINE void insert_4ub_4f_abgr_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); + v[1] = 0x00; + v[0] = 0xff; +} + +static INLINE void insert_4ub_4f_abgr_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); + v[2] = 0x00; + v[1] = 0x00; + v[0] = 0xff; +} + +static INLINE void insert_3ub_3f_rgb_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]); +} + +static INLINE void insert_3ub_3f_rgb_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + v[2] = 0; +} + +static INLINE void insert_3ub_3f_rgb_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); + v[1] = 0; + v[2] = 0; +} + +static INLINE void insert_3ub_3f_bgr_3( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]); +} + +static INLINE void insert_3ub_3f_bgr_2( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); + UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); + v[0] = 0; +} + +static INLINE void insert_3ub_3f_bgr_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); + v[1] = 0; + v[0] = 0; +} + + +static INLINE void insert_1ub_1f_1( const struct vf_attr *a, GLubyte *v, + const GLfloat *in ) +{ + (void) a; + UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); +} + + +/*********************************************************************** + * Functions to perform the reverse operations to the above, for + * swrast translation and clip-interpolation. + * + * Currently always extracts a full 4 floats. + */ + +static void extract_4f_viewport( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + /* Although included for completeness, the position coordinate is + * usually handled differently during clipping. + */ + out[0] = (in[0] - trans[0]) / scale[0]; + out[1] = (in[1] - trans[1]) / scale[1]; + out[2] = (in[2] - trans[2]) / scale[2]; + out[3] = in[3]; +} + +static void extract_3f_viewport( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = (in[0] - trans[0]) / scale[0]; + out[1] = (in[1] - trans[1]) / scale[1]; + out[2] = (in[2] - trans[2]) / scale[2]; + out[3] = 1; +} + + +static void extract_2f_viewport( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + const GLfloat *scale = a->vf->vp; + const GLfloat *trans = a->vf->vp + 4; + + out[0] = (in[0] - trans[0]) / scale[0]; + out[1] = (in[1] - trans[1]) / scale[1]; + out[2] = 0; + out[3] = 1; +} + + +static void extract_4f( const struct vf_attr *a, GLfloat *out, const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; +} + +static void extract_3f_xyw( const struct vf_attr *a, GLfloat *out, const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = 0; + out[3] = in[2]; +} + + +static void extract_3f( const struct vf_attr *a, GLfloat *out, const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = 1; +} + + +static void extract_2f( const struct vf_attr *a, GLfloat *out, const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + (void) a; + + out[0] = in[0]; + out[1] = in[1]; + out[2] = 0; + out[3] = 1; +} + +static void extract_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v ) +{ + const GLfloat *in = (const GLfloat *)v; + (void) a; + + out[0] = in[0]; + out[1] = 0; + out[2] = 0; + out[3] = 1; +} + +static void extract_4chan_4f_rgba( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + GLchan *c = (GLchan *)v; + (void) a; + + out[0] = CHAN_TO_FLOAT(c[0]); + out[1] = CHAN_TO_FLOAT(c[1]); + out[2] = CHAN_TO_FLOAT(c[2]); + out[3] = CHAN_TO_FLOAT(c[3]); +} + +static void extract_4ub_4f_rgba( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + (void) a; + out[0] = UBYTE_TO_FLOAT(v[0]); + out[1] = UBYTE_TO_FLOAT(v[1]); + out[2] = UBYTE_TO_FLOAT(v[2]); + out[3] = UBYTE_TO_FLOAT(v[3]); +} + +static void extract_4ub_4f_bgra( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + (void) a; + out[2] = UBYTE_TO_FLOAT(v[0]); + out[1] = UBYTE_TO_FLOAT(v[1]); + out[0] = UBYTE_TO_FLOAT(v[2]); + out[3] = UBYTE_TO_FLOAT(v[3]); +} + +static void extract_4ub_4f_argb( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + (void) a; + out[3] = UBYTE_TO_FLOAT(v[0]); + out[0] = UBYTE_TO_FLOAT(v[1]); + out[1] = UBYTE_TO_FLOAT(v[2]); + out[2] = UBYTE_TO_FLOAT(v[3]); +} + +static void extract_4ub_4f_abgr( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + (void) a; + out[3] = UBYTE_TO_FLOAT(v[0]); + out[2] = UBYTE_TO_FLOAT(v[1]); + out[1] = UBYTE_TO_FLOAT(v[2]); + out[0] = UBYTE_TO_FLOAT(v[3]); +} + +static void extract_3ub_3f_rgb( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + (void) a; + out[0] = UBYTE_TO_FLOAT(v[0]); + out[1] = UBYTE_TO_FLOAT(v[1]); + out[2] = UBYTE_TO_FLOAT(v[2]); + out[3] = 1; +} + +static void extract_3ub_3f_bgr( const struct vf_attr *a, GLfloat *out, + const GLubyte *v ) +{ + (void) a; + out[2] = UBYTE_TO_FLOAT(v[0]); + out[1] = UBYTE_TO_FLOAT(v[1]); + out[0] = UBYTE_TO_FLOAT(v[2]); + out[3] = 1; +} + +static void extract_1ub_1f( const struct vf_attr *a, GLfloat *out, const GLubyte *v ) +{ + (void) a; + out[0] = UBYTE_TO_FLOAT(v[0]); + out[1] = 0; + out[2] = 0; + out[3] = 1; +} + + +const struct vf_format_info vf_format_info[EMIT_MAX] = +{ + { "1f", + extract_1f, + { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 }, + sizeof(GLfloat) }, + + { "2f", + extract_2f, + { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 }, + 2 * sizeof(GLfloat) }, + + { "3f", + extract_3f, + { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 }, + 3 * sizeof(GLfloat) }, + + { "4f", + extract_4f, + { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 }, + 4 * sizeof(GLfloat) }, + + { "2f_viewport", + extract_2f_viewport, + { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2, + insert_2f_viewport_2 }, + 2 * sizeof(GLfloat) }, + + { "3f_viewport", + extract_3f_viewport, + { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3, + insert_3f_viewport_3 }, + 3 * sizeof(GLfloat) }, + + { "4f_viewport", + extract_4f_viewport, + { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3, + insert_4f_viewport_4 }, + 4 * sizeof(GLfloat) }, + + { "3f_xyw", + extract_3f_xyw, + { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err, + insert_3f_xyw_4 }, + 3 * sizeof(GLfloat) }, + + { "1ub_1f", + extract_1ub_1f, + { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 }, + sizeof(GLubyte) }, + + { "3ub_3f_rgb", + extract_3ub_3f_rgb, + { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3, + insert_3ub_3f_rgb_3 }, + 3 * sizeof(GLubyte) }, + + { "3ub_3f_bgr", + extract_3ub_3f_bgr, + { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3, + insert_3ub_3f_bgr_3 }, + 3 * sizeof(GLubyte) }, + + { "4ub_4f_rgba", + extract_4ub_4f_rgba, + { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3, + insert_4ub_4f_rgba_4 }, + 4 * sizeof(GLubyte) }, + + { "4ub_4f_bgra", + extract_4ub_4f_bgra, + { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3, + insert_4ub_4f_bgra_4 }, + 4 * sizeof(GLubyte) }, + + { "4ub_4f_argb", + extract_4ub_4f_argb, + { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3, + insert_4ub_4f_argb_4 }, + 4 * sizeof(GLubyte) }, + + { "4ub_4f_abgr", + extract_4ub_4f_abgr, + { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3, + insert_4ub_4f_abgr_4 }, + 4 * sizeof(GLubyte) }, + + { "4chan_4f_rgba", + extract_4chan_4f_rgba, + { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3, + insert_4chan_4f_rgba_4 }, + 4 * sizeof(GLchan) }, + + { "pad", + NULL, + { NULL, NULL, NULL, NULL }, + 0 } + +}; + + + + +/*********************************************************************** + * Hardwired fastpaths for emitting whole vertices or groups of + * vertices + */ +#define EMIT5(NR, F0, F1, F2, F3, F4, NAME) \ +static void NAME( struct vertex_fetch *vf, \ + GLuint count, \ + GLubyte *v ) \ +{ \ + struct vf_attr *a = vf->attr; \ + GLuint i; \ + \ + for (i = 0 ; i < count ; i++, v += vf->vertex_stride) { \ + if (NR > 0) { \ + F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr ); \ + a[0].inputptr += a[0].inputstride; \ + } \ + \ + if (NR > 1) { \ + F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr ); \ + a[1].inputptr += a[1].inputstride; \ + } \ + \ + if (NR > 2) { \ + F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr ); \ + a[2].inputptr += a[2].inputstride; \ + } \ + \ + if (NR > 3) { \ + F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr ); \ + a[3].inputptr += a[3].inputstride; \ + } \ + \ + if (NR > 4) { \ + F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr ); \ + a[4].inputptr += a[4].inputstride; \ + } \ + } \ +} + + +#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \ + insert_null, insert_null, NAME) + +#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \ + insert_null, NAME) + +#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \ + insert_null, NAME) + + +EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4) +EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4) +EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4) + +EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2) +EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, emit_viewport4_bgra4_st2) +EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2) + +EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2) +EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2, emit_viewport4_bgra4_st2_st2) +EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2) + + +/* Use the codegen paths to select one of a number of hardwired + * fastpaths. + */ +void vf_generate_hardwired_emit( struct vertex_fetch *vf ) +{ + vf_emit_func func = NULL; + + /* Does it fit a hardwired fastpath? Help! this is growing out of + * control! + */ + switch (vf->attr_count) { + case 2: + if (vf->attr[0].do_insert == insert_3f_viewport_3) { + if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4) + func = emit_viewport3_bgra4; + else if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) + func = emit_viewport3_rgba4; + } + else if (vf->attr[0].do_insert == insert_3f_3 && + vf->attr[1].do_insert == insert_4ub_4f_rgba_4) { + func = emit_xyz3_rgba4; + } + break; + case 3: + if (vf->attr[2].do_insert == insert_2f_2) { + if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) { + if (vf->attr[0].do_insert == insert_4f_viewport_4) + func = emit_viewport4_rgba4_st2; + else if (vf->attr[0].do_insert == insert_4f_4) + func = emit_xyzw4_rgba4_st2; + } + else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 && + vf->attr[0].do_insert == insert_4f_viewport_4) + func = emit_viewport4_bgra4_st2; + } + break; + case 4: + if (vf->attr[2].do_insert == insert_2f_2 && + vf->attr[3].do_insert == insert_2f_2) { + if (vf->attr[1].do_insert == insert_4ub_4f_rgba_4) { + if (vf->attr[0].do_insert == insert_4f_viewport_4) + func = emit_viewport4_rgba4_st2_st2; + else if (vf->attr[0].do_insert == insert_4f_4) + func = emit_xyzw4_rgba4_st2_st2; + } + else if (vf->attr[1].do_insert == insert_4ub_4f_bgra_4 && + vf->attr[0].do_insert == insert_4f_viewport_4) + func = emit_viewport4_bgra4_st2_st2; + } + break; + } + + vf->emit = func; +} + +/*********************************************************************** + * Generic (non-codegen) functions for whole vertices or groups of + * vertices + */ + +void vf_generic_emit( struct vertex_fetch *vf, + GLuint count, + GLubyte *v ) +{ + struct vf_attr *a = vf->attr; + const GLuint attr_count = vf->attr_count; + const GLuint stride = vf->vertex_stride; + GLuint i, j; + + for (i = 0 ; i < count ; i++, v += stride) { + for (j = 0; j < attr_count; j++) { + GLfloat *in = (GLfloat *)a[j].inputptr; + a[j].inputptr += a[j].inputstride; + a[j].do_insert( &a[j], v + a[j].vertoffset, in ); + } + } +} + + diff --git a/src/mesa/vf/vf_sse.c b/src/mesa/vf/vf_sse.c new file mode 100644 index 00000000000..a5d143461bf --- /dev/null +++ b/src/mesa/vf/vf_sse.c @@ -0,0 +1,664 @@ +/* + * Copyright 2003 Tungsten Graphics, 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 + * 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 + * TUNGSTEN GRAPHICS 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: + * Keith Whitwell <[email protected]> + */ + +#include "glheader.h" +#include "colormac.h" +#include "simple_list.h" +#include "enums.h" + +#include "vf/vf.h" + +#if defined(USE_SSE_ASM) + +#include "x86/rtasm/x86sse.h" +#include "x86/common_x86_asm.h" + + +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + + +struct x86_program { + struct x86_function func; + + struct vertex_fetch *vf; + GLboolean inputs_safe; + GLboolean outputs_safe; + GLboolean have_sse2; + + struct x86_reg identity; + struct x86_reg chan0; +}; + + +static struct x86_reg get_identity( struct x86_program *p ) +{ + return p->identity; +} + +static void emit_load4f_4( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + sse_movups(&p->func, dest, arg0); +} + +static void emit_load4f_3( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + /* Have to jump through some hoops: + * + * c 0 0 0 + * c 0 0 1 + * 0 0 c 1 + * a b c 1 + */ + sse_movss(&p->func, dest, x86_make_disp(arg0, 8)); + sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) ); + sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) ); + sse_movlps(&p->func, dest, arg0); +} + +static void emit_load4f_2( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + /* Initialize from identity, then pull in low two words: + */ + sse_movups(&p->func, dest, get_identity(p)); + sse_movlps(&p->func, dest, arg0); +} + +static void emit_load4f_1( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + /* Pull in low word, then swizzle in identity */ + sse_movss(&p->func, dest, arg0); + sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) ); +} + + + +static void emit_load3f_3( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + /* Over-reads by 1 dword - potential SEGV if input is a vertex + * array. + */ + if (p->inputs_safe) { + sse_movups(&p->func, dest, arg0); + } + else { + /* c 0 0 0 + * c c c c + * a b c c + */ + sse_movss(&p->func, dest, x86_make_disp(arg0, 8)); + sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X)); + sse_movlps(&p->func, dest, arg0); + } +} + +static void emit_load3f_2( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + emit_load4f_2(p, dest, arg0); +} + +static void emit_load3f_1( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + emit_load4f_1(p, dest, arg0); +} + +static void emit_load2f_2( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + sse_movlps(&p->func, dest, arg0); +} + +static void emit_load2f_1( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + emit_load4f_1(p, dest, arg0); +} + +static void emit_load1f_1( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + sse_movss(&p->func, dest, arg0); +} + +static void (*load[4][4])( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) = { + { emit_load1f_1, + emit_load1f_1, + emit_load1f_1, + emit_load1f_1 }, + + { emit_load2f_1, + emit_load2f_2, + emit_load2f_2, + emit_load2f_2 }, + + { emit_load3f_1, + emit_load3f_2, + emit_load3f_3, + emit_load3f_3 }, + + { emit_load4f_1, + emit_load4f_2, + emit_load4f_3, + emit_load4f_4 } +}; + +static void emit_load( struct x86_program *p, + struct x86_reg dest, + GLuint sz, + struct x86_reg src, + GLuint src_sz) +{ + load[sz-1][src_sz-1](p, dest, src); +} + +static void emit_store4f( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + sse_movups(&p->func, dest, arg0); +} + +static void emit_store3f( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + if (p->outputs_safe) { + /* Emit the extra dword anyway. This may hurt writecombining, + * may cause other problems. + */ + sse_movups(&p->func, dest, arg0); + } + else { + /* Alternate strategy - emit two, shuffle, emit one. + */ + sse_movlps(&p->func, dest, arg0); + sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */ + sse_movss(&p->func, x86_make_disp(dest,8), arg0); + } +} + +static void emit_store2f( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + sse_movlps(&p->func, dest, arg0); +} + +static void emit_store1f( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) +{ + sse_movss(&p->func, dest, arg0); +} + + +static void (*store[4])( struct x86_program *p, + struct x86_reg dest, + struct x86_reg arg0 ) = +{ + emit_store1f, + emit_store2f, + emit_store3f, + emit_store4f +}; + +static void emit_store( struct x86_program *p, + struct x86_reg dest, + GLuint sz, + struct x86_reg temp ) + +{ + store[sz-1](p, dest, temp); +} + +static void emit_pack_store_4ub( struct x86_program *p, + struct x86_reg dest, + struct x86_reg temp ) +{ + /* Scale by 255.0 + */ + sse_mulps(&p->func, temp, p->chan0); + + if (p->have_sse2) { + sse2_cvtps2dq(&p->func, temp, temp); + sse2_packssdw(&p->func, temp, temp); + sse2_packuswb(&p->func, temp, temp); + sse_movss(&p->func, dest, temp); + } + else { + struct x86_reg mmx0 = x86_make_reg(file_MMX, 0); + struct x86_reg mmx1 = x86_make_reg(file_MMX, 1); + sse_cvtps2pi(&p->func, mmx0, temp); + sse_movhlps(&p->func, temp, temp); + sse_cvtps2pi(&p->func, mmx1, temp); + mmx_packssdw(&p->func, mmx0, mmx1); + mmx_packuswb(&p->func, mmx0, mmx0); + mmx_movd(&p->func, dest, mmx0); + } +} + +static GLint get_offset( const void *a, const void *b ) +{ + return (const char *)b - (const char *)a; +} + +/* Not much happens here. Eventually use this function to try and + * avoid saving/reloading the source pointers each vertex (if some of + * them can fit in registers). + */ +static void get_src_ptr( struct x86_program *p, + struct x86_reg srcREG, + struct x86_reg vfREG, + struct vf_attr *a ) +{ + struct vertex_fetch *vf = p->vf; + struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr)); + + /* Load current a[j].inputptr + */ + x86_mov(&p->func, srcREG, ptr_to_src); +} + +static void update_src_ptr( struct x86_program *p, + struct x86_reg srcREG, + struct x86_reg vfREG, + struct vf_attr *a ) +{ + if (a->inputstride) { + struct vertex_fetch *vf = p->vf; + struct x86_reg ptr_to_src = x86_make_disp(vfREG, get_offset(vf, &a->inputptr)); + + /* add a[j].inputstride (hardcoded value - could just as easily + * pull the stride value from memory each time). + */ + x86_lea(&p->func, srcREG, x86_make_disp(srcREG, a->inputstride)); + + /* save new value of a[j].inputptr + */ + x86_mov(&p->func, ptr_to_src, srcREG); + } +} + + +/* Lots of hardcoding + * + * EAX -- pointer to current output vertex + * ECX -- pointer to current attribute + * + */ +static GLboolean build_vertex_emit( struct x86_program *p ) +{ + struct vertex_fetch *vf = p->vf; + GLuint j = 0; + + struct x86_reg vertexEAX = x86_make_reg(file_REG32, reg_AX); + struct x86_reg srcECX = x86_make_reg(file_REG32, reg_CX); + struct x86_reg countEBP = x86_make_reg(file_REG32, reg_BP); + struct x86_reg vfESI = x86_make_reg(file_REG32, reg_SI); + struct x86_reg temp = x86_make_reg(file_XMM, 0); + struct x86_reg vp0 = x86_make_reg(file_XMM, 1); + struct x86_reg vp1 = x86_make_reg(file_XMM, 2); + GLubyte *fixup, *label; + + x86_init_func(&p->func); + + /* Push a few regs? + */ + x86_push(&p->func, countEBP); + x86_push(&p->func, vfESI); + + + /* Get vertex count, compare to zero + */ + x86_xor(&p->func, srcECX, srcECX); + x86_mov(&p->func, countEBP, x86_fn_arg(&p->func, 2)); + x86_cmp(&p->func, countEBP, srcECX); + fixup = x86_jcc_forward(&p->func, cc_E); + + /* Initialize destination register. + */ + x86_mov(&p->func, vertexEAX, x86_fn_arg(&p->func, 3)); + + /* Move argument 1 (vf) into a reg: + */ + x86_mov(&p->func, vfESI, x86_fn_arg(&p->func, 1)); + + + /* Possibly load vp0, vp1 for viewport calcs: + */ + if (vf->allow_viewport_emits) { + sse_movups(&p->func, vp0, x86_make_disp(vfESI, get_offset(vf, &vf->vp[0]))); + sse_movups(&p->func, vp1, x86_make_disp(vfESI, get_offset(vf, &vf->vp[4]))); + } + + /* always load, needed or not: + */ + sse_movups(&p->func, p->chan0, x86_make_disp(vfESI, get_offset(vf, &vf->chan_scale[0]))); + sse_movups(&p->func, p->identity, x86_make_disp(vfESI, get_offset(vf, &vf->identity[0]))); + + /* Note address for loop jump */ + label = x86_get_label(&p->func); + + /* Emit code for each of the attributes. Currently routes + * everything through SSE registers, even when it might be more + * efficient to stick with regular old x86. No optimization or + * other tricks - enough new ground to cover here just getting + * things working. + */ + while (j < vf->attr_count) { + struct vf_attr *a = &vf->attr[j]; + struct x86_reg dest = x86_make_disp(vertexEAX, a->vertoffset); + + /* Now, load an XMM reg from src, perhaps transform, then save. + * Could be shortcircuited in specific cases: + */ + switch (a->format) { + case EMIT_1F: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize); + emit_store(p, dest, 1, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_2F: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize); + emit_store(p, dest, 2, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_3F: + /* Potentially the worst case - hardcode 2+1 copying: + */ + if (0) { + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); + emit_store(p, dest, 3, temp); + update_src_ptr(p, srcECX, vfESI, a); + } + else { + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize); + emit_store(p, dest, 2, temp); + if (a->inputsize > 2) { + emit_load(p, temp, 1, x86_make_disp(srcECX, 8), 1); + emit_store(p, x86_make_disp(dest,8), 1, temp); + } + else { + sse_movss(&p->func, x86_make_disp(dest,8), get_identity(p)); + } + update_src_ptr(p, srcECX, vfESI, a); + } + break; + case EMIT_4F: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + emit_store(p, dest, 4, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_2F_VIEWPORT: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize); + sse_mulps(&p->func, temp, vp0); + sse_addps(&p->func, temp, vp1); + emit_store(p, dest, 2, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_3F_VIEWPORT: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); + sse_mulps(&p->func, temp, vp0); + sse_addps(&p->func, temp, vp1); + emit_store(p, dest, 3, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_4F_VIEWPORT: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + sse_mulps(&p->func, temp, vp0); + sse_addps(&p->func, temp, vp1); + emit_store(p, dest, 4, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_3F_XYW: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z)); + emit_store(p, dest, 3, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + + case EMIT_1UB_1F: + /* Test for PAD3 + 1UB: + */ + if (j > 0 && + a[-1].vertoffset + a[-1].vertattrsize <= a->vertoffset - 3) + { + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize); + sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X)); + emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */ + update_src_ptr(p, srcECX, vfESI, a); + } + else { + _mesa_printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize ); + return GL_FALSE; + } + break; + case EMIT_3UB_3F_RGB: + case EMIT_3UB_3F_BGR: + /* Test for 3UB + PAD1: + */ + if (j == vf->attr_count - 1 || + a[1].vertoffset >= a->vertoffset + 4) { + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); + if (a->format == EMIT_3UB_3F_BGR) + sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W)); + emit_pack_store_4ub(p, dest, temp); + update_src_ptr(p, srcECX, vfESI, a); + } + /* Test for 3UB + 1UB: + */ + else if (j < vf->attr_count - 1 && + a[1].format == EMIT_1UB_1F && + a[1].vertoffset == a->vertoffset + 3) { + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); + update_src_ptr(p, srcECX, vfESI, a); + + /* Make room for incoming value: + */ + sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z)); + + get_src_ptr(p, srcECX, vfESI, &a[1]); + emit_load(p, temp, 1, x86_deref(srcECX), a[1].inputsize); + update_src_ptr(p, srcECX, vfESI, &a[1]); + + /* Rearrange and possibly do BGR conversion: + */ + if (a->format == EMIT_3UB_3F_BGR) + sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X)); + else + sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X)); + + emit_pack_store_4ub(p, dest, temp); + j++; /* NOTE: two attrs consumed */ + } + else { + _mesa_printf("Can't emit 3ub\n"); + } + return GL_FALSE; /* add this later */ + break; + + case EMIT_4UB_4F_RGBA: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + emit_pack_store_4ub(p, dest, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_4UB_4F_BGRA: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W)); + emit_pack_store_4ub(p, dest, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_4UB_4F_ARGB: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z)); + emit_pack_store_4ub(p, dest, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_4UB_4F_ABGR: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X)); + emit_pack_store_4ub(p, dest, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case EMIT_4CHAN_4F_RGBA: + switch (CHAN_TYPE) { + case GL_UNSIGNED_BYTE: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + emit_pack_store_4ub(p, dest, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case GL_FLOAT: + get_src_ptr(p, srcECX, vfESI, a); + emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); + emit_store(p, dest, 4, temp); + update_src_ptr(p, srcECX, vfESI, a); + break; + case GL_UNSIGNED_SHORT: + default: + _mesa_printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE)); + return GL_FALSE; + } + break; + default: + _mesa_printf("unknown a[%d].format %d\n", j, a->format); + return GL_FALSE; /* catch any new opcodes */ + } + + /* Increment j by at least 1 - may have been incremented above also: + */ + j++; + } + + /* Next vertex: + */ + x86_lea(&p->func, vertexEAX, x86_make_disp(vertexEAX, vf->vertex_stride)); + + /* decr count, loop if not zero + */ + x86_dec(&p->func, countEBP); + x86_test(&p->func, countEBP, countEBP); + x86_jcc(&p->func, cc_NZ, label); + + /* Exit mmx state? + */ + if (p->func.need_emms) + mmx_emms(&p->func); + + /* Land forward jump here: + */ + x86_fixup_fwd_jump(&p->func, fixup); + + /* Pop regs and return + */ + x86_pop(&p->func, x86_get_base_reg(vfESI)); + x86_pop(&p->func, countEBP); + x86_ret(&p->func); + + vf->emit = (vf_emit_func)x86_get_func(&p->func); + return GL_TRUE; +} + + + +void vf_generate_sse_emit( struct vertex_fetch *vf ) +{ + struct x86_program p; + + if (!cpu_has_xmm) { + vf->codegen_emit = NULL; + return; + } + + _mesa_memset(&p, 0, sizeof(p)); + + p.vf = vf; + p.inputs_safe = 0; /* for now */ + p.outputs_safe = 1; /* for now */ + p.have_sse2 = cpu_has_xmm2; + p.identity = x86_make_reg(file_XMM, 6); + p.chan0 = x86_make_reg(file_XMM, 7); + + x86_init_func(&p.func); + + if (build_vertex_emit(&p)) { + vf_register_fastpath( vf, GL_TRUE ); + } + else { + /* Note the failure so that we don't keep trying to codegen an + * impossible state: + */ + vf_register_fastpath( vf, GL_FALSE ); + x86_release_func(&p.func); + } +} + +#else + +void vf_generate_sse_emit( struct vertex_fetch *vf ) +{ + /* Dummy version for when USE_SSE_ASM not defined */ +} + +#endif |