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
;
149 if (sPriv
->devPrivSize
!= sizeof(I830DRIRec
)) {
150 fprintf(stderr
,"\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
154 /* Allocate the private area */
155 i830Screen
= (i830ScreenPrivate
*)CALLOC(sizeof(i830ScreenPrivate
));
157 fprintf(stderr
,"\nERROR! Allocating private area failed\n");
161 /* parse information in __driConfigOptions */
162 driParseOptionInfo (&i830Screen
->optionCache
,
163 __driConfigOptions
, __driNConfigOptions
);
166 i830Screen
->driScrnPriv
= sPriv
;
167 sPriv
->private = (void *)i830Screen
;
169 i830Screen
->deviceID
= gDRIPriv
->deviceID
;
170 i830Screen
->width
= gDRIPriv
->width
;
171 i830Screen
->height
= gDRIPriv
->height
;
172 i830Screen
->mem
= gDRIPriv
->mem
;
173 i830Screen
->cpp
= gDRIPriv
->cpp
;
174 i830Screen
->fbStride
= gDRIPriv
->fbStride
;
175 i830Screen
->fbOffset
= gDRIPriv
->fbOffset
;
177 switch (gDRIPriv
->bitsPerPixel
) {
178 case 15: i830Screen
->fbFormat
= DV_PF_555
; break;
179 case 16: i830Screen
->fbFormat
= DV_PF_565
; break;
180 case 32: i830Screen
->fbFormat
= DV_PF_8888
; break;
183 i830Screen
->backOffset
= gDRIPriv
->backOffset
;
184 i830Screen
->depthOffset
= gDRIPriv
->depthOffset
;
185 i830Screen
->backPitch
= gDRIPriv
->auxPitch
;
186 i830Screen
->backPitchBits
= gDRIPriv
->auxPitchBits
;
187 i830Screen
->textureOffset
= gDRIPriv
->textureOffset
;
188 i830Screen
->textureSize
= gDRIPriv
->textureSize
;
189 i830Screen
->logTextureGranularity
= gDRIPriv
->logTextureGranularity
;
192 i830Screen
->bufs
= i830_create_empty_buffers();
193 if(i830Screen
->bufs
== NULL
) {
194 fprintf(stderr
,"\nERROR: Failed to create empty buffers in %s \n",
200 /* Check if you need to create a fake buffer */
201 if(i830_check_copy(sPriv
->fd
) == 1) {
202 i830_malloc_proxy_buf(i830Screen
->bufs
);
203 i830Screen
->use_copy_buf
= 1;
205 i830Screen
->use_copy_buf
= 0;
208 i830Screen
->back
.handle
= gDRIPriv
->backbuffer
;
209 i830Screen
->back
.size
= gDRIPriv
->backbufferSize
;
211 if (drmMap(sPriv
->fd
,
212 i830Screen
->back
.handle
,
213 i830Screen
->back
.size
,
214 (drmAddress
*)&i830Screen
->back
.map
) != 0) {
215 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
216 __LINE__
, __FUNCTION__
, __FILE__
);
218 sPriv
->private = NULL
;
222 i830Screen
->depth
.handle
= gDRIPriv
->depthbuffer
;
223 i830Screen
->depth
.size
= gDRIPriv
->depthbufferSize
;
225 if (drmMap(sPriv
->fd
,
226 i830Screen
->depth
.handle
,
227 i830Screen
->depth
.size
,
228 (drmAddress
*)&i830Screen
->depth
.map
) != 0) {
229 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
230 __LINE__
, __FUNCTION__
, __FILE__
);
232 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
233 sPriv
->private = NULL
;
237 i830Screen
->tex
.handle
= gDRIPriv
->textures
;
238 i830Screen
->tex
.size
= gDRIPriv
->textureSize
;
240 if (drmMap(sPriv
->fd
,
241 i830Screen
->tex
.handle
,
242 i830Screen
->tex
.size
,
243 (drmAddress
*)&i830Screen
->tex
.map
) != 0) {
244 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
245 __LINE__
, __FUNCTION__
, __FILE__
);
247 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
248 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
249 sPriv
->private = NULL
;
253 i830Screen
->sarea_priv_offset
= gDRIPriv
->sarea_priv_offset
;
255 if (0) i830PrintDRIInfo(i830Screen
, sPriv
, gDRIPriv
);
257 i830Screen
->drmMinor
= sPriv
->drmMinor
;
259 if (sPriv
->drmMinor
>= 3) {
263 gp
.param
= I830_PARAM_IRQ_ACTIVE
;
264 gp
.value
= &i830Screen
->irq_active
;
266 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
269 fprintf(stderr
, "drmI830GetParam: %d\n", ret
);
275 if (sPriv
->drmMinor
>= 3) {
279 sp
.param
= I830_SETPARAM_PERF_BOXES
;
280 sp
.value
= (getenv("I830_DO_BOXES") != 0);
282 ret
= drmCommandWrite( sPriv
->fd
, DRM_I830_SETPARAM
,
285 fprintf(stderr
, "Couldn't set perfboxes: %d\n", ret
);
289 if ( glx_enable_extension
!= NULL
) {
290 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
297 static void i830DestroyScreen(__DRIscreenPrivate
*sPriv
)
299 i830ScreenPrivate
*i830Screen
= (i830ScreenPrivate
*)sPriv
->private;
301 /* Need to unmap all the bufs and maps here:
303 drmUnmap(i830Screen
->back
.map
, i830Screen
->back
.size
);
304 drmUnmap(i830Screen
->depth
.map
, i830Screen
->depth
.size
);
305 drmUnmap(i830Screen
->tex
.map
, i830Screen
->tex
.size
);
307 sPriv
->private = NULL
;
311 static GLboolean
i830CreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
312 __DRIdrawablePrivate
*driDrawPriv
,
313 const __GLcontextModes
*mesaVis
,
316 i830ScreenPrivate
*screen
= (i830ScreenPrivate
*) driScrnPriv
->private;
319 return GL_FALSE
; /* not implemented */
323 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
324 mesaVis
->depthBits
!= 24);
326 GLboolean swStencil
= mesaVis
->stencilBits
> 0;
329 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
332 driRenderbuffer
*frontRb
333 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
334 /*screen->frontOffset*/0, screen
->backPitch
,
336 i830SetSpanFunctions(frontRb
, mesaVis
);
337 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
340 if (mesaVis
->doubleBufferMode
) {
341 driRenderbuffer
*backRb
342 = driNewRenderbuffer(GL_RGBA
, NULL
, screen
->cpp
,
343 screen
->backOffset
, screen
->backPitch
,
345 i830SetSpanFunctions(backRb
, mesaVis
);
346 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
349 if (mesaVis
->depthBits
== 16) {
350 driRenderbuffer
*depthRb
351 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
, NULL
, screen
->cpp
,
352 screen
->depthOffset
, screen
->backPitch
,
354 i830SetSpanFunctions(depthRb
, mesaVis
);
355 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
357 else if (mesaVis
->depthBits
== 24) {
358 if (mesaVis
->stencilBits
== 8) {
359 driRenderbuffer
*depthRb
360 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
, NULL
, screen
->cpp
,
361 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
, NULL
, screen
->cpp
,
370 screen
->depthOffset
, screen
->backPitch
,
372 i830SetSpanFunctions(depthRb
, mesaVis
);
373 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
377 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
378 driRenderbuffer
*stencilRb
379 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
, NULL
, screen
->cpp
,
380 screen
->depthOffset
, screen
->backPitch
,
382 i830SetSpanFunctions(stencilRb
, mesaVis
);
383 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
386 _mesa_add_soft_renderbuffers(fb
,
387 GL_FALSE
, /* color */
388 GL_FALSE
, /* depth */
390 mesaVis
->accumRedBits
> 0,
391 GL_FALSE
, /* alpha */
393 driDrawPriv
->driverPrivate
= (void *) fb
;
395 return (driDrawPriv
->driverPrivate
!= NULL
);
399 static void i830DestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
401 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
404 static const struct __DriverAPIRec i830API
= {
405 .InitDriver
= i830InitDriver
,
406 .DestroyScreen
= i830DestroyScreen
,
407 .CreateContext
= i830CreateContext
,
408 .DestroyContext
= i830DestroyContext
,
409 .CreateBuffer
= i830CreateBuffer
,
410 .DestroyBuffer
= i830DestroyBuffer
,
411 .SwapBuffers
= i830SwapBuffers
,
412 .MakeCurrent
= i830MakeCurrent
,
413 .UnbindContext
= i830UnbindContext
,
418 .SwapBuffersMSC
= NULL
422 static __GLcontextModes
*
423 i830FillInModes( unsigned pixel_bits
, unsigned depth_bits
,
424 unsigned stencil_bits
, GLboolean have_back_buffer
)
426 __GLcontextModes
* modes
;
427 __GLcontextModes
* m
;
429 unsigned depth_buffer_factor
;
430 unsigned back_buffer_factor
;
434 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
435 * support pageflipping at all.
437 static const GLenum back_buffer_modes
[] = {
438 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
441 u_int8_t depth_bits_array
[2];
442 u_int8_t stencil_bits_array
[2];
445 depth_bits_array
[0] = 0;
446 depth_bits_array
[1] = depth_bits
;
448 /* Just like with the accumulation buffer, always provide some modes
449 * with a stencil buffer. It will be a sw fallback, but some apps won't
452 stencil_bits_array
[0] = 0;
453 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
455 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
456 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
458 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
460 if ( pixel_bits
== 16 ) {
462 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
466 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
469 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
471 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
472 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
473 back_buffer_modes
, back_buffer_factor
,
475 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
476 __func__
, __LINE__
);
480 /* There's no direct color modes on i830? */
482 /* Mark the visual as slow if there are "fake" stencil bits.
484 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
485 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
486 m
->visualRating
= GLX_SLOW_CONFIG
;
495 * This is the bootstrap function for the driver. libGL supplies all of the
496 * requisite information about the system, and the driver initializes itself.
497 * This routine also fills in the linked list pointed to by \c driver_modes
498 * with the \c __GLcontextModes that the driver can support for windows or
501 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
505 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
506 const __GLcontextModes
* modes
,
507 const __DRIversion
* ddx_version
,
508 const __DRIversion
* dri_version
,
509 const __DRIversion
* drm_version
,
510 const __DRIframebuffer
* frame_buffer
,
511 drmAddress pSAREA
, int fd
,
512 int internal_api_version
,
513 const __DRIinterfaceMethods
* interface
,
514 __GLcontextModes
** driver_modes
)
517 __DRIscreenPrivate
*psp
;
518 static const __DRIversion ddx_expected
= { 1, 0, 0 };
519 static const __DRIversion dri_expected
= { 4, 0, 0 };
520 static const __DRIversion drm_expected
= { 1, 3, 0 };
522 dri_interface
= interface
;
524 if ( ! driCheckDriDdxDrmVersions2( "i830",
525 dri_version
, & dri_expected
,
526 ddx_version
, & ddx_expected
,
527 drm_version
, & drm_expected
) ) {
531 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
532 ddx_version
, dri_version
, drm_version
,
533 frame_buffer
, pSAREA
, fd
,
534 internal_api_version
, &i830API
);
536 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
537 *driver_modes
= i830FillInModes( dri_priv
->cpp
* 8,
538 (dri_priv
->cpp
== 2) ? 16 : 24,
539 (dri_priv
->cpp
== 2) ? 0 : 8,
540 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
542 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
543 * enable the extensions. It just makes sure that all the dispatch offsets for all
544 * the extensions that *might* be enables are known. This is needed because the
545 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
546 * enable the extensions until we have a context pointer.
548 * Hello chicken. Hello egg. How are you two today?
550 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);