This isn't present on master, so probably shouldn't be here either.tags/mesa_20090313
@@ -1,239 +0,0 @@ | |||
/************************************************************************** | |||
Copyright 2006 Stephane Marchesin | |||
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 | |||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 __NOUVEAU_CONTEXT_H__ | |||
#define __NOUVEAU_CONTEXT_H__ | |||
#include "dri_util.h" | |||
#include "drm.h" | |||
#include "nouveau_drm.h" | |||
#include "mtypes.h" | |||
#include "tnl/t_vertex.h" | |||
#include "nouveau_screen.h" | |||
#include "nouveau_state_cache.h" | |||
#include "nouveau_buffers.h" | |||
#include "nouveau_shader.h" | |||
#include "nouveau_sync.h" | |||
#include "xmlconfig.h" | |||
typedef struct nouveau_fifo_t{ | |||
int channel; | |||
uint32_t* buffer; | |||
uint32_t* mmio; | |||
uint32_t put_base; | |||
uint32_t current; | |||
uint32_t put; | |||
uint32_t free; | |||
uint32_t max; | |||
} | |||
nouveau_fifo; | |||
#define TAG(x) nouveau##x | |||
#include "tnl_dd/t_dd_vertex.h" | |||
#undef TAG | |||
/* Subpixel offsets for window coordinates (triangles): */ | |||
#define SUBPIXEL_X (0.0F) | |||
#define SUBPIXEL_Y (0.125F) | |||
struct nouveau_context; | |||
typedef void (*nouveau_tri_func)( struct nouveau_context*, | |||
nouveauVertex *, | |||
nouveauVertex *, | |||
nouveauVertex * ); | |||
typedef void (*nouveau_line_func)( struct nouveau_context*, | |||
nouveauVertex *, | |||
nouveauVertex * ); | |||
typedef void (*nouveau_point_func)( struct nouveau_context*, | |||
nouveauVertex * ); | |||
typedef struct nouveau_hw_func_t { | |||
/* Initialise any card-specific non-GL related state */ | |||
GLboolean (*InitCard)(struct nouveau_context *); | |||
/* Update buffer offset/pitch/format */ | |||
GLboolean (*BindBuffers)(struct nouveau_context *, int num_color, | |||
nouveau_renderbuffer **color, | |||
nouveau_renderbuffer *depth); | |||
/* Update anything that depends on the window position/size */ | |||
void (*WindowMoved)(struct nouveau_context *); | |||
} nouveau_hw_func; | |||
typedef struct nouveau_context { | |||
/* Mesa context */ | |||
GLcontext *glCtx; | |||
/* The per-context fifo */ | |||
nouveau_fifo fifo; | |||
/* The read-only regs */ | |||
volatile unsigned char* mmio; | |||
/* The per-channel notifier block */ | |||
volatile void *notifier_block; | |||
/* Physical addresses of AGP/VRAM apertures */ | |||
uint64_t vram_phys; | |||
uint64_t vram_size; | |||
uint64_t gart_phys; | |||
uint64_t gart_size; | |||
/* Channel synchronisation */ | |||
struct drm_nouveau_notifier_alloc *syncNotifier; | |||
/* ARB_occlusion_query / EXT_timer_query */ | |||
GLuint query_object_max; | |||
GLboolean * query_alloc; | |||
struct drm_nouveau_notifier_alloc *queryNotifier; | |||
/* Additional hw-specific functions */ | |||
nouveau_hw_func hw_func; | |||
/* FIXME : do we want to put all state into a separate struct ? */ | |||
/* State for tris */ | |||
GLuint color_offset; | |||
GLuint specular_offset; | |||
/* Vertex state */ | |||
GLuint vertex_size; | |||
GLubyte *verts; | |||
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; | |||
GLuint vertex_attr_count; | |||
/* Color buffer clear value */ | |||
uint32_t clear_color_value; | |||
/* Depth/stencil clear value */ | |||
uint32_t clear_value; | |||
/* Light state */ | |||
GLboolean lighting_enabled; | |||
uint32_t enabled_lights; | |||
/* Cached state */ | |||
nouveau_state_cache state_cache; | |||
/* The drawing fallbacks */ | |||
GLuint Fallback; | |||
nouveau_tri_func draw_tri; | |||
nouveau_line_func draw_line; | |||
nouveau_point_func draw_point; | |||
/* Cliprects information */ | |||
GLuint numClipRects; | |||
drm_clip_rect_t *pClipRects; | |||
drm_clip_rect_t osClipRect; | |||
GLuint drawX, drawY, drawW, drawH; | |||
/* The rendering context information */ | |||
GLenum current_primitive; /* the current primitive enum */ | |||
DECLARE_RENDERINPUTS(render_inputs_bitset); /* the current render inputs */ | |||
/* Shader state */ | |||
nvsFunc VPfunc; | |||
nvsFunc FPfunc; | |||
nouveauShader *current_fragprog; | |||
nouveauShader *current_vertprog; | |||
nouveauShader *passthrough_vp; | |||
nouveauShader *passthrough_fp; | |||
nouveauScreenRec *screen; | |||
struct drm_nouveau_sarea *sarea; | |||
__DRIcontextPrivate *driContext; /* DRI context */ | |||
__DRIscreenPrivate *driScreen; /* DRI screen */ | |||
__DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */ | |||
GLint lastStamp; | |||
drm_context_t hHWContext; | |||
drm_hw_lock_t *driHwLock; | |||
int driFd; | |||
/* Configuration cache */ | |||
driOptionCache optionCache; | |||
/* vblank stuff */ | |||
uint32_t vblank_flags; | |||
uint32_t vblank_seq; | |||
GLuint new_state; | |||
GLuint new_render_state; | |||
GLuint render_index; | |||
GLmatrix viewport; | |||
GLfloat depth_scale; | |||
}nouveauContextRec, *nouveauContextPtr; | |||
#define NOUVEAU_CONTEXT(ctx) ((nouveauContextPtr)(ctx->DriverCtx)) | |||
/* Flags for software fallback cases: */ | |||
#define NOUVEAU_FALLBACK_TEXTURE 0x0001 | |||
#define NOUVEAU_FALLBACK_DRAW_BUFFER 0x0002 | |||
#define NOUVEAU_FALLBACK_READ_BUFFER 0x0004 | |||
#define NOUVEAU_FALLBACK_STENCIL 0x0008 | |||
#define NOUVEAU_FALLBACK_RENDER_MODE 0x0010 | |||
#define NOUVEAU_FALLBACK_LOGICOP 0x0020 | |||
#define NOUVEAU_FALLBACK_SEP_SPECULAR 0x0040 | |||
#define NOUVEAU_FALLBACK_BLEND_EQ 0x0080 | |||
#define NOUVEAU_FALLBACK_BLEND_FUNC 0x0100 | |||
#define NOUVEAU_FALLBACK_PROJTEX 0x0200 | |||
#define NOUVEAU_FALLBACK_DISABLE 0x0400 | |||
extern GLboolean nouveauCreateContext( const __GLcontextModes *glVisual, | |||
__DRIcontextPrivate *driContextPriv, | |||
void *sharedContextPrivate ); | |||
extern void nouveauDestroyContext( __DRIcontextPrivate * ); | |||
extern GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv, | |||
__DRIdrawablePrivate *driDrawPriv, | |||
__DRIdrawablePrivate *driReadPriv ); | |||
extern GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv ); | |||
extern void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv); | |||
extern void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv, | |||
int x, int y, int w, int h); | |||
/* Debugging utils: */ | |||
extern int NOUVEAU_DEBUG; | |||
#define DEBUG_SHADERS 0x00000001 | |||
#define DEBUG_MEM 0x00000002 | |||
#define DEBUG_BUFFEROBJ 0x00000004 | |||
#endif /* __NOUVEAU_CONTEXT_H__ */ | |||
@@ -1,152 +0,0 @@ | |||
/************************************************************************** | |||
Copyright 2006 Stephane Marchesin | |||
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 | |||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 "vblank.h" | |||
#include <errno.h> | |||
#include "mtypes.h" | |||
#include "macros.h" | |||
#include "dd.h" | |||
#include "swrast/swrast.h" | |||
#include "nouveau_context.h" | |||
#include "nouveau_msg.h" | |||
#include "nouveau_fifo.h" | |||
#include "nouveau_lock.h" | |||
#include "nouveau_object.h" | |||
#include "nouveau_sync.h" | |||
#ifdef NOUVEAU_RING_DEBUG | |||
int nouveau_fifo_remaining=0; | |||
#endif | |||
#define RING_SKIPS 8 | |||
void WAIT_RING(nouveauContextPtr nmesa,uint32_t size) | |||
{ | |||
#ifdef NOUVEAU_RING_DEBUG | |||
return; | |||
#endif | |||
uint32_t fifo_get; | |||
while(nmesa->fifo.free < size+1) { | |||
fifo_get = NV_FIFO_READ_GET(); | |||
if(nmesa->fifo.put >= fifo_get) { | |||
nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current; | |||
if(nmesa->fifo.free < size+1) { | |||
OUT_RING(NV03_FIFO_CMD_JUMP | nmesa->fifo.put_base); | |||
if(fifo_get <= RING_SKIPS) { | |||
if(nmesa->fifo.put <= RING_SKIPS) /* corner case - will be idle */ | |||
NV_FIFO_WRITE_PUT(RING_SKIPS + 1); | |||
do { fifo_get = NV_FIFO_READ_GET(); } | |||
while(fifo_get <= RING_SKIPS); | |||
} | |||
NV_FIFO_WRITE_PUT(RING_SKIPS); | |||
nmesa->fifo.current = nmesa->fifo.put = RING_SKIPS; | |||
nmesa->fifo.free = fifo_get - (RING_SKIPS + 1); | |||
} | |||
} else | |||
nmesa->fifo.free = fifo_get - nmesa->fifo.current - 1; | |||
} | |||
} | |||
/* | |||
* Wait for the channel to be idle | |||
*/ | |||
void nouveauWaitForIdleLocked(nouveauContextPtr nmesa) | |||
{ | |||
/* Wait for FIFO idle */ | |||
FIRE_RING(); | |||
while(RING_AHEAD()>0); | |||
/* Wait on notifier to indicate all commands in the channel have | |||
* been completed. | |||
*/ | |||
nouveau_notifier_wait_nop(nmesa->glCtx, nmesa->syncNotifier, NvSub3D); | |||
} | |||
void nouveauWaitForIdle(nouveauContextPtr nmesa) | |||
{ | |||
LOCK_HARDWARE(nmesa); | |||
nouveauWaitForIdleLocked(nmesa); | |||
UNLOCK_HARDWARE(nmesa); | |||
} | |||
// here we call the fifo initialization ioctl and fill in stuff accordingly | |||
GLboolean nouveauFifoInit(nouveauContextPtr nmesa) | |||
{ | |||
struct drm_nouveau_fifo_alloc fifo_init; | |||
int i, ret; | |||
#ifdef NOUVEAU_RING_DEBUG | |||
return GL_TRUE; | |||
#endif | |||
fifo_init.fb_ctxdma_handle = NvDmaFB; | |||
fifo_init.tt_ctxdma_handle = NvDmaTT; | |||
ret=drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_FIFO_ALLOC, &fifo_init, sizeof(fifo_init)); | |||
if (ret) { | |||
FATAL("Fifo initialization ioctl failed (returned %d)\n",ret); | |||
return GL_FALSE; | |||
} | |||
ret = drmMap(nmesa->driFd, fifo_init.cmdbuf, fifo_init.cmdbuf_size, &nmesa->fifo.buffer); | |||
if (ret) { | |||
FATAL("Unable to map the fifo (returned %d)\n",ret); | |||
return GL_FALSE; | |||
} | |||
ret = drmMap(nmesa->driFd, fifo_init.ctrl, fifo_init.ctrl_size, &nmesa->fifo.mmio); | |||
if (ret) { | |||
FATAL("Unable to map the control regs (returned %d)\n",ret); | |||
return GL_FALSE; | |||
} | |||
ret = drmMap(nmesa->driFd, fifo_init.notifier, | |||
fifo_init.notifier_size, | |||
&nmesa->notifier_block); | |||
if (ret) { | |||
FATAL("Unable to map the notifier block (returned %d)\n",ret); | |||
return GL_FALSE; | |||
} | |||
/* Setup our initial FIFO tracking params */ | |||
nmesa->fifo.channel = fifo_init.channel; | |||
nmesa->fifo.put_base = fifo_init.put_base; | |||
nmesa->fifo.current = 0; | |||
nmesa->fifo.put = 0; | |||
nmesa->fifo.max = (fifo_init.cmdbuf_size >> 2) - 1; | |||
nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current; | |||
for (i=0; i<RING_SKIPS; i++) | |||
OUT_RING(0); | |||
nmesa->fifo.free -= RING_SKIPS; | |||
MESSAGE("Fifo init ok. Using context %d\n", fifo_init.channel); | |||
return GL_TRUE; | |||
} | |||
@@ -1,195 +0,0 @@ | |||
/************************************************************************** | |||
Copyright 2006 Stephane Marchesin | |||
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 | |||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 __NOUVEAU_FIFO_H__ | |||
#define __NOUVEAU_FIFO_H__ | |||
#include "nouveau_context.h" | |||
#include "nouveau_ctrlreg.h" | |||
#include "nouveau_state_cache.h" | |||
//#define NOUVEAU_RING_TRACE | |||
//#define NOUVEAU_RING_DEBUG | |||
//#define NOUVEAU_STATE_CACHE_DISABLE | |||
#ifndef NOUVEAU_RING_TRACE | |||
#define NOUVEAU_RING_TRACE 0 | |||
#else | |||
#undef NOUVEAU_RING_TRACE | |||
#define NOUVEAU_RING_TRACE 1 | |||
#endif | |||
#define NV_READ(reg) *(volatile uint32_t *)(nmesa->mmio + (reg)) | |||
#define NV_FIFO_READ(reg) *(volatile uint32_t *)(nmesa->fifo.mmio + (reg/4)) | |||
#define NV_FIFO_WRITE(reg,value) *(volatile uint32_t *)(nmesa->fifo.mmio + (reg/4)) = value; | |||
#define NV_FIFO_READ_GET() ((NV_FIFO_READ(NV03_FIFO_REGS_DMAGET) - nmesa->fifo.put_base) >> 2) | |||
#define NV_FIFO_WRITE_PUT(val) do { \ | |||
if (NOUVEAU_RING_TRACE) {\ | |||
printf("FIRE_RING : 0x%08x\n", nmesa->fifo.current << 2); \ | |||
fflush(stdout); \ | |||
sleep(1); \ | |||
} \ | |||
NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT, ((val)<<2) + nmesa->fifo.put_base); \ | |||
} while(0) | |||
/* | |||
* Ring/fifo interface | |||
* | |||
* - Begin a ring section with BEGIN_RING_SIZE (if you know the full size in advance) | |||
* - Output stuff to the ring with either OUT_RINGp (outputs a raw mem chunk), OUT_RING (1 uint32_t) or OUT_RINGf (1 float) | |||
* - RING_AVAILABLE returns the available fifo (in uint32_ts) | |||
* - RING_AHEAD returns how much ahead of the last submission point we are | |||
* - FIRE_RING fires whatever we have that wasn't fired before | |||
* - WAIT_RING waits for size (in uint32_ts) to be available in the fifo | |||
*/ | |||
/* Enable for ring debugging. Prints out writes to the ring buffer | |||
* but does not actually write to it. | |||
*/ | |||
#ifdef NOUVEAU_RING_DEBUG | |||
extern int nouveau_fifo_remaining; | |||
#define OUT_RINGp(ptr,sz) do { \ | |||
uint32_t* p=(uint32_t*)(ptr); \ | |||
int i; printf("OUT_RINGp: (size 0x%x dwords)\n",sz); for(i=0;i<sz;i++) printf(" 0x%08x %f\n", *(p+i), *((float*)(p+i))); \ | |||
nouveau_fifo_remaining-=sz; \ | |||
}while(0) | |||
#define OUT_RING(n) do { \ | |||
printf("OUT_RINGn: 0x%08x (%s)\n", n, __func__); \ | |||
nouveau_fifo_remaining--; \ | |||
}while(0) | |||
#define OUT_RINGf(n) do { \ | |||
printf("OUT_RINGf: %.04f (%s)\n", n, __func__); \ | |||
nouveau_fifo_remaining--; \ | |||
}while(0) | |||
#define BEGIN_RING_SIZE(subchannel,tag,size) do { \ | |||
if (nouveau_fifo_remaining!=0) \ | |||
printf("RING ERROR : remaining %d\n",nouveau_fifo_remaining); \ | |||
nouveau_state_cache_flush(nmesa); \ | |||
if (nmesa->fifo.free <= (size)) \ | |||
WAIT_RING(nmesa,(size)); \ | |||
OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \ | |||
nmesa->fifo.free -= ((size) + 1); \ | |||
nouveau_fifo_remaining=size; \ | |||
}while(0) | |||
#else | |||
#define OUT_RINGp(ptr,sz) do{ \ | |||
if (NOUVEAU_RING_TRACE) { \ | |||
uint32_t* p=(uint32_t*)(ptr); \ | |||
int i; printf("OUT_RINGp: (size 0x%x dwords) (%s)\n",sz, __func__); for(i=0;i<sz;i++) printf(" [0x%08x] 0x%08x %f\n", (nmesa->fifo.current+i) << 2, *(p+i), *((float*)(p+i))); \ | |||
} \ | |||
memcpy(nmesa->fifo.buffer+nmesa->fifo.current,ptr,(sz)*4); \ | |||
nmesa->fifo.current+=(sz); \ | |||
}while(0) | |||
#define OUT_RING(n) do { \ | |||
if (NOUVEAU_RING_TRACE) \ | |||
printf("OUT_RINGn: [0x%08x] 0x%08x (%s)\n", nmesa->fifo.current << 2, n, __func__); \ | |||
nmesa->fifo.buffer[nmesa->fifo.current++]=(n); \ | |||
}while(0) | |||
#define OUT_RINGf(n) do { \ | |||
if (NOUVEAU_RING_TRACE) \ | |||
printf("OUT_RINGf: [0x%08x] %.04f (%s)\n", nmesa->fifo.current << 2, n, __func__); \ | |||
*((float*)(nmesa->fifo.buffer+nmesa->fifo.current++))=(n); \ | |||
}while(0) | |||
#define BEGIN_RING_SIZE(subchannel,tag,size) do { \ | |||
nouveau_state_cache_flush(nmesa); \ | |||
if (nmesa->fifo.free <= (size)) \ | |||
WAIT_RING(nmesa,(size)); \ | |||
OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \ | |||
nmesa->fifo.free -= ((size) + 1); \ | |||
}while(0) | |||
#endif | |||
extern void WAIT_RING(nouveauContextPtr nmesa,uint32_t size); | |||
extern void nouveau_state_cache_flush(nouveauContextPtr nmesa); | |||
extern void nouveau_state_cache_init(nouveauContextPtr nmesa); | |||
#ifdef NOUVEAU_STATE_CACHE_DISABLE | |||
#define BEGIN_RING_CACHE(subc,tag,size) BEGIN_RING_SIZE((subc), (tag), (size)) | |||
#define OUT_RING_CACHE(n) OUT_RING((n)) | |||
#define OUT_RING_CACHEf(n) OUT_RINGf((n)) | |||
#define OUT_RING_CACHEp(ptr, sz) OUT_RINGp((ptr), (sz)) | |||
#else | |||
#define BEGIN_RING_CACHE(subchannel,tag,size) do { \ | |||
nmesa->state_cache.dirty=1; \ | |||
nmesa->state_cache.current_pos=((tag)/4); \ | |||
}while(0) | |||
#define OUT_RING_CACHE(n) do { \ | |||
if (nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value!=(n)) { \ | |||
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \ | |||
nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \ | |||
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value=(n); \ | |||
} \ | |||
nmesa->state_cache.current_pos++; \ | |||
}while(0) | |||
#define OUT_RING_CACHEf(n) do { \ | |||
if ((*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))!=(n)){ \ | |||
nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \ | |||
nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \ | |||
(*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))=(n);\ | |||
} \ | |||
nmesa->state_cache.current_pos++; \ | |||
}while(0) | |||
#define OUT_RING_CACHEp(ptr,sz) do { \ | |||
uint32_t* p=(uint32_t*)(ptr); \ | |||
int i; for(i=0;i<sz;i++) OUT_RING_CACHE(*(p+i)); \ | |||
}while(0) | |||
#endif | |||
#define RING_AVAILABLE() (nmesa->fifo.free-1) | |||
#define RING_AHEAD() ((nmesa->fifo.put<=nmesa->fifo.current)?(nmesa->fifo.current-nmesa->fifo.put):nmesa->fifo.max-nmesa->fifo.put+nmesa->fifo.current) | |||
#define FIRE_RING() do { \ | |||
if (nmesa->fifo.current!=nmesa->fifo.put) { \ | |||
nmesa->fifo.put=nmesa->fifo.current; \ | |||
NV_FIFO_WRITE_PUT(nmesa->fifo.put); \ | |||
} \ | |||
}while(0) | |||
extern void nouveauWaitForIdle(nouveauContextPtr nmesa); | |||
extern void nouveauWaitForIdleLocked(nouveauContextPtr nmesa); | |||
extern GLboolean nouveauFifoInit(nouveauContextPtr nmesa); | |||
#endif /* __NOUVEAU_FIFO_H__ */ | |||
@@ -1,382 +0,0 @@ | |||
/************************************************************************** | |||
Copyright 2006 Stephane Marchesin | |||
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 | |||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM, | |||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | |||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | |||
USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
**************************************************************************/ | |||
#include "glheader.h" | |||
#include "imports.h" | |||
#include "mtypes.h" | |||
#include "framebuffer.h" | |||
#include "renderbuffer.h" | |||
#include "nouveau_context.h" | |||
#include "nouveau_screen.h" | |||
#include "nouveau_object.h" | |||
#include "nouveau_span.h" | |||
#include "utils.h" | |||
#include "context.h" | |||
#include "vblank.h" | |||
#include "drirenderbuffer.h" | |||
#include "GL/internal/dri_interface.h" | |||
#include "xmlpool.h" | |||
PUBLIC const char __driConfigOptions[] = | |||
DRI_CONF_BEGIN | |||
DRI_CONF_SECTION_DEBUG | |||
DRI_CONF_NO_RAST(false) | |||
DRI_CONF_SECTION_END | |||
DRI_CONF_END; | |||
static const GLuint __driNConfigOptions = 1; | |||
extern const struct dri_extension common_extensions[]; | |||
extern const struct dri_extension nv10_extensions[]; | |||
extern const struct dri_extension nv20_extensions[]; | |||
extern const struct dri_extension nv30_extensions[]; | |||
extern const struct dri_extension nv40_extensions[]; | |||
extern const struct dri_extension nv50_extensions[]; | |||
static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv) | |||
{ | |||
nouveauScreenPtr screen; | |||
NOUVEAUDRIPtr dri_priv=(NOUVEAUDRIPtr)sPriv->pDevPriv; | |||
/* allocate screen */ | |||
screen = (nouveauScreenPtr) CALLOC( sizeof(*screen) ); | |||
if ( !screen ) { | |||
__driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__); | |||
return NULL; | |||
} | |||
screen->card=nouveau_card_lookup(dri_priv->device_id); | |||
if (!screen->card) { | |||
__driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n", | |||
__func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF); | |||
FREE(screen); | |||
return NULL; | |||
} | |||
/* parse information in __driConfigOptions */ | |||
driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions); | |||
screen->fbFormat = dri_priv->bpp / 8; | |||
screen->frontOffset = dri_priv->front_offset; | |||
screen->frontPitch = dri_priv->front_pitch; | |||
screen->backOffset = dri_priv->back_offset; | |||
screen->backPitch = dri_priv->back_pitch; | |||
screen->depthOffset = dri_priv->depth_offset; | |||
screen->depthPitch = dri_priv->depth_pitch; | |||
screen->driScreen = sPriv; | |||
return screen; | |||
} | |||
static void | |||
nouveauDestroyScreen(__DRIscreenPrivate *sPriv) | |||
{ | |||
nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private; | |||
if (!screen) return; | |||
/* free all option information */ | |||
driDestroyOptionInfo (&screen->optionCache); | |||
FREE(screen); | |||
sPriv->private = NULL; | |||
} | |||
static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv) | |||
{ | |||
sPriv->private = (void *) nouveauCreateScreen( sPriv ); | |||
if ( !sPriv->private ) { | |||
nouveauDestroyScreen( sPriv ); | |||
return GL_FALSE; | |||
} | |||
return GL_TRUE; | |||
} | |||
/** | |||
* Create the Mesa framebuffer and renderbuffers for a given window/drawable. | |||
* | |||
* \todo This function (and its interface) will need to be updated to support | |||
* pbuffers. | |||
*/ | |||
static GLboolean | |||
nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv, | |||
__DRIdrawablePrivate *driDrawPriv, | |||
const __GLcontextModes *mesaVis, | |||
GLboolean isPixmap) | |||
{ | |||
nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private; | |||
nouveau_renderbuffer *nrb; | |||
struct gl_framebuffer *fb; | |||
const GLboolean swAccum = mesaVis->accumRedBits > 0; | |||
const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24; | |||
GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5; | |||
if (isPixmap) | |||
return GL_FALSE; /* not implemented */ | |||
fb = _mesa_create_framebuffer(mesaVis); | |||
if (!fb) | |||
return GL_FALSE; | |||
/* Front buffer */ | |||
nrb = nouveau_renderbuffer_new(color_format, | |||
driScrnPriv->pFB + screen->frontOffset, | |||
screen->frontOffset, | |||
screen->frontPitch * screen->fbFormat, | |||
driDrawPriv); | |||
nouveauSpanSetFunctions(nrb, mesaVis); | |||
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa); | |||
if (0 /* unified buffers if we choose to support them.. */) { | |||
} else { | |||
if (mesaVis->doubleBufferMode) { | |||
nrb = nouveau_renderbuffer_new(color_format, NULL, | |||
0, 0, | |||
NULL); | |||
nouveauSpanSetFunctions(nrb, mesaVis); | |||
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa); | |||
} | |||
if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { | |||
nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL, | |||
0, 0, | |||
NULL); | |||
nouveauSpanSetFunctions(nrb, mesaVis); | |||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); | |||
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa); | |||
} else if (mesaVis->depthBits == 24) { | |||
nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL, | |||
0, 0, | |||
NULL); | |||
nouveauSpanSetFunctions(nrb, mesaVis); | |||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); | |||
} else if (mesaVis->depthBits == 16) { | |||
nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL, | |||
0, 0, | |||
NULL); | |||
nouveauSpanSetFunctions(nrb, mesaVis); | |||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); | |||
} | |||
} | |||
_mesa_add_soft_renderbuffers(fb, | |||
GL_FALSE, /* color */ | |||
GL_FALSE, /* depth */ | |||
swStencil, | |||
swAccum, | |||
GL_FALSE, /* alpha */ | |||
GL_FALSE /* aux */); | |||
driDrawPriv->driverPrivate = (void *) fb; | |||
return (driDrawPriv->driverPrivate != NULL); | |||
} | |||
static void | |||
nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) | |||
{ | |||
_mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); | |||
} | |||
static int | |||
nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo) | |||
{ | |||
return -1; | |||
} | |||
static const struct __DriverAPIRec nouveauAPI = { | |||
.InitDriver = nouveauInitDriver, | |||
.DestroyScreen = nouveauDestroyScreen, | |||
.CreateContext = nouveauCreateContext, | |||
.DestroyContext = nouveauDestroyContext, | |||
.CreateBuffer = nouveauCreateBuffer, | |||
.DestroyBuffer = nouveauDestroyBuffer, | |||
.SwapBuffers = nouveauSwapBuffers, | |||
.MakeCurrent = nouveauMakeCurrent, | |||
.UnbindContext = nouveauUnbindContext, | |||
.GetSwapInfo = nouveauGetSwapInfo, | |||
.GetMSC = driGetMSC32, | |||
.WaitForMSC = driWaitForMSC32, | |||
.WaitForSBC = NULL, | |||
.SwapBuffersMSC = NULL, | |||
.CopySubBuffer = nouveauCopySubBuffer | |||
}; | |||
static __GLcontextModes * | |||
nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits, | |||
unsigned stencil_bits, GLboolean have_back_buffer ) | |||
{ | |||
__GLcontextModes * modes; | |||
__GLcontextModes * m; | |||
unsigned num_modes; | |||
unsigned depth_buffer_factor; | |||
unsigned back_buffer_factor; | |||
int i; | |||
static const struct { | |||
GLenum format; | |||
GLenum type; | |||
} fb_format_array[] = { | |||
{ GL_RGB , GL_UNSIGNED_SHORT_5_6_5 }, | |||
{ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, | |||
{ GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, | |||
}; | |||
/* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't | |||
* support pageflipping at all. | |||
*/ | |||
static const GLenum back_buffer_modes[] = { | |||
GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML | |||
}; | |||
uint8_t depth_bits_array[4] = { 0, 16, 24, 24 }; | |||
uint8_t stencil_bits_array[4] = { 0, 0, 0, 8 }; | |||
depth_buffer_factor = 4; | |||
back_buffer_factor = (have_back_buffer) ? 3 : 1; | |||
num_modes = ((pixel_bits==16) ? 1 : 2) * | |||
depth_buffer_factor * back_buffer_factor * 4; | |||
modes = (*dri_interface->createContextModes)(num_modes, | |||
sizeof(__GLcontextModes)); | |||
m = modes; | |||
for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) { | |||
if (!driFillInModes(&m, fb_format_array[i].format, | |||
fb_format_array[i].type, | |||
depth_bits_array, | |||
stencil_bits_array, | |||
depth_buffer_factor, | |||
back_buffer_modes, | |||
back_buffer_factor, | |||
GLX_TRUE_COLOR)) { | |||
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", | |||
__func__, __LINE__ ); | |||
return NULL; | |||
} | |||
if (!driFillInModes(&m, fb_format_array[i].format, | |||
fb_format_array[i].type, | |||
depth_bits_array, | |||
stencil_bits_array, | |||
depth_buffer_factor, | |||
back_buffer_modes, | |||
back_buffer_factor, | |||
GLX_DIRECT_COLOR)) { | |||
fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", | |||
__func__, __LINE__ ); | |||
return NULL; | |||
} | |||
} | |||
return modes; | |||
} | |||
/** | |||
* This is the bootstrap function for the driver. libGL supplies all of the | |||
* requisite information about the system, and the driver initializes itself. | |||
* This routine also fills in the linked list pointed to by \c driver_modes | |||
* with the \c __GLcontextModes that the driver can support for windows or | |||
* pbuffers. | |||
* | |||
* \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on | |||
* failure. | |||
*/ | |||
PUBLIC | |||
void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, | |||
const __GLcontextModes * modes, | |||
const __DRIversion * ddx_version, | |||
const __DRIversion * dri_version, | |||
const __DRIversion * drm_version, | |||
const __DRIframebuffer * frame_buffer, | |||
drmAddress pSAREA, int fd, | |||
int internal_api_version, | |||
const __DRIinterfaceMethods * interface, | |||
__GLcontextModes ** driver_modes) | |||
{ | |||
__DRIscreenPrivate *psp; | |||
static const __DRIversion ddx_expected = { 1, 2, 0 }; | |||
static const __DRIversion dri_expected = { 4, 0, 0 }; | |||
static const __DRIversion drm_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; | |||
#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 9 | |||
#error nouveau_drm.h version doesn't match expected version | |||
#endif | |||
dri_interface = interface; | |||
if (!driCheckDriDdxDrmVersions2("nouveau", | |||
dri_version, & dri_expected, | |||
ddx_version, & ddx_expected, | |||
drm_version, & drm_expected)) { | |||
return NULL; | |||
} | |||
// temporary lock step versioning | |||
if (drm_expected.patch!=drm_version->patch) { | |||
__driUtilMessage("%s: wrong DRM version, expected %d, got %d\n", | |||
__func__, | |||
drm_expected.patch, drm_version->patch); | |||
return NULL; | |||
} | |||
psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, | |||
ddx_version, dri_version, drm_version, | |||
frame_buffer, pSAREA, fd, | |||
internal_api_version, &nouveauAPI); | |||
if ( psp != NULL ) { | |||
NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv; | |||
*driver_modes = nouveauFillInModes(dri_priv->bpp, | |||
(dri_priv->bpp == 16) ? 16 : 24, | |||
(dri_priv->bpp == 16) ? 0 : 8, | |||
1 | |||
); | |||
/* Calling driInitExtensions here, with a NULL context pointer, does not actually | |||
* enable the extensions. It just makes sure that all the dispatch offsets for all | |||
* the extensions that *might* be enables are known. This is needed because the | |||
* dispatch offsets need to be known when _mesa_context_create is called, but we can't | |||
* enable the extensions until we have a context pointer. | |||
* | |||
* Hello chicken. Hello egg. How are you two today? | |||
*/ | |||
driInitExtensions( NULL, common_extensions, GL_FALSE ); | |||
driInitExtensions( NULL, nv10_extensions, GL_FALSE ); | |||
driInitExtensions( NULL, nv10_extensions, GL_FALSE ); | |||
driInitExtensions( NULL, nv30_extensions, GL_FALSE ); | |||
driInitExtensions( NULL, nv40_extensions, GL_FALSE ); | |||
driInitExtensions( NULL, nv50_extensions, GL_FALSE ); | |||
} | |||
return (void *) psp; | |||
} | |||
@@ -1,61 +0,0 @@ | |||
/************************************************************************** | |||
Copyright 2006 Stephane Marchesin | |||
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 | |||
ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 __NOUVEAU_SCREEN_H__ | |||
#define __NOUVEAU_SCREEN_H__ | |||
#include "xmlconfig.h" | |||
#include "nouveau_dri.h" | |||
#include "nouveau_card.h" | |||
typedef struct { | |||
nouveau_card* card; | |||
uint32_t bus_type; | |||
uint32_t agp_mode; | |||
GLint fbFormat; | |||
GLuint frontOffset; | |||
GLuint frontPitch; | |||
GLuint backOffset; | |||
GLuint backPitch; | |||
GLuint depthOffset; | |||
GLuint depthPitch; | |||
GLuint spanOffset; | |||
__DRIscreenPrivate *driScreen; | |||
unsigned int sarea_priv_offset; | |||
/* Configuration cache with default values for all contexts */ | |||
driOptionCache optionCache; | |||
} nouveauScreenRec, *nouveauScreenPtr; | |||
#endif /* __NOUVEAU_SCREEN_H__ */ |