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"
44 #include "i830_screen.h"
47 #include "i830_state.h"
49 #include "i830_span.h"
50 #include "i830_tris.h"
51 #include "i830_ioctl.h"
58 const char __driConfigOptions
[] =
60 DRI_CONF_SECTION_PERFORMANCE
61 DRI_CONF_MAX_TEXTURE_UNITS(4,2,4)
62 DRI_CONF_FORCE_S3TC_ENABLE(false)
65 const GLuint __driNConfigOptions
= 2;
67 #ifdef USE_NEW_INTERFACE
68 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
69 #endif /*USE_NEW_INTERFACE*/
71 static int i830_malloc_proxy_buf(drmBufMapPtr buffers
)
77 buffer
= ALIGN_MALLOC(I830_DMA_BUF_SZ
, 32);
78 if(buffer
== NULL
) return -1;
79 for(i
= 0; i
< I830_DMA_BUF_NR
; i
++) {
80 buf
= &(buffers
->list
[i
]);
81 buf
->address
= (drmAddress
)buffer
;
87 static drmBufMapPtr
i830_create_empty_buffers(void)
91 retval
= (drmBufMapPtr
)ALIGN_MALLOC(sizeof(drmBufMap
), 32);
92 if(retval
== NULL
) return NULL
;
93 memset(retval
, 0, sizeof(drmBufMap
));
94 retval
->list
= (drmBufPtr
)ALIGN_MALLOC(sizeof(drmBuf
) * I830_DMA_BUF_NR
, 32);
95 if(retval
->list
== NULL
) {
100 memset(retval
->list
, 0, sizeof(drmBuf
) * I830_DMA_BUF_NR
);
104 static void i830PrintDRIInfo(i830ScreenPrivate
*i830Screen
,
105 __DRIscreenPrivate
*sPriv
,
108 GLuint size
= (gDRIPriv
->ringSize
+
109 i830Screen
->textureSize
+
110 i830Screen
->depth
.size
+
111 i830Screen
->back
.size
+
113 I830_DMA_BUF_NR
* I830_DMA_BUF_SZ
+
114 32768 /* Context Memory */ +
115 16*4096 /* Ring buffer */ +
116 64*1024 /* Scratch buffer */ +
118 GLuint size_low
= (gDRIPriv
->ringSize
+
119 i830Screen
->textureSize
+
121 I830_DMA_BUF_NR
* I830_DMA_BUF_SZ
+
122 32768 /* Context Memory */ +
123 16*4096 /* Ring buffer */ +
124 64*1024 /* Scratch buffer */);
126 fprintf(stderr
, "\nFront size : 0x%x\n", sPriv
->fbSize
);
127 fprintf(stderr
, "Front offset : 0x%x\n", i830Screen
->fbOffset
);
128 fprintf(stderr
, "Back size : 0x%x\n", i830Screen
->back
.size
);
129 fprintf(stderr
, "Back offset : 0x%x\n", i830Screen
->backOffset
);
130 fprintf(stderr
, "Depth size : 0x%x\n", i830Screen
->depth
.size
);
131 fprintf(stderr
, "Depth offset : 0x%x\n", i830Screen
->depthOffset
);
132 fprintf(stderr
, "Texture size : 0x%x\n", i830Screen
->textureSize
);
133 fprintf(stderr
, "Texture offset : 0x%x\n", i830Screen
->textureOffset
);
134 fprintf(stderr
, "Ring offset : 0x%x\n", gDRIPriv
->ringOffset
);
135 fprintf(stderr
, "Ring size : 0x%x\n", gDRIPriv
->ringSize
);
136 fprintf(stderr
, "Memory : 0x%x\n", gDRIPriv
->mem
);
137 fprintf(stderr
, "Used Memory : low(0x%x) high(0x%x)\n", size_low
, size
);
140 static GLboolean
i830InitDriver(__DRIscreenPrivate
*sPriv
)
142 i830ScreenPrivate
*i830Screen
;
143 I830DRIPtr gDRIPriv
= (I830DRIPtr
)sPriv
->pDevPriv
;
146 /* Allocate the private area */
147 i830Screen
= (i830ScreenPrivate
*)CALLOC(sizeof(i830ScreenPrivate
));
149 fprintf(stderr
,"\nERROR! Allocating private area failed\n");
153 /* parse information in __driConfigOptions */
154 driParseOptionInfo (&i830Screen
->optionCache
,
155 __driConfigOptions
, __driNConfigOptions
);
158 i830Screen
->driScrnPriv
= sPriv
;
159 sPriv
->private = (void *)i830Screen
;
161 i830Screen
->deviceID
= gDRIPriv
->deviceID
;
162 i830Screen
->width
= gDRIPriv
->width
;
163 i830Screen
->height
= gDRIPriv
->height
;
164 i830Screen
->mem
= gDRIPriv
->mem
;
165 i830Screen
->cpp
= gDRIPriv
->cpp
;
166 i830Screen
->fbStride
= gDRIPriv
->fbStride
;
167 i830Screen
->fbOffset
= gDRIPriv
->fbOffset
;
169 switch (gDRIPriv
->bitsPerPixel
) {
170 case 15: i830Screen
->fbFormat
= DV_PF_555
; break;
171 case 16: i830Screen
->fbFormat
= DV_PF_565
; break;
172 case 32: i830Screen
->fbFormat
= DV_PF_8888
; break;
175 i830Screen
->backOffset
= gDRIPriv
->backOffset
;
176 i830Screen
->depthOffset
= gDRIPriv
->depthOffset
;
177 i830Screen
->backPitch
= gDRIPriv
->auxPitch
;
178 i830Screen
->backPitchBits
= gDRIPriv
->auxPitchBits
;
179 i830Screen
->textureOffset
= gDRIPriv
->textureOffset
;
180 i830Screen
->textureSize
= gDRIPriv
->textureSize
;
181 i830Screen
->logTextureGranularity
= gDRIPriv
->logTextureGranularity
;
184 i830Screen
->bufs
= i830_create_empty_buffers();
185 if(i830Screen
->bufs
== NULL
) {
186 fprintf(stderr
,"\nERROR: Failed to create empty buffers in %s \n",
192 /* Check if you need to create a fake buffer */
193 if(i830_check_copy(sPriv
->fd
) == 1) {
194 i830_malloc_proxy_buf(i830Screen
->bufs
);
195 i830Screen
->use_copy_buf
= 1;
197 i830Screen
->use_copy_buf
= 0;
200 i830Screen
->back
.handle
= gDRIPriv
->backbuffer
;
201 i830Screen
->back
.size
= gDRIPriv
->backbufferSize
;
203 if (drmMap(sPriv
->fd
,
204 i830Screen
->back
.handle
,
205 i830Screen
->back
.size
,
206 (drmAddress
*)&i830Screen
->back
.map
) != 0) {
207 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
208 __LINE__
, __FUNCTION__
, __FILE__
);
210 sPriv
->private = NULL
;
214 i830Screen
->depth
.handle
= gDRIPriv
->depthbuffer
;
215 i830Screen
->depth
.size
= gDRIPriv
->depthbufferSize
;
217 if (drmMap(sPriv
->fd
,
218 i830Screen
->depth
.handle
,
219 i830Screen
->depth
.size
,
220 (drmAddress
*)&i830Screen
->depth
.map
) != 0) {
221 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
222 __LINE__
, __FUNCTION__
, __FILE__
);
224 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
225 sPriv
->private = NULL
;
229 i830Screen
->tex
.handle
= gDRIPriv
->textures
;
230 i830Screen
->tex
.size
= gDRIPriv
->textureSize
;
232 if (drmMap(sPriv
->fd
,
233 i830Screen
->tex
.handle
,
234 i830Screen
->tex
.size
,
235 (drmAddress
*)&i830Screen
->tex
.map
) != 0) {
236 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
237 __LINE__
, __FUNCTION__
, __FILE__
);
239 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
240 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
241 sPriv
->private = NULL
;
245 i830Screen
->sarea_priv_offset
= gDRIPriv
->sarea_priv_offset
;
247 if (0) i830PrintDRIInfo(i830Screen
, sPriv
, gDRIPriv
);
249 i830Screen
->drmMinor
= sPriv
->drmMinor
;
251 if (sPriv
->drmMinor
>= 3) {
255 gp
.param
= I830_PARAM_IRQ_ACTIVE
;
256 gp
.value
= &i830Screen
->irq_active
;
258 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
261 fprintf(stderr
, "drmI830GetParam: %d\n", ret
);
267 if (sPriv
->drmMinor
>= 3) {
271 sp
.param
= I830_SETPARAM_PERF_BOXES
;
272 sp
.value
= (getenv("I830_DO_BOXES") != 0);
274 ret
= drmCommandWrite( sPriv
->fd
, DRM_I830_SETPARAM
,
277 fprintf(stderr
, "Couldn't set perfboxes: %d\n", ret
);
281 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
282 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
283 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
284 void * const psc
= sPriv
->psc
->screenConfigs
;
286 if ( glx_enable_extension
!= NULL
) {
287 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
289 if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
290 (*glx_enable_extension
)( psc
, "GLX_SGIX_fbconfig" );
291 (*glx_enable_extension
)( psc
, "GLX_OML_swap_method" );
300 static void i830DestroyScreen(__DRIscreenPrivate
*sPriv
)
302 i830ScreenPrivate
*i830Screen
= (i830ScreenPrivate
*)sPriv
->private;
304 /* Need to unmap all the bufs and maps here:
306 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
307 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
308 drmUnmap(i830Screen
->tex
.map
, i830Screen
->tex
.size
);
310 sPriv
->private = NULL
;
313 static GLboolean
i830CreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
314 __DRIdrawablePrivate
*driDrawPriv
,
315 const __GLcontextModes
*mesaVis
,
319 return GL_FALSE
; /* not implemented */
322 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
323 mesaVis
->depthBits
!= 24);
325 GLboolean swStencil
= mesaVis
->stencilBits
> 0;
327 driDrawPriv
->driverPrivate
= (void *)
328 _mesa_create_framebuffer(mesaVis
,
329 GL_FALSE
, /* software depth buffer? */
331 mesaVis
->accumRedBits
> 0,
332 GL_FALSE
/* s/w alpha planes */);
334 return (driDrawPriv
->driverPrivate
!= NULL
);
338 static void i830DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
340 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
343 static const struct __DriverAPIRec i830API
= {
344 .InitDriver
= i830InitDriver
,
345 .DestroyScreen
= i830DestroyScreen
,
346 .CreateContext
= i830CreateContext
,
347 .DestroyContext
= i830DestroyContext
,
348 .CreateBuffer
= i830CreateBuffer
,
349 .DestroyBuffer
= i830DestroyBuffer
,
350 .SwapBuffers
= i830SwapBuffers
,
351 .MakeCurrent
= i830MakeCurrent
,
352 .UnbindContext
= i830UnbindContext
,
357 .SwapBuffersMSC
= NULL
362 * This is the bootstrap function for the driver.
363 * The __driCreateScreen name is the symbol that libGL.so fetches.
364 * Return: pointer to a __DRIscreenPrivate.
366 #if !defined(DRI_NEW_INTERFACE_ONLY)
367 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
368 int numConfigs
, __GLXvisualConfig
*config
)
370 __DRIscreenPrivate
*psp
;
371 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &i830API
);
374 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
377 #ifdef USE_NEW_INTERFACE
378 static __GLcontextModes
*
379 i830FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
380 unsigned stencil_bits
, GLboolean have_back_buffer
)
382 __GLcontextModes
* modes
;
383 __GLcontextModes
* m
;
385 unsigned depth_buffer_factor
;
386 unsigned back_buffer_factor
;
390 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
391 * support pageflipping at all.
393 static const GLenum back_buffer_modes
[] = {
394 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
397 u_int8_t depth_bits_array
[2];
398 u_int8_t stencil_bits_array
[2];
401 depth_bits_array
[0] = 0;
402 depth_bits_array
[1] = depth_bits
;
404 /* Just like with the accumulation buffer, always provide some modes
405 * with a stencil buffer. It will be a sw fallback, but some apps won't
408 stencil_bits_array
[0] = 0;
409 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
411 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
412 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
414 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
416 if ( pixel_bits
== 16 ) {
418 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
422 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
425 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
427 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
428 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
429 back_buffer_modes
, back_buffer_factor
,
431 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
432 __func__
, __LINE__
);
436 /* There's no direct color modes on i830? */
438 /* Mark the visual as slow if there are "fake" stencil bits.
440 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
441 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
442 m
->visualRating
= GLX_SLOW_CONFIG
;
448 #endif /* USE_NEW_INTERFACE */
452 * This is the bootstrap function for the driver. libGL supplies all of the
453 * requisite information about the system, and the driver initializes itself.
454 * This routine also fills in the linked list pointed to by \c driver_modes
455 * with the \c __GLcontextModes that the driver can support for windows or
458 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
461 #ifdef USE_NEW_INTERFACE
463 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
464 const __GLcontextModes
* modes
,
465 const __DRIversion
* ddx_version
,
466 const __DRIversion
* dri_version
,
467 const __DRIversion
* drm_version
,
468 const __DRIframebuffer
* frame_buffer
,
469 drmAddress pSAREA
, int fd
,
470 int internal_api_version
,
471 __GLcontextModes
** driver_modes
)
474 __DRIscreenPrivate
*psp
;
475 static const __DRIversion ddx_expected
= { 1, 0, 0 };
476 static const __DRIversion dri_expected
= { 4, 0, 0 };
477 static const __DRIversion drm_expected
= { 1, 3, 0 };
479 if ( ! driCheckDriDdxDrmVersions2( "i830",
480 dri_version
, & dri_expected
,
481 ddx_version
, & ddx_expected
,
482 drm_version
, & drm_expected
) ) {
486 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
487 ddx_version
, dri_version
, drm_version
,
488 frame_buffer
, pSAREA
, fd
,
489 internal_api_version
, &i830API
);
491 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
492 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
493 if ( create_context_modes
!= NULL
) {
494 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
495 *driver_modes
= i830FillInModes( dri_priv
->cpp
* 8,
496 (dri_priv
->cpp
== 2) ? 16 : 24,
497 (dri_priv
->cpp
== 2) ? 0 : 8,
498 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
504 #endif /* USE_NEW_INTERFACE */