/* (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) (c) Copyright 2000-2004 Convergence (integrated media) GmbH All rights reserved. Written by Denis Oliver Kropp , Andreas Hundt , Sven Neumann , Ville Syrjälä and 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 #include #include #include #include #include #include DFB_GRAPHICS_DRIVER( nvidia ) #include "nvidia.h" #include "nvidia_regs.h" #include "nvidia_accel.h" #include "nvidia_objects.h" #include "nvidia_state.h" #include "nvidia_2d.h" #include "nvidia_3d.h" /* Riva TNT */ #define NV4_SUPPORTED_DRAWINGFLAGS \ (DSDRAW_BLEND) #define NV4_SUPPORTED_DRAWINGFUNCTIONS \ (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | \ DFXL_FILLTRIANGLE | DFXL_DRAWLINE) #define NV4_SUPPORTED_BLITTINGFLAGS \ (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL | \ DSBLIT_DEINTERLACE) #define NV4_SUPPORTED_BLITTINGFUNCTIONS \ (DFXL_BLIT | DFXL_STRETCHBLIT | DFXL_TEXTRIANGLES) /* Riva TNT2 */ #define NV5_SUPPORTED_DRAWINGFLAGS \ (DSDRAW_BLEND) #define NV5_SUPPORTED_DRAWINGFUNCTIONS \ (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | \ DFXL_FILLTRIANGLE | DFXL_DRAWLINE) #define NV5_SUPPORTED_BLITTINGFLAGS \ (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL | \ DSBLIT_COLORIZE | DSBLIT_DEINTERLACE) #define NV5_SUPPORTED_BLITTINGFUNCTIONS \ (DFXL_BLIT | DFXL_STRETCHBLIT | DFXL_TEXTRIANGLES) /* GeForce1/GeForce2/GeForce4 */ #define NV10_SUPPORTED_DRAWINGFLAGS \ (DSDRAW_BLEND) #define NV10_SUPPORTED_DRAWINGFUNCTIONS \ (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | \ DFXL_FILLTRIANGLE | DFXL_DRAWLINE) #define NV10_SUPPORTED_BLITTINGFLAGS \ (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL | \ DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR | \ DSBLIT_DEINTERLACE) #define NV10_SUPPORTED_BLITTINGFUNCTIONS \ (DFXL_BLIT | DFXL_STRETCHBLIT | DFXL_TEXTRIANGLES) /* GeForce3/GeForce4Ti */ #define NV20_SUPPORTED_DRAWINGFLAGS \ (DSDRAW_BLEND) #define NV20_SUPPORTED_DRAWINGFUNCTIONS \ (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | \ DFXL_FILLTRIANGLE | DFXL_DRAWLINE) #define NV20_SUPPORTED_BLITTINGFLAGS \ (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL | \ DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR | \ DSBLIT_DEINTERLACE) #define NV20_SUPPORTED_BLITTINGFUNCTIONS \ (DFXL_BLIT | DFXL_STRETCHBLIT) /* GeForceFX */ #define NV30_SUPPORTED_DRAWINGFLAGS \ (DSDRAW_BLEND) #define NV30_SUPPORTED_DRAWINGFUNCTIONS \ (DFXL_FILLRECTANGLE | DFXL_DRAWRECTANGLE | \ DFXL_FILLTRIANGLE | DFXL_DRAWLINE) #define NV30_SUPPORTED_BLITTINGFLAGS \ (DSBLIT_NOFX) #define NV30_SUPPORTED_BLITTINGFUNCTIONS \ (DFXL_BLIT) #define DSBLIT_MODULATE_ALPHA \ (DSBLIT_BLEND_COLORALPHA | DSBLIT_BLEND_ALPHACHANNEL) #define DSBLIT_MODULATE_COLOR \ (DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR) #define DSBLIT_MODULATE \ (DSBLIT_MODULATE_ALPHA | DSBLIT_MODULATE_COLOR) static void nvAfterSetVar( void *driver_data, void *device_data ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) device_data; volatile u8 *mmio = nvdrv->mmio_base; int i; nv_waitidle( nvdrv, nvdev ); /* reconfigure PFIFO for selected mode (DMA/PIO) */ nv_out32( mmio, PFIFO_CACHES, PFIFO_CACHES_REASSIGN_DISABLED ); if (nvdev->use_dma) { nv_out32( mmio, PFIFO_MODE, PFIFO_MODE_CHANNEL_0_DMA ); nv_out32( mmio, PFIFO_NEXT_CHANNEL, PFIFO_NEXT_CHANNEL_MODE_DMA ); } else { nv_out32( mmio, PFIFO_MODE, PFIFO_MODE_CHANNEL_0_PIO ); nv_out32( mmio, PFIFO_NEXT_CHANNEL, PFIFO_NEXT_CHANNEL_MODE_PIO ); } nv_out32( mmio, PFIFO_CACHE1_PUSH0, PFIFO_CACHE1_PULL1_ENGINE_SW ); nv_out32( mmio, PFIFO_CACHE1_PULL0, PFIFO_CACHE1_PULL0_ACCESS_DISABLED ); if (nvdev->use_dma) { nv_out32( mmio, PFIFO_CACHE1_PUSH1, PFIFO_CACHE1_PUSH1_MODE_DMA ); } else { nv_out32( mmio, PFIFO_CACHE1_PUSH1, PFIFO_CACHE1_PUSH1_MODE_PIO ); } nv_out32( mmio, PFIFO_CACHE1_DMA_PUT, 0 ); nv_out32( mmio, PFIFO_CACHE1_DMA_GET, 0 ); if (nvdev->use_dma) { nv_out32( mmio, PFIFO_CACHE1_DMA_INSTANCE, ADDR_DMA_OUT ); } else { nv_out32( mmio, PFIFO_CACHE1_DMA_INSTANCE, 0 ); } nv_out32( mmio, PFIFO_CACHE0_PUSH0, PFIFO_CACHE0_PUSH0_ACCESS_DISABLED ); nv_out32( mmio, PFIFO_CACHE0_PULL0, PFIFO_CACHE0_PULL0_ACCESS_DISABLED ); nv_out32( mmio, PFIFO_RAMHT, 0x00000100 | PFIFO_RAMHT_SIZE_4K | PFIFO_RAMHT_SEARCH_128 ); nv_out32( mmio, PFIFO_RAMFC, 0x00000110 ); nv_out32( mmio, PFIFO_RAMRO, 0x00000112 | PFIFO_RAMRO_SIZE_512 ); nv_out32( mmio, PFIFO_SIZE, 0x0000FFFF ); nv_out32( mmio, PFIFO_CACHE1_HASH, 0x0000FFFF ); nv_out32( mmio, PFIFO_INTR_EN, PFIFO_INTR_EN_DISABLED ); nv_out32( mmio, PFIFO_INTR, PFIFO_INTR_RESET ); nv_out32( mmio, PFIFO_CACHE0_PULL1, PFIFO_CACHE0_PULL1_ENGINE_GRAPHICS ); if (nvdev->use_dma) { if (nvdev->use_agp) { nv_out32( mmio, PFIFO_CACHE1_DMA_CTL, PFIFO_CACHE1_DMA_CTL_PAGE_TABLE_PRESENT | PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY_LINEAR | PFIFO_CACHE1_DMA_CTL_TARGET_NODE_AGP ); } else { nv_out32( mmio, PFIFO_CACHE1_DMA_CTL, PFIFO_CACHE1_DMA_CTL_PAGE_TABLE_PRESENT | PFIFO_CACHE1_DMA_CTL_PAGE_ENTRY_LINEAR | PFIFO_CACHE1_DMA_CTL_TARGET_NODE_NVM ); } nv_out32( mmio, PFIFO_CACHE1_DMA_LIMIT, nvdev->dma_size - 4 ); nv_out32( mmio, PFIFO_CACHE1_ENGINE, PFIFO_CACHE1_ENGINE_0_SW ); #ifdef WORDS_BIGENDIAN nv_out32( mmio, PFIFO_CACHE1_DMA_FETCH, PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 | PFIFO_CACHE1_BIG_ENDIAN ); #else nv_out32( mmio, PFIFO_CACHE1_DMA_FETCH, PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | PFIFO_CACHE1_DMA_FETCH_MAX_REQS_15 | PFIFO_CACHE1_LITTLE_ENDIAN ); #endif nv_out32( mmio, PFIFO_CACHE1_DMA_PUSH, PFIFO_CACHE1_DMA_PUSH_ACCESS_ENABLED ); } else { nv_out32( mmio, PFIFO_CACHE1_DMA_PUSH, PFIFO_CACHE1_DMA_PUSH_ACCESS_DISABLED ); } nv_out32( mmio, PFIFO_CACHE1_PUSH0, PFIFO_CACHE1_PUSH0_ACCESS_ENABLED ); nv_out32( mmio, PFIFO_CACHE1_PULL0, PFIFO_CACHE1_PULL0_ACCESS_ENABLED ); nv_out32( mmio, PFIFO_CACHE1_PULL1, PFIFO_CACHE1_PULL1_ENGINE_GRAPHICS ); nv_out32( mmio, PFIFO_CACHES, PFIFO_CACHES_REASSIGN_ENABLED ); nv_out32( mmio, PFIFO_INTR_EN, PFIFO_INTR_EN_CACHE_ERROR_ENABLED ); if (nvdev->arch == NV_ARCH_10) { nv_out32( mmio, PGRAPH_DEBUG_1, 0x00118701 ); nv_out32( mmio, PGRAPH_DEBUG_2, 0x24F82AD9 ); for (i = 0; i < 8; i++) { nv_out32( mmio, NV10_PGRAPH_WINDOWCLIP_HORIZONTAL+i*4, 0x07FF0800 ); nv_out32( mmio, NV10_PGRAPH_WINDOWCLIP_VERTICAL +i*4, 0x07FF0800 ); } nv_out32( mmio, NV10_PGRAPH_XFMODE0, 0x10000000 ); nv_out32( mmio, NV10_PGRAPH_XFMODE1, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006740 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006750 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x40000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x40000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x40000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x40000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006760 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006770 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC5000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC5000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006780 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x000067A0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006AB0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006AC0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006C10 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xBF800000 ); for (i = 0; i < 8; i++) { nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x7030+i*16 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x7149F2CA ); } nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006A80 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006AA0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000005 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006400 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x4B7FFFFF ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006410 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC5000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC5000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006420 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x00006430 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x000064C0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x477FFFFF ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x3F800000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x000064D0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC5000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC5000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x000064E0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC4FFF000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0xC4FFF000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_ADDRESS, 0x000064F0 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_PIPE_DATA, 0x00000000 ); nv_out32( mmio, NV10_PGRAPH_XFMODE0, 0x30000000 ); nv_out32( mmio, NV10_PGRAPH_XFMODE1, 0x00000004 ); nv_out32( mmio, NV10_PGRAPH_GLOBALSTATE0, 0x10000000 ); nv_out32( mmio, NV10_PGRAPH_GLOBALSTATE1, 0x00000000 ); } nvdev->dma_max = nvdev->dma_size/4 - 1; nvdev->dma_cur = 0; nvdev->dma_free = nvdev->dma_max; nvdev->dma_put = 0; nvdev->dma_get = 0; nvdev->fifo_free = 0; } static void nvEngineReset( void *drv, void *dev ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; int i; /* reput objects into subchannels */ for (i = 0; i < 8; i++) { nv_assign_object( nvdrv, nvdev, i, nvdev->subchannel_object[i], true ); } nvdev->set = 0; nvdev->dst_format = DSPF_UNKNOWN; nvdev->dst_pitch = 0; nvdev->src_pitch = 0; nvdev->beta1_set = false; nvdev->beta4_set = false; } static DFBResult nvEngineSync( void *drv, void *dev ) { nv_waitidle( (NVidiaDriverData*)drv, (NVidiaDeviceData*)dev ); return DFB_OK; } static void nvFlushTextureCache( void *drv, void *dev ) { NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; /* invalidate source texture */ nvdev->set &= ~SMF_SOURCE_TEXTURE; } static void nvEmitCommands( void *drv, void *dev ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; if (nvdev->use_dma) nv_emitdma( nvdrv, nvdev ); } static void nv4CheckState( void *drv, void *dev, CardState *state, DFBAccelerationMask accel ) { NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; CoreSurface *destination = state->destination; CoreSurface *source = state->source; switch (destination->config.format) { case DSPF_A8: case DSPF_LUT8: case DSPF_ALUT44: case DSPF_RGB332: if (DFB_BLITTING_FUNCTION( accel )) { if (accel != DFXL_BLIT || state->blittingflags || source->config.format != destination->config.format) return; } else { if (state->drawingflags != DSDRAW_NOFX) return; } break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: break; case DSPF_YUY2: case DSPF_UYVY: if (DFB_BLITTING_FUNCTION( accel )) { if (accel & ~(DFXL_BLIT | DFXL_STRETCHBLIT) || state->blittingflags != DSBLIT_NOFX || source->config.format != destination->config.format) return; } else { if (accel & (DFXL_FILLTRIANGLE | DFXL_DRAWLINE) || state->drawingflags != DSDRAW_NOFX) return; } break; default: return; } if (DFB_BLITTING_FUNCTION( accel )) { /* check unsupported blitting flags */ if (accel & ~NV4_SUPPORTED_BLITTINGFUNCTIONS || state->blittingflags & ~NV4_SUPPORTED_BLITTINGFLAGS) return; if (accel == DFXL_TEXTRIANGLES) { u32 size = 1 << (direct_log2(source->config.size.w) + direct_log2(source->config.size.h)); if (size > nvdev->max_texture_size) return; } else { if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL) { if (state->src_blend != DSBF_SRCALPHA || state->dst_blend != DSBF_INVSRCALPHA) return; } if (state->render_options & DSRO_MATRIX && (state->matrix[0] < 0 || state->matrix[1] || state->matrix[3] || state->matrix[4] < 0)) return; } switch (source->config.format) { case DSPF_LUT8: case DSPF_ALUT44: if (destination->config.format != source->config.format || !dfb_palette_equal( source->palette, destination->palette )) return; break; case DSPF_A8: case DSPF_RGB332: if (destination->config.format != source->config.format) return; break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB32: case DSPF_ARGB: break; case DSPF_RGB16: switch (accel) { case DFXL_BLIT: if (state->blittingflags != DSBLIT_NOFX || destination->config.format != DSPF_RGB16) return; break; case DFXL_STRETCHBLIT: return; default: break; } break; case DSPF_YUY2: case DSPF_UYVY: if (accel == DFXL_TEXTRIANGLES) return; break; default: return; } state->accel |= accel; } else { /* check unsupported drawing flags */ if (accel & ~NV4_SUPPORTED_DRAWINGFUNCTIONS || state->drawingflags & ~NV4_SUPPORTED_DRAWINGFLAGS) return; state->accel |= NV4_SUPPORTED_DRAWINGFUNCTIONS; } } static void nv5CheckState( void *drv, void *dev, CardState *state, DFBAccelerationMask accel ) { NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; CoreSurface *destination = state->destination; CoreSurface *source = state->source; switch (destination->config.format) { case DSPF_A8: case DSPF_LUT8: case DSPF_ALUT44: case DSPF_RGB332: if (DFB_BLITTING_FUNCTION( accel )) { if (accel != DFXL_BLIT || state->blittingflags || source->config.format != destination->config.format) return; } else { if (state->drawingflags != DSDRAW_NOFX) return; } break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: break; case DSPF_YUY2: case DSPF_UYVY: if (DFB_BLITTING_FUNCTION( accel )) { if (accel & ~(DFXL_BLIT | DFXL_STRETCHBLIT) || state->blittingflags != DSBLIT_NOFX || source->config.format != destination->config.format) return; } else { if (accel & (DFXL_FILLTRIANGLE | DFXL_DRAWLINE) || state->drawingflags != DSDRAW_NOFX) return; } break; default: return; } if (DFB_BLITTING_FUNCTION( accel )) { /* check unsupported blitting flags */ if (accel & ~NV5_SUPPORTED_BLITTINGFUNCTIONS || state->blittingflags & ~NV5_SUPPORTED_BLITTINGFLAGS) return; if (accel == DFXL_TEXTRIANGLES) { u32 size = 1 << (direct_log2(source->config.size.w) + direct_log2(source->config.size.h)); if (size > nvdev->max_texture_size) return; } else { if (state->blittingflags & DSBLIT_MODULATE) { if (state->blittingflags & DSBLIT_MODULATE_ALPHA && state->blittingflags & DSBLIT_MODULATE_COLOR) return; if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL) { if (state->src_blend != DSBF_SRCALPHA || state->dst_blend != DSBF_INVSRCALPHA) return; } } if (state->render_options & DSRO_MATRIX && (state->matrix[0] < 0 || state->matrix[1] || state->matrix[3] || state->matrix[4] < 0)) return; } switch (source->config.format) { case DSPF_LUT8: case DSPF_ALUT44: if (destination->config.format != source->config.format || /*state->src.buffer->policy == CSP_SYSTEMONLY ||*/ !dfb_palette_equal( source->palette, destination->palette )) return; break; case DSPF_A8: case DSPF_RGB332: if (destination->config.format != source->config.format /*|| state->src.buffer->policy == CSP_SYSTEMONLY*/) return; break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: /* disable host-to-video blit for simple blits */ /*if (state->src.buffer->policy == CSP_SYSTEMONLY && accel == DFXL_BLIT && !state->blittingflags && source->config.format == destination->config.format) return;*/ break; case DSPF_YUY2: case DSPF_UYVY: if (accel & ~(DFXL_BLIT | DFXL_STRETCHBLIT) /*|| state->src.buffer->policy == CSP_SYSTEMONLY*/) return; break; default: return; } state->accel |= accel; } else { /* check unsupported drawing flags */ if (accel & ~NV5_SUPPORTED_DRAWINGFUNCTIONS || state->drawingflags & ~NV5_SUPPORTED_DRAWINGFLAGS) return; state->accel |= NV5_SUPPORTED_DRAWINGFUNCTIONS; } } static void nv10CheckState( void *drv, void *dev, CardState *state, DFBAccelerationMask accel ) { NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; CoreSurface *destination = state->destination; CoreSurface *source = state->source; switch (destination->config.format) { case DSPF_A8: case DSPF_LUT8: case DSPF_ALUT44: case DSPF_RGB332: if (DFB_BLITTING_FUNCTION( accel )) { if (accel != DFXL_BLIT || state->blittingflags || source->config.format != destination->config.format) return; } else { if (state->drawingflags != DSDRAW_NOFX) return; } break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: break; case DSPF_YUY2: case DSPF_UYVY: if (DFB_BLITTING_FUNCTION( accel )) { if (accel & ~(DFXL_BLIT | DFXL_STRETCHBLIT) || state->blittingflags != DSBLIT_NOFX || source->config.format != destination->config.format) return; } else { if (accel & (DFXL_FILLTRIANGLE | DFXL_DRAWLINE) || state->drawingflags != DSDRAW_NOFX) return; } break; default: return; } if (DFB_BLITTING_FUNCTION( accel )) { /* check unsupported blitting flags */ if (accel & ~NV10_SUPPORTED_BLITTINGFUNCTIONS || state->blittingflags & ~NV10_SUPPORTED_BLITTINGFLAGS) return; if (accel == DFXL_TEXTRIANGLES) { u32 size = 1 << (direct_log2(source->config.size.w) + direct_log2(source->config.size.h)); if (size > nvdev->max_texture_size) return; } else { if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL) { if (state->blittingflags & DSBLIT_MODULATE_COLOR) { if (source->config.format == DSPF_ARGB && state->src_blend != DSBF_ONE) return; } if (state->src_blend != DSBF_ONE && state->src_blend != DSBF_SRCALPHA) return; if (state->dst_blend != DSBF_INVSRCALPHA) return; } if (state->render_options & DSRO_MATRIX && (state->matrix[0] < 0 || state->matrix[1] || state->matrix[3] || state->matrix[4] < 0)) return; } switch (source->config.format) { case DSPF_A8: if (DFB_BYTES_PER_PIXEL(destination->config.format) != 4 /*|| state->src.buffer->policy == CSP_SYSTEMONLY*/) return; break; case DSPF_LUT8: case DSPF_ALUT44: if (destination->config.format != source->config.format || /*state->src.buffer->policy == CSP_SYSTEMONLY ||*/ !dfb_palette_equal( source->palette, destination->palette )) return; break; case DSPF_RGB332: if (destination->config.format != source->config.format /*|| state->src.buffer->policy == CSP_SYSTEMONLY*/) return; break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: /* disable host-to-video blit for simple blits */ /*if (state->src.buffer->policy == CSP_SYSTEMONLY && accel == DFXL_BLIT && !state->blittingflags && source->config.format == destination->config.format) return;*/ break; case DSPF_YUY2: case DSPF_UYVY: if (accel & ~(DFXL_BLIT | DFXL_STRETCHBLIT) /*|| state->src.buffer->policy == CSP_SYSTEMONLY*/) return; break; default: return; } state->accel |= accel; } else { /* check unsupported drawing flags */ if (accel & ~NV10_SUPPORTED_DRAWINGFUNCTIONS || state->drawingflags & ~NV10_SUPPORTED_DRAWINGFLAGS) return; state->accel |= NV10_SUPPORTED_DRAWINGFUNCTIONS; } } static void nv20CheckState( void *drv, void *dev, CardState *state, DFBAccelerationMask accel ) { CoreSurface *destination = state->destination; CoreSurface *source = state->source; switch (destination->config.format) { case DSPF_A8: case DSPF_LUT8: case DSPF_ALUT44: case DSPF_RGB332: if (DFB_BLITTING_FUNCTION( accel )) { if (state->blittingflags != DSBLIT_NOFX || source->config.format != destination->config.format) return; } else { if (state->drawingflags != DSDRAW_NOFX) return; } break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: break; case DSPF_YUY2: case DSPF_UYVY: if (DFB_BLITTING_FUNCTION( accel )) { if (accel & ~(DFXL_BLIT | DFXL_STRETCHBLIT) || state->blittingflags != DSBLIT_NOFX || source->config.format != destination->config.format) return; } else { if (accel & (DFXL_FILLTRIANGLE | DFXL_DRAWLINE) || state->drawingflags != DSDRAW_NOFX) return; } break; default: return; } if (DFB_BLITTING_FUNCTION( accel )) { /* check unsupported blitting functions/flags */ if (accel & ~NV20_SUPPORTED_BLITTINGFUNCTIONS || state->blittingflags & ~NV20_SUPPORTED_BLITTINGFLAGS) return; if (state->blittingflags & DSBLIT_BLEND_ALPHACHANNEL) { if (state->blittingflags & DSBLIT_MODULATE_COLOR) { if (source->config.format == DSPF_ARGB && state->src_blend != DSBF_ONE) return; } if (state->src_blend != DSBF_ONE && state->src_blend != DSBF_SRCALPHA) return; if (state->dst_blend != DSBF_INVSRCALPHA) return; } if (state->render_options & DSRO_MATRIX && (state->matrix[0] < 0 || state->matrix[1] || state->matrix[3] || state->matrix[4] < 0)) return; switch (source->config.format) { case DSPF_A8: /*if (state->src.buffer->policy == CSP_SYSTEMONLY) return;*/ break; case DSPF_LUT8: case DSPF_ALUT44: if (destination->config.format != source->config.format || /*state->src.buffer->policy == CSP_SYSTEMONLY ||*/ !dfb_palette_equal( source->palette, destination->palette )) return; break; case DSPF_RGB332: if (destination->config.format != source->config.format /*|| state->src.buffer->policy == CSP_SYSTEMONLY*/) return; break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: /* disable host-to-video blit for simple blits */ /*if (state->src.buffer->policy == CSP_SYSTEMONLY && accel == DFXL_BLIT && !state->blittingflags && source->config.format == destination->config.format) return;*/ break; case DSPF_YUY2: case DSPF_UYVY: /*if (state->src.buffer->policy == CSP_SYSTEMONLY) return;*/ break; default: return; } state->accel |= accel; } else { /* check unsupported drawing flags */ if (accel & ~NV20_SUPPORTED_DRAWINGFUNCTIONS || state->drawingflags & ~NV20_SUPPORTED_DRAWINGFLAGS) return; if (state->drawingflags & DSDRAW_BLEND && state->src_blend != DSBF_SRCALPHA && state->dst_blend != DSBF_INVSRCALPHA) return; state->accel |= NV20_SUPPORTED_DRAWINGFUNCTIONS; } } static void nv30CheckState( void *drv, void *dev, CardState *state, DFBAccelerationMask accel ) { CoreSurface *destination = state->destination; CoreSurface *source = state->source; switch (destination->config.format) { case DSPF_A8: case DSPF_LUT8: case DSPF_ALUT44: case DSPF_RGB332: if (DFB_DRAWING_FUNCTION( accel ) && state->drawingflags != DSDRAW_NOFX) return; break; case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: break; case DSPF_YUY2: case DSPF_UYVY: if (accel & (DFXL_FILLTRIANGLE | DFXL_DRAWLINE) || state->drawingflags != DSDRAW_NOFX) return; break; default: return; } if (DFB_BLITTING_FUNCTION( accel )) { /* check unsupported blitting functions/flags */ if (accel & ~NV30_SUPPORTED_BLITTINGFUNCTIONS || state->blittingflags & ~NV30_SUPPORTED_BLITTINGFLAGS) return; if (state->render_options & DSRO_MATRIX && (state->matrix[0] != 0x10000 || state->matrix[1] || state->matrix[3] || state->matrix[4] != 0x10000)) return; switch (source->config.format) { case DSPF_LUT8: case DSPF_ALUT44: if (!dfb_palette_equal( source->palette, destination->palette )) return; case DSPF_A8: case DSPF_RGB332: case DSPF_RGB555: case DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB32: case DSPF_ARGB: case DSPF_YUY2: case DSPF_UYVY: if (/*state->src.buffer->policy == CSP_SYSTEMONLY ||*/ source->config.format != destination->config.format) return; break; default: return; } state->accel |= accel; } else { /* check unsupported drawing flags */ if (accel & ~NV30_SUPPORTED_DRAWINGFUNCTIONS || state->drawingflags & ~NV30_SUPPORTED_DRAWINGFLAGS) return; if (state->drawingflags & DSDRAW_BLEND && state->src_blend != DSBF_SRCALPHA && state->dst_blend != DSBF_INVSRCALPHA) return; state->accel |= NV30_SUPPORTED_DRAWINGFUNCTIONS; } } #define M_IDENTITY(m) ((m)[0] == 0x10000 && (m)[1] == 0 && (m)[2] == 0 && \ (m)[3] == 0 && (m)[4] == 0x10000 && (m)[5] == 0) static void nv4SetState( void *drv, void *dev, GraphicsDeviceFuncs *funcs, CardState *state, DFBAccelerationMask accel ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; nvdev->set &= ~state->mod_hw; if (state->mod_hw & SMF_COLOR) nvdev->set &= ~(SMF_DRAWING_COLOR | SMF_BLITTING_COLOR); nv_set_destination( nvdrv, nvdev, state ); nv_set_clip( nvdrv, nvdev, state ); if (state->render_options & DSRO_MATRIX && !M_IDENTITY(state->matrix)) nvdev->matrix = state->matrix; else nvdev->matrix = NULL; switch (accel) { case DFXL_FILLRECTANGLE: case DFXL_FILLTRIANGLE: case DFXL_DRAWRECTANGLE: case DFXL_DRAWLINE: nv_set_drawing_color( nvdrv, nvdev, state ); if (state->drawingflags & DSDRAW_BLEND) nv_set_blend_function( nvdrv, nvdev, state ); nv_set_drawingflags( nvdrv, nvdev, state ); if ((state->drawingflags & DSDRAW_BLEND || nvdev->matrix) && nvdev->enabled_3d) { nvdev->state3d[0].modified = true; funcs->FillRectangle = nvFillRectangle3D; funcs->FillTriangle = nvFillTriangle3D; funcs->DrawRectangle = nvDrawRectangle3D; funcs->DrawLine = nvDrawLine3D; } else { funcs->FillRectangle = nvFillRectangle2D; funcs->FillTriangle = nvFillTriangle2D; funcs->DrawRectangle = nvDrawRectangle2D; funcs->DrawLine = nvDrawLine2D; } state->set = DFXL_FILLRECTANGLE | DFXL_FILLTRIANGLE | DFXL_DRAWRECTANGLE | DFXL_DRAWLINE; break; case DFXL_BLIT: case DFXL_STRETCHBLIT: case DFXL_TEXTRIANGLES: nv_set_source( nvdrv, nvdev, state ); if (state->blittingflags & DSBLIT_MODULATE_ALPHA) { nv_set_blend_function( nvdrv, nvdev, state ); nv_set_blitting_color( nvdrv, nvdev, state ); } nv_set_blittingflags( nvdrv, nvdev, state ); if (accel == DFXL_TEXTRIANGLES) { if (nvdev->src_texture != state->src.buffer) nvdev->set &= ~SMF_SOURCE_TEXTURE; nvdev->src_texture = state->src.buffer; nvdev->state3d[1].modified = true; state->set = DFXL_TEXTRIANGLES; } else { state->set = DFXL_BLIT | DFXL_STRETCHBLIT; } break; default: D_BUG( "unexpected drawing/blitting function" ); break; } state->mod_hw = 0; } static void nv5SetState( void *drv, void *dev, GraphicsDeviceFuncs *funcs, CardState *state, DFBAccelerationMask accel ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; nvdev->set &= ~state->mod_hw; if (state->mod_hw & SMF_COLOR) nvdev->set &= ~(SMF_DRAWING_COLOR | SMF_BLITTING_COLOR); nv_set_destination( nvdrv, nvdev, state ); nv_set_clip( nvdrv, nvdev, state ); if (state->render_options & DSRO_MATRIX && !M_IDENTITY(state->matrix)) nvdev->matrix = state->matrix; else nvdev->matrix = NULL; switch (accel) { case DFXL_FILLRECTANGLE: case DFXL_FILLTRIANGLE: case DFXL_DRAWRECTANGLE: case DFXL_DRAWLINE: nv_set_drawing_color( nvdrv, nvdev, state ); if (state->drawingflags & DSDRAW_BLEND) nv_set_blend_function( nvdrv, nvdev, state ); nv_set_drawingflags( nvdrv, nvdev, state ); if ((state->drawingflags & DSDRAW_BLEND || nvdev->matrix) && nvdev->enabled_3d) { nvdev->state3d[0].modified = true; funcs->FillRectangle = nvFillRectangle3D; funcs->FillTriangle = nvFillTriangle3D; funcs->DrawRectangle = nvDrawRectangle3D; funcs->DrawLine = nvDrawLine3D; } else { funcs->FillRectangle = nvFillRectangle2D; funcs->FillTriangle = nvFillTriangle2D; funcs->DrawRectangle = nvDrawRectangle2D; funcs->DrawLine = nvDrawLine2D; } state->set = DFXL_FILLRECTANGLE | DFXL_FILLTRIANGLE | DFXL_DRAWRECTANGLE | DFXL_DRAWLINE; break; case DFXL_BLIT: case DFXL_STRETCHBLIT: case DFXL_TEXTRIANGLES: nv_set_source( nvdrv, nvdev, state ); if (state->blittingflags & DSBLIT_MODULATE) { nv_set_blend_function( nvdrv, nvdev, state ); nv_set_blitting_color( nvdrv, nvdev, state ); } nv_set_blittingflags( nvdrv, nvdev, state ); if (accel == DFXL_TEXTRIANGLES) { if (nvdev->src_texture != state->src.buffer) nvdev->set &= ~SMF_SOURCE_TEXTURE; nvdev->src_texture = state->src.buffer; nvdev->state3d[1].modified = true; state->set = DFXL_TEXTRIANGLES; } else { if (nvdev->src_system) { funcs->Blit = nvBlitFromCPU; funcs->StretchBlit = nvStretchBlitFromCPU; } else { funcs->Blit = nvBlit; funcs->StretchBlit = nvStretchBlit; } state->set = DFXL_BLIT | DFXL_STRETCHBLIT; } break; default: D_BUG( "unexpected drawing/blitting function" ); break; } state->mod_hw = 0; } static void nv10SetState( void *drv, void *dev, GraphicsDeviceFuncs *funcs, CardState *state, DFBAccelerationMask accel ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; nvdev->set &= ~state->mod_hw; if (state->mod_hw & SMF_COLOR) nvdev->set &= ~(SMF_DRAWING_COLOR | SMF_BLITTING_COLOR); nv_set_destination( nvdrv, nvdev, state ); nv_set_clip( nvdrv, nvdev, state ); if (state->render_options & DSRO_MATRIX && !M_IDENTITY(state->matrix)) nvdev->matrix = state->matrix; else nvdev->matrix = NULL; switch (accel) { case DFXL_FILLRECTANGLE: case DFXL_FILLTRIANGLE: case DFXL_DRAWRECTANGLE: case DFXL_DRAWLINE: nv_set_drawing_color( nvdrv, nvdev, state ); if (state->drawingflags & DSDRAW_BLEND) nv_set_blend_function( nvdrv, nvdev, state ); nv_set_drawingflags( nvdrv, nvdev, state ); if ((state->drawingflags & DSDRAW_BLEND || nvdev->matrix) && nvdev->enabled_3d) { nvdev->state3d[0].modified = true; funcs->FillRectangle = nvFillRectangle3D; funcs->FillTriangle = nvFillTriangle3D; funcs->DrawRectangle = nvDrawRectangle3D; funcs->DrawLine = nvDrawLine3D; } else { funcs->FillRectangle = nvFillRectangle2D; funcs->FillTriangle = nvFillTriangle2D; funcs->DrawRectangle = nvDrawRectangle2D; funcs->DrawLine = nvDrawLine2D; } state->set = DFXL_FILLRECTANGLE | DFXL_FILLTRIANGLE | DFXL_DRAWRECTANGLE | DFXL_DRAWLINE; break; case DFXL_BLIT: case DFXL_STRETCHBLIT: case DFXL_TEXTRIANGLES: nv_set_source( nvdrv, nvdev, state ); if (state->blittingflags & DSBLIT_MODULATE) { nv_set_blend_function( nvdrv, nvdev, state ); nv_set_blitting_color( nvdrv, nvdev, state ); } nv_set_blittingflags( nvdrv, nvdev, state ); if (accel == DFXL_TEXTRIANGLES) { if (nvdev->src_texture != state->src.buffer) nvdev->set &= ~SMF_SOURCE_TEXTURE; nvdev->src_texture = state->src.buffer; nvdev->state3d[1].modified = true; state->set = DFXL_TEXTRIANGLES; } else { if (nvdev->src_system) { funcs->Blit = nvBlitFromCPU; funcs->StretchBlit = nvStretchBlitFromCPU; } else { funcs->Blit = nvBlit; funcs->StretchBlit = nvStretchBlit; } state->set = DFXL_BLIT | DFXL_STRETCHBLIT; } break; default: D_BUG( "unexpected drawing/blitting function" ); break; } state->mod_hw = 0; } static void nv20SetState( void *drv, void *dev, GraphicsDeviceFuncs *funcs, CardState *state, DFBAccelerationMask accel ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; nvdev->set &= ~state->mod_hw; if (state->mod_hw & SMF_COLOR) nvdev->set &= ~(SMF_DRAWING_COLOR | SMF_BLITTING_COLOR); nv_set_destination( nvdrv, nvdev, state ); nv_set_clip( nvdrv, nvdev, state ); if (state->render_options & DSRO_MATRIX && !M_IDENTITY(state->matrix)) nvdev->matrix = state->matrix; else nvdev->matrix = NULL; switch (accel) { case DFXL_FILLRECTANGLE: case DFXL_FILLTRIANGLE: case DFXL_DRAWRECTANGLE: case DFXL_DRAWLINE: nv_set_drawing_color( nvdrv, nvdev, state ); nv_set_drawingflags( nvdrv, nvdev, state ); state->set = DFXL_FILLRECTANGLE | DFXL_FILLTRIANGLE | DFXL_DRAWRECTANGLE | DFXL_DRAWLINE; break; case DFXL_BLIT: case DFXL_STRETCHBLIT: nv_set_source( nvdrv, nvdev, state ); if (state->blittingflags & DSBLIT_MODULATE) { if (state->modified & SMF_SRC_BLEND) nvdev->set &= ~SMF_BLITTING_FLAGS; nv_set_blitting_color( nvdrv, nvdev, state ); } nv_set_blittingflags( nvdrv, nvdev, state ); if (nvdev->src_system) { funcs->Blit = nvBlitFromCPU; funcs->StretchBlit = nvStretchBlitFromCPU; } else { if (DFB_BITS_PER_PIXEL(nvdev->dst_format) == 8) nvdev->scaler_filter = SCALER_IN_FORMAT_ORIGIN_CORNER | SCALER_IN_FORMAT_FILTER_NEAREST; else nvdev->scaler_filter = SCALER_IN_FORMAT_ORIGIN_CENTER | SCALER_IN_FORMAT_FILTER_LINEAR; funcs->Blit = nvBlit; funcs->StretchBlit = nvStretchBlit; } state->set = DFXL_BLIT | DFXL_STRETCHBLIT; break; default: D_BUG( "unexpected drawing/blitting function" ); break; } state->mod_hw = 0; } static void nv30SetState( void *drv, void *dev, GraphicsDeviceFuncs *funcs, CardState *state, DFBAccelerationMask accel ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) drv; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) dev; nvdev->set &= ~state->mod_hw; if (state->mod_hw & SMF_COLOR) nvdev->set &= ~(SMF_DRAWING_COLOR | SMF_BLITTING_COLOR); nv_set_destination( nvdrv, nvdev, state ); nv_set_clip( nvdrv, nvdev, state ); if (state->render_options & DSRO_MATRIX && !M_IDENTITY(state->matrix)) nvdev->matrix = state->matrix; else nvdev->matrix = NULL; switch (accel) { case DFXL_FILLRECTANGLE: case DFXL_FILLTRIANGLE: case DFXL_DRAWRECTANGLE: case DFXL_DRAWLINE: nv_set_drawing_color( nvdrv, nvdev, state ); nv_set_drawingflags( nvdrv, nvdev, state ); state->set = DFXL_FILLRECTANGLE | DFXL_FILLTRIANGLE | DFXL_DRAWRECTANGLE | DFXL_DRAWLINE; break; case DFXL_BLIT: nv_set_source( nvdrv, nvdev, state ); state->set = DFXL_BLIT; break; default: D_BUG( "unexpected drawing/blitting function" ); break; } state->mod_hw = 0; } /* exported symbols */ static int driver_probe( CoreGraphicsDevice *device ) { switch (dfb_gfxcard_get_accelerator( device )) { case FB_ACCEL_NV4: case FB_ACCEL_NV5: case FB_ACCEL_NV_10: case FB_ACCEL_NV_20: case FB_ACCEL_NV_30: case FB_ACCEL_NV_40: return 1; } return 0; } static void driver_get_info( CoreGraphicsDevice *device, GraphicsDriverInfo *info ) { /* fill driver info structure */ snprintf( info->name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, "nVidia NV4/NV5/NV10/NV20/NV30 Driver" ); snprintf( info->vendor, DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH, "directfb.org" ); snprintf( info->url, DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH, "http://www.directfb.org" ); snprintf( info->license, DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH, "LGPL" ); info->version.major = 0; info->version.minor = 6; info->driver_data_size = sizeof(NVidiaDriverData); info->device_data_size = sizeof(NVidiaDeviceData); } static void nv_find_architecture( NVidiaDriverData *nvdrv, u32 *ret_chip, u32 *ret_arch ) { unsigned int vendor_id; unsigned int device_id; unsigned int arch = 0; device_id = nv_in32( nvdrv->mmio_base, 0x00 ) >> 16; /* id:rev */ if (!device_id) { dfb_system_get_deviceid( &vendor_id, &device_id ); if (vendor_id != 0x10DE) { D_ERROR( "DirectFB/NVidia: Could not detect device id!\n" " -> Please, specify the bus location of" " the card by using the 'busid' option.\n" ); vendor_id = device_id = 0; } } switch (device_id & 0xFFF0) { case 0x0020: /* Riva TNT/TNT2 */ arch = (device_id == 0x0020) ? NV_ARCH_04 : NV_ARCH_05; break; case 0x0100: /* GeForce */ case 0x0110: /* GeForce2 MX */ case 0x0150: /* GeForce2 GTS/Ti/Ultra */ case 0x0170: /* GeForce4 MX/Go */ case 0x0180: /* GeForce4 MX/Go AGP8X */ //case 0x01A0: /* GeForce2 Integrated GPU */ //case 0x01F0: /* GeForce4 MX Integrated GPU */ arch = NV_ARCH_10; break; case 0x0200: /* GeForce3 */ case 0x0250: /* GeForce4 Ti */ case 0x0280: /* GeForce4 Ti AGP8X */ case 0x02A0: /* GeForce3 Integrated GPU (XBox) */ arch = NV_ARCH_20; break; case 0x0300: /* GeForce FX 5800 */ case 0x0310: /* GeForce FX 5600 */ case 0x0320: /* GeForce FX 5200 */ case 0x0330: /* GeForce FX 5900 */ case 0x0340: /* GeForce FX 5700 */ arch = NV_ARCH_30; break; default: break; } if (ret_chip) *ret_chip = device_id; if (ret_arch) *ret_arch = arch; } static DFBResult driver_init_driver( CoreGraphicsDevice *device, GraphicsDeviceFuncs *funcs, void *driver_data, void *device_data, CoreDFB *core ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) device_data; u32 arch = 0; nvdrv->device = device; nvdrv->device_data = device_data; nvdrv->fb_base = (volatile void*) dfb_gfxcard_memory_virtual( device, 0 ); nvdrv->agp_base = (volatile void*) dfb_gfxcard_auxmemory_virtual( device, 0 ); nvdrv->mmio_base = (volatile void*) dfb_gfxcard_map_mmio( device, 0, -1 ); if (!nvdrv->mmio_base) return DFB_IO; if (nvdev->use_dma) { nvdrv->dma_base = nvdev->use_agp ? nvdrv->agp_base : nvdrv->fb_base; nvdrv->dma_base += nvdev->dma_offset; } funcs->AfterSetVar = nvAfterSetVar; funcs->EngineReset = nvEngineReset; funcs->EngineSync = nvEngineSync; funcs->EmitCommands = nvEmitCommands; funcs->FillRectangle = nvFillRectangle2D; // dynamic funcs->FillTriangle = nvFillTriangle2D; // dynamic funcs->DrawRectangle = nvDrawRectangle2D; // dynamic funcs->DrawLine = nvDrawLine2D; // dynamic funcs->Blit = nvBlit; // dynamic nv_find_architecture( nvdrv, NULL, &arch ); switch (arch) { case NV_ARCH_04: funcs->FlushTextureCache = nvFlushTextureCache; funcs->CheckState = nv4CheckState; funcs->SetState = nv4SetState; funcs->StretchBlit = nvStretchBlit; funcs->TextureTriangles = nvTextureTriangles; break; case NV_ARCH_05: funcs->FlushTextureCache = nvFlushTextureCache; funcs->CheckState = nv5CheckState; funcs->SetState = nv5SetState; funcs->StretchBlit = nvStretchBlit; funcs->TextureTriangles = nvTextureTriangles; break; case NV_ARCH_10: funcs->FlushTextureCache = nvFlushTextureCache; funcs->CheckState = nv10CheckState; funcs->SetState = nv10SetState; funcs->StretchBlit = nvStretchBlit; funcs->TextureTriangles = nvTextureTriangles; break; case NV_ARCH_20: funcs->CheckState = nv20CheckState; funcs->SetState = nv20SetState; funcs->StretchBlit = nvStretchBlit; break; case NV_ARCH_30: funcs->CheckState = nv30CheckState; funcs->SetState = nv30SetState; break; default: funcs->AfterSetVar = NULL; funcs->EngineReset = NULL; break; } dfb_screens_hook_primary( device, driver_data, &nvidiaPrimaryScreenFuncs, &OldPrimaryScreenFuncs, &OldPrimaryScreenDriverData ); dfb_layers_hook_primary( device, driver_data, &nvidiaPrimaryLayerFuncs, &OldPrimaryLayerFuncs, &OldPrimaryLayerDriverData ); dfb_layers_register( dfb_screens_at( DSCID_PRIMARY ), driver_data, &nvidiaOverlayFuncs ); return DFB_OK; } static DFBResult driver_init_device( CoreGraphicsDevice *device, GraphicsDeviceInfo *device_info, void *driver_data, void *device_data ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; NVidiaDeviceData *nvdev = (NVidiaDeviceData*) device_data; int ram_total = dfb_system_videoram_length(); int ram_used = dfb_gfxcard_memory_length(); nv_find_architecture( nvdrv, &nvdev->chip, &nvdev->arch ); snprintf( device_info->name, DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "NV%02X (%04x)", (nvdev->chip >> 4) & 0xFF, nvdev->chip ); snprintf( device_info->vendor, DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "nVidia" ); switch (nvdev->arch) { case NV_ARCH_04: device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS; device_info->caps.accel = NV4_SUPPORTED_DRAWINGFUNCTIONS | NV4_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = NV4_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = NV4_SUPPORTED_BLITTINGFLAGS; break; case NV_ARCH_05: device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS /*| CCF_READSYSMEM*/; device_info->caps.accel = NV5_SUPPORTED_DRAWINGFUNCTIONS | NV5_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = NV5_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = NV5_SUPPORTED_BLITTINGFLAGS; break; case NV_ARCH_10: device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS /*| CCF_READSYSMEM*/; device_info->caps.accel = NV10_SUPPORTED_DRAWINGFUNCTIONS | NV10_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = NV10_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = NV10_SUPPORTED_BLITTINGFLAGS; break; case NV_ARCH_20: device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS /* | CCF_READSYSMEM*/; /* Crash reported when the flag is on. */ device_info->caps.accel = NV20_SUPPORTED_DRAWINGFUNCTIONS | NV20_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = NV20_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = NV20_SUPPORTED_BLITTINGFLAGS; break; case NV_ARCH_30: device_info->caps.flags = CCF_CLIPPING | CCF_RENDEROPTS; device_info->caps.accel = NV30_SUPPORTED_DRAWINGFUNCTIONS | NV30_SUPPORTED_BLITTINGFUNCTIONS; device_info->caps.drawing = NV30_SUPPORTED_DRAWINGFLAGS; device_info->caps.blitting = NV30_SUPPORTED_BLITTINGFLAGS; break; default: device_info->caps.flags = 0; device_info->caps.accel = 0; device_info->caps.drawing = 0; device_info->caps.blitting = 0; break; } device_info->limits.surface_byteoffset_alignment = 64; device_info->limits.surface_pixelpitch_alignment = 32; dfb_config->pollvsync_after = 1; /* GeForce3 Intergrated GPU (XBox) */ if (nvdev->chip == 0x02A0) { nvdev->fb_offset = (long)nvdrv->fb_base & 0x0FFFFFFF; ram_total += nvdev->fb_offset; } nvdev->fb_size = 1 << direct_log2( ram_total ); /* skip if unsupported arch (NV40) */ if (!nvdev->arch) return DFB_OK; nvdev->agp_offset = dfb_gfxcard_auxmemory_physical( nvdrv->device, 0 ); if (dfb_config->dma) { int offset = -1; if (dfb_gfxcard_auxmemory_length() >= 64*1024) { offset = dfb_gfxcard_reserve_auxmemory( nvdrv->device, 64*1024 ); if (offset < 0) { D_ERROR( "DirectFB/NVidia: " "couldn't reserve 64Kb of agp memory!\n" ); } else { nvdev->use_agp = true; nvdev->use_dma = true; nvdev->dma_size = 64*1024; nvdev->dma_offset = offset; nvdrv->dma_base = nvdrv->agp_base + offset; } } if (offset < 0) { int len; len = 32*1024 + ((ram_used - 32*1024) & 0x1FFFF); offset = dfb_gfxcard_reserve_memory( nvdrv->device, len ); if (offset < 0) { D_ERROR( "DirectFB/NVidia: " "couldn't reserve %d bytes of video memory!\n", len ); } else { nvdev->use_dma = true; nvdev->dma_size = 32*1024; nvdev->dma_offset = offset; nvdrv->dma_base = nvdrv->fb_base + offset; ram_used -= len; } } D_INFO ( "DirectFB/NVidia: DMA acceleration %s.\n", nvdev->use_dma ? "enabled" : "disabled" ); D_DEBUG( "DirectFB/NVidia: DMA target is %s.\n", nvdev->use_agp ? "AGP" : "NVM" ); } /* reserve memory for textures/color buffers */ if (device_info->caps.accel & DFXL_TEXTRIANGLES) { unsigned tex_size; int len, offset; /* if we have more than 32MB of video memory, use a 1024x1024 texture */ if (ram_used > (32 << 20)) tex_size = 1024*1024; /* if we have more than 16MB of video memory, use a 1024x512 texture */ else if (ram_used > (16 << 20)) tex_size = 1024*512; /* otherwise use a 512x512 texture */ else tex_size = 512*512; len = tex_size*2 + 8; len += (ram_used - len) & 0xFF; offset = dfb_gfxcard_reserve_memory( nvdrv->device, len ); if (offset < 0) { /* if video memory allocation failed, disable 3d acceleration */ D_ERROR( "DirectFB/NVidia: " "couldn't reserve %d bytes of video memory!\n", len ); D_INFO( "DirectFB/NVidia: 3D acceleration disabled.\n" ); device_info->caps.accel &= ~DFXL_TEXTRIANGLES; } else { D_DEBUG( "DirectFB/NVidia: " "reserved %d bytes for 3D buffers at offset 0x%08x.\n", len, offset ); nvdev->enabled_3d = true; nvdev->buf_offset[0] = offset + tex_size*2; // color nvdev->buf_offset[1] = offset; // texture nvdev->max_texture_size = tex_size; } } if (nvdev->enabled_3d) { /* set default 3d state for drawing functions */ nvdev->state3d[0].modified = true; nvdev->state3d[0].colorkey = 0; nvdev->state3d[0].offset = nvdev->fb_offset + nvdev->buf_offset[0]; nvdev->state3d[0].format = TXTRI_FORMAT_CONTEXT_DMA_A | TXTRI_FORMAT_ORIGIN_ZOH_CORNER | TXTRI_FORMAT_ORIGIN_FOH_CORNER | TXTRI_FORMAT_COLOR_R5G6B5 | TXTRI_FORMAT_U_WRAP | TXTRI_FORMAT_V_WRAP | 0x00111000; // 2x2 nvdev->state3d[0].filter = TXTRI_FILTER_TEXTUREMIN_NEAREST | TXTRI_FILTER_TEXTUREMAG_NEAREST; nvdev->state3d[0].blend = TXTRI_BLEND_TEXTUREMAPBLEND_MODULATEALPHA | TXTRI_BLEND_OPERATION_MUX_TALPHAMSB | TXTRI_BLEND_SHADEMODE_FLAT | TXTRI_BLEND_SRCBLEND_ONE | TXTRI_BLEND_DESTBLEND_ZERO; nvdev->state3d[0].control = TXTRI_CONTROL_ALPHAFUNC_ALWAYS | TXTRI_CONTROL_ORIGIN_CORNER | TXTRI_CONTROL_ZFUNC_ALWAYS | TXTRI_CONTROL_CULLMODE_NONE | TXTRI_CONTROL_Z_FORMAT_FIXED; nvdev->state3d[0].fog = 0; /* set default 3d state for blitting functions */ nvdev->state3d[1].modified = true; nvdev->state3d[1].colorkey = 0; nvdev->state3d[1].offset = nvdev->fb_offset + nvdev->buf_offset[1]; nvdev->state3d[1].format = TXTRI_FORMAT_CONTEXT_DMA_A | TXTRI_FORMAT_ORIGIN_ZOH_CORNER | TXTRI_FORMAT_ORIGIN_FOH_CORNER | TXTRI_FORMAT_COLOR_R5G6B5 | TXTRI_FORMAT_U_CLAMP | TXTRI_FORMAT_V_CLAMP | 0x00001000; nvdev->state3d[1].filter = TXTRI_FILTER_TEXTUREMIN_LINEAR | TXTRI_FILTER_TEXTUREMAG_LINEAR; nvdev->state3d[1].blend = TXTRI_BLEND_TEXTUREMAPBLEND_COPY | TXTRI_BLEND_OPERATION_MUX_TALPHAMSB | TXTRI_BLEND_SHADEMODE_GOURAUD | TXTRI_BLEND_TEXTUREPERSPECTIVE_ENABLE | TXTRI_BLEND_SRCBLEND_ONE | TXTRI_BLEND_DESTBLEND_ZERO; nvdev->state3d[1].control = TXTRI_CONTROL_ALPHAFUNC_ALWAYS | TXTRI_CONTROL_ORIGIN_CENTER | TXTRI_CONTROL_ZFUNC_ALWAYS | TXTRI_CONTROL_CULLMODE_NONE | TXTRI_CONTROL_DITHER_ENABLE | TXTRI_CONTROL_Z_FORMAT_FIXED; nvdev->state3d[1].fog = 0; /* clear color buffer */ memset( dfb_gfxcard_memory_virtual( device, nvdev->buf_offset[0] ), 0xFF, 8 ); } /* write dma objects configuration */ nv_store_dma( nvdrv, OBJ_DMA_IN, ADDR_DMA_IN, 0x00, DMA_FLAG_PAGE_TABLE | DMA_FLAG_PAGE_ENTRY_LINEAR | DMA_FLAG_ACCESS_RDWR | DMA_FLAG_TARGET_NVM, nvdev->fb_size, 0x00000000, DMA_FRAME_ACCESS_RDWR ); if (nvdev->use_dma) { if (nvdev->use_agp) { nv_store_dma( nvdrv, OBJ_DMA_OUT, ADDR_DMA_OUT, 0x02, DMA_FLAG_PAGE_TABLE | DMA_FLAG_PAGE_ENTRY_LINEAR | DMA_FLAG_ACCESS_RDWR | DMA_FLAG_TARGET_AGP, nvdev->dma_size, nvdev->agp_offset+nvdev->dma_offset, DMA_FRAME_ACCESS_RDWR ); } else { nv_store_dma( nvdrv, OBJ_DMA_OUT, ADDR_DMA_OUT, 0x02, DMA_FLAG_PAGE_TABLE | DMA_FLAG_PAGE_ENTRY_LINEAR | DMA_FLAG_ACCESS_RDWR | DMA_FLAG_TARGET_NVM, nvdev->dma_size, nvdev->fb_offset+nvdev->dma_offset, DMA_FRAME_ACCESS_RDWR ); } } /* write graphics objects configuration */ nv_store_object( nvdrv, OBJ_SURFACES2D, ADDR_SURFACES2D, 0x42, 0, 0, 0 ); nv_store_object( nvdrv, OBJ_CLIP, ADDR_CLIP, 0x19, 0, 0, 0 ); nv_store_object( nvdrv, OBJ_BETA1, ADDR_BETA1, 0x12, 0, 0, 0 ); nv_store_object( nvdrv, OBJ_BETA4, ADDR_BETA4, 0x72, 0, 0, 0 ); nv_store_object( nvdrv, OBJ_RECTANGLE, ADDR_RECTANGLE, 0x5E, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_TRIANGLE, ADDR_TRIANGLE, 0x5D, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_LINE, ADDR_LINE, 0x5C, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH, ADDR_DMA_IN, ADDR_DMA_IN ); switch (nvdev->arch) { case NV_ARCH_04: nv_store_object( nvdrv, OBJ_SCREENBLT, ADDR_SCREENBLT, 0x1F, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SCALEDIMAGE, ADDR_SCALEDIMAGE, 0x37, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_COPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_TEXTRIANGLE, ADDR_TEXTRIANGLE, 0x54, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_COPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SURFACES3D, ADDR_SURFACES3D, 0x53, 0, 0, 0 ); break; case NV_ARCH_05: nv_store_object( nvdrv, OBJ_SCREENBLT, ADDR_SCREENBLT, 0x5F, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_IMAGEBLT, ADDR_IMAGEBLT, 0x65, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SCALEDIMAGE, ADDR_SCALEDIMAGE, 0x63, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_STRETCHEDIMAGE, ADDR_STRETCHEDIMAGE, 0x66, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_TEXTRIANGLE, ADDR_TEXTRIANGLE, 0x54, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SURFACES3D, ADDR_SURFACES3D, 0x53, 0, 0, 0 ); break; case NV_ARCH_10: nv_store_object( nvdrv, OBJ_SCREENBLT, ADDR_SCREENBLT, 0x5F, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_IMAGEBLT, ADDR_IMAGEBLT, 0x65, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SCALEDIMAGE, ADDR_SCALEDIMAGE, 0x89, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_STRETCHEDIMAGE, ADDR_STRETCHEDIMAGE, 0x66, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_TEXTRIANGLE, ADDR_TEXTRIANGLE, 0x94, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SURFACES3D, ADDR_SURFACES3D, 0x93, 0, 0, 0 ); break; case NV_ARCH_20: case NV_ARCH_30: default: nv_store_object( nvdrv, OBJ_SCREENBLT, ADDR_SCREENBLT, 0x9F, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_IMAGEBLT, ADDR_IMAGEBLT, 0x65, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SCALEDIMAGE, ADDR_SCALEDIMAGE, 0x89, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_STRETCHEDIMAGE, ADDR_STRETCHEDIMAGE, 0x66, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CONVERSION_DITHER | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_TEXTRIANGLE, ADDR_TEXTRIANGLE, 0x94, CTX_FLAG_USER_CLIP | CTX_FLAG_PATCH_SRCCOPY | CTX_FLAG_PATCH | CTX_FLAG_CTX_SURFACE0, ADDR_DMA_IN, ADDR_DMA_IN ); nv_store_object( nvdrv, OBJ_SURFACES3D, ADDR_SURFACES3D, 0x93, 0, 0, 0 ); break; } /* assign default objects to subchannels */ nvdev->subchannel_object[SUBC_SURFACES2D] = OBJ_SURFACES2D; nvdev->subchannel_object[SUBC_CLIP] = OBJ_CLIP; nvdev->subchannel_object[SUBC_RECTANGLE] = OBJ_RECTANGLE; nvdev->subchannel_object[SUBC_TRIANGLE] = OBJ_TRIANGLE; nvdev->subchannel_object[SUBC_LINE] = OBJ_LINE; nvdev->subchannel_object[SUBC_SCREENBLT] = OBJ_SCREENBLT; nvdev->subchannel_object[SUBC_SCALEDIMAGE] = OBJ_SCALEDIMAGE; nvdev->subchannel_object[SUBC_TEXTRIANGLE] = OBJ_TEXTRIANGLE; if (nvdev->arch == NV_ARCH_04) { nvdev->drawing_operation = OPERATION_COPY; nvdev->scaler_operation = OPERATION_COPY; nvdev->scaler_filter = 0; nvdev->system_operation = OPERATION_COPY; } else { nvdev->drawing_operation = OPERATION_SRCCOPY; nvdev->scaler_operation = OPERATION_SRCCOPY; nvdev->scaler_filter = SCALER_IN_FORMAT_ORIGIN_CENTER | SCALER_IN_FORMAT_FILTER_LINEAR; nvdev->system_operation = OPERATION_SRCCOPY; } nvAfterSetVar( driver_data, device_data ); return DFB_OK; } static void driver_close_device( CoreGraphicsDevice *device, void *driver_data, void *device_data ) { NVidiaDeviceData *nvdev = (NVidiaDeviceData*) device_data; D_DEBUG( "DirectFB/NVidia: Performance Monitoring:\n" ); D_DEBUG( "DirectFB/NVidia: %9d nv_wait* calls\n", nvdev->waitfree_calls ); D_DEBUG( "DirectFB/NVidia: %9d register writes\n", nvdev->waitfree_sum ); D_DEBUG( "DirectFB/NVidia: %9d FIFO/DMA wait cycles (depends on CPU)\n", nvdev->free_waitcycles ); D_DEBUG( "DirectFB/NVidia: %9d IDLE wait cycles (depends on CPU)\n", nvdev->idle_waitcycles ); D_DEBUG( "DirectFB/NVidia: %9d FIFO/DMA space cache hits (depends on CPU)\n", nvdev->cache_hits ); D_DEBUG( "DirectFB/NVidia: Conclusion:\n" ); D_DEBUG( "DirectFB/NVidia: Average register writes/nv_wait* call:%.2f\n", nvdev->waitfree_sum/(float)(nvdev->waitfree_calls ? : 1) ); D_DEBUG( "DirectFB/NVidia: Average wait cycles/nv_wait* call: %.2f\n", nvdev->free_waitcycles/(float)(nvdev->waitfree_calls ? : 1) ); D_DEBUG( "DirectFB/NVidia: Average FIFO/DMA space cache hits: %02d%%\n", (int)(100 * nvdev->cache_hits/ (float)(nvdev->waitfree_calls ? : 1)) ); /* reset channel mode to PIO to avoid crash in rivafb */ if (nvdev->use_dma) { nvdev->use_dma = false; nvAfterSetVar( driver_data, device_data ); } } static void driver_close_driver( CoreGraphicsDevice *device, void *driver_data ) { NVidiaDriverData *nvdrv = (NVidiaDriverData*) driver_data; dfb_gfxcard_unmap_mmio( device, nvdrv->mmio_base, -1 ); }