1 /**************************************************************************
3 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * **************************************************************************/
27 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_screen.c,v 1.3 2002/12/10 01:26:53 dawes Exp $ */
32 * Adapted for use on the I830M by Jeff Hartmann.
34 * \author Keith Whitwell <keith@tungstengraphics.com>
35 * \author Jeff Hartmann <jhartmann@2d3d.com>
42 #include "simple_list.h"
43 #include "framebuffer.h"
44 #include "renderbuffer.h"
46 #include "i830_screen.h"
49 #include "i830_state.h"
51 #include "i830_span.h"
52 #include "i830_tris.h"
53 #include "i830_ioctl.h"
59 #include "drirenderbuffer.h"
61 PUBLIC
const char __driConfigOptions
[] =
63 DRI_CONF_SECTION_PERFORMANCE
64 DRI_CONF_MAX_TEXTURE_UNITS(4,2,4)
65 DRI_CONF_FORCE_S3TC_ENABLE(false)
68 const GLuint __driNConfigOptions
= 2;
70 extern const struct dri_extension card_extensions
[];
72 static int i830_malloc_proxy_buf(drmBufMapPtr buffers
)
78 buffer
= ALIGN_MALLOC(I830_DMA_BUF_SZ
, 32);
79 if(buffer
== NULL
) return -1;
80 for(i
= 0; i
< I830_DMA_BUF_NR
; i
++) {
81 buf
= &(buffers
->list
[i
]);
82 buf
->address
= (drmAddress
)buffer
;
88 static drmBufMapPtr
i830_create_empty_buffers(void)
92 retval
= (drmBufMapPtr
)ALIGN_MALLOC(sizeof(drmBufMap
), 32);
93 if(retval
== NULL
) return NULL
;
94 memset(retval
, 0, sizeof(drmBufMap
));
95 retval
->list
= (drmBufPtr
)ALIGN_MALLOC(sizeof(drmBuf
) * I830_DMA_BUF_NR
, 32);
96 if(retval
->list
== NULL
) {
101 memset(retval
->list
, 0, sizeof(drmBuf
) * I830_DMA_BUF_NR
);
105 static void i830PrintDRIInfo(i830ScreenPrivate
*i830Screen
,
106 __DRIscreenPrivate
*sPriv
,
109 GLuint size
= (gDRIPriv
->ringSize
+
110 i830Screen
->textureSize
+
111 i830Screen
->depth
.size
+
112 i830Screen
->back
.size
+
114 I830_DMA_BUF_NR
* I830_DMA_BUF_SZ
+
115 32768 /* Context Memory */ +
116 16*4096 /* Ring buffer */ +
117 64*1024 /* Scratch buffer */ +
119 GLuint size_low
= (gDRIPriv
->ringSize
+
120 i830Screen
->textureSize
+
122 I830_DMA_BUF_NR
* I830_DMA_BUF_SZ
+
123 32768 /* Context Memory */ +
124 16*4096 /* Ring buffer */ +
125 64*1024 /* Scratch buffer */);
127 fprintf(stderr
, "\nFront size : 0x%x\n", sPriv
->fbSize
);
128 fprintf(stderr
, "Front offset : 0x%x\n", i830Screen
->fbOffset
);
129 fprintf(stderr
, "Back size : 0x%x\n", i830Screen
->back
.size
);
130 fprintf(stderr
, "Back offset : 0x%x\n", i830Screen
->backOffset
);
131 fprintf(stderr
, "Depth size : 0x%x\n", i830Screen
->depth
.size
);
132 fprintf(stderr
, "Depth offset : 0x%x\n", i830Screen
->depthOffset
);
133 fprintf(stderr
, "Texture size : 0x%x\n", i830Screen
->textureSize
);
134 fprintf(stderr
, "Texture offset : 0x%x\n", i830Screen
->textureOffset
);
135 fprintf(stderr
, "Ring offset : 0x%x\n", gDRIPriv
->ringOffset
);
136 fprintf(stderr
, "Ring size : 0x%x\n", gDRIPriv
->ringSize
);
137 fprintf(stderr
, "Memory : 0x%x\n", gDRIPriv
->mem
);
138 fprintf(stderr
, "Used Memory : low(0x%x) high(0x%x)\n", size_low
, size
);
141 static GLboolean
i830InitDriver(__DRIscreenPrivate
*sPriv
)
143 i830ScreenPrivate
*i830Screen
;
144 I830DRIPtr gDRIPriv
= (I830DRIPtr
)sPriv
->pDevPriv
;
145 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
146 (PFNGLXSCRENABLEEXTENSIONPROC
) (*dri_interface
->getProcAddress("glxEnableExtension"));
147 void * const psc
= sPriv
->psc
->screenConfigs
;
150 /* Allocate the private area */
151 i830Screen
= (i830ScreenPrivate
*)CALLOC(sizeof(i830ScreenPrivate
));
153 fprintf(stderr
,"\nERROR! Allocating private area failed\n");
157 /* parse information in __driConfigOptions */
158 driParseOptionInfo (&i830Screen
->optionCache
,
159 __driConfigOptions
, __driNConfigOptions
);
162 i830Screen
->driScrnPriv
= sPriv
;
163 sPriv
->private = (void *)i830Screen
;
165 i830Screen
->deviceID
= gDRIPriv
->deviceID
;
166 i830Screen
->width
= gDRIPriv
->width
;
167 i830Screen
->height
= gDRIPriv
->height
;
168 i830Screen
->mem
= gDRIPriv
->mem
;
169 i830Screen
->cpp
= gDRIPriv
->cpp
;
170 i830Screen
->fbStride
= gDRIPriv
->fbStride
;
171 i830Screen
->fbOffset
= gDRIPriv
->fbOffset
;
173 switch (gDRIPriv
->bitsPerPixel
) {
174 case 15: i830Screen
->fbFormat
= DV_PF_555
; break;
175 case 16: i830Screen
->fbFormat
= DV_PF_565
; break;
176 case 32: i830Screen
->fbFormat
= DV_PF_8888
; break;
179 i830Screen
->backOffset
= gDRIPriv
->backOffset
;
180 i830Screen
->depthOffset
= gDRIPriv
->depthOffset
;
181 i830Screen
->backPitch
= gDRIPriv
->auxPitch
;
182 i830Screen
->backPitchBits
= gDRIPriv
->auxPitchBits
;
183 i830Screen
->textureOffset
= gDRIPriv
->textureOffset
;
184 i830Screen
->textureSize
= gDRIPriv
->textureSize
;
185 i830Screen
->logTextureGranularity
= gDRIPriv
->logTextureGranularity
;
188 i830Screen
->bufs
= i830_create_empty_buffers();
189 if(i830Screen
->bufs
== NULL
) {
190 fprintf(stderr
,"\nERROR: Failed to create empty buffers in %s \n",
196 /* Check if you need to create a fake buffer */
197 if(i830_check_copy(sPriv
->fd
) == 1) {
198 i830_malloc_proxy_buf(i830Screen
->bufs
);
199 i830Screen
->use_copy_buf
= 1;
201 i830Screen
->use_copy_buf
= 0;
204 i830Screen
->back
.handle
= gDRIPriv
->backbuffer
;
205 i830Screen
->back
.size
= gDRIPriv
->backbufferSize
;
207 if (drmMap(sPriv
->fd
,
208 i830Screen
->back
.handle
,
209 i830Screen
->back
.size
,
210 (drmAddress
*)&i830Screen
->back
.map
) != 0) {
211 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
212 __LINE__
, __FUNCTION__
, __FILE__
);
214 sPriv
->private = NULL
;
218 i830Screen
->depth
.handle
= gDRIPriv
->depthbuffer
;
219 i830Screen
->depth
.size
= gDRIPriv
->depthbufferSize
;
221 if (drmMap(sPriv
->fd
,
222 i830Screen
->depth
.handle
,
223 i830Screen
->depth
.size
,
224 (drmAddress
*)&i830Screen
->depth
.map
) != 0) {
225 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
226 __LINE__
, __FUNCTION__
, __FILE__
);
228 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
229 sPriv
->private = NULL
;
233 i830Screen
->tex
.handle
= gDRIPriv
->textures
;
234 i830Screen
->tex
.size
= gDRIPriv
->textureSize
;
236 if (drmMap(sPriv
->fd
,
237 i830Screen
->tex
.handle
,
238 i830Screen
->tex
.size
,
239 (drmAddress
*)&i830Screen
->tex
.map
) != 0) {
240 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
241 __LINE__
, __FUNCTION__
, __FILE__
);
243 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
244 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
245 sPriv
->private = NULL
;
249 i830Screen
->sarea_priv_offset
= gDRIPriv
->sarea_priv_offset
;
251 if (0) i830PrintDRIInfo(i830Screen
, sPriv
, gDRIPriv
);
253 i830Screen
->drmMinor
= sPriv
->drmMinor
;
255 if (sPriv
->drmMinor
>= 3) {
259 gp
.param
= I830_PARAM_IRQ_ACTIVE
;
260 gp
.value
= &i830Screen
->irq_active
;
262 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
265 fprintf(stderr
, "drmI830GetParam: %d\n", ret
);
271 if (sPriv
->drmMinor
>= 3) {
275 sp
.param
= I830_SETPARAM_PERF_BOXES
;
276 sp
.value
= (getenv("I830_DO_BOXES") != 0);
278 ret
= drmCommandWrite( sPriv
->fd
, DRM_I830_SETPARAM
,
281 fprintf(stderr
, "Couldn't set perfboxes: %d\n", ret
);
285 if ( glx_enable_extension
!= NULL
) {
286 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
293 static void i830DestroyScreen(__DRIscreenPrivate
*sPriv
)
295 i830ScreenPrivate
*i830Screen
= (i830ScreenPrivate
*)sPriv
->private;
297 /* Need to unmap all the bufs and maps here:
299 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
300 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
301 drmUnmap(i830Screen
->tex
.map
, i830Screen
->tex
.size
);
303 sPriv
->private = NULL
;
307 static GLboolean
i830CreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
308 __DRIdrawablePrivate
*driDrawPriv
,
309 const __GLcontextModes
*mesaVis
,
312 i830ScreenPrivate
*screen
= (i830ScreenPrivate
*) driScrnPriv
->private;
315 return GL_FALSE
; /* not implemented */
319 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
320 mesaVis
->depthBits
!= 24);
322 GLboolean swStencil
= mesaVis
->stencilBits
> 0;
326 driDrawPriv
->driverPrivate
= (void *)
327 _mesa_create_framebuffer(mesaVis
,
328 GL_FALSE
, /* software depth buffer? */
330 mesaVis
->accumRedBits
> 0,
331 GL_FALSE
/* s/w alpha planes */);
333 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
336 driRenderbuffer
*frontRb
337 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
338 /*screen->frontOffset*/0, screen
->backPitch
);
339 i830SetSpanFunctions(frontRb
, mesaVis
);
340 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
343 if (mesaVis
->doubleBufferMode
) {
344 driRenderbuffer
*backRb
345 = driNewRenderbuffer(GL_RGBA
, screen
->cpp
,
346 screen
->backOffset
, screen
->backPitch
);
347 i830SetSpanFunctions(backRb
, mesaVis
);
348 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
351 if (mesaVis
->depthBits
== 16) {
352 driRenderbuffer
*depthRb
353 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, screen
->cpp
,
354 screen
->depthOffset
, screen
->backPitch
);
355 i830SetSpanFunctions(depthRb
, mesaVis
);
356 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
358 else if (mesaVis
->depthBits
== 24) {
359 if (mesaVis
->stencilBits
== 8) {
360 driRenderbuffer
*depthRb
361 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, screen
->cpp
,
362 screen
->depthOffset
, screen
->backPitch
);
363 i830SetSpanFunctions(depthRb
, mesaVis
);
364 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
367 /* not really 32-bit Z, but use GL_DEPTH_COMPONENT32 anyway */
368 driRenderbuffer
*depthRb
369 = driNewRenderbuffer(GL_DEPTH_COMPONENT32
, screen
->cpp
,
370 screen
->depthOffset
, screen
->backPitch
);
371 i830SetSpanFunctions(depthRb
, mesaVis
);
372 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
376 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
377 driRenderbuffer
*stencilRb
378 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
, screen
->cpp
,
379 screen
->depthOffset
, screen
->backPitch
);
380 i830SetSpanFunctions(stencilRb
, mesaVis
);
381 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
384 _mesa_add_soft_renderbuffers(fb
,
385 GL_FALSE
, /* color */
386 GL_FALSE
, /* depth */
388 mesaVis
->accumRedBits
> 0,
389 GL_FALSE
, /* alpha */
391 driDrawPriv
->driverPrivate
= (void *) fb
;
394 return (driDrawPriv
->driverPrivate
!= NULL
);
398 static void i830DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
400 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
403 static const struct __DriverAPIRec i830API
= {
404 .InitDriver
= i830InitDriver
,
405 .DestroyScreen
= i830DestroyScreen
,
406 .CreateContext
= i830CreateContext
,
407 .DestroyContext
= i830DestroyContext
,
408 .CreateBuffer
= i830CreateBuffer
,
409 .DestroyBuffer
= i830DestroyBuffer
,
410 .SwapBuffers
= i830SwapBuffers
,
411 .MakeCurrent
= i830MakeCurrent
,
412 .UnbindContext
= i830UnbindContext
,
417 .SwapBuffersMSC
= NULL
421 static __GLcontextModes
*
422 i830FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
423 unsigned stencil_bits
, GLboolean have_back_buffer
)
425 __GLcontextModes
* modes
;
426 __GLcontextModes
* m
;
428 unsigned depth_buffer_factor
;
429 unsigned back_buffer_factor
;
433 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
434 * support pageflipping at all.
436 static const GLenum back_buffer_modes
[] = {
437 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
440 u_int8_t depth_bits_array
[2];
441 u_int8_t stencil_bits_array
[2];
444 depth_bits_array
[0] = 0;
445 depth_bits_array
[1] = depth_bits
;
447 /* Just like with the accumulation buffer, always provide some modes
448 * with a stencil buffer. It will be a sw fallback, but some apps won't
451 stencil_bits_array
[0] = 0;
452 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
454 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
455 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
457 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
459 if ( pixel_bits
== 16 ) {
461 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
465 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
468 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
470 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
471 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
472 back_buffer_modes
, back_buffer_factor
,
474 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
475 __func__
, __LINE__
);
479 /* There's no direct color modes on i830? */
481 /* Mark the visual as slow if there are "fake" stencil bits.
483 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
484 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
485 m
->visualRating
= GLX_SLOW_CONFIG
;
494 * This is the bootstrap function for the driver. libGL supplies all of the
495 * requisite information about the system, and the driver initializes itself.
496 * This routine also fills in the linked list pointed to by \c driver_modes
497 * with the \c __GLcontextModes that the driver can support for windows or
500 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
504 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
505 const __GLcontextModes
* modes
,
506 const __DRIversion
* ddx_version
,
507 const __DRIversion
* dri_version
,
508 const __DRIversion
* drm_version
,
509 const __DRIframebuffer
* frame_buffer
,
510 drmAddress pSAREA
, int fd
,
511 int internal_api_version
,
512 const __DRIinterfaceMethods
* interface
,
513 __GLcontextModes
** driver_modes
)
516 __DRIscreenPrivate
*psp
;
517 static const __DRIversion ddx_expected
= { 1, 0, 0 };
518 static const __DRIversion dri_expected
= { 4, 0, 0 };
519 static const __DRIversion drm_expected
= { 1, 3, 0 };
521 dri_interface
= interface
;
523 if ( ! driCheckDriDdxDrmVersions2( "i830",
524 dri_version
, & dri_expected
,
525 ddx_version
, & ddx_expected
,
526 drm_version
, & drm_expected
) ) {
530 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
531 ddx_version
, dri_version
, drm_version
,
532 frame_buffer
, pSAREA
, fd
,
533 internal_api_version
, &i830API
);
535 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
536 *driver_modes
= i830FillInModes( dri_priv
->cpp
* 8,
537 (dri_priv
->cpp
== 2) ? 16 : 24,
538 (dri_priv
->cpp
== 2) ? 0 : 8,
539 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
541 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
542 * enable the extensions. It just makes sure that all the dispatch offsets for all
543 * the extensions that *might* be enables are known. This is needed because the
544 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
545 * enable the extensions until we have a context pointer.
547 * Hello chicken. Hello egg. How are you two today?
549 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);