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)
64 const GLuint __driNConfigOptions
= 1;
66 #ifdef USE_NEW_INTERFACE
67 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
68 #endif /*USE_NEW_INTERFACE*/
70 static int i830_malloc_proxy_buf(drmBufMapPtr buffers
)
76 buffer
= ALIGN_MALLOC(I830_DMA_BUF_SZ
, 32);
77 if(buffer
== NULL
) return -1;
78 for(i
= 0; i
< I830_DMA_BUF_NR
; i
++) {
79 buf
= &(buffers
->list
[i
]);
80 buf
->address
= (drmAddress
)buffer
;
86 static drmBufMapPtr
i830_create_empty_buffers(void)
90 retval
= (drmBufMapPtr
)ALIGN_MALLOC(sizeof(drmBufMap
), 32);
91 if(retval
== NULL
) return NULL
;
92 memset(retval
, 0, sizeof(drmBufMap
));
93 retval
->list
= (drmBufPtr
)ALIGN_MALLOC(sizeof(drmBuf
) * I830_DMA_BUF_NR
, 32);
94 if(retval
->list
== NULL
) {
99 memset(retval
->list
, 0, sizeof(drmBuf
) * I830_DMA_BUF_NR
);
103 static void i830PrintDRIInfo(i830ScreenPrivate
*i830Screen
,
104 __DRIscreenPrivate
*sPriv
,
107 GLuint size
= (gDRIPriv
->ringSize
+
108 i830Screen
->textureSize
+
109 i830Screen
->depth
.size
+
110 i830Screen
->back
.size
+
112 I830_DMA_BUF_NR
* I830_DMA_BUF_SZ
+
113 32768 /* Context Memory */ +
114 16*4096 /* Ring buffer */ +
115 64*1024 /* Scratch buffer */ +
117 GLuint size_low
= (gDRIPriv
->ringSize
+
118 i830Screen
->textureSize
+
120 I830_DMA_BUF_NR
* I830_DMA_BUF_SZ
+
121 32768 /* Context Memory */ +
122 16*4096 /* Ring buffer */ +
123 64*1024 /* Scratch buffer */);
125 fprintf(stderr
, "\nFront size : 0x%x\n", sPriv
->fbSize
);
126 fprintf(stderr
, "Front offset : 0x%x\n", i830Screen
->fbOffset
);
127 fprintf(stderr
, "Back size : 0x%x\n", i830Screen
->back
.size
);
128 fprintf(stderr
, "Back offset : 0x%x\n", i830Screen
->backOffset
);
129 fprintf(stderr
, "Depth size : 0x%x\n", i830Screen
->depth
.size
);
130 fprintf(stderr
, "Depth offset : 0x%x\n", i830Screen
->depthOffset
);
131 fprintf(stderr
, "Texture size : 0x%x\n", i830Screen
->textureSize
);
132 fprintf(stderr
, "Texture offset : 0x%x\n", i830Screen
->textureOffset
);
133 fprintf(stderr
, "Ring offset : 0x%x\n", gDRIPriv
->ringOffset
);
134 fprintf(stderr
, "Ring size : 0x%x\n", gDRIPriv
->ringSize
);
135 fprintf(stderr
, "Memory : 0x%x\n", gDRIPriv
->mem
);
136 fprintf(stderr
, "Used Memory : low(0x%x) high(0x%x)\n", size_low
, size
);
139 static GLboolean
i830InitDriver(__DRIscreenPrivate
*sPriv
)
141 i830ScreenPrivate
*i830Screen
;
142 I830DRIPtr gDRIPriv
= (I830DRIPtr
)sPriv
->pDevPriv
;
145 /* Allocate the private area */
146 i830Screen
= (i830ScreenPrivate
*)CALLOC(sizeof(i830ScreenPrivate
));
148 fprintf(stderr
,"\nERROR! Allocating private area failed\n");
152 /* parse information in __driConfigOptions */
153 driParseOptionInfo (&i830Screen
->optionCache
,
154 __driConfigOptions
, __driNConfigOptions
);
157 i830Screen
->driScrnPriv
= sPriv
;
158 sPriv
->private = (void *)i830Screen
;
160 i830Screen
->deviceID
= gDRIPriv
->deviceID
;
161 i830Screen
->width
= gDRIPriv
->width
;
162 i830Screen
->height
= gDRIPriv
->height
;
163 i830Screen
->mem
= gDRIPriv
->mem
;
164 i830Screen
->cpp
= gDRIPriv
->cpp
;
165 i830Screen
->fbStride
= gDRIPriv
->fbStride
;
166 i830Screen
->fbOffset
= gDRIPriv
->fbOffset
;
168 switch (gDRIPriv
->bitsPerPixel
) {
169 case 15: i830Screen
->fbFormat
= DV_PF_555
; break;
170 case 16: i830Screen
->fbFormat
= DV_PF_565
; break;
171 case 32: i830Screen
->fbFormat
= DV_PF_8888
; break;
174 i830Screen
->backOffset
= gDRIPriv
->backOffset
;
175 i830Screen
->depthOffset
= gDRIPriv
->depthOffset
;
176 i830Screen
->backPitch
= gDRIPriv
->auxPitch
;
177 i830Screen
->backPitchBits
= gDRIPriv
->auxPitchBits
;
178 i830Screen
->textureOffset
= gDRIPriv
->textureOffset
;
179 i830Screen
->textureSize
= gDRIPriv
->textureSize
;
180 i830Screen
->logTextureGranularity
= gDRIPriv
->logTextureGranularity
;
183 i830Screen
->bufs
= i830_create_empty_buffers();
184 if(i830Screen
->bufs
== NULL
) {
185 fprintf(stderr
,"\nERROR: Failed to create empty buffers in %s \n",
191 /* Check if you need to create a fake buffer */
192 if(i830_check_copy(sPriv
->fd
) == 1) {
193 i830_malloc_proxy_buf(i830Screen
->bufs
);
194 i830Screen
->use_copy_buf
= 1;
196 i830Screen
->use_copy_buf
= 0;
199 i830Screen
->back
.handle
= gDRIPriv
->backbuffer
;
200 i830Screen
->back
.size
= gDRIPriv
->backbufferSize
;
202 if (drmMap(sPriv
->fd
,
203 i830Screen
->back
.handle
,
204 i830Screen
->back
.size
,
205 (drmAddress
*)&i830Screen
->back
.map
) != 0) {
206 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
207 __LINE__
, __FUNCTION__
, __FILE__
);
209 sPriv
->private = NULL
;
213 i830Screen
->depth
.handle
= gDRIPriv
->depthbuffer
;
214 i830Screen
->depth
.size
= gDRIPriv
->depthbufferSize
;
216 if (drmMap(sPriv
->fd
,
217 i830Screen
->depth
.handle
,
218 i830Screen
->depth
.size
,
219 (drmAddress
*)&i830Screen
->depth
.map
) != 0) {
220 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
221 __LINE__
, __FUNCTION__
, __FILE__
);
223 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
224 sPriv
->private = NULL
;
228 i830Screen
->tex
.handle
= gDRIPriv
->textures
;
229 i830Screen
->tex
.size
= gDRIPriv
->textureSize
;
231 if (drmMap(sPriv
->fd
,
232 i830Screen
->tex
.handle
,
233 i830Screen
->tex
.size
,
234 (drmAddress
*)&i830Screen
->tex
.map
) != 0) {
235 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
236 __LINE__
, __FUNCTION__
, __FILE__
);
238 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
239 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
240 sPriv
->private = NULL
;
244 i830Screen
->sarea_priv_offset
= gDRIPriv
->sarea_priv_offset
;
246 if (0) i830PrintDRIInfo(i830Screen
, sPriv
, gDRIPriv
);
248 i830Screen
->drmMinor
= sPriv
->drmMinor
;
250 if (sPriv
->drmMinor
>= 3) {
254 gp
.param
= I830_PARAM_IRQ_ACTIVE
;
255 gp
.value
= &i830Screen
->irq_active
;
257 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
260 fprintf(stderr
, "drmI830GetParam: %d\n", ret
);
266 if (sPriv
->drmMinor
>= 3) {
270 sp
.param
= I830_SETPARAM_PERF_BOXES
;
271 sp
.value
= (getenv("I830_DO_BOXES") != 0);
273 ret
= drmCommandWrite( sPriv
->fd
, DRM_I830_SETPARAM
,
276 fprintf(stderr
, "Couldn't set perfboxes: %d\n", ret
);
280 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
281 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
282 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
283 void * const psc
= sPriv
->psc
->screenConfigs
;
285 if ( glx_enable_extension
!= NULL
) {
286 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
288 if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
289 (*glx_enable_extension
)( psc
, "GLX_SGIX_fbconfig" );
290 (*glx_enable_extension
)( psc
, "GLX_OML_swap_method" );
299 static void i830DestroyScreen(__DRIscreenPrivate
*sPriv
)
301 i830ScreenPrivate
*i830Screen
= (i830ScreenPrivate
*)sPriv
->private;
303 /* Need to unmap all the bufs and maps here:
305 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
306 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
307 drmUnmap(i830Screen
->tex
.map
, i830Screen
->tex
.size
);
309 sPriv
->private = NULL
;
312 static GLboolean
i830CreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
313 __DRIdrawablePrivate
*driDrawPriv
,
314 const __GLcontextModes
*mesaVis
,
318 return GL_FALSE
; /* not implemented */
321 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
322 mesaVis
->depthBits
!= 24);
324 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 return (driDrawPriv
->driverPrivate
!= NULL
);
337 static void i830DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
339 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
342 static const struct __DriverAPIRec i830API
= {
343 .InitDriver
= i830InitDriver
,
344 .DestroyScreen
= i830DestroyScreen
,
345 .CreateContext
= i830CreateContext
,
346 .DestroyContext
= i830DestroyContext
,
347 .CreateBuffer
= i830CreateBuffer
,
348 .DestroyBuffer
= i830DestroyBuffer
,
349 .SwapBuffers
= i830SwapBuffers
,
350 .MakeCurrent
= i830MakeCurrent
,
351 .UnbindContext
= i830UnbindContext
,
356 .SwapBuffersMSC
= NULL
361 * This is the bootstrap function for the driver.
362 * The __driCreateScreen name is the symbol that libGL.so fetches.
363 * Return: pointer to a __DRIscreenPrivate.
365 #if !defined(DRI_NEW_INTERFACE_ONLY)
366 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
367 int numConfigs
, __GLXvisualConfig
*config
)
369 __DRIscreenPrivate
*psp
;
370 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &i830API
);
373 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
376 #ifdef USE_NEW_INTERFACE
377 static __GLcontextModes
*
378 i830FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
379 unsigned stencil_bits
, GLboolean have_back_buffer
)
381 __GLcontextModes
* modes
;
382 __GLcontextModes
* m
;
384 unsigned depth_buffer_factor
;
385 unsigned back_buffer_factor
;
389 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
390 * support pageflipping at all.
392 static const GLenum back_buffer_modes
[] = {
393 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
396 uint8_t depth_bits_array
[2];
397 uint8_t stencil_bits_array
[2];
400 depth_bits_array
[0] = 0;
401 depth_bits_array
[1] = depth_bits
;
403 /* Just like with the accumulation buffer, always provide some modes
404 * with a stencil buffer. It will be a sw fallback, but some apps won't
407 stencil_bits_array
[0] = 0;
408 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
410 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
411 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
413 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
415 if ( pixel_bits
== 16 ) {
417 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
421 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
424 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
426 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
427 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
428 back_buffer_modes
, back_buffer_factor
,
430 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
431 __func__
, __LINE__
);
435 /* There's no direct color modes on i830? */
437 /* Mark the visual as slow if there are "fake" stencil bits.
439 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
440 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
441 m
->visualRating
= GLX_SLOW_CONFIG
;
447 #endif /* USE_NEW_INTERFACE */
451 * This is the bootstrap function for the driver. libGL supplies all of the
452 * requisite information about the system, and the driver initializes itself.
453 * This routine also fills in the linked list pointed to by \c driver_modes
454 * with the \c __GLcontextModes that the driver can support for windows or
457 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
460 #ifdef USE_NEW_INTERFACE
461 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
462 const __GLcontextModes
* modes
,
463 const __DRIversion
* ddx_version
,
464 const __DRIversion
* dri_version
,
465 const __DRIversion
* drm_version
,
466 const __DRIframebuffer
* frame_buffer
,
467 drmAddress pSAREA
, int fd
,
468 int internal_api_version
,
469 __GLcontextModes
** driver_modes
)
472 __DRIscreenPrivate
*psp
;
473 static const __DRIversion ddx_expected
= { 1, 0, 0 };
474 static const __DRIversion dri_expected
= { 4, 0, 0 };
475 static const __DRIversion drm_expected
= { 1, 3, 0 };
477 if ( ! driCheckDriDdxDrmVersions2( "i830",
478 dri_version
, & dri_expected
,
479 ddx_version
, & ddx_expected
,
480 drm_version
, & drm_expected
) ) {
484 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
485 ddx_version
, dri_version
, drm_version
,
486 frame_buffer
, pSAREA
, fd
,
487 internal_api_version
, &i830API
);
489 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
490 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
491 if ( create_context_modes
!= NULL
) {
492 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
493 *driver_modes
= i830FillInModes( dri_priv
->cpp
* 8,
494 (dri_priv
->cpp
== 2) ? 16 : 24,
495 (dri_priv
->cpp
== 2) ? 0 : 8,
496 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
502 #endif /* USE_NEW_INTERFACE */