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"
33 #include "array_cache/acache.h"
36 #include "tnl/t_pipeline.h"
39 #include "simple_list.h"
41 #include "extensions.h"
42 #include "framebuffer.h"
43 #include "renderbuffer.h"
44 #if defined(USE_X86_ASM)
45 #include "x86/common_x86_asm.h"
47 #include "simple_list.h"
49 #include "drirenderbuffer.h"
51 #include "drivers/common/driverfuncs.h"
54 static const struct tnl_pipeline_stage
*trident_pipeline
[] = {
55 &_tnl_vertex_transform_stage
,
56 &_tnl_normal_transform_stage
,
59 &_tnl_texture_transform_stage
,
65 GLboolean
tridentCreateContext( const __GLcontextModes
*glVisual
,
66 __DRIcontextPrivate
*driContextPriv
,
67 void *sharedContextPrivate
)
69 GLcontext
*ctx
, *shareCtx
;
70 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
71 tridentContextPtr tmesa
;
72 tridentScreenPtr tridentscrn
;
73 struct dd_function_table functions
;
75 drm_trident_sarea_t
*saPriv
=(drm_trident_sarea_t
*)(((char*)sPriv
->pSAREA
)+
76 sizeof(XF86DRISAREARec
));
79 tmesa
= (tridentContextPtr
) CALLOC( sizeof(*tmesa
) );
80 if ( !tmesa
) return GL_FALSE
;
82 /* Allocate the Mesa context */
83 if (sharedContextPrivate
)
84 shareCtx
= ((tridentContextPtr
) sharedContextPrivate
)->glCtx
;
88 _mesa_init_driver_functions(&functions
);
91 _mesa_create_context(glVisual
, shareCtx
, &functions
, (void *)tmesa
);
98 tmesa
->driContext
= driContextPriv
;
99 tmesa
->driScreen
= sPriv
;
100 tmesa
->driDrawable
= NULL
; /* Set by XMesaMakeCurrent */
102 tmesa
->hHWContext
= driContextPriv
->hHWContext
;
103 tmesa
->driHwLock
= (drmLock
*)&sPriv
->pSAREA
->lock
;
104 tmesa
->driFd
= sPriv
->fd
;
106 tmesa
->sarea
= saPriv
;
109 tridentscrn
= tmesa
->tridentScreen
= (tridentScreenPtr
)(sPriv
->private);
113 ctx
->Const
.MaxTextureLevels
= 13; /* 4K by 4K? Is that right? */
114 ctx
->Const
.MaxTextureUnits
= 1; /* Permedia 3 */
116 ctx
->Const
.MinLineWidth
= 0.0;
117 ctx
->Const
.MaxLineWidth
= 255.0;
119 ctx
->Const
.MinLineWidthAA
= 0.0;
120 ctx
->Const
.MaxLineWidthAA
= 65536.0;
122 ctx
->Const
.MinPointSize
= 0.0;
123 ctx
->Const
.MaxPointSize
= 255.0;
125 ctx
->Const
.MinPointSizeAA
= 0.5; /* 4x4 quality mode */
126 ctx
->Const
.MaxPointSizeAA
= 16.0;
127 ctx
->Const
.PointSizeGranularity
= 0.25;
130 tmesa
->texHeap
= mmInit( 0, tmesa
->tridentScreen
->textureSize
);
132 make_empty_list(&tmesa
->TexObjList
);
133 make_empty_list(&tmesa
->SwappedOut
);
135 tmesa
->CurrentTexObj
[0] = 0;
136 tmesa
->CurrentTexObj
[1] = 0; /* Permedia 3, second texture */
138 tmesa
->RenderIndex
= ~0;
141 /* Initialize the software rasterizer and helper modules.
143 _swrast_CreateContext( ctx
);
144 _ac_CreateContext( ctx
);
145 _tnl_CreateContext( ctx
);
146 _swsetup_CreateContext( ctx
);
148 /* Install the customized pipeline:
150 _tnl_destroy_pipeline( ctx
);
151 _tnl_install_pipeline( ctx
, trident_pipeline
);
153 /* Configure swrast to match hardware characteristics:
155 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
156 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
158 tridentInitVB( ctx
);
159 tridentDDInitExtensions( ctx
);
160 tridentDDInitDriverFuncs( ctx
);
161 tridentDDInitStateFuncs( ctx
);
163 tridentDDInitSpanFuncs( ctx
);
164 tridentDDInitTextureFuncs( ctx
);
166 tridentDDInitTriFuncs( ctx
);
167 tridentDDInitState( tmesa
);
169 driContextPriv
->driverPrivate
= (void *)tmesa
;
171 UNLOCK_HARDWARE(tmesa
);
177 tridentDestroyContext(__DRIcontextPrivate
*driContextPriv
)
179 tridentContextPtr tmesa
= (tridentContextPtr
)driContextPriv
->driverPrivate
;
182 _swsetup_DestroyContext( tmesa
->glCtx
);
183 _tnl_DestroyContext( tmesa
->glCtx
);
184 _ac_DestroyContext( tmesa
->glCtx
);
185 _swrast_DestroyContext( tmesa
->glCtx
);
187 /* free the Mesa context */
188 tmesa
->glCtx
->DriverCtx
= NULL
;
189 _mesa_destroy_context(tmesa
->glCtx
);
192 driContextPriv
->driverPrivate
= NULL
;
198 tridentCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
199 __DRIdrawablePrivate
*driDrawPriv
,
200 const __GLcontextModes
*mesaVis
,
203 tridentScreenPtr screen
= (tridentScreenPtr
) driScrnPriv
->private;
206 return GL_FALSE
; /* not implemented */
210 driDrawPriv
->driverPrivate
= (void *)
211 _mesa_create_framebuffer(mesaVis
,
212 GL_FALSE
, /* software depth buffer? */
213 mesaVis
->stencilBits
> 0,
214 mesaVis
->accumRedBits
> 0,
215 mesaVis
->alphaBits
> 0
218 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
221 driRenderbuffer
*frontRb
222 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
223 screen
->frontOffset
, screen
->frontPitch
);
225 tridentSetSpanFunctions(frontRb, mesaVis);
227 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
230 if (mesaVis
->doubleBufferMode
) {
231 driRenderbuffer
*backRb
232 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
233 screen
->backOffset
, screen
->backPitch
);
235 tridentSetSpanFunctions(backRb, mesaVis);
237 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
240 if (mesaVis
->depthBits
== 16) {
241 driRenderbuffer
*depthRb
242 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, screen
->cpp
,
243 screen
->depthOffset
, screen
->depthPitch
);
245 tridentSetSpanFunctions(depthRb, mesaVis);
247 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
249 else if (mesaVis
->depthBits
== 24) {
250 driRenderbuffer
*depthRb
251 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, screen
->cpp
,
252 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_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
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 tridentScreenPtr
tridentCreateScreen( __DRIscreenPrivate
*sPriv
)
358 TRIDENTDRIPtr tDRIPriv
= (TRIDENTDRIPtr
)sPriv
->pDevPriv
;
359 tridentScreenPtr tridentScreen
;
362 /* Allocate the private area */
363 tridentScreen
= (tridentScreenPtr
) CALLOC( sizeof(*tridentScreen
) );
364 if ( !tridentScreen
) return NULL
;
366 tridentScreen
->driScreen
= sPriv
;
368 tridentScreen
->frontOffset
= tDRIPriv
->frontOffset
;
369 tridentScreen
->backOffset
= tDRIPriv
->backOffset
;
370 tridentScreen
->depthOffset
= tDRIPriv
->depthOffset
;
371 tridentScreen
->frontPitch
= tDRIPriv
->frontPitch
;
372 tridentScreen
->backPitch
= tDRIPriv
->backPitch
;
373 tridentScreen
->depthPitch
= tDRIPriv
->depthPitch
;
374 tridentScreen
->width
= tDRIPriv
->width
;
375 tridentScreen
->height
= tDRIPriv
->height
;
377 printf("%d %d\n",tridentScreen
->width
,tridentScreen
->height
);
378 printf("%d %d\n",tridentScreen
->frontPitch
,tridentScreen
->backPitch
);
379 printf("offset 0x%x 0x%x\n",tridentScreen
->backOffset
,tridentScreen
->depthOffset
);
381 tridentScreen
->mmio
.handle
= tDRIPriv
->regs
;
382 tridentScreen
->mmio
.size
= 0x20000;
384 if (drmMap(sPriv
->fd
,
385 tridentScreen
->mmio
.handle
, tridentScreen
->mmio
.size
,
386 (drmAddressPtr
)&tridentScreen
->mmio
.map
)) {
390 printf("MAPPED at %p\n", tridentScreen
->mmio
.map
);
392 return tridentScreen
;
395 /* Destroy the device specific screen private data struct.
397 void tridentDestroyScreen( __DRIscreenPrivate
*sPriv
)
399 tridentScreenPtr tridentScreen
= (tridentScreenPtr
)sPriv
->private;
404 tridentInitDriver(__DRIscreenPrivate
*sPriv
)
406 sPriv
->private = (void *) tridentCreateScreen( sPriv
);
408 if (!sPriv
->private) {
409 tridentDestroyScreen( sPriv
);
416 static struct __DriverAPIRec tridentAPI
= {
418 tridentDestroyScreen
,
419 tridentCreateContext
,
420 tridentDestroyContext
,
422 tridentDestroyBuffer
,
425 tridentUnbindContext
,
429 PUBLIC
void *__driCreateNewScreen_20050725( __DRInativeDisplay
*dpy
, int scrn
,
431 const __GLcontextModes
* modes
,
432 const __DRIversion
* ddx_version
,
433 const __DRIversion
* dri_version
,
434 const __DRIversion
* drm_version
,
435 const __DRIframebuffer
* frame_buffer
,
436 drmAddress pSAREA
, int fd
,
437 int internal_api_version
,
438 const __DRIinterfaceMethods
* interface
,
439 __GLcontextModes
** driver_modes
)
441 __DRIscreenPrivate
*psp
;
442 static const __DRIversion ddx_expected
= { 4, 0, 0 };
443 static const __DRIversion dri_expected
= { 3, 1, 0 };
444 static const __DRIversion drm_expected
= { 1, 0, 0 };
446 dri_interface
= interface
;
448 if ( ! driCheckDriDdxDrmVersions2( "Trident",
449 dri_version
, & dri_expected
,
450 ddx_version
, & ddx_expected
,
451 drm_version
, & drm_expected
) ) {
455 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
456 ddx_version
, dri_version
, drm_version
,
457 frame_buffer
, pSAREA
, fd
,
458 internal_api_version
, &tridentAPI
);
462 TRIDENTDRIPtr dri_priv
= (TRIDENTDRIPtr
) psp
->pDevPriv
;
463 *driver_modes
= tridentFillInModes( dri_priv
->bytesPerPixel
* 8,