From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/gfxdrivers/nvidia/nvidia_3d.c | 522 ++++++++++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100755 Source/DirectFB/gfxdrivers/nvidia/nvidia_3d.c (limited to 'Source/DirectFB/gfxdrivers/nvidia/nvidia_3d.c') diff --git a/Source/DirectFB/gfxdrivers/nvidia/nvidia_3d.c b/Source/DirectFB/gfxdrivers/nvidia/nvidia_3d.c new file mode 100755 index 0000000..ae8dffc --- /dev/null +++ b/Source/DirectFB/gfxdrivers/nvidia/nvidia_3d.c @@ -0,0 +1,522 @@ +/* + Copyright (C) 2004-2006 Claudio Ciccani + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include "nvidia.h" +#include "nvidia_regs.h" +#include "nvidia_accel.h" +#include "nvidia_3d.h" + + +static __inline__ u32 +f2d( float f ) { + union { + float f; + u32 d; + } t; + t.f = f; + return t.d; +} + +#define nv_setstate3d( state3d ) { \ + if ((state3d)->modified) { \ + nv_begin( SUBC_TEXTRIANGLE, TXTRI_COLOR_KEY, 7 ); \ + nv_outr( (state3d)->colorkey ); \ + nv_outr( (state3d)->offset ); \ + nv_outr( (state3d)->format ); \ + nv_outr( (state3d)->filter ); \ + nv_outr( (state3d)->blend ); \ + nv_outr( (state3d)->control ); \ + nv_outr( (state3d)->fog ); \ + \ + (state3d)->modified = false; \ + } \ +} + +#define nv_putvertex( i, x, y, z, w, col, spc, s, t ) { \ + nv_begin( SUBC_TEXTRIANGLE, TXTRI_VERTEX0+(i)*32, 8 ); \ + nv_outr( f2d( x ) ); \ + nv_outr( f2d( y ) ); \ + nv_outr( f2d( z ) ); \ + nv_outr( f2d( w ) ); \ + nv_outr( col ); \ + nv_outr( spc ); \ + nv_outr( f2d( s ) ); \ + nv_outr( f2d( t ) ); \ +} + +#define nv_emit_vertices( i, v0, v1, v2, v3, v4, v5, v6, v7 ) { \ + nv_begin( SUBC_TEXTRIANGLE, TXTRI_PRIMITIVE0+(i)*4, 1 ); \ + nv_outr( ((v7) << 28) | ((v6) << 24) | \ + ((v5) << 20) | ((v4) << 16) | \ + ((v3) << 12) | ((v2) << 8) | \ + ((v1) << 4) | (v0) ); \ +} + + +static void nv_load_texture( NVidiaDriverData *nvdrv, NVidiaDeviceData *nvdev ); + + +#define M_TRANSFORM(x, y, retx, rety, m) { \ + float _x, _y; \ + _x = ((x) * (m)[0] + (y) * (m)[1] + (m)[2]) / 65536.f; \ + _y = ((x) * (m)[3] + (y) * (m)[4] + (m)[5]) / 65536.f; \ + retx = _x; \ + rety = _y; \ +} + + +bool nvFillRectangle3D( void *drv, void *dev, DFBRectangle *rect ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; + NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; + float x1, y1; + float x2, y2; + + x1 = rect->x; x2 = rect->x+rect->w; + y1 = rect->y; y2 = rect->y+rect->h; + + nv_setstate3d( &nvdev->state3d[0] ); + + if (nvdev->matrix) { + float x, y; + + M_TRANSFORM( x1, y1, x, y, nvdev->matrix ); + nv_putvertex( 0, x, y, 0, 1, nvdev->color3d, 0, 0, 0 ); + M_TRANSFORM( x2, y1, x, y, nvdev->matrix ); + nv_putvertex( 1, x, y, 0, 1, nvdev->color3d, 0, 0, 0 ); + M_TRANSFORM( x2, y2, x, y, nvdev->matrix ); + nv_putvertex( 2, x, y, 0, 1, nvdev->color3d, 0, 0, 0 ); + M_TRANSFORM( x1, y2, x, y, nvdev->matrix ); + nv_putvertex( 3, x, y, 0, 1, nvdev->color3d, 0, 0, 0 ); + } + else { + nv_putvertex( 0, x1, y1, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 1, x2, y1, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 2, x2, y2, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 3, x1, y2, 0, 1, nvdev->color3d, 0, 0, 0 ); + } + + nv_emit_vertices( 0, 0, 1, 2, 0, 2, 3, 0, 0 ); + + return true; +} + +bool nvFillTriangle3D( void *drv, void *dev, DFBTriangle *tri ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; + NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; + float x1, y1; + float x2, y2; + float x3, y3; + + x1 = tri->x1; x2 = tri->x2; x3 = tri->x3; + y1 = tri->y1; y2 = tri->y2; y3 = tri->y3; + if (nvdev->matrix) { + M_TRANSFORM( x1, y1, x1, y1, nvdev->matrix ); + M_TRANSFORM( x2, y2, x2, y2, nvdev->matrix ); + M_TRANSFORM( x3, y3, x3, y3, nvdev->matrix ); + } + + nv_setstate3d( &nvdev->state3d[0] ); + + nv_putvertex( 0, x1, y1, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 1, x2, y2, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 2, x3, y3, 0, 1, nvdev->color3d, 0, 0, 0 ); + + nv_emit_vertices( 0, 0, 1, 2, 0, 0, 0, 0, 0 ); + + return true; +} + +bool nvDrawRectangle3D( void *drv, void *dev, DFBRectangle *rect ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; + NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; + DFBRegion r[4]; + int i; + + if (nvdev->matrix) { + DFBRegion line; + + /* top */ + line = (DFBRegion) { rect->x, rect->y, rect->x+rect->w, rect->y }; + nvDrawLine3D( drv, dev, &line ); + /* right */ + line = (DFBRegion) { rect->x+rect->w, rect->y, rect->x+rect->w, rect->y+rect->h }; + nvDrawLine3D( drv, dev, &line ); + /* bottom */ + line = (DFBRegion) { rect->x, rect->y+rect->h, rect->x+rect->w, rect->y+rect->h }; + nvDrawLine3D( drv, dev, &line ); + /* left */ + line = (DFBRegion) { rect->x, rect->y, rect->x, rect->y+rect->h }; + nvDrawLine3D( drv, dev, &line ); + + return true; + } + + /* top */ + r[0].x1 = rect->x; + r[0].y1 = rect->y; + r[0].x2 = rect->x + rect->w; + r[0].y2 = rect->y + 1; + + /* right */ + r[1].x1 = rect->x + rect->w - 1; + r[1].y1 = rect->y + 1; + r[1].x2 = rect->x + rect->w; + r[1].y2 = rect->y + rect->h - 1; + + /* bottom */ + r[2].x1 = rect->x; + r[2].y1 = rect->y + rect->h - 1; + r[2].x2 = rect->x + rect->w; + r[2].y2 = rect->y + rect->h; + + /* left */ + r[3].x1 = rect->x; + r[3].y1 = rect->y + 1; + r[3].x2 = rect->x + 1; + r[3].y2 = rect->y + rect->h - 1; + + nv_setstate3d( &nvdev->state3d[0] ); + + for (i = 0; i < 4; i++) { + nv_putvertex( 0, r[i].x1, r[i].y1, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 1, r[i].x2, r[i].y1, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 2, r[i].x2, r[i].y2, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 3, r[i].x1, r[i].y2, 0, 1, nvdev->color3d, 0, 0, 0 ); + + nv_emit_vertices( 0, 0, 1, 2, 0, 2, 3, 0, 0 ); + } + + return true; +} + +bool nvDrawLine3D( void *drv, void *dev, DFBRegion *line ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; + NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; + float xinc, yinc; + float x1, y1; + float x2, y2; + float dx, dy; + + x1 = line->x1; x2 = line->x2; + y1 = line->y1; y2 = line->y2; + if (nvdev->matrix) { + M_TRANSFORM( x1, y1, x1, y1, nvdev->matrix ); + M_TRANSFORM( x2, y2, x2, y2, nvdev->matrix ); + + dx = fabs(x2 - x1); + dy = fabs(y2 - y1); + } + else { + dx = abs(line->x2 - line->x1); + dy = abs(line->y2 - line->y1); + } + + if (dx > dy) { /* more horizontal */ + xinc = 0.0; + yinc = 0.5; + } else { /* more vertical */ + xinc = 0.5; + yinc = 0.0; + } + + nv_setstate3d( &nvdev->state3d[0] ); + + nv_putvertex( 0, x1 - xinc, y1 - yinc, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 1, x1 + xinc, y1 + yinc, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 2, x2 + xinc, y2 + yinc, 0, 1, nvdev->color3d, 0, 0, 0 ); + nv_putvertex( 3, x2 - xinc, y2 - yinc, 0, 1, nvdev->color3d, 0, 0, 0 ); + + nv_emit_vertices( 0, 2, 0, 1, 3, 0, 2, 0, 0 ); + + return true; +} + +bool nvTextureTriangles( void *drv, void *dev, DFBVertex *ve, + int num, DFBTriangleFormation formation ) +{ + NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; + NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; + float s_scale; + float t_scale; + int i; + + /* load source texture into texture buffer */ + nv_load_texture( nvdrv, nvdev ); + + s_scale = (float)nvdev->src_width / + (float)(1 << ((nvdev->state3d[1].format >> 16) & 0xF)); + t_scale = (float)nvdev->src_height / + (float)(1 << ((nvdev->state3d[1].format >> 20) & 0xF)); + + for (i = 0; i < num; i++) { + if (nvdev->matrix) + M_TRANSFORM( ve[i].x, ve[i].y, ve[i].x, ve[i].y, nvdev->matrix ); + ve[i].x += 0.5; + ve[i].y += 0.5; + ve[i].s *= s_scale; + ve[i].t *= t_scale; + } + + nv_setstate3d( &nvdev->state3d[1] ); + + switch (formation) { + case DTTF_LIST: + for (i = 0; i < num; i += 3) { + nv_putvertex( 0, ve[i].x, ve[i].y, ve[i].z, ve[i].w, + nvdev->color3d, 0, ve[i].s, ve[i].t ); + nv_putvertex( 1, ve[i+1].x, ve[i+1].y, ve[i+1].z, ve[i+1].w, + nvdev->color3d, 0, ve[i+1].s, ve[i+1].t ); + nv_putvertex( 2, ve[i+2].x, ve[i+2].y, ve[i+2].z, ve[i+2].w, + nvdev->color3d, 0, ve[i+2].s, ve[i+2].t ); + nv_emit_vertices( 0, 0, 1, 2, 0, 0, 0, 0, 0 ); + } + break; + + case DTTF_STRIP: + nv_putvertex( 0, ve[0].x, ve[0].y, ve[0].z, ve[0].w, + nvdev->color3d, 0, ve[0].s, ve[0].t ); + nv_putvertex( 1, ve[1].x, ve[1].y, ve[1].z, ve[1].w, + nvdev->color3d, 0, ve[1].s, ve[1].t ); + nv_putvertex( 2, ve[2].x, ve[2].y, ve[2].z, ve[2].w, + nvdev->color3d, 0, ve[2].s, ve[2].t ); + nv_emit_vertices( 0, 0, 1, 2, 0, 0, 0, 0, 0 ); + + for (i = 3; i < num; i++) { + nv_putvertex( 0, ve[i-2].x, ve[i-2].y, ve[i-2].z, ve[i-2].w, + nvdev->color3d, 0, ve[i-2].s, ve[i-2].t ); + nv_putvertex( 1, ve[i-1].x, ve[i-1].y, ve[i-1].z, ve[i-1].w, + nvdev->color3d, 0, ve[i-1].s, ve[i-1].t ); + nv_putvertex( 2, ve[i].x, ve[i].y, ve[i].z, ve[i].w, + nvdev->color3d, 0, ve[i].s, ve[i].t ); + nv_emit_vertices( 0, 0, 1, 2, 0, 0, 0, 0, 0 ); + } + break; + + case DTTF_FAN: + nv_putvertex( 0, ve[0].x, ve[0].y, ve[0].z, ve[0].w, + nvdev->color3d, 0, ve[0].s, ve[0].t ); + nv_putvertex( 1, ve[1].x, ve[1].y, ve[1].z, ve[1].w, + nvdev->color3d, 0, ve[1].s, ve[1].t ); + nv_putvertex( 2, ve[2].x, ve[2].y, ve[2].z, ve[2].w, + nvdev->color3d, 0, ve[2].s, ve[2].t ); + nv_emit_vertices( 0, 0, 1, 2, 0, 0, 0, 0, 0 ); + + for (i = 3; i < num; i++) { + nv_putvertex( 0, ve[0].x, ve[0].y, ve[0].z, ve[0].w, + nvdev->color3d, 0, ve[0].s, ve[0].t ); + nv_putvertex( 1, ve[i-1].x, ve[i-1].y, ve[i-1].z, ve[i-1].w, + nvdev->color3d, 0, ve[i-1].s, ve[i-1].t ); + nv_putvertex( 2, ve[i].x, ve[i].y, ve[i].z, ve[i].w, + nvdev->color3d, 0, ve[i].s, ve[i].t ); + nv_emit_vertices( 0, 0, 1, 2, 0, 0, 0, 0, 0 ); + } + break; + + default: + D_BUG( "unexpected triangle formation" ); + return false; + } + + return true; +} + +/* + * Surface to Texture conversion routines. + */ + +#define VINC 0xAAAAAAAC +#define VMASK 0x55555555 +#define UINC 0x55555558 +#define UMASK 0xAAAAAAAA + +static inline void +a8_to_tex( u32 *dst, u8 *src, int pitch, int width, int height ) +{ + u32 u, v; + int i; + + for (v = 0; height--; v = (v + VINC) & VMASK) { + for (i = 0, u = 0; i < width; i += 2, u = (u + UINC) & UMASK) { +#ifdef WORDS_BIGENDIAN + dst[(u|v)/4] = ((src[i+0] & 0xF0) << 24) | + ((src[i+1] & 0xF0) << 8) | + 0x0FFF0FFF; +#else + dst[(u|v)/4] = ((src[i+0] & 0xF0) << 8) | + ((src[i+1] & 0xF0) << 24) | + 0x0FFF0FFF; +#endif + } + + if (width & 1) { + u = (u + UINC) & UMASK; + dst[(u|v)/4] = ((src[width-1] & 0xF0) << 8) | 0x0FFF; + } + + src += pitch; + } +} + +static inline void +rgb16_to_tex( u32 *dst, u8 *src, int pitch, int width, int height ) +{ + u32 u, v; + int i; + + for (v = 0; height--; v = (v + VINC) & VMASK) { + for (i = 0, u = 0; i < width/2; i++, u = (u + UINC) & UMASK) + dst[(u|v)/4] = ((u32*) src)[i]; + + if (width & 1) { + u = (u + UINC) & UMASK; + dst[(u|v)/4] = ((u16*) src)[width-1]; + } + + src += pitch; + } +} + +static inline void +rgb32_to_tex( u32 *dst, u8 *src, int pitch, int width, int height ) +{ + u32 u, v; + int i; + + for (v = 0; height--; v = (v + VINC) & VMASK) { + for (i = 0, u = 0; i < width; i += 2, u = (u + UINC) & UMASK) { + register u32 pix0, pix1; + pix0 = ((u32*) src)[i]; + pix0 = RGB32_TO_RGB16( pix0 ); + pix1 = ((u32*) src)[i+1]; + pix1 = RGB32_TO_RGB16( pix1 ); +#ifdef WORDS_BIGENDIAN + dst[(u|v)/4] = (pix0 << 16) | pix1; +#else + dst[(u|v)/4] = pix0 | (pix1 << 16); +#endif + } + + if (width & 1) { + u = (u + UINC) & UMASK; + dst[(u|v)/4] = RGB32_TO_RGB16( ((u32*) src)[width-1] ); + } + + src += pitch; + } +} + +static inline void +argb_to_tex( u32 *dst, u8 *src, int pitch, int width, int height ) +{ + u32 u, v; + int i; + + for (v = 0; height--; v = (v + VINC) & VMASK) { + for (i = 0, u = 0; i < width; i += 2, u = (u + UINC) & UMASK) { + register u32 pix0, pix1; + pix0 = ((u32*) src)[i]; + pix0 = ARGB_TO_ARGB4444( pix0 ); + pix1 = ((u32*) src)[i+1]; + pix1 = ARGB_TO_ARGB4444( pix1 ); +#ifdef WORDS_BIGENDIAN + dst[(u|v)/4] = (pix0 << 16) | pix1; +#else + dst[(u|v)/4] = pix0 | (pix1 << 16); +#endif + } + + if (width & 1) { + u = (u + UINC) & UMASK; + dst[(u|v)/4] = ARGB_TO_ARGB4444( ((u32*) src)[width-1] ); + } + + src += pitch; + } +} + +static void nv_load_texture( NVidiaDriverData *nvdrv, + NVidiaDeviceData *nvdev ) +{ + CoreSurfaceBuffer *buffer = nvdev->src_texture; + u32 *dst; + + dst = dfb_gfxcard_memory_virtual( nvdrv->device, nvdev->buf_offset[1] ); + +#if 0 + if (nvdev->src_interlaced) { + if (surface->caps & DSCAPS_SEPARATED) { + if (surface->field) + field_offset = nvdev->src_height * src_pitch; + } else { + if (surface->field) + field_offset = src_pitch; + src_pitch *= 2; + } + } +#endif + + switch (buffer->format) { + case DSPF_A8: + a8_to_tex( dst, nvdev->src_lock->addr, nvdev->src_lock->pitch, + nvdev->src_width, nvdev->src_height ); + break; + case DSPF_ARGB1555: + case DSPF_RGB16: + rgb16_to_tex( dst, nvdev->src_lock->addr, nvdev->src_lock->pitch, + nvdev->src_width, nvdev->src_height ); + break; + case DSPF_RGB32: + rgb32_to_tex( dst, nvdev->src_lock->addr, nvdev->src_lock->pitch, + nvdev->src_width, nvdev->src_height ); + break; + case DSPF_ARGB: + argb_to_tex( dst, nvdev->src_lock->addr, nvdev->src_lock->pitch, + nvdev->src_width, nvdev->src_height ); + break; + default: + D_BUG( "unexpected pixelformat" ); + break; + } +} + -- cgit