2 * Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
24 * Trident CyberBladeXP driver.
27 #include "trident_dri.h"
28 #include "trident_context.h"
29 #include "trident_lock.h"
31 #include "swrast/swrast.h"
32 #include "swrast_setup/swrast_setup.h"
36 #include "tnl/t_pipeline.h"
38 #include "main/context.h"
39 #include "main/simple_list.h"
40 #include "main/matrix.h"
41 #include "main/extensions.h"
42 #include "main/framebuffer.h"
43 #include "main/renderbuffer.h"
44 #if defined(USE_X86_ASM)
45 #include "x86/common_x86_asm.h"
47 #include "main/simple_list.h"
49 #include "drirenderbuffer.h"
51 #include "drivers/common/driverfuncs.h"
55 static const struct tnl_pipeline_stage
*trident_pipeline
[] = {
56 &_tnl_vertex_transform_stage
,
57 &_tnl_normal_transform_stage
,
60 &_tnl_texture_transform_stage
,
67 tridentCreateContext( const __GLcontextModes
*glVisual
,
68 __DRIcontextPrivate
*driContextPriv
,
69 void *sharedContextPrivate
)
71 GLcontext
*ctx
, *shareCtx
;
72 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
73 tridentContextPtr tmesa
;
74 tridentScreenPtr tridentscrn
;
75 struct dd_function_table functions
;
77 drm_trident_sarea_t
*saPriv
=(drm_trident_sarea_t
*)(((char*)sPriv
->pSAREA
)+
78 sizeof(XF86DRISAREARec
));
81 tmesa
= (tridentContextPtr
) CALLOC( sizeof(*tmesa
) );
82 if ( !tmesa
) return GL_FALSE
;
84 /* Allocate the Mesa context */
85 if (sharedContextPrivate
)
86 shareCtx
= ((tridentContextPtr
) sharedContextPrivate
)->glCtx
;
90 _mesa_init_driver_functions(&functions
);
93 _mesa_create_context(glVisual
, shareCtx
, &functions
, (void *)tmesa
);
100 tmesa
->driContext
= driContextPriv
;
101 tmesa
->driScreen
= sPriv
;
102 tmesa
->driDrawable
= NULL
; /* Set by XMesaMakeCurrent */
104 tmesa
->hHWContext
= driContextPriv
->hHWContext
;
105 tmesa
->driHwLock
= (drmLock
*)&sPriv
->pSAREA
->lock
;
106 tmesa
->driFd
= sPriv
->fd
;
108 tmesa
->sarea
= saPriv
;
111 tridentscrn
= tmesa
->tridentScreen
= (tridentScreenPtr
)(sPriv
->private);
115 ctx
->Const
.MaxTextureLevels
= 13; /* 4K by 4K? Is that right? */
116 ctx
->Const
.MaxTextureUnits
= 1; /* Permedia 3 */
118 ctx
->Const
.MinLineWidth
= 0.0;
119 ctx
->Const
.MaxLineWidth
= 255.0;
121 ctx
->Const
.MinLineWidthAA
= 0.0;
122 ctx
->Const
.MaxLineWidthAA
= 65536.0;
124 ctx
->Const
.MinPointSize
= 0.0;
125 ctx
->Const
.MaxPointSize
= 255.0;
127 ctx
->Const
.MinPointSizeAA
= 0.5; /* 4x4 quality mode */
128 ctx
->Const
.MaxPointSizeAA
= 16.0;
129 ctx
->Const
.PointSizeGranularity
= 0.25;
132 tmesa
->texHeap
= mmInit( 0, tmesa
->tridentScreen
->textureSize
);
134 make_empty_list(&tmesa
->TexObjList
);
135 make_empty_list(&tmesa
->SwappedOut
);
137 tmesa
->CurrentTexObj
[0] = 0;
138 tmesa
->CurrentTexObj
[1] = 0; /* Permedia 3, second texture */
140 tmesa
->RenderIndex
= ~0;
143 /* Initialize the software rasterizer and helper modules.
145 _swrast_CreateContext( ctx
);
146 _vbo_CreateContext( ctx
);
147 _tnl_CreateContext( ctx
);
148 _swsetup_CreateContext( ctx
);
150 /* Install the customized pipeline:
152 _tnl_destroy_pipeline( ctx
);
153 _tnl_install_pipeline( ctx
, trident_pipeline
);
155 /* Configure swrast to match hardware characteristics:
157 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
158 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
160 tridentInitVB( ctx
);
161 tridentDDInitExtensions( ctx
);
162 tridentDDInitDriverFuncs( ctx
);
163 tridentDDInitStateFuncs( ctx
);
165 tridentDDInitSpanFuncs( ctx
);
166 tridentDDInitTextureFuncs( ctx
);
168 tridentDDInitTriFuncs( ctx
);
169 tridentDDInitState( tmesa
);
171 driContextPriv
->driverPrivate
= (void *)tmesa
;
173 UNLOCK_HARDWARE(tmesa
);
179 tridentDestroyContext(__DRIcontextPrivate
*driContextPriv
)
181 tridentContextPtr tmesa
= (tridentContextPtr
)driContextPriv
->driverPrivate
;
184 _swsetup_DestroyContext( tmesa
->glCtx
);
185 _tnl_DestroyContext( tmesa
->glCtx
);
186 _vbo_DestroyContext( tmesa
->glCtx
);
187 _swrast_DestroyContext( tmesa
->glCtx
);
189 /* free the Mesa context */
190 tmesa
->glCtx
->DriverCtx
= NULL
;
191 _mesa_destroy_context(tmesa
->glCtx
);
194 driContextPriv
->driverPrivate
= NULL
;
200 tridentCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
201 __DRIdrawablePrivate
*driDrawPriv
,
202 const __GLcontextModes
*mesaVis
,
205 tridentScreenPtr screen
= (tridentScreenPtr
) driScrnPriv
->private;
208 return GL_FALSE
; /* not implemented */
211 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
214 driRenderbuffer
*frontRb
215 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
216 screen
->frontOffset
, screen
->frontPitch
,
219 tridentSetSpanFunctions(frontRb, mesaVis);
221 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
224 if (mesaVis
->doubleBufferMode
) {
225 driRenderbuffer
*backRb
226 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
227 screen
->backOffset
, screen
->backPitch
,
230 tridentSetSpanFunctions(backRb, mesaVis);
232 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
235 if (mesaVis
->depthBits
== 16) {
236 driRenderbuffer
*depthRb
237 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, NULL
, screen
->cpp
,
238 screen
->depthOffset
, screen
->depthPitch
,
241 tridentSetSpanFunctions(depthRb, mesaVis);
243 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
245 else if (mesaVis
->depthBits
== 24) {
246 driRenderbuffer
*depthRb
247 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, NULL
, screen
->cpp
,
248 screen
->depthOffset
, screen
->depthPitch
,
251 tridentSetSpanFunctions(depthRb, mesaVis);
253 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
257 if (mesaVis->stencilBits > 0 && !swStencil) {
258 driRenderbuffer *stencilRb
259 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT);
260 tridentSetSpanFunctions(stencilRb, mesaVis);
261 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
265 _mesa_add_soft_renderbuffers(fb
,
266 GL_FALSE
, /* color */
267 GL_FALSE
, /* depth */
268 mesaVis
->stencilBits
> 0,
269 mesaVis
->accumRedBits
> 0,
270 GL_FALSE
, /* alpha */
272 driDrawPriv
->driverPrivate
= (void *) fb
;
274 return (driDrawPriv
->driverPrivate
!= NULL
);
280 tridentDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
282 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
286 tridentSwapBuffers(__DRIdrawablePrivate
*drawablePrivate
)
288 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
290 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
291 tridentContextPtr tmesa
;
293 tmesa
= (tridentContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
295 if (ctx
->Visual
.doubleBufferMode
) {
296 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
297 tridentCopyBuffer( dPriv
);
301 /* XXX this shouldn't be an error but we can't handle it for now */
302 _mesa_problem(NULL
, "tridentSwapBuffers: drawable has no context!\n");
307 tridentMakeCurrent(__DRIcontextPrivate
*driContextPriv
,
308 __DRIdrawablePrivate
*driDrawPriv
,
309 __DRIdrawablePrivate
*driReadPriv
)
311 if (driContextPriv
) {
312 GET_CURRENT_CONTEXT(ctx
);
313 tridentContextPtr oldCtx
= ctx
? TRIDENT_CONTEXT(ctx
) : NULL
;
314 tridentContextPtr newCtx
= (tridentContextPtr
) driContextPriv
->driverPrivate
;
316 if ( newCtx
!= oldCtx
) {
320 if (newCtx
->driDrawable
!= driDrawPriv
) {
321 newCtx
->driDrawable
= driDrawPriv
;
323 tridentUpdateWindow ( newCtx
->glCtx
);
324 tridentUpdateViewportOffset( newCtx
->glCtx
);
328 newCtx
->drawOffset
= newCtx
->tridentScreen
->backOffset
;
329 newCtx
->drawPitch
= newCtx
->tridentScreen
->backPitch
;
331 _mesa_make_current( newCtx
->glCtx
,
332 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
333 (GLframebuffer
*) driReadPriv
->driverPrivate
);
335 if (!newCtx
->glCtx
->Viewport
.Width
) {
336 _mesa_set_viewport(newCtx
->glCtx
, 0, 0,
337 driDrawPriv
->w
, driDrawPriv
->h
);
340 _mesa_make_current( NULL
, NULL
, NULL
);
347 tridentUnbindContext( __DRIcontextPrivate
*driContextPriv
)
353 static tridentScreenPtr
354 tridentCreateScreen( __DRIscreenPrivate
*sPriv
)
356 TRIDENTDRIPtr tDRIPriv
= (TRIDENTDRIPtr
)sPriv
->pDevPriv
;
357 tridentScreenPtr tridentScreen
;
359 if (sPriv
->devPrivSize
!= sizeof(TRIDENTDRIRec
)) {
360 fprintf(stderr
,"\nERROR! sizeof(TRIDENTDRIRec) does not match passed size from device driver\n");
364 /* Allocate the private area */
365 tridentScreen
= (tridentScreenPtr
) CALLOC( sizeof(*tridentScreen
) );
366 if ( !tridentScreen
) return NULL
;
368 tridentScreen
->driScreen
= sPriv
;
370 tridentScreen
->frontOffset
= tDRIPriv
->frontOffset
;
371 tridentScreen
->backOffset
= tDRIPriv
->backOffset
;
372 tridentScreen
->depthOffset
= tDRIPriv
->depthOffset
;
373 tridentScreen
->frontPitch
= tDRIPriv
->frontPitch
;
374 tridentScreen
->backPitch
= tDRIPriv
->backPitch
;
375 tridentScreen
->depthPitch
= tDRIPriv
->depthPitch
;
376 tridentScreen
->width
= tDRIPriv
->width
;
377 tridentScreen
->height
= tDRIPriv
->height
;
379 printf("%d %d\n",tridentScreen
->width
,tridentScreen
->height
);
380 printf("%d %d\n",tridentScreen
->frontPitch
,tridentScreen
->backPitch
);
381 printf("offset 0x%x 0x%x\n",tridentScreen
->backOffset
,tridentScreen
->depthOffset
);
383 tridentScreen
->mmio
.handle
= tDRIPriv
->regs
;
384 tridentScreen
->mmio
.size
= 0x20000;
386 if (drmMap(sPriv
->fd
,
387 tridentScreen
->mmio
.handle
, tridentScreen
->mmio
.size
,
388 (drmAddressPtr
)&tridentScreen
->mmio
.map
)) {
392 printf("MAPPED at %p\n", tridentScreen
->mmio
.map
);
394 return tridentScreen
;
397 /* Destroy the device specific screen private data struct.
400 tridentDestroyScreen( __DRIscreenPrivate
*sPriv
)
402 tridentScreenPtr tridentScreen
= (tridentScreenPtr
)sPriv
->private;
408 tridentInitDriver(__DRIscreenPrivate
*sPriv
)
410 sPriv
->private = (void *) tridentCreateScreen( sPriv
);
412 if (!sPriv
->private) {
413 tridentDestroyScreen( sPriv
);
421 * This is the driver specific part of the createNewScreen entry point.
423 * \todo maybe fold this into intelInitDriver
425 * \return the __GLcontextModes supported by this driver
427 const __DRIconfig
**tridentInitScreen(__DRIscreenPrivate
*psp
)
429 static const __DRIversion ddx_expected
= { 4, 0, 0 };
430 static const __DRIversion dri_expected
= { 3, 1, 0 };
431 static const __DRIversion drm_expected
= { 1, 0, 0 };
433 if ( ! driCheckDriDdxDrmVersions2( "Trident",
434 &psp
->dri_version
, & dri_expected
,
435 &psp
->ddx_version
, & ddx_expected
,
436 &psp
->drm_version
, & drm_expected
) )
439 if (!tridentInitDriver(psp
))
442 /* Wait... what? This driver doesn't report any modes... */
444 TRIDENTDRIPtr dri_priv
= (TRIDENTDRIPtr
) psp
->pDevPriv
;
445 *driver_modes
= tridentFillInModes( dri_priv
->bytesPerPixel
* 8,
452 const struct __DriverAPIRec driDriverAPI
= {
454 tridentDestroyScreen
,
455 tridentCreateContext
,
456 tridentDestroyContext
,
458 tridentDestroyBuffer
,
461 tridentUnbindContext
,