1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, 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 TUNGSTEN GRAPHICS 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 **************************************************************************/
31 #include "simple_list.h"
35 #include "intel_screen.h"
37 #include "intel_tex.h"
38 #include "intel_span.h"
39 #include "intel_tris.h"
40 #include "intel_ioctl.h"
46 #ifdef USE_NEW_INTERFACE
47 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
48 #endif /*USE_NEW_INTERFACE*/
51 static void intelPrintDRIInfo(intelScreenPrivate
*intelScreen
,
52 __DRIscreenPrivate
*sPriv
,
55 fprintf(stderr
, "Front size : 0x%x\n", sPriv
->fbSize
);
56 fprintf(stderr
, "Front offset : 0x%x\n", intelScreen
->frontOffset
);
57 fprintf(stderr
, "Back size : 0x%x\n", intelScreen
->back
.size
);
58 fprintf(stderr
, "Back offset : 0x%x\n", intelScreen
->backOffset
);
59 fprintf(stderr
, "Depth size : 0x%x\n", intelScreen
->depth
.size
);
60 fprintf(stderr
, "Depth offset : 0x%x\n", intelScreen
->depthOffset
);
61 fprintf(stderr
, "Texture size : 0x%x\n", intelScreen
->textureSize
);
62 fprintf(stderr
, "Texture offset : 0x%x\n", intelScreen
->textureOffset
);
63 fprintf(stderr
, "Memory : 0x%x\n", gDRIPriv
->mem
);
66 static GLboolean
intelInitDriver(__DRIscreenPrivate
*sPriv
)
68 intelScreenPrivate
*intelScreen
;
69 I830DRIPtr gDRIPriv
= (I830DRIPtr
)sPriv
->pDevPriv
;
72 /* Allocate the private area */
73 intelScreen
= (intelScreenPrivate
*)MALLOC(sizeof(intelScreenPrivate
));
75 fprintf(stderr
,"\nERROR! Allocating private area failed\n");
79 intelScreen
->driScrnPriv
= sPriv
;
80 sPriv
->private = (void *)intelScreen
;
82 intelScreen
->deviceID
= gDRIPriv
->deviceID
;
83 intelScreen
->width
= gDRIPriv
->width
;
84 intelScreen
->height
= gDRIPriv
->height
;
85 intelScreen
->mem
= gDRIPriv
->mem
;
86 intelScreen
->cpp
= gDRIPriv
->cpp
;
87 intelScreen
->frontPitch
= gDRIPriv
->fbStride
;
88 intelScreen
->frontOffset
= gDRIPriv
->fbOffset
;
90 switch (gDRIPriv
->bitsPerPixel
) {
91 case 15: intelScreen
->fbFormat
= DV_PF_555
; break;
92 case 16: intelScreen
->fbFormat
= DV_PF_565
; break;
93 case 32: intelScreen
->fbFormat
= DV_PF_8888
; break;
96 intelScreen
->backOffset
= gDRIPriv
->backOffset
;
97 intelScreen
->backPitch
= gDRIPriv
->backPitch
;
98 intelScreen
->depthOffset
= gDRIPriv
->depthOffset
;
99 intelScreen
->depthPitch
= gDRIPriv
->depthPitch
;
100 intelScreen
->textureOffset
= gDRIPriv
->textureOffset
;
101 intelScreen
->textureSize
= gDRIPriv
->textureSize
;
102 intelScreen
->logTextureGranularity
= gDRIPriv
->logTextureGranularity
;
103 intelScreen
->back
.handle
= gDRIPriv
->backbuffer
;
104 intelScreen
->back
.size
= gDRIPriv
->backbufferSize
;
106 if (drmMap(sPriv
->fd
,
107 intelScreen
->back
.handle
,
108 intelScreen
->back
.size
,
109 (drmAddress
*)&intelScreen
->back
.map
) != 0) {
110 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
111 __LINE__
, __FUNCTION__
, __FILE__
);
113 sPriv
->private = NULL
;
117 intelScreen
->depth
.handle
= gDRIPriv
->depthbuffer
;
118 intelScreen
->depth
.size
= gDRIPriv
->depthbufferSize
;
120 if (drmMap(sPriv
->fd
,
121 intelScreen
->depth
.handle
,
122 intelScreen
->depth
.size
,
123 (drmAddress
*)&intelScreen
->depth
.map
) != 0) {
124 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
125 __LINE__
, __FUNCTION__
, __FILE__
);
127 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
128 sPriv
->private = NULL
;
132 intelScreen
->tex
.handle
= gDRIPriv
->textures
;
133 intelScreen
->tex
.size
= gDRIPriv
->textureSize
;
135 if (drmMap(sPriv
->fd
,
136 intelScreen
->tex
.handle
,
137 intelScreen
->tex
.size
,
138 (drmAddress
*)&intelScreen
->tex
.map
) != 0) {
139 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
140 __LINE__
, __FUNCTION__
, __FILE__
);
142 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
143 drmUnmap(intelScreen
->depth
.map
, intelScreen
->depth
.size
);
144 sPriv
->private = NULL
;
148 intelScreen
->sarea_priv_offset
= gDRIPriv
->sarea_priv_offset
;
150 if (0) intelPrintDRIInfo(intelScreen
, sPriv
, gDRIPriv
);
152 intelScreen
->drmMinor
= sPriv
->drmMinor
;
158 gp
.param
= I830_PARAM_IRQ_ACTIVE
;
159 gp
.value
= &intelScreen
->irq_active
;
161 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
164 fprintf(stderr
, "drmI830GetParam: %d\n", ret
);
173 gp
.param
= I830_PARAM_ALLOW_BATCHBUFFER
;
174 gp
.value
= &intelScreen
->allow_batchbuffer
;
176 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
179 fprintf(stderr
, "drmI830GetParam: (%d) %d\n", gp
.param
, ret
);
185 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
186 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
187 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
188 void * const psc
= sPriv
->psc
->screenConfigs
;
190 if (glx_enable_extension
!= NULL
) {
191 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
193 if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
194 (*glx_enable_extension
)( psc
, "GLX_SGIX_fbconfig" );
195 (*glx_enable_extension
)( psc
, "GLX_OML_swap_method" );
198 if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
199 sPriv
->psc
->allocateMemory
= (void *) intelAllocateMemoryMESA
;
200 sPriv
->psc
->freeMemory
= (void *) intelFreeMemoryMESA
;
201 sPriv
->psc
->memoryOffset
= (void *) intelGetMemoryOffsetMESA
;
203 (*glx_enable_extension
)( psc
, "GLX_MESA_allocate_memory" );
213 static void intelDestroyScreen(__DRIscreenPrivate
*sPriv
)
215 intelScreenPrivate
*intelScreen
= (intelScreenPrivate
*)sPriv
->private;
217 /* Need to unmap all the bufs and maps here:
219 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
220 drmUnmap(intelScreen
->depth
.map
, intelScreen
->depth
.size
);
221 drmUnmap(intelScreen
->tex
.map
, intelScreen
->tex
.size
);
223 sPriv
->private = NULL
;
226 static GLboolean
intelCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
227 __DRIdrawablePrivate
*driDrawPriv
,
228 const __GLcontextModes
*mesaVis
,
232 return GL_FALSE
; /* not implemented */
234 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
235 mesaVis
->depthBits
!= 24);
237 driDrawPriv
->driverPrivate
= (void *)
238 _mesa_create_framebuffer(mesaVis
,
239 GL_FALSE
, /* software depth buffer? */
241 mesaVis
->accumRedBits
> 0,
242 GL_FALSE
/* s/w alpha planes */);
244 return (driDrawPriv
->driverPrivate
!= NULL
);
248 static void intelDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
250 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
254 /* There are probably better ways to do this, such as an
255 * init-designated function to register chipids and createcontext
258 extern GLboolean
i830CreateContext( const __GLcontextModes
*mesaVis
,
259 __DRIcontextPrivate
*driContextPriv
,
260 void *sharedContextPrivate
);
262 extern GLboolean
i915CreateContext( const __GLcontextModes
*mesaVis
,
263 __DRIcontextPrivate
*driContextPriv
,
264 void *sharedContextPrivate
);
269 static GLboolean
intelCreateContext( const __GLcontextModes
*mesaVis
,
270 __DRIcontextPrivate
*driContextPriv
,
271 void *sharedContextPrivate
)
273 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
274 intelScreenPrivate
*intelScreen
= (intelScreenPrivate
*)sPriv
->private;
276 switch (intelScreen
->deviceID
) {
278 case PCI_CHIP_I830_M
:
279 case PCI_CHIP_I855_GM
:
280 case PCI_CHIP_I865_G
:
281 return i830CreateContext( mesaVis
, driContextPriv
,
282 sharedContextPrivate
);
284 case PCI_CHIP_I915_G
:
285 return i915CreateContext( mesaVis
, driContextPriv
,
286 sharedContextPrivate
);
289 fprintf(stderr
, "Unrecognized deviceID %x\n", intelScreen
->deviceID
);
295 static const struct __DriverAPIRec intelAPI
= {
296 .InitDriver
= intelInitDriver
,
297 .DestroyScreen
= intelDestroyScreen
,
298 .CreateContext
= intelCreateContext
,
299 .DestroyContext
= intelDestroyContext
,
300 .CreateBuffer
= intelCreateBuffer
,
301 .DestroyBuffer
= intelDestroyBuffer
,
302 .SwapBuffers
= intelSwapBuffers
,
303 .MakeCurrent
= intelMakeCurrent
,
304 .UnbindContext
= intelUnbindContext
,
309 .SwapBuffersMSC
= NULL
313 * This is the bootstrap function for the driver.
314 * The __driCreateScreen name is the symbol that libGL.so fetches.
315 * Return: pointer to a __DRIscreenPrivate.
317 #if !defined(DRI_NEW_INTERFACE_ONLY)
319 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
320 int numConfigs
, __GLXvisualConfig
*config
)
322 __DRIscreenPrivate
*psp
;
323 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &intelAPI
);
327 void *__driCreateScreen(struct DRIDriverRec
*driver
,
328 struct DRIDriverContextRec
*driverContext
)
330 __DRIscreenPrivate
*psp
;
331 psp
= __driUtilCreateScreen(driver
, driverContext
, &i830API
);
335 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
338 /* This function is called by libGL.so as soon as libGL.so is loaded.
339 * This is where we'd register new extension functions with the dispatcher.
341 * Note: Most of these are probably already registered - just doing
342 * this for the benefit of old libGL.so's out there.
344 #include "glapioffsets.h"
346 void __driRegisterExtensions( void )
349 static struct { const char *name
; int offset
; } funcs
[] = {
350 { "glSecondaryColor3bEXT", _gloffset_SecondaryColor3bEXT
},
351 { "glSecondaryColor3dEXT", _gloffset_SecondaryColor3dEXT
},
352 { "glSecondaryColor3fEXT", _gloffset_SecondaryColor3fEXT
},
353 { "glSecondaryColor3iEXT", _gloffset_SecondaryColor3iEXT
},
354 { "glSecondaryColor3sEXT", _gloffset_SecondaryColor3sEXT
},
355 { "glSecondaryColor3ubEXT", _gloffset_SecondaryColor3ubEXT
},
356 { "glSecondaryColor3uiEXT", _gloffset_SecondaryColor3uiEXT
},
357 { "glSecondaryColor3usEXT", _gloffset_SecondaryColor3usEXT
},
358 { "glSecondaryColor3bvEXT", _gloffset_SecondaryColor3bvEXT
},
359 { "glSecondaryColor3dvEXT", _gloffset_SecondaryColor3dvEXT
},
360 { "glSecondaryColor3fvEXT", _gloffset_SecondaryColor3fvEXT
},
361 { "glSecondaryColor3ivEXT", _gloffset_SecondaryColor3ivEXT
},
362 { "glSecondaryColor3svEXT", _gloffset_SecondaryColor3svEXT
},
363 { "glSecondaryColor3ubvEXT", _gloffset_SecondaryColor3ubvEXT
},
364 { "glSecondaryColor3uivEXT", _gloffset_SecondaryColor3uivEXT
},
365 { "glSecondaryColor3usvEXT", _gloffset_SecondaryColor3usvEXT
},
366 { "glSecondaryColorPointerEXT", _gloffset_SecondaryColorPointerEXT
}
369 for (i
= 0 ; i
< sizeof(funcs
) / sizeof(*funcs
) ; i
++ )
370 _glapi_add_entrypoint( funcs
[i
].name
, funcs
[i
].offset
);
374 #ifdef USE_NEW_INTERFACE
375 static __GLcontextModes
* fill_in_modes( __GLcontextModes
* modes
,
378 unsigned stencil_bits
,
379 const GLenum
* db_modes
,
380 unsigned num_db_modes
,
383 static const uint8_t bits
[2][4] = {
388 static const uint32_t masks
[2][4] = {
389 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
390 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }
395 const unsigned index
= ((pixel_bits
+ 15) / 16) - 1;
397 for ( i
= 0 ; i
< num_db_modes
; i
++ ) {
398 for ( j
= 0 ; j
< 2 ; j
++ ) {
400 modes
->redBits
= bits
[index
][0];
401 modes
->greenBits
= bits
[index
][1];
402 modes
->blueBits
= bits
[index
][2];
403 modes
->alphaBits
= bits
[index
][3];
404 modes
->redMask
= masks
[index
][0];
405 modes
->greenMask
= masks
[index
][1];
406 modes
->blueMask
= masks
[index
][2];
407 modes
->alphaMask
= masks
[index
][3];
408 modes
->rgbBits
= modes
->redBits
+ modes
->greenBits
409 + modes
->blueBits
+ modes
->alphaBits
;
411 modes
->accumRedBits
= 16 * j
;
412 modes
->accumGreenBits
= 16 * j
;
413 modes
->accumBlueBits
= 16 * j
;
414 modes
->accumAlphaBits
= (masks
[index
][3] != 0) ? 16 * j
: 0;
415 modes
->visualRating
= (j
== 0) ? GLX_NONE
: GLX_SLOW_CONFIG
;
417 modes
->stencilBits
= stencil_bits
;
418 modes
->depthBits
= depth_bits
;
420 modes
->visualType
= visType
;
421 modes
->renderType
= GLX_RGBA_BIT
;
422 modes
->drawableType
= GLX_WINDOW_BIT
;
423 modes
->rgbMode
= GL_TRUE
;
425 if ( db_modes
[i
] == GLX_NONE
) {
426 modes
->doubleBufferMode
= GL_FALSE
;
429 modes
->doubleBufferMode
= GL_TRUE
;
430 modes
->swapMethod
= db_modes
[i
];
439 #endif /* USE_NEW_INTERFACE */
442 #ifdef USE_NEW_INTERFACE
443 static __GLcontextModes
*
444 intelFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
445 unsigned stencil_bits
, GLboolean have_back_buffer
)
447 __GLcontextModes
* modes
;
448 __GLcontextModes
* m
;
450 unsigned depth_buffer_factor
;
451 unsigned back_buffer_factor
;
454 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
455 * support pageflipping at all.
457 static const GLenum back_buffer_modes
[] = {
458 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
461 int depth_buffer_modes
[2][2];
464 depth_buffer_modes
[0][0] = depth_bits
;
465 depth_buffer_modes
[1][0] = depth_bits
;
467 /* Just like with the accumulation buffer, always provide some modes
468 * with a stencil buffer. It will be a sw fallback, but some apps won't
471 depth_buffer_modes
[0][1] = 0;
472 depth_buffer_modes
[1][1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
474 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
475 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
477 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
479 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
481 for ( i
= 0 ; i
< depth_buffer_factor
; i
++ ) {
482 m
= fill_in_modes( m
, pixel_bits
,
483 depth_buffer_modes
[i
][0], depth_buffer_modes
[i
][1],
484 back_buffer_modes
, back_buffer_factor
,
488 /* There's no direct color modes on intel? */
490 for ( i
= 0 ; i
< depth_buffer_factor
; i
++ ) {
491 m
= fill_in_modes( m
, pixel_bits
,
492 depth_buffer_modes
[i
][0], depth_buffer_modes
[i
][1],
493 back_buffer_modes
, back_buffer_factor
,
498 /* Mark the visual as slow if there are "fake" stencil bits.
500 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
501 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
502 m
->visualRating
= GLX_SLOW_CONFIG
;
508 #endif /* USE_NEW_INTERFACE */
512 * This is the bootstrap function for the driver. libGL supplies all of the
513 * requisite information about the system, and the driver initializes itself.
514 * This routine also fills in the linked list pointed to by \c driver_modes
515 * with the \c __GLcontextModes that the driver can support for windows or
518 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
521 #ifdef USE_NEW_INTERFACE
522 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
523 const __GLcontextModes
* modes
,
524 const __DRIversion
* ddx_version
,
525 const __DRIversion
* dri_version
,
526 const __DRIversion
* drm_version
,
527 const __DRIframebuffer
* frame_buffer
,
528 drmAddress pSAREA
, int fd
,
529 int internal_api_version
,
530 __GLcontextModes
** driver_modes
)
533 __DRIscreenPrivate
*psp
;
534 static const __DRIversion ddx_expected
= { 1, 0, 0 };
535 static const __DRIversion dri_expected
= { 4, 0, 0 };
536 static const __DRIversion drm_expected
= { 1, 1, 0 };
538 if ( ! driCheckDriDdxDrmVersions2( "i915",
539 dri_version
, & dri_expected
,
540 ddx_version
, & ddx_expected
,
541 drm_version
, & drm_expected
) ) {
545 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
546 ddx_version
, dri_version
, drm_version
,
547 frame_buffer
, pSAREA
, fd
,
548 internal_api_version
, &intelAPI
);
550 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
551 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
552 if ( create_context_modes
!= NULL
) {
553 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
554 *driver_modes
= intelFillInModes( dri_priv
->cpp
* 8,
555 (dri_priv
->cpp
== 2) ? 16 : 24,
556 (dri_priv
->cpp
== 2) ? 0 : 8,
557 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
563 #endif /* USE_NEW_INTERFACE */