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 **************************************************************************/
30 #include "framebuffer.h"
32 #include "renderbuffer.h"
33 #include "simple_list.h"
38 #include "intel_screen.h"
40 #include "intel_tex.h"
41 #include "intel_span.h"
42 #include "intel_tris.h"
43 #include "intel_ioctl.h"
49 PUBLIC
const char __driConfigOptions
[] =
51 DRI_CONF_SECTION_PERFORMANCE
52 DRI_CONF_FORCE_S3TC_ENABLE(false)
55 const GLuint __driNConfigOptions
= 1;
57 extern const struct dri_extension card_extensions
[];
59 static void intelPrintDRIInfo(intelScreenPrivate
*intelScreen
,
60 __DRIscreenPrivate
*sPriv
,
63 fprintf(stderr
, "Front size : 0x%x\n", sPriv
->fbSize
);
64 fprintf(stderr
, "Front offset : 0x%x\n", intelScreen
->front
.offset
);
65 fprintf(stderr
, "Back size : 0x%x\n", intelScreen
->back
.size
);
66 fprintf(stderr
, "Back offset : 0x%x\n", intelScreen
->back
.offset
);
67 fprintf(stderr
, "Depth size : 0x%x\n", intelScreen
->depth
.size
);
68 fprintf(stderr
, "Depth offset : 0x%x\n", intelScreen
->depth
.offset
);
69 fprintf(stderr
, "Texture size : 0x%x\n", intelScreen
->tex
.size
);
70 fprintf(stderr
, "Texture offset : 0x%x\n", intelScreen
->tex
.offset
);
71 fprintf(stderr
, "Memory : 0x%x\n", gDRIPriv
->mem
);
74 static GLboolean
intelInitDriver(__DRIscreenPrivate
*sPriv
)
76 intelScreenPrivate
*intelScreen
;
77 I830DRIPtr gDRIPriv
= (I830DRIPtr
)sPriv
->pDevPriv
;
78 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
79 (PFNGLXSCRENABLEEXTENSIONPROC
) (*dri_interface
->getProcAddress("glxEnableExtension"));
80 void * const psc
= sPriv
->psc
->screenConfigs
;
82 if (sPriv
->devPrivSize
!= sizeof(I830DRIRec
)) {
83 fprintf(stderr
,"\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
87 /* Allocate the private area */
88 intelScreen
= (intelScreenPrivate
*)CALLOC(sizeof(intelScreenPrivate
));
90 fprintf(stderr
,"\nERROR! Allocating private area failed\n");
93 /* parse information in __driConfigOptions */
94 driParseOptionInfo (&intelScreen
->optionCache
,
95 __driConfigOptions
, __driNConfigOptions
);
97 intelScreen
->driScrnPriv
= sPriv
;
98 sPriv
->private = (void *)intelScreen
;
100 intelScreen
->deviceID
= gDRIPriv
->deviceID
;
101 intelScreen
->width
= gDRIPriv
->width
;
102 intelScreen
->height
= gDRIPriv
->height
;
103 intelScreen
->mem
= gDRIPriv
->mem
;
104 intelScreen
->cpp
= gDRIPriv
->cpp
;
106 switch (gDRIPriv
->bitsPerPixel
) {
107 case 15: intelScreen
->fbFormat
= DV_PF_555
; break;
108 case 16: intelScreen
->fbFormat
= DV_PF_565
; break;
109 case 32: intelScreen
->fbFormat
= DV_PF_8888
; break;
112 intelScreen
->front
.pitch
= gDRIPriv
->fbStride
;
113 intelScreen
->front
.offset
= gDRIPriv
->fbOffset
;
114 intelScreen
->front
.map
= sPriv
->pFB
;
116 intelScreen
->back
.offset
= gDRIPriv
->backOffset
;
117 intelScreen
->back
.pitch
= gDRIPriv
->backPitch
;
118 intelScreen
->back
.handle
= gDRIPriv
->backbuffer
;
119 intelScreen
->back
.size
= gDRIPriv
->backbufferSize
;
121 if (drmMap(sPriv
->fd
,
122 intelScreen
->back
.handle
,
123 intelScreen
->back
.size
,
124 (drmAddress
*)&intelScreen
->back
.map
) != 0) {
125 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
126 __LINE__
, __FUNCTION__
, __FILE__
);
128 sPriv
->private = NULL
;
132 intelScreen
->depth
.offset
= gDRIPriv
->depthOffset
;
133 intelScreen
->depth
.pitch
= gDRIPriv
->depthPitch
;
134 intelScreen
->depth
.handle
= gDRIPriv
->depthbuffer
;
135 intelScreen
->depth
.size
= gDRIPriv
->depthbufferSize
;
137 if (drmMap(sPriv
->fd
,
138 intelScreen
->depth
.handle
,
139 intelScreen
->depth
.size
,
140 (drmAddress
*)&intelScreen
->depth
.map
) != 0) {
141 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
142 __LINE__
, __FUNCTION__
, __FILE__
);
144 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
145 sPriv
->private = NULL
;
149 intelScreen
->tex
.offset
= gDRIPriv
->textureOffset
;
150 intelScreen
->logTextureGranularity
= gDRIPriv
->logTextureGranularity
;
151 intelScreen
->tex
.handle
= gDRIPriv
->textures
;
152 intelScreen
->tex
.size
= gDRIPriv
->textureSize
;
154 if (drmMap(sPriv
->fd
,
155 intelScreen
->tex
.handle
,
156 intelScreen
->tex
.size
,
157 (drmAddress
*)&intelScreen
->tex
.map
) != 0) {
158 fprintf(stderr
, "\nERROR: line %d, Function %s, File %s\n",
159 __LINE__
, __FUNCTION__
, __FILE__
);
161 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
162 drmUnmap(intelScreen
->depth
.map
, intelScreen
->depth
.size
);
163 sPriv
->private = NULL
;
167 intelScreen
->sarea_priv_offset
= gDRIPriv
->sarea_priv_offset
;
169 if (0) intelPrintDRIInfo(intelScreen
, sPriv
, gDRIPriv
);
171 intelScreen
->drmMinor
= sPriv
->drmMinor
;
177 gp
.param
= I830_PARAM_IRQ_ACTIVE
;
178 gp
.value
= &intelScreen
->irq_active
;
180 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
183 fprintf(stderr
, "drmI830GetParam: %d\n", ret
);
192 gp
.param
= I830_PARAM_ALLOW_BATCHBUFFER
;
193 gp
.value
= &intelScreen
->allow_batchbuffer
;
195 ret
= drmCommandWriteRead( sPriv
->fd
, DRM_I830_GETPARAM
,
198 fprintf(stderr
, "drmI830GetParam: (%d) %d\n", gp
.param
, ret
);
203 if (glx_enable_extension
!= NULL
) {
204 (*glx_enable_extension
)( psc
, "GLX_SGI_make_current_read" );
205 (*glx_enable_extension
)( psc
, "GLX_MESA_allocate_memory" );
208 sPriv
->psc
->allocateMemory
= (void *) intelAllocateMemoryMESA
;
209 sPriv
->psc
->freeMemory
= (void *) intelFreeMemoryMESA
;
210 sPriv
->psc
->memoryOffset
= (void *) intelGetMemoryOffsetMESA
;
216 static void intelDestroyScreen(__DRIscreenPrivate
*sPriv
)
218 intelScreenPrivate
*intelScreen
= (intelScreenPrivate
*)sPriv
->private;
220 /* Need to unmap all the bufs and maps here:
222 drmUnmap(intelScreen
->back
.map
, intelScreen
->back
.size
);
223 drmUnmap(intelScreen
->depth
.map
, intelScreen
->depth
.size
);
224 drmUnmap(intelScreen
->tex
.map
, intelScreen
->tex
.size
);
226 sPriv
->private = NULL
;
230 static GLboolean
intelCreateBuffer( __DRIscreenPrivate
*driScrnPriv
,
231 __DRIdrawablePrivate
*driDrawPriv
,
232 const __GLcontextModes
*mesaVis
,
235 intelScreenPrivate
*screen
= (intelScreenPrivate
*) driScrnPriv
->private;
238 return GL_FALSE
; /* not implemented */
240 GLboolean swStencil
= (mesaVis
->stencilBits
> 0 &&
241 mesaVis
->depthBits
!= 24);
243 struct gl_framebuffer
*fb
= _mesa_create_framebuffer(mesaVis
);
246 driRenderbuffer
*frontRb
247 = driNewRenderbuffer(GL_RGBA
,
250 screen
->front
.offset
, screen
->front
.pitch
,
252 intelSetSpanFunctions(frontRb
, mesaVis
);
253 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &frontRb
->Base
);
256 if (mesaVis
->doubleBufferMode
) {
257 driRenderbuffer
*backRb
258 = driNewRenderbuffer(GL_RGBA
,
261 screen
->back
.offset
, screen
->back
.pitch
,
263 intelSetSpanFunctions(backRb
, mesaVis
);
264 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &backRb
->Base
);
267 if (mesaVis
->depthBits
== 16) {
268 driRenderbuffer
*depthRb
269 = driNewRenderbuffer(GL_DEPTH_COMPONENT16
,
272 screen
->depth
.offset
, screen
->depth
.pitch
,
274 intelSetSpanFunctions(depthRb
, mesaVis
);
275 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
277 else if (mesaVis
->depthBits
== 24) {
278 driRenderbuffer
*depthRb
279 = driNewRenderbuffer(GL_DEPTH_COMPONENT24
,
282 screen
->depth
.offset
, screen
->depth
.pitch
,
284 intelSetSpanFunctions(depthRb
, mesaVis
);
285 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &depthRb
->Base
);
288 if (mesaVis
->stencilBits
> 0 && !swStencil
) {
289 driRenderbuffer
*stencilRb
290 = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT
,
293 screen
->depth
.offset
, screen
->depth
.pitch
,
295 intelSetSpanFunctions(stencilRb
, mesaVis
);
296 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &stencilRb
->Base
);
299 _mesa_add_soft_renderbuffers(fb
,
300 GL_FALSE
, /* color */
301 GL_FALSE
, /* depth */
303 mesaVis
->accumRedBits
> 0,
304 GL_FALSE
, /* alpha */
306 driDrawPriv
->driverPrivate
= (void *) fb
;
308 return (driDrawPriv
->driverPrivate
!= NULL
);
312 static void intelDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
314 _mesa_destroy_framebuffer((GLframebuffer
*) (driDrawPriv
->driverPrivate
));
318 /* There are probably better ways to do this, such as an
319 * init-designated function to register chipids and createcontext
322 extern GLboolean
i830CreateContext( const __GLcontextModes
*mesaVis
,
323 __DRIcontextPrivate
*driContextPriv
,
324 void *sharedContextPrivate
);
326 extern GLboolean
i915CreateContext( const __GLcontextModes
*mesaVis
,
327 __DRIcontextPrivate
*driContextPriv
,
328 void *sharedContextPrivate
);
333 static GLboolean
intelCreateContext( const __GLcontextModes
*mesaVis
,
334 __DRIcontextPrivate
*driContextPriv
,
335 void *sharedContextPrivate
)
337 __DRIscreenPrivate
*sPriv
= driContextPriv
->driScreenPriv
;
338 intelScreenPrivate
*intelScreen
= (intelScreenPrivate
*)sPriv
->private;
340 switch (intelScreen
->deviceID
) {
342 case PCI_CHIP_I830_M
:
343 case PCI_CHIP_I855_GM
:
344 case PCI_CHIP_I865_G
:
345 return i830CreateContext( mesaVis
, driContextPriv
,
346 sharedContextPrivate
);
348 case PCI_CHIP_I915_G
:
349 case PCI_CHIP_I915_GM
:
350 case PCI_CHIP_I945_G
:
351 return i915CreateContext( mesaVis
, driContextPriv
,
352 sharedContextPrivate
);
355 fprintf(stderr
, "Unrecognized deviceID %x\n", intelScreen
->deviceID
);
361 static const struct __DriverAPIRec intelAPI
= {
362 .InitDriver
= intelInitDriver
,
363 .DestroyScreen
= intelDestroyScreen
,
364 .CreateContext
= intelCreateContext
,
365 .DestroyContext
= intelDestroyContext
,
366 .CreateBuffer
= intelCreateBuffer
,
367 .DestroyBuffer
= intelDestroyBuffer
,
368 .SwapBuffers
= intelSwapBuffers
,
369 .MakeCurrent
= intelMakeCurrent
,
370 .UnbindContext
= intelUnbindContext
,
375 .SwapBuffersMSC
= NULL
379 static __GLcontextModes
*
380 intelFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
381 unsigned stencil_bits
, GLboolean have_back_buffer
)
383 __GLcontextModes
* modes
;
384 __GLcontextModes
* m
;
386 unsigned depth_buffer_factor
;
387 unsigned back_buffer_factor
;
391 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
392 * support pageflipping at all.
394 static const GLenum back_buffer_modes
[] = {
395 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
398 u_int8_t depth_bits_array
[3];
399 u_int8_t stencil_bits_array
[3];
402 depth_bits_array
[0] = 0;
403 depth_bits_array
[1] = depth_bits
;
404 depth_bits_array
[2] = depth_bits
;
406 /* Just like with the accumulation buffer, always provide some modes
407 * with a stencil buffer. It will be a sw fallback, but some apps won't
410 stencil_bits_array
[0] = 0;
411 stencil_bits_array
[1] = 0;
412 stencil_bits_array
[2] = (stencil_bits
== 0) ? 8 : stencil_bits
;
414 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 3 : 1;
415 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
417 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
419 if ( pixel_bits
== 16 ) {
421 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
425 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
428 modes
= (*dri_interface
->createContextModes
)( num_modes
, sizeof( __GLcontextModes
) );
430 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
431 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
432 back_buffer_modes
, back_buffer_factor
,
434 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
435 __func__
, __LINE__
);
438 if ( ! driFillInModes( & m
, fb_format
, fb_type
,
439 depth_bits_array
, stencil_bits_array
, depth_buffer_factor
,
440 back_buffer_modes
, back_buffer_factor
,
441 GLX_DIRECT_COLOR
) ) {
442 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
443 __func__
, __LINE__
);
447 /* Mark the visual as slow if there are "fake" stencil bits.
449 for ( m
= modes
; m
!= NULL
; m
= m
->next
) {
450 if ( (m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
) ) {
451 m
->visualRating
= GLX_SLOW_CONFIG
;
460 * This is the bootstrap function for the driver. libGL supplies all of the
461 * requisite information about the system, and the driver initializes itself.
462 * This routine also fills in the linked list pointed to by \c driver_modes
463 * with the \c __GLcontextModes that the driver can support for windows or
466 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
470 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
471 const __GLcontextModes
* modes
,
472 const __DRIversion
* ddx_version
,
473 const __DRIversion
* dri_version
,
474 const __DRIversion
* drm_version
,
475 const __DRIframebuffer
* frame_buffer
,
476 drmAddress pSAREA
, int fd
,
477 int internal_api_version
,
478 const __DRIinterfaceMethods
* interface
,
479 __GLcontextModes
** driver_modes
)
482 __DRIscreenPrivate
*psp
;
483 static const __DRIversion ddx_expected
= { 1, 4, 0 };
484 static const __DRIversion dri_expected
= { 4, 0, 0 };
485 static const __DRIversion drm_expected
= { 1, 1, 0 };
487 dri_interface
= interface
;
489 if ( ! driCheckDriDdxDrmVersions2( "i915",
490 dri_version
, & dri_expected
,
491 ddx_version
, & ddx_expected
,
492 drm_version
, & drm_expected
) ) {
496 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
497 ddx_version
, dri_version
, drm_version
,
498 frame_buffer
, pSAREA
, fd
,
499 internal_api_version
, &intelAPI
);
501 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
502 *driver_modes
= intelFillInModes( dri_priv
->cpp
* 8,
503 (dri_priv
->cpp
== 2) ? 16 : 24,
504 (dri_priv
->cpp
== 2) ? 0 : 8,
505 (dri_priv
->backOffset
!= dri_priv
->depthOffset
) );
507 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
508 * enable the extensions. It just makes sure that all the dispatch offsets for all
509 * the extensions that *might* be enables are known. This is needed because the
510 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
511 * enable the extensions until we have a context pointer.
513 * Hello chicken. Hello egg. How are you two today?
515 driInitExtensions( NULL
, card_extensions
, GL_FALSE
);