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"
36 #include "intel_screen.h"
38 #include "intel_tex.h"
39 #include "intel_span.h"
40 #include "intel_tris.h"
41 #include "intel_ioctl.h"
47 const char __driConfigOptions
[] =
49 DRI_CONF_SECTION_PERFORMANCE
50 DRI_CONF_FORCE_S3TC_ENABLE(false)
53 const GLuint __driNConfigOptions
= 1;
55 #ifdef USE_NEW_INTERFACE
56 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
57 #endif /*USE_NEW_INTERFACE*/
60 static void intelPrintDRIInfo(intelScreenPrivate
*intelScreen
,
61 __DRIscreenPrivate
*sPriv
,
64 fprintf(stderr
, "Front size : 0x%x\n", sPriv
->fbSize
);
65 fprintf(stderr
, "Front offset : 0x%x\n", intelScreen
->frontOffset
);
66 fprintf(stderr
, "Back size : 0x%x\n", intelScreen
->back
.size
);
67 fprintf(stderr
, "Back offset : 0x%x\n", intelScreen
->backOffset
);
68 fprintf(stderr
, "Depth size : 0x%x\n", intelScreen
->depth
.size
);
69 fprintf(stderr
, "Depth offset : 0x%x\n", intelScreen
->depthOffset
);
70 fprintf(stderr
, "Texture size : 0x%x\n", intelScreen
->textureSize
);
71 fprintf(stderr
, "Texture offset : 0x%x\n", intelScreen
->textureOffset
);
72 fprintf(stderr
, "Memory : 0x%x\n", gDRIPriv
->mem
);
75 static GLboolean
intelInitDriver(__DRIscreenPrivate
*sPriv
)
77 intelScreenPrivate
*intelScreen
;
78 I830DRIPtr gDRIPriv
= (I830DRIPtr
)sPriv
->pDevPriv
;
81 /* Allocate the private area */
82 intelScreen
= (intelScreenPrivate
*)MALLOC(sizeof(intelScreenPrivate
));
84 fprintf(stderr
,"\nERROR! Allocating private area failed\n");
87 /* parse information in __driConfigOptions */
88 driParseOptionInfo (&intelScreen
->optionCache
,
89 __driConfigOptions
, __driNConfigOptions
);
91 intelScreen
->driScrnPriv
= sPriv
;
92 sPriv
->private = (void *)intelScreen
;
94 intelScreen
->deviceID
= gDRIPriv
->deviceID
;
95 intelScreen
->width
= gDRIPriv
->width
;
96 intelScreen
->height
= gDRIPriv
->height
;
97 intelScreen
->mem
= gDRIPriv
->mem
;
98 intelScreen
->cpp
= gDRIPriv
->cpp
;
99 intelScreen
->frontPitch
= gDRIPriv
->fbStride
;
100 intelScreen
->frontOffset
= gDRIPriv
->fbOffset
;
102 switch (gDRIPriv
->bitsPerPixel
) {
103 case 15: intelScreen
->fbFormat
= DV_PF_555
; break;
104 case 16: intelScreen
->fbFormat
= DV_PF_565
; break;
105 case 32: intelScreen
->fbFormat
= DV_PF_8888
; break;
108 intelScreen
->backOffset
= gDRIPriv
->backOffset
;
109 intelScreen
->backPitch
= gDRIPriv
->backPitch
;
110 intelScreen
->depthOffset
= gDRIPriv
->depthOffset
;
111 intelScreen
->depthPitch
= gDRIPriv
->depthPitch
;
112 intelScreen
->textureOffset
= gDRIPriv
->textureOffset
;
113 intelScreen
->textureSize
= gDRIPriv
->textureSize
;
114 intelScreen
->logTextureGranularity
= gDRIPriv
->logTextureGranularity
;
115 intelScreen
->back
.handle
= gDRIPriv
->backbuffer
;
116 intelScreen
->back
.size
= gDRIPriv
->backbufferSize
;
118 if (drmMap(sPriv
->fd
,
119 intelScreen
->back
.handle
,
120 intelScreen
->back
.size
,
121 (drmAddress
*)&intelScreen
->back
.map
) != 0) {
122 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
123 __LINE__
, __FUNCTION__
, __FILE__
);
125 sPriv
->private = NULL
;
129 intelScreen
->depth
.handle
= gDRIPriv
->depthbuffer
;
130 intelScreen
->depth
.size
= gDRIPriv
->depthbufferSize
;
132 if (drmMap(sPriv
->fd
,
133 intelScreen
->depth
.handle
,
134 intelScreen
->depth
.size
,
135 (drmAddress
*)&intelScreen
->depth
.map
) != 0) {
136 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
137 __LINE__
, __FUNCTION__
, __FILE__
);
139 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
140 sPriv
->private = NULL
;
144 intelScreen
->tex
.handle
= gDRIPriv
->textures
;
145 intelScreen
->tex
.size
= gDRIPriv
->textureSize
;
147 if (drmMap(sPriv
->fd
,
148 intelScreen
->tex
.handle
,
149 intelScreen
->tex
.size
,
150 (drmAddress
*)&intelScreen
->tex
.map
) != 0) {
151 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
152 __LINE__
, __FUNCTION__
, __FILE__
);
154 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
155 drmUnmap(intelScreen
->depth
.map
, intelScreen
->depth
.size
);
156 sPriv
->private = NULL
;
160 intelScreen
->sarea_priv_offset
= gDRIPriv
->sarea_priv_offset
;
162 if (0) intelPrintDRIInfo(intelScreen
, sPriv
, gDRIPriv
);
164 intelScreen
->drmMinor
= sPriv
->drmMinor
;
170 gp
.param
= I830_PARAM_IRQ_ACTIVE
;
171 gp
.value
= &intelScreen
->irq_active
;
173 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
176 fprintf(stderr
, "drmI830GetParam: %d\n", ret
);
185 gp
.param
= I830_PARAM_ALLOW_BATCHBUFFER
;
186 gp
.value
= &intelScreen
->allow_batchbuffer
;
188 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
191 fprintf(stderr
, "drmI830GetParam: (%d) %d\n", gp
.param
, ret
);
196 if ( driCompareGLXAPIVersion( 20030813 ) >= 0 ) {
197 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
198 (PFNGLXSCRENABLEEXTENSIONPROC
) glXGetProcAddress( (const GLubyte
*) "__glXScrEnableExtension" );
199 void * const psc
= sPriv
->psc
->screenConfigs
;
201 if (glx_enable_extension
!= NULL
) {
202 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
204 if ( driCompareGLXAPIVersion( 20030915 ) >= 0 ) {
205 (*glx_enable_extension
)( psc
, "GLX_SGIX_fbconfig" );
206 (*glx_enable_extension
)( psc
, "GLX_OML_swap_method" );
209 if ( driCompareGLXAPIVersion( 20030818 ) >= 0 ) {
210 sPriv
->psc
->allocateMemory
= (void *) intelAllocateMemoryMESA
;
211 sPriv
->psc
->freeMemory
= (void *) intelFreeMemoryMESA
;
212 sPriv
->psc
->memoryOffset
= (void *) intelGetMemoryOffsetMESA
;
214 (*glx_enable_extension
)( psc
, "GLX_MESA_allocate_memory" );
223 static void intelDestroyScreen(__DRIscreenPrivate
*sPriv
)
225 intelScreenPrivate
*intelScreen
= (intelScreenPrivate
*)sPriv
->private;
227 /* Need to unmap all the bufs and maps here:
229 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
230 drmUnmap(intelScreen
->depth
.map
, intelScreen
->depth
.size
);
231 drmUnmap(intelScreen
->tex
.map
, intelScreen
->tex
.size
);
233 sPriv
->private = NULL
;
236 static GLboolean
intelCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
237 __DRIdrawablePrivate
*driDrawPriv
,
238 const __GLcontextModes
*mesaVis
,
242 return GL_FALSE
; /* not implemented */
244 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
245 mesaVis
->depthBits
!= 24);
247 driDrawPriv
->driverPrivate
= (void *)
248 _mesa_create_framebuffer(mesaVis
,
249 GL_FALSE
, /* software depth buffer? */
251 mesaVis
->accumRedBits
> 0,
252 GL_FALSE
/* s/w alpha planes */);
254 return (driDrawPriv
->driverPrivate
!= NULL
);
258 static void intelDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
260 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
264 /* There are probably better ways to do this, such as an
265 * init-designated function to register chipids and createcontext
268 extern GLboolean
i830CreateContext( const __GLcontextModes
*mesaVis
,
269 __DRIcontextPrivate
*driContextPriv
,
270 void *sharedContextPrivate
);
272 extern GLboolean
i915CreateContext( const __GLcontextModes
*mesaVis
,
273 __DRIcontextPrivate
*driContextPriv
,
274 void *sharedContextPrivate
);
279 static GLboolean
intelCreateContext( const __GLcontextModes
*mesaVis
,
280 __DRIcontextPrivate
*driContextPriv
,
281 void *sharedContextPrivate
)
283 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
284 intelScreenPrivate
*intelScreen
= (intelScreenPrivate
*)sPriv
->private;
286 switch (intelScreen
->deviceID
) {
288 case PCI_CHIP_I830_M
:
289 case PCI_CHIP_I855_GM
:
290 case PCI_CHIP_I865_G
:
291 return i830CreateContext( mesaVis
, driContextPriv
,
292 sharedContextPrivate
);
294 case PCI_CHIP_I915_G
:
295 return i915CreateContext( mesaVis
, driContextPriv
,
296 sharedContextPrivate
);
299 fprintf(stderr
, "Unrecognized deviceID %x\n", intelScreen
->deviceID
);
305 static const struct __DriverAPIRec intelAPI
= {
306 .InitDriver
= intelInitDriver
,
307 .DestroyScreen
= intelDestroyScreen
,
308 .CreateContext
= intelCreateContext
,
309 .DestroyContext
= intelDestroyContext
,
310 .CreateBuffer
= intelCreateBuffer
,
311 .DestroyBuffer
= intelDestroyBuffer
,
312 .SwapBuffers
= intelSwapBuffers
,
313 .MakeCurrent
= intelMakeCurrent
,
314 .UnbindContext
= intelUnbindContext
,
319 .SwapBuffersMSC
= NULL
323 * This is the bootstrap function for the driver.
324 * The __driCreateScreen name is the symbol that libGL.so fetches.
325 * Return: pointer to a __DRIscreenPrivate.
327 #if !defined(DRI_NEW_INTERFACE_ONLY)
328 void *__driCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
329 int numConfigs
, __GLXvisualConfig
*config
)
331 __DRIscreenPrivate
*psp
;
332 psp
= __driUtilCreateScreen(dpy
, scrn
, psc
, numConfigs
, config
, &intelAPI
);
335 #endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
338 #ifdef USE_NEW_INTERFACE
339 static __GLcontextModes
*
340 intelFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
341 unsigned stencil_bits
, GLboolean have_back_buffer
)
343 __GLcontextModes
* modes
;
344 __GLcontextModes
* m
;
346 unsigned depth_buffer_factor
;
347 unsigned back_buffer_factor
;
351 /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
352 * support pageflipping at all.
354 static const GLenum back_buffer_modes
[] = {
355 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
358 uint8_t depth_bits_array
[2];
359 uint8_t stencil_bits_array
[2];
362 depth_bits_array
[0] = 0;
363 depth_bits_array
[1] = depth_bits
;
365 /* Just like with the accumulation buffer, always provide some modes
366 * with a stencil buffer. It will be a sw fallback, but some apps won't
369 stencil_bits_array
[0] = 0;
370 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
372 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 2 : 1;
373 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
375 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
377 if ( pixel_bits
== 16 ) {
379 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
383 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
386 modes
= (*create_context_modes
)( num_modes
, sizeof( __GLcontextModes
) );
388 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
389 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
390 back_buffer_modes
, back_buffer_factor
,
392 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
393 __func__
, __LINE__
);
397 /* There's no direct color modes on intel? */
399 /* Mark the visual as slow if there are "fake" stencil bits.
401 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
402 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
403 m
->visualRating
= GLX_SLOW_CONFIG
;
409 #endif /* USE_NEW_INTERFACE */
413 * This is the bootstrap function for the driver. libGL supplies all of the
414 * requisite information about the system, and the driver initializes itself.
415 * This routine also fills in the linked list pointed to by \c driver_modes
416 * with the \c __GLcontextModes that the driver can support for windows or
419 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
422 #ifdef USE_NEW_INTERFACE
423 void * __driCreateNewScreen( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
424 const __GLcontextModes
* modes
,
425 const __DRIversion
* ddx_version
,
426 const __DRIversion
* dri_version
,
427 const __DRIversion
* drm_version
,
428 const __DRIframebuffer
* frame_buffer
,
429 drmAddress pSAREA
, int fd
,
430 int internal_api_version
,
431 __GLcontextModes
** driver_modes
)
434 __DRIscreenPrivate
*psp
;
435 static const __DRIversion ddx_expected
= { 1, 0, 0 };
436 static const __DRIversion dri_expected
= { 4, 0, 0 };
437 static const __DRIversion drm_expected
= { 1, 1, 0 };
439 if ( ! driCheckDriDdxDrmVersions2( "i915",
440 dri_version
, & dri_expected
,
441 ddx_version
, & ddx_expected
,
442 drm_version
, & drm_expected
) ) {
446 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
447 ddx_version
, dri_version
, drm_version
,
448 frame_buffer
, pSAREA
, fd
,
449 internal_api_version
, &intelAPI
);
451 create_context_modes
= (PFNGLXCREATECONTEXTMODES
)
452 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextModes" );
453 if ( create_context_modes
!= NULL
) {
454 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
455 *driver_modes
= intelFillInModes( dri_priv
->cpp
* 8,
456 (dri_priv
->cpp
== 2) ? 16 : 24,
457 (dri_priv
->cpp
== 2) ? 0 : 8,
458 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
464 #endif /* USE_NEW_INTERFACE */