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 #include "main/viewport.h"
45 #if defined(USE_X86_ASM)
46 #include "x86/common_x86_asm.h"
48 #include "main/simple_list.h"
50 #include "drirenderbuffer.h"
52 #include "drivers/common/driverfuncs.h"
56 static const struct tnl_pipeline_stage
*trident_pipeline
[] = {
57 &_tnl_vertex_transform_stage
,
58 &_tnl_normal_transform_stage
,
61 &_tnl_texture_transform_stage
,
68 tridentCreateContext( const __GLcontextModes
*glVisual
,
69 __DRIcontextPrivate
*driContextPriv
,
70 void *sharedContextPrivate
)
72 GLcontext
*ctx
, *shareCtx
;
73 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
74 tridentContextPtr tmesa
;
75 tridentScreenPtr tridentscrn
;
76 struct dd_function_table functions
;
78 drm_trident_sarea_t
*saPriv
=(drm_trident_sarea_t
*)(((char*)sPriv
->pSAREA
)+
79 sizeof(XF86DRISAREARec
));
82 tmesa
= (tridentContextPtr
) CALLOC( sizeof(*tmesa
) );
83 if ( !tmesa
) return GL_FALSE
;
85 /* Allocate the Mesa context */
86 if (sharedContextPrivate
)
87 shareCtx
= ((tridentContextPtr
) sharedContextPrivate
)->glCtx
;
91 _mesa_init_driver_functions(&functions
);
94 _mesa_create_context(glVisual
, shareCtx
, &functions
, (void *)tmesa
);
101 tmesa
->driContext
= driContextPriv
;
102 tmesa
->driScreen
= sPriv
;
103 tmesa
->driDrawable
= NULL
; /* Set by XMesaMakeCurrent */
105 tmesa
->hHWContext
= driContextPriv
->hHWContext
;
106 tmesa
->driHwLock
= (drmLock
*)&sPriv
->pSAREA
->lock
;
107 tmesa
->driFd
= sPriv
->fd
;
109 tmesa
->sarea
= saPriv
;
112 tridentscrn
= tmesa
->tridentScreen
= (tridentScreenPtr
)(sPriv
->private);
116 ctx
->Const
.MaxTextureLevels
= 13; /* 4K by 4K? Is that right? */
117 ctx
->Const
.MaxTextureUnits
= 1; /* Permedia 3 */
119 ctx
->Const
.MinLineWidth
= 0.0;
120 ctx
->Const
.MaxLineWidth
= 255.0;
122 ctx
->Const
.MinLineWidthAA
= 0.0;
123 ctx
->Const
.MaxLineWidthAA
= 65536.0;
125 ctx
->Const
.MinPointSize
= 0.0;
126 ctx
->Const
.MaxPointSize
= 255.0;
128 ctx
->Const
.MinPointSizeAA
= 0.5; /* 4x4 quality mode */
129 ctx
->Const
.MaxPointSizeAA
= 16.0;
130 ctx
->Const
.PointSizeGranularity
= 0.25;
132 ctx
->Const
.MaxDrawBuffers
= 1;
135 tmesa
->texHeap
= mmInit( 0, tmesa
->tridentScreen
->textureSize
);
137 make_empty_list(&tmesa
->TexObjList
);
138 make_empty_list(&tmesa
->SwappedOut
);
140 tmesa
->CurrentTexObj
[0] = 0;
141 tmesa
->CurrentTexObj
[1] = 0; /* Permedia 3, second texture */
143 tmesa
->RenderIndex
= ~0;
146 /* Initialize the software rasterizer and helper modules.
148 _swrast_CreateContext( ctx
);
149 _vbo_CreateContext( ctx
);
150 _tnl_CreateContext( ctx
);
151 _swsetup_CreateContext( ctx
);
153 /* Install the customized pipeline:
155 _tnl_destroy_pipeline( ctx
);
156 _tnl_install_pipeline( ctx
, trident_pipeline
);
158 /* Configure swrast to match hardware characteristics:
160 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
161 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
163 tridentInitVB( ctx
);
164 tridentDDInitExtensions( ctx
);
165 tridentDDInitDriverFuncs( ctx
);
166 tridentDDInitStateFuncs( ctx
);
168 tridentDDInitSpanFuncs( ctx
);
169 tridentDDInitTextureFuncs( ctx
);
171 tridentDDInitTriFuncs( ctx
);
172 tridentDDInitState( tmesa
);
174 driContextPriv
->driverPrivate
= (void *)tmesa
;
176 UNLOCK_HARDWARE(tmesa
);
182 tridentDestroyContext(__DRIcontextPrivate
*driContextPriv
)
184 tridentContextPtr tmesa
= (tridentContextPtr
)driContextPriv
->driverPrivate
;
187 _swsetup_DestroyContext( tmesa
->glCtx
);
188 _tnl_DestroyContext( tmesa
->glCtx
);
189 _vbo_DestroyContext( tmesa
->glCtx
);
190 _swrast_DestroyContext( tmesa
->glCtx
);
192 /* free the Mesa context */
193 tmesa
->glCtx
->DriverCtx
= NULL
;
194 _mesa_destroy_context(tmesa
->glCtx
);
197 driContextPriv
->driverPrivate
= NULL
;
203 tridentCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
204 __DRIdrawablePrivate
*driDrawPriv
,
205 const __GLcontextModes
*mesaVis
,
208 tridentScreenPtr screen
= (tridentScreenPtr
) driScrnPriv
->private;
211 return GL_FALSE
; /* not implemented */
214 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
217 driRenderbuffer
*frontRb
218 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
219 screen
->frontOffset
, screen
->frontPitch
,
222 tridentSetSpanFunctions(frontRb, mesaVis);
224 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
227 if (mesaVis
->doubleBufferMode
) {
228 driRenderbuffer
*backRb
229 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
230 screen
->backOffset
, screen
->backPitch
,
233 tridentSetSpanFunctions(backRb, mesaVis);
235 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
238 if (mesaVis
->depthBits
== 16) {
239 driRenderbuffer
*depthRb
240 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, NULL
, screen
->cpp
,
241 screen
->depthOffset
, screen
->depthPitch
,
244 tridentSetSpanFunctions(depthRb, mesaVis);
246 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
248 else if (mesaVis
->depthBits
== 24) {
249 driRenderbuffer
*depthRb
250 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, NULL
, screen
->cpp
,
251 screen
->depthOffset
, screen
->depthPitch
,
254 tridentSetSpanFunctions(depthRb, mesaVis);
256 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
260 if (mesaVis->stencilBits > 0 && !swStencil) {
261 driRenderbuffer *stencilRb
262 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT);
263 tridentSetSpanFunctions(stencilRb, mesaVis);
264 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
268 _mesa_add_soft_renderbuffers(fb
,
269 GL_FALSE
, /* color */
270 GL_FALSE
, /* depth */
271 mesaVis
->stencilBits
> 0,
272 mesaVis
->accumRedBits
> 0,
273 GL_FALSE
, /* alpha */
275 driDrawPriv
->driverPrivate
= (void *) fb
;
277 return (driDrawPriv
->driverPrivate
!= NULL
);
283 tridentDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
285 _mesa_reference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)), NULL
);
289 tridentSwapBuffers(__DRIdrawablePrivate
*drawablePrivate
)
291 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
293 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
294 tridentContextPtr tmesa
;
296 tmesa
= (tridentContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
298 if (ctx
->Visual
.doubleBufferMode
) {
299 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
300 tridentCopyBuffer( dPriv
);
304 /* XXX this shouldn't be an error but we can't handle it for now */
305 _mesa_problem(NULL
, "tridentSwapBuffers: drawable has no context!\n");
310 tridentMakeCurrent(__DRIcontextPrivate
*driContextPriv
,
311 __DRIdrawablePrivate
*driDrawPriv
,
312 __DRIdrawablePrivate
*driReadPriv
)
314 if (driContextPriv
) {
315 GET_CURRENT_CONTEXT(ctx
);
316 tridentContextPtr oldCtx
= ctx
? TRIDENT_CONTEXT(ctx
) : NULL
;
317 tridentContextPtr newCtx
= (tridentContextPtr
) driContextPriv
->driverPrivate
;
319 if ( newCtx
!= oldCtx
) {
323 if (newCtx
->driDrawable
!= driDrawPriv
) {
324 newCtx
->driDrawable
= driDrawPriv
;
326 tridentUpdateWindow ( newCtx
->glCtx
);
327 tridentUpdateViewportOffset( newCtx
->glCtx
);
331 newCtx
->drawOffset
= newCtx
->tridentScreen
->backOffset
;
332 newCtx
->drawPitch
= newCtx
->tridentScreen
->backPitch
;
334 _mesa_make_current( newCtx
->glCtx
,
335 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
336 (GLframebuffer
*) driReadPriv
->driverPrivate
);
338 if (!newCtx
->glCtx
->Viewport
.Width
) {
339 _mesa_set_viewport(newCtx
->glCtx
, 0, 0,
340 driDrawPriv
->w
, driDrawPriv
->h
);
343 _mesa_make_current( NULL
, NULL
, NULL
);
350 tridentUnbindContext( __DRIcontextPrivate
*driContextPriv
)
356 static tridentScreenPtr
357 tridentCreateScreen( __DRIscreenPrivate
*sPriv
)
359 TRIDENTDRIPtr tDRIPriv
= (TRIDENTDRIPtr
)sPriv
->pDevPriv
;
360 tridentScreenPtr tridentScreen
;
362 if (sPriv
->devPrivSize
!= sizeof(TRIDENTDRIRec
)) {
363 fprintf(stderr
,"\nERROR! sizeof(TRIDENTDRIRec) does not match passed size from device driver\n");
367 /* Allocate the private area */
368 tridentScreen
= (tridentScreenPtr
) CALLOC( sizeof(*tridentScreen
) );
369 if ( !tridentScreen
) return NULL
;
371 tridentScreen
->driScreen
= sPriv
;
373 tridentScreen
->frontOffset
= tDRIPriv
->frontOffset
;
374 tridentScreen
->backOffset
= tDRIPriv
->backOffset
;
375 tridentScreen
->depthOffset
= tDRIPriv
->depthOffset
;
376 tridentScreen
->frontPitch
= tDRIPriv
->frontPitch
;
377 tridentScreen
->backPitch
= tDRIPriv
->backPitch
;
378 tridentScreen
->depthPitch
= tDRIPriv
->depthPitch
;
379 tridentScreen
->width
= tDRIPriv
->width
;
380 tridentScreen
->height
= tDRIPriv
->height
;
382 printf("%d %d\n",tridentScreen
->width
,tridentScreen
->height
);
383 printf("%d %d\n",tridentScreen
->frontPitch
,tridentScreen
->backPitch
);
384 printf("offset 0x%x 0x%x\n",tridentScreen
->backOffset
,tridentScreen
->depthOffset
);
386 tridentScreen
->mmio
.handle
= tDRIPriv
->regs
;
387 tridentScreen
->mmio
.size
= 0x20000;
389 if (drmMap(sPriv
->fd
,
390 tridentScreen
->mmio
.handle
, tridentScreen
->mmio
.size
,
391 (drmAddressPtr
)&tridentScreen
->mmio
.map
)) {
395 printf("MAPPED at %p\n", tridentScreen
->mmio
.map
);
397 return tridentScreen
;
400 /* Destroy the device specific screen private data struct.
403 tridentDestroyScreen( __DRIscreenPrivate
*sPriv
)
405 tridentScreenPtr tridentScreen
= (tridentScreenPtr
)sPriv
->private;
411 tridentInitDriver(__DRIscreenPrivate
*sPriv
)
413 sPriv
->private = (void *) tridentCreateScreen( sPriv
);
415 if (!sPriv
->private) {
416 tridentDestroyScreen( sPriv
);
424 * This is the driver specific part of the createNewScreen entry point.
426 * \todo maybe fold this into intelInitDriver
428 * \return the __GLcontextModes supported by this driver
430 const __DRIconfig
**tridentInitScreen(__DRIscreenPrivate
*psp
)
432 static const __DRIversion ddx_expected
= { 4, 0, 0 };
433 static const __DRIversion dri_expected
= { 3, 1, 0 };
434 static const __DRIversion drm_expected
= { 1, 0, 0 };
436 if ( ! driCheckDriDdxDrmVersions2( "Trident",
437 &psp
->dri_version
, & dri_expected
,
438 &psp
->ddx_version
, & ddx_expected
,
439 &psp
->drm_version
, & drm_expected
) )
442 if (!tridentInitDriver(psp
))
445 /* Wait... what? This driver doesn't report any modes... */
447 TRIDENTDRIPtr dri_priv
= (TRIDENTDRIPtr
) psp
->pDevPriv
;
448 *driver_modes
= tridentFillInModes( dri_priv
->bytesPerPixel
* 8,
455 const struct __DriverAPIRec driDriverAPI
= {
457 tridentDestroyScreen
,
458 tridentCreateContext
,
459 tridentDestroyContext
,
461 tridentDestroyBuffer
,
464 tridentUnbindContext
,