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 **************************************************************************/
32 #include "intel_context.h"
33 #include "intel_screen.h"
34 #include "intel_batchbuffer.h"
35 #include "intel_swapbuffers.h"
38 #include "ws_dri_bufpool.h"
40 #include "pipe/p_context.h"
41 #include "pipe/p_screen.h"
42 #include "pipe/p_inlines.h"
43 #include "state_tracker/st_public.h"
44 #include "state_tracker/st_cb_fbo.h"
47 intelCreateSurface(struct intel_screen
*intelScreen
, struct pipe_winsys
*winsys
, unsigned handle
);
50 intelCreateSurface(struct intel_screen
*intelScreen
, struct pipe_winsys
*winsys
, unsigned handle
)
52 struct pipe_screen
*screen
= intelScreen
->base
.screen
;
53 struct pipe_texture
*texture
;
54 struct pipe_texture templat
;
55 struct pipe_surface
*surface
;
56 struct pipe_buffer
*buffer
;
59 assert(intelScreen
->front
.cpp
== 4);
61 buffer
= intel_be_buffer_from_handle(&intelScreen
->base
,
67 intelScreen
->front
.buffer
= dri_bo(buffer
);
69 memset(&templat
, 0, sizeof(templat
));
70 templat
.tex_usage
|= PIPE_TEXTURE_USAGE_DISPLAY_TARGET
;
71 templat
.target
= PIPE_TEXTURE_2D
;
72 templat
.last_level
= 0;
74 templat
.format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
75 templat
.width
[0] = intelScreen
->front
.width
;
76 templat
.height
[0] = intelScreen
->front
.height
;
77 pf_get_block(templat
.format
, &templat
.block
);
78 pitch
= intelScreen
->front
.pitch
;
80 texture
= screen
->texture_blanket(screen
,
85 /* Unref the buffer we don't need it anyways */
86 pipe_buffer_reference(screen
, &buffer
, NULL
);
88 surface
= screen
->get_tex_surface(screen
,
93 PIPE_BUFFER_USAGE_GPU_WRITE
);
95 intelScreen
->front
.texture
= texture
;
96 intelScreen
->front
.surface
= surface
;
99 PUBLIC
const char __driConfigOptions
[] =
100 DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
101 DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS
)
102 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0
)
103 DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
104 // DRI_CONF_FORCE_S3TC_ENABLE(false)
105 DRI_CONF_ALLOW_LARGE_TEXTURES(1)
106 DRI_CONF_SECTION_END DRI_CONF_END
;
108 const uint __driNConfigOptions
= 3;
110 #ifdef USE_NEW_INTERFACE
111 static PFNGLXCREATECONTEXTMODES create_context_modes
= NULL
;
112 #endif /*USE_NEW_INTERFACE */
114 extern const struct dri_extension card_extensions
[];
120 intelPrintDRIInfo(struct intel_screen
* intelScreen
,
121 __DRIscreenPrivate
* sPriv
, I830DRIPtr gDRIPriv
)
123 fprintf(stderr
, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
124 intelScreen
->front
.size
, intelScreen
->front
.offset
,
125 intelScreen
->front
.pitch
);
126 fprintf(stderr
, "*** Memory : 0x%x\n", gDRIPriv
->mem
);
132 intelPrintSAREA(const drmI830Sarea
* sarea
)
134 fprintf(stderr
, "SAREA: sarea width %d height %d\n", sarea
->width
,
136 fprintf(stderr
, "SAREA: pitch: %d\n", sarea
->pitch
);
138 "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
139 sarea
->front_offset
, sarea
->front_size
,
140 (unsigned) sarea
->front_handle
);
142 "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
143 sarea
->back_offset
, sarea
->back_size
,
144 (unsigned) sarea
->back_handle
);
145 fprintf(stderr
, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
146 sarea
->depth_offset
, sarea
->depth_size
,
147 (unsigned) sarea
->depth_handle
);
148 fprintf(stderr
, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
149 sarea
->tex_offset
, sarea
->tex_size
, (unsigned) sarea
->tex_handle
);
150 fprintf(stderr
, "SAREA: rotation: %d\n", sarea
->rotation
);
152 "SAREA: rotated offset: 0x%08x size: 0x%x\n",
153 sarea
->rotated_offset
, sarea
->rotated_size
);
154 fprintf(stderr
, "SAREA: rotated pitch: %d\n", sarea
->rotated_pitch
);
160 * Use the information in the sarea to update the screen parameters
161 * related to screen rotation. Needs to be called locked.
164 intelUpdateScreenRotation(__DRIscreenPrivate
* sPriv
, drmI830Sarea
* sarea
)
166 struct intel_screen
*intelScreen
= intel_screen(sPriv
);
168 if (intelScreen
->front
.map
) {
169 drmUnmap(intelScreen
->front
.map
, intelScreen
->front
.size
);
170 intelScreen
->front
.map
= NULL
;
173 if (intelScreen
->front
.buffer
)
174 driDeleteBuffers(1, &intelScreen
->front
.buffer
);
176 intelScreen
->front
.width
= sarea
->width
;
177 intelScreen
->front
.height
= sarea
->height
;
178 intelScreen
->front
.offset
= sarea
->front_offset
;
179 intelScreen
->front
.pitch
= sarea
->pitch
* intelScreen
->front
.cpp
;
180 intelScreen
->front
.size
= sarea
->front_size
;
181 intelScreen
->front
.handle
= sarea
->front_handle
;
183 assert( sarea
->front_size
>=
184 intelScreen
->front
.pitch
* intelScreen
->front
.height
);
186 #if 0 /* JB not important */
187 if (!sarea
->front_handle
)
190 if (drmMap(sPriv
->fd
,
192 intelScreen
->front
.size
,
193 (drmAddress
*) & intelScreen
->front
.map
) != 0) {
194 fprintf(stderr
, "drmMap(frontbuffer) failed!\n");
200 if (intelScreen
->staticPool
) {
201 driGenBuffers(intelScreen
->staticPool
, "static region", 1,
202 &intelScreen
->front
.buffer
, 64,
203 DRM_BO_FLAG_MEM_TT
| DRM_BO_FLAG_NO_MOVE
|
204 DRM_BO_FLAG_READ
| DRM_BO_FLAG_WRITE
, 0);
206 driBOSetStatic(intelScreen
->front
.buffer
,
207 intelScreen
->front
.offset
,
208 intelScreen
->front
.pitch
* intelScreen
->front
.height
,
209 intelScreen
->front
.map
, 0);
212 if (intelScreen
->base
.staticPool
) {
213 if (intelScreen
->front
.buffer
) {
214 driBOUnReference(intelScreen
->front
.buffer
);
215 pipe_surface_reference(&intelScreen
->front
.surface
, NULL
);
216 pipe_texture_reference(&intelScreen
->front
.texture
, NULL
);
218 intelCreateSurface(intelScreen
, &intelScreen
->base
.base
, sarea
->front_bo_handle
);
225 intelCreatePools(__DRIscreenPrivate
* sPriv
)
227 //unsigned batchPoolSize = 1024*1024;
228 struct intel_screen
*intelScreen
= intel_screen(sPriv
);
230 if (intelScreen
->havePools
)
233 intelScreen
->havePools
= GL_TRUE
;
235 intelUpdateScreenRotation(sPriv
, intelScreen
->sarea
);
241 intel_get_name( struct pipe_winsys
*winsys
)
243 return "Intel/DRI/ttm";
247 * The state tracker (should!) keep track of whether the fake
248 * frontbuffer has been touched by any rendering since the last time
249 * we copied its contents to the real frontbuffer. Our task is easy:
252 intel_flush_frontbuffer( struct pipe_winsys
*winsys
,
253 struct pipe_surface
*surf
,
254 void *context_private
)
256 struct intel_context
*intel
= (struct intel_context
*) context_private
;
257 __DRIdrawablePrivate
*dPriv
= intel
->driDrawable
;
259 intelDisplaySurface(dPriv
, surf
, NULL
);
263 intelInitDriver(__DRIscreenPrivate
* sPriv
)
265 struct intel_screen
*intelScreen
;
266 I830DRIPtr gDRIPriv
= (I830DRIPtr
) sPriv
->pDevPriv
;
268 PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension
=
269 (PFNGLXSCRENABLEEXTENSIONPROC
) (*dri_interface
->
270 getProcAddress("glxEnableExtension"));
271 void *const psc
= sPriv
->psc
->screenConfigs
;
273 if (sPriv
->devPrivSize
!= sizeof(I830DRIRec
)) {
275 "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
279 /* Allocate the private area */
280 intelScreen
= CALLOC_STRUCT(intel_screen
);
284 /* parse information in __driConfigOptions */
285 driParseOptionInfo(&intelScreen
->optionCache
,
286 __driConfigOptions
, __driNConfigOptions
);
288 sPriv
->private = (void *) intelScreen
;
290 intelScreen
->sarea
= (drmI830Sarea
*) (((GLubyte
*) sPriv
->pSAREA
) +
291 gDRIPriv
->sarea_priv_offset
);
292 intelScreen
->deviceID
= gDRIPriv
->deviceID
;
293 intelScreen
->front
.cpp
= gDRIPriv
->cpp
;
294 intelScreen
->drmMinor
= sPriv
->drmMinor
;
296 assert(gDRIPriv
->bitsPerPixel
== 16 ||
297 gDRIPriv
->bitsPerPixel
== 32);
299 intelUpdateScreenRotation(sPriv
, intelScreen
->sarea
);
302 intelPrintDRIInfo(intelScreen
, sPriv
, gDRIPriv
);
304 if (glx_enable_extension
!= NULL
) {
305 (*glx_enable_extension
) (psc
, "GLX_SGI_swap_control");
306 (*glx_enable_extension
) (psc
, "GLX_SGI_video_sync");
307 (*glx_enable_extension
) (psc
, "GLX_MESA_swap_control");
308 (*glx_enable_extension
) (psc
, "GLX_MESA_swap_frame_usage");
309 (*glx_enable_extension
) (psc
, "GLX_SGI_make_current_read");
312 intelScreen
->base
.base
.flush_frontbuffer
= intel_flush_frontbuffer
;
313 intelScreen
->base
.base
.get_name
= intel_get_name
;
314 intel_be_init_device(&intelScreen
->base
, sPriv
->fd
, intelScreen
->deviceID
);
321 intelDestroyScreen(__DRIscreenPrivate
* sPriv
)
323 struct intel_screen
*intelScreen
= intel_screen(sPriv
);
325 intel_be_destroy_device(&intelScreen
->base
);
326 /* intelUnmapScreenRegions(intelScreen); */
329 sPriv
->private = NULL
;
334 * This is called when we need to set up GL rendering to a new X window.
337 intelCreateBuffer(__DRIscreenPrivate
* driScrnPriv
,
338 __DRIdrawablePrivate
* driDrawPriv
,
339 const __GLcontextModes
* visual
, boolean isPixmap
)
342 return GL_FALSE
; /* not implemented */
345 enum pipe_format colorFormat
, depthFormat
, stencilFormat
;
346 struct intel_framebuffer
*intelfb
= CALLOC_STRUCT(intel_framebuffer
);
351 if (visual
->redBits
== 5)
352 colorFormat
= PIPE_FORMAT_R5G6B5_UNORM
;
354 colorFormat
= PIPE_FORMAT_A8R8G8B8_UNORM
;
356 if (visual
->depthBits
== 16)
357 depthFormat
= PIPE_FORMAT_Z16_UNORM
;
358 else if (visual
->depthBits
== 24)
359 depthFormat
= PIPE_FORMAT_S8Z24_UNORM
;
361 depthFormat
= PIPE_FORMAT_NONE
;
363 if (visual
->stencilBits
== 8)
364 stencilFormat
= PIPE_FORMAT_S8Z24_UNORM
;
366 stencilFormat
= PIPE_FORMAT_NONE
;
368 intelfb
->stfb
= st_create_framebuffer(visual
,
375 if (!intelfb
->stfb
) {
380 driDrawPriv
->driverPrivate
= (void *) intelfb
;
386 intelDestroyBuffer(__DRIdrawablePrivate
* driDrawPriv
)
388 struct intel_framebuffer
*intelfb
= intel_framebuffer(driDrawPriv
);
389 assert(intelfb
->stfb
);
390 st_unreference_framebuffer(&intelfb
->stfb
);
396 * Get information about previous buffer swaps.
399 intelGetSwapInfo(__DRIdrawablePrivate
* dPriv
, __DRIswapInfo
* sInfo
)
401 if ((dPriv
== NULL
) || (dPriv
->driverPrivate
== NULL
)
402 || (sInfo
== NULL
)) {
411 intelSetTexOffset(__DRIcontext
*pDRICtx
, int texname
,
412 unsigned long long offset
, int depth
, uint pitch
)
416 struct intel_context
*intel
= (struct intel_context
*)
417 ((__DRIcontextPrivate
*)pDRICtx
->private)->driverPrivate
;
418 struct gl_texture_object
*tObj
= _mesa_lookup_texture(&intel
->ctx
, texname
);
419 struct st_texture_object
*stObj
= st_texture_object(tObj
);
425 st
->pipe
->texture_release(intel
->st
->pipe
, &stObj
->pt
);
427 stObj
->imageOverride
= GL_TRUE
;
428 stObj
->depthOverride
= depth
;
429 stObj
->pitchOverride
= pitch
;
432 stObj
->textureOffset
= offset
;
437 static const struct __DriverAPIRec intelAPI
= {
438 .InitDriver
= intelInitDriver
,
439 .DestroyScreen
= intelDestroyScreen
,
440 .CreateContext
= intelCreateContext
,
441 .DestroyContext
= intelDestroyContext
,
442 .CreateBuffer
= intelCreateBuffer
,
443 .DestroyBuffer
= intelDestroyBuffer
,
444 .SwapBuffers
= intelSwapBuffers
,
445 .MakeCurrent
= intelMakeCurrent
,
446 .UnbindContext
= intelUnbindContext
,
447 .GetSwapInfo
= intelGetSwapInfo
,
448 .GetMSC
= driGetMSC32
,
449 .WaitForMSC
= driWaitForMSC32
,
451 .SwapBuffersMSC
= NULL
,
452 .CopySubBuffer
= intelCopySubBuffer
,
453 .setTexOffset
= intelSetTexOffset
,
457 static __GLcontextModes
*
458 intelFillInModes(unsigned pixel_bits
, unsigned depth_bits
,
459 unsigned stencil_bits
, boolean have_back_buffer
)
461 __GLcontextModes
*modes
;
464 unsigned depth_buffer_factor
;
465 unsigned back_buffer_factor
;
469 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
470 * support pageflipping at all.
472 static const GLenum back_buffer_modes
[] = {
473 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
476 uint8_t depth_bits_array
[3];
477 uint8_t stencil_bits_array
[3];
478 uint8_t msaa_samples_array
[1];
481 depth_bits_array
[0] = 0;
482 depth_bits_array
[1] = depth_bits
;
483 depth_bits_array
[2] = depth_bits
;
484 msaa_samples_array
[0] = 0;
486 /* Just like with the accumulation buffer, always provide some modes
487 * with a stencil buffer. It will be a sw fallback, but some apps won't
490 stencil_bits_array
[0] = 0;
491 stencil_bits_array
[1] = 0;
492 if (depth_bits
== 24)
493 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
495 stencil_bits_array
[2] = (stencil_bits
== 0) ? 8 : stencil_bits
;
497 depth_buffer_factor
= ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 3 : 1;
498 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
500 num_modes
= depth_buffer_factor
* back_buffer_factor
* 4;
502 if (pixel_bits
== 16) {
504 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
508 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
512 (*dri_interface
->createContextModes
) (num_modes
,
513 sizeof(__GLcontextModes
));
515 if (!driFillInModes(&m
, fb_format
, fb_type
,
516 depth_bits_array
, stencil_bits_array
,
517 depth_buffer_factor
, back_buffer_modes
,
518 back_buffer_factor
, msaa_samples_array
, 1, GLX_TRUE_COLOR
)) {
519 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
523 if (!driFillInModes(&m
, fb_format
, fb_type
,
524 depth_bits_array
, stencil_bits_array
,
525 depth_buffer_factor
, back_buffer_modes
,
526 back_buffer_factor
, msaa_samples_array
, 1, GLX_DIRECT_COLOR
)) {
527 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n", __func__
,
532 /* Mark the visual as slow if there are "fake" stencil bits.
534 for (m
= modes
; m
!= NULL
; m
= m
->next
) {
535 if ((m
->stencilBits
!= 0) && (m
->stencilBits
!= stencil_bits
)) {
536 m
->visualRating
= GLX_SLOW_CONFIG
;
545 * This is the bootstrap function for the driver. libGL supplies all of the
546 * requisite information about the system, and the driver initializes itself.
547 * This routine also fills in the linked list pointed to by \c driver_modes
548 * with the \c __GLcontextModes that the driver can support for windows or
551 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
555 __driCreateNewScreen_20050727(__DRInativeDisplay
* dpy
, int scrn
,
557 const __GLcontextModes
* modes
,
558 const __DRIversion
* ddx_version
,
559 const __DRIversion
* dri_version
,
560 const __DRIversion
* drm_version
,
561 const __DRIframebuffer
* frame_buffer
,
562 drmAddress pSAREA
, int fd
,
563 int internal_api_version
,
564 const __DRIinterfaceMethods
* interface
,
565 __GLcontextModes
** driver_modes
)
567 __DRIscreenPrivate
*psp
;
568 static const __DRIversion ddx_expected
= { 1, 7, 0 };
569 static const __DRIversion dri_expected
= { 4, 0, 0 };
570 static const __DRIversion drm_expected
= { 1, 7, 0 };
572 dri_interface
= interface
;
574 if (!driCheckDriDdxDrmVersions2("i915",
575 dri_version
, &dri_expected
,
576 ddx_version
, &ddx_expected
,
577 drm_version
, &drm_expected
)) {
581 psp
= __driUtilCreateNewScreen(dpy
, scrn
, psc
, NULL
,
582 ddx_version
, dri_version
, drm_version
,
583 frame_buffer
, pSAREA
, fd
,
584 internal_api_version
, &intelAPI
);
587 I830DRIPtr dri_priv
= (I830DRIPtr
) psp
->pDevPriv
;
588 *driver_modes
= intelFillInModes(dri_priv
->cpp
* 8,
589 (dri_priv
->cpp
== 2) ? 16 : 24,
590 (dri_priv
->cpp
== 2) ? 0 : 8, 1);
592 /* Calling driInitExtensions here, with a NULL context pointer,
593 * does not actually enable the extensions. It just makes sure
594 * that all the dispatch offsets for all the extensions that
595 * *might* be enables are known. This is needed because the
596 * dispatch offsets need to be known when _mesa_context_create
597 * is called, but we can't enable the extensions until we have a
600 * Hello chicken. Hello egg. How are you two today?
602 driInitExtensions(NULL
, card_extensions
, GL_FALSE
);