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;
131 ctx
->Const
.MaxDrawBuffers
= 1;
134 tmesa
->texHeap
= mmInit( 0, tmesa
->tridentScreen
->textureSize
);
136 make_empty_list(&tmesa
->TexObjList
);
137 make_empty_list(&tmesa
->SwappedOut
);
139 tmesa
->CurrentTexObj
[0] = 0;
140 tmesa
->CurrentTexObj
[1] = 0; /* Permedia 3, second texture */
142 tmesa
->RenderIndex
= ~0;
145 /* Initialize the software rasterizer and helper modules.
147 _swrast_CreateContext( ctx
);
148 _vbo_CreateContext( ctx
);
149 _tnl_CreateContext( ctx
);
150 _swsetup_CreateContext( ctx
);
152 /* Install the customized pipeline:
154 _tnl_destroy_pipeline( ctx
);
155 _tnl_install_pipeline( ctx
, trident_pipeline
);
157 /* Configure swrast to match hardware characteristics:
159 _swrast_allow_pixel_fog( ctx
, GL_FALSE
);
160 _swrast_allow_vertex_fog( ctx
, GL_TRUE
);
162 tridentInitVB( ctx
);
163 tridentDDInitExtensions( ctx
);
164 tridentDDInitDriverFuncs( ctx
);
165 tridentDDInitStateFuncs( ctx
);
167 tridentDDInitSpanFuncs( ctx
);
168 tridentDDInitTextureFuncs( ctx
);
170 tridentDDInitTriFuncs( ctx
);
171 tridentDDInitState( tmesa
);
173 driContextPriv
->driverPrivate
= (void *)tmesa
;
175 UNLOCK_HARDWARE(tmesa
);
181 tridentDestroyContext(__DRIcontextPrivate
*driContextPriv
)
183 tridentContextPtr tmesa
= (tridentContextPtr
)driContextPriv
->driverPrivate
;
186 _swsetup_DestroyContext( tmesa
->glCtx
);
187 _tnl_DestroyContext( tmesa
->glCtx
);
188 _vbo_DestroyContext( tmesa
->glCtx
);
189 _swrast_DestroyContext( tmesa
->glCtx
);
191 /* free the Mesa context */
192 tmesa
->glCtx
->DriverCtx
= NULL
;
193 _mesa_destroy_context(tmesa
->glCtx
);
196 driContextPriv
->driverPrivate
= NULL
;
202 tridentCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
203 __DRIdrawablePrivate
*driDrawPriv
,
204 const __GLcontextModes
*mesaVis
,
207 tridentScreenPtr screen
= (tridentScreenPtr
) driScrnPriv
->private;
210 return GL_FALSE
; /* not implemented */
213 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
216 driRenderbuffer
*frontRb
217 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
218 screen
->frontOffset
, screen
->frontPitch
,
221 tridentSetSpanFunctions(frontRb, mesaVis);
223 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
226 if (mesaVis
->doubleBufferMode
) {
227 driRenderbuffer
*backRb
228 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
229 screen
->backOffset
, screen
->backPitch
,
232 tridentSetSpanFunctions(backRb, mesaVis);
234 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
237 if (mesaVis
->depthBits
== 16) {
238 driRenderbuffer
*depthRb
239 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, NULL
, screen
->cpp
,
240 screen
->depthOffset
, screen
->depthPitch
,
243 tridentSetSpanFunctions(depthRb, mesaVis);
245 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
247 else if (mesaVis
->depthBits
== 24) {
248 driRenderbuffer
*depthRb
249 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, NULL
, screen
->cpp
,
250 screen
->depthOffset
, screen
->depthPitch
,
253 tridentSetSpanFunctions(depthRb, mesaVis);
255 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
259 if (mesaVis->stencilBits > 0 && !swStencil) {
260 driRenderbuffer *stencilRb
261 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT);
262 tridentSetSpanFunctions(stencilRb, mesaVis);
263 _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
267 _mesa_add_soft_renderbuffers(fb
,
268 GL_FALSE
, /* color */
269 GL_FALSE
, /* depth */
270 mesaVis
->stencilBits
> 0,
271 mesaVis
->accumRedBits
> 0,
272 GL_FALSE
, /* alpha */
274 driDrawPriv
->driverPrivate
= (void *) fb
;
276 return (driDrawPriv
->driverPrivate
!= NULL
);
282 tridentDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
284 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
288 tridentSwapBuffers(__DRIdrawablePrivate
*drawablePrivate
)
290 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
292 if (dPriv
->driContextPriv
&& dPriv
->driContextPriv
->driverPrivate
) {
293 tridentContextPtr tmesa
;
295 tmesa
= (tridentContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
297 if (ctx
->Visual
.doubleBufferMode
) {
298 _mesa_notifySwapBuffers( ctx
); /* flush pending rendering comands */
299 tridentCopyBuffer( dPriv
);
303 /* XXX this shouldn't be an error but we can't handle it for now */
304 _mesa_problem(NULL
, "tridentSwapBuffers: drawable has no context!\n");
309 tridentMakeCurrent(__DRIcontextPrivate
*driContextPriv
,
310 __DRIdrawablePrivate
*driDrawPriv
,
311 __DRIdrawablePrivate
*driReadPriv
)
313 if (driContextPriv
) {
314 GET_CURRENT_CONTEXT(ctx
);
315 tridentContextPtr oldCtx
= ctx
? TRIDENT_CONTEXT(ctx
) : NULL
;
316 tridentContextPtr newCtx
= (tridentContextPtr
) driContextPriv
->driverPrivate
;
318 if ( newCtx
!= oldCtx
) {
322 if (newCtx
->driDrawable
!= driDrawPriv
) {
323 newCtx
->driDrawable
= driDrawPriv
;
325 tridentUpdateWindow ( newCtx
->glCtx
);
326 tridentUpdateViewportOffset( newCtx
->glCtx
);
330 newCtx
->drawOffset
= newCtx
->tridentScreen
->backOffset
;
331 newCtx
->drawPitch
= newCtx
->tridentScreen
->backPitch
;
333 _mesa_make_current( newCtx
->glCtx
,
334 (GLframebuffer
*) driDrawPriv
->driverPrivate
,
335 (GLframebuffer
*) driReadPriv
->driverPrivate
);
337 if (!newCtx
->glCtx
->Viewport
.Width
) {
338 _mesa_set_viewport(newCtx
->glCtx
, 0, 0,
339 driDrawPriv
->w
, driDrawPriv
->h
);
342 _mesa_make_current( NULL
, NULL
, NULL
);
349 tridentUnbindContext( __DRIcontextPrivate
*driContextPriv
)
355 static tridentScreenPtr
356 tridentCreateScreen( __DRIscreenPrivate
*sPriv
)
358 TRIDENTDRIPtr tDRIPriv
= (TRIDENTDRIPtr
)sPriv
->pDevPriv
;
359 tridentScreenPtr tridentScreen
;
361 if (sPriv
->devPrivSize
!= sizeof(TRIDENTDRIRec
)) {
362 fprintf(stderr
,"\nERROR! sizeof(TRIDENTDRIRec) does not match passed size from device driver\n");
366 /* Allocate the private area */
367 tridentScreen
= (tridentScreenPtr
) CALLOC( sizeof(*tridentScreen
) );
368 if ( !tridentScreen
) return NULL
;
370 tridentScreen
->driScreen
= sPriv
;
372 tridentScreen
->frontOffset
= tDRIPriv
->frontOffset
;
373 tridentScreen
->backOffset
= tDRIPriv
->backOffset
;
374 tridentScreen
->depthOffset
= tDRIPriv
->depthOffset
;
375 tridentScreen
->frontPitch
= tDRIPriv
->frontPitch
;
376 tridentScreen
->backPitch
= tDRIPriv
->backPitch
;
377 tridentScreen
->depthPitch
= tDRIPriv
->depthPitch
;
378 tridentScreen
->width
= tDRIPriv
->width
;
379 tridentScreen
->height
= tDRIPriv
->height
;
381 printf("%d %d\n",tridentScreen
->width
,tridentScreen
->height
);
382 printf("%d %d\n",tridentScreen
->frontPitch
,tridentScreen
->backPitch
);
383 printf("offset 0x%x 0x%x\n",tridentScreen
->backOffset
,tridentScreen
->depthOffset
);
385 tridentScreen
->mmio
.handle
= tDRIPriv
->regs
;
386 tridentScreen
->mmio
.size
= 0x20000;
388 if (drmMap(sPriv
->fd
,
389 tridentScreen
->mmio
.handle
, tridentScreen
->mmio
.size
,
390 (drmAddressPtr
)&tridentScreen
->mmio
.map
)) {
394 printf("MAPPED at %p\n", tridentScreen
->mmio
.map
);
396 return tridentScreen
;
399 /* Destroy the device specific screen private data struct.
402 tridentDestroyScreen( __DRIscreenPrivate
*sPriv
)
404 tridentScreenPtr tridentScreen
= (tridentScreenPtr
)sPriv
->private;
410 tridentInitDriver(__DRIscreenPrivate
*sPriv
)
412 sPriv
->private = (void *) tridentCreateScreen( sPriv
);
414 if (!sPriv
->private) {
415 tridentDestroyScreen( sPriv
);
423 * This is the driver specific part of the createNewScreen entry point.
425 * \todo maybe fold this into intelInitDriver
427 * \return the __GLcontextModes supported by this driver
429 const __DRIconfig
**tridentInitScreen(__DRIscreenPrivate
*psp
)
431 static const __DRIversion ddx_expected
= { 4, 0, 0 };
432 static const __DRIversion dri_expected
= { 3, 1, 0 };
433 static const __DRIversion drm_expected
= { 1, 0, 0 };
435 if ( ! driCheckDriDdxDrmVersions2( "Trident",
436 &psp
->dri_version
, & dri_expected
,
437 &psp
->ddx_version
, & ddx_expected
,
438 &psp
->drm_version
, & drm_expected
) )
441 if (!tridentInitDriver(psp
))
444 /* Wait... what? This driver doesn't report any modes... */
446 TRIDENTDRIPtr dri_priv
= (TRIDENTDRIPtr
) psp
->pDevPriv
;
447 *driver_modes
= tridentFillInModes( dri_priv
->bytesPerPixel
* 8,
454 const struct __DriverAPIRec driDriverAPI
= {
456 tridentDestroyScreen
,
457 tridentCreateContext
,
458 tridentDestroyContext
,
460 tridentDestroyBuffer
,
463 tridentUnbindContext
,