1 /**************************************************************************
3 Copyright 2006 Stephane Marchesin
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 on the rights to use, copy, modify, merge, publish, distribute, sub
10 license, and/or sell copies of the Software, and to permit persons to whom
11 the Software is furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice (including the next
14 paragraph) shall be included in all copies or substantial portions of the
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
30 #include "framebuffer.h"
31 #include "renderbuffer.h"
33 #include "nouveau_context.h"
34 #include "nouveau_screen.h"
35 #include "nouveau_object.h"
36 #include "nouveau_span.h"
41 #include "drirenderbuffer.h"
43 #include "GL/internal/dri_interface.h"
47 PUBLIC
const char __driConfigOptions
[] =
49 DRI_CONF_SECTION_DEBUG
50 DRI_CONF_NO_RAST(false)
53 static const GLuint __driNConfigOptions
= 1;
55 extern const struct dri_extension common_extensions
[];
56 extern const struct dri_extension nv10_extensions
[];
57 extern const struct dri_extension nv20_extensions
[];
58 extern const struct dri_extension nv30_extensions
[];
59 extern const struct dri_extension nv40_extensions
[];
60 extern const struct dri_extension nv50_extensions
[];
62 static nouveauScreenPtr
nouveauCreateScreen(__DRIscreenPrivate
*sPriv
)
64 nouveauScreenPtr screen
;
65 NOUVEAUDRIPtr dri_priv
=(NOUVEAUDRIPtr
)sPriv
->pDevPriv
;
68 screen
= (nouveauScreenPtr
) CALLOC( sizeof(*screen
) );
70 __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__
);
74 screen
->card
=nouveau_card_lookup(dri_priv
->device_id
);
76 __driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n",
77 __func__
, dri_priv
->device_id
>> 16, dri_priv
->device_id
& 0xFFFF);
82 /* parse information in __driConfigOptions */
83 driParseOptionInfo (&screen
->optionCache
,__driConfigOptions
, __driNConfigOptions
);
85 screen
->fbFormat
= dri_priv
->bpp
/ 8;
86 screen
->frontOffset
= dri_priv
->front_offset
;
87 screen
->frontPitch
= dri_priv
->front_pitch
;
88 screen
->backOffset
= dri_priv
->back_offset
;
89 screen
->backPitch
= dri_priv
->back_pitch
;
90 screen
->depthOffset
= dri_priv
->depth_offset
;
91 screen
->depthPitch
= dri_priv
->depth_pitch
;
93 screen
->driScreen
= sPriv
;
98 nouveauDestroyScreen(__DRIscreenPrivate
*sPriv
)
100 nouveauScreenPtr screen
= (nouveauScreenPtr
)sPriv
->private;
104 /* free all option information */
105 driDestroyOptionInfo (&screen
->optionCache
);
108 sPriv
->private = NULL
;
111 static GLboolean
nouveauInitDriver(__DRIscreenPrivate
*sPriv
)
113 sPriv
->private = (void *) nouveauCreateScreen( sPriv
);
114 if ( !sPriv
->private ) {
115 nouveauDestroyScreen( sPriv
);
123 * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
125 * \todo This function (and its interface) will need to be updated to support
129 nouveauCreateBuffer(__DRIscreenPrivate
*driScrnPriv
,
130 __DRIdrawablePrivate
*driDrawPriv
,
131 const __GLcontextModes
*mesaVis
,
134 nouveauScreenPtr screen
= (nouveauScreenPtr
) driScrnPriv
->private;
135 nouveau_renderbuffer
*nrb
;
136 struct gl_framebuffer
*fb
;
137 const GLboolean swAccum
= mesaVis
->accumRedBits
> 0;
138 const GLboolean swStencil
= mesaVis
->stencilBits
> 0 && mesaVis
->depthBits
!= 24;
139 GLenum color_format
= screen
->fbFormat
== 4 ? GL_RGBA8
: GL_RGB5
;
142 return GL_FALSE
; /* not implemented */
144 fb
= _mesa_create_framebuffer(mesaVis
);
149 nrb
= nouveau_renderbuffer_new(color_format
,
150 driScrnPriv
->pFB
+ screen
->frontOffset
,
152 screen
->frontPitch
* screen
->fbFormat
,
154 nouveauSpanSetFunctions(nrb
, mesaVis
);
155 _mesa_add_renderbuffer(fb
, BUFFER_FRONT_LEFT
, &nrb
->mesa
);
157 if (0 /* unified buffers if we choose to support them.. */) {
159 if (mesaVis
->doubleBufferMode
) {
160 nrb
= nouveau_renderbuffer_new(color_format
, NULL
,
163 nouveauSpanSetFunctions(nrb
, mesaVis
);
164 _mesa_add_renderbuffer(fb
, BUFFER_BACK_LEFT
, &nrb
->mesa
);
167 if (mesaVis
->depthBits
== 24 && mesaVis
->stencilBits
== 8) {
168 nrb
= nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT
, NULL
,
171 nouveauSpanSetFunctions(nrb
, mesaVis
);
172 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &nrb
->mesa
);
173 _mesa_add_renderbuffer(fb
, BUFFER_STENCIL
, &nrb
->mesa
);
174 } else if (mesaVis
->depthBits
== 24) {
175 nrb
= nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24
, NULL
,
178 nouveauSpanSetFunctions(nrb
, mesaVis
);
179 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &nrb
->mesa
);
180 } else if (mesaVis
->depthBits
== 16) {
181 nrb
= nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16
, NULL
,
184 nouveauSpanSetFunctions(nrb
, mesaVis
);
185 _mesa_add_renderbuffer(fb
, BUFFER_DEPTH
, &nrb
->mesa
);
189 _mesa_add_soft_renderbuffers(fb
,
190 GL_FALSE
, /* color */
191 GL_FALSE
, /* depth */
194 GL_FALSE
, /* alpha */
197 driDrawPriv
->driverPrivate
= (void *) fb
;
198 return (driDrawPriv
->driverPrivate
!= NULL
);
203 nouveauDestroyBuffer(__DRIdrawablePrivate
*driDrawPriv
)
205 _mesa_unreference_framebuffer((GLframebuffer
**)(&(driDrawPriv
->driverPrivate
)));
209 nouveauGetSwapInfo(__DRIdrawablePrivate
*dpriv
, __DRIswapInfo
*sInfo
)
214 static const struct __DriverAPIRec nouveauAPI
= {
215 .InitDriver
= nouveauInitDriver
,
216 .DestroyScreen
= nouveauDestroyScreen
,
217 .CreateContext
= nouveauCreateContext
,
218 .DestroyContext
= nouveauDestroyContext
,
219 .CreateBuffer
= nouveauCreateBuffer
,
220 .DestroyBuffer
= nouveauDestroyBuffer
,
221 .SwapBuffers
= nouveauSwapBuffers
,
222 .MakeCurrent
= nouveauMakeCurrent
,
223 .UnbindContext
= nouveauUnbindContext
,
224 .GetSwapInfo
= nouveauGetSwapInfo
,
225 .GetMSC
= driGetMSC32
,
226 .WaitForMSC
= driWaitForMSC32
,
228 .SwapBuffersMSC
= NULL
,
229 .CopySubBuffer
= nouveauCopySubBuffer
233 static __GLcontextModes
*
234 nouveauFillInModes( unsigned pixel_bits
, unsigned depth_bits
,
235 unsigned stencil_bits
, GLboolean have_back_buffer
)
237 __GLcontextModes
* modes
;
238 __GLcontextModes
* m
;
240 unsigned depth_buffer_factor
;
241 unsigned back_buffer_factor
;
244 static const struct {
247 } fb_format_array
[] = {
248 { GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
},
249 { GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
},
250 { GL_BGR
, GL_UNSIGNED_INT_8_8_8_8_REV
},
253 /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
254 * support pageflipping at all.
256 static const GLenum back_buffer_modes
[] = {
257 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
, GLX_SWAP_COPY_OML
260 u_int8_t depth_bits_array
[4] = { 0, 16, 24, 24 };
261 u_int8_t stencil_bits_array
[4] = { 0, 0, 0, 8 };
263 depth_buffer_factor
= 4;
264 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
266 num_modes
= ((pixel_bits
==16) ? 1 : 2) *
267 depth_buffer_factor
* back_buffer_factor
* 4;
268 modes
= (*dri_interface
->createContextModes
)(num_modes
,
269 sizeof(__GLcontextModes
));
272 for (i
=((pixel_bits
==16)?0:1);i
<((pixel_bits
==16)?1:3);i
++) {
273 if (!driFillInModes(&m
, fb_format_array
[i
].format
,
274 fb_format_array
[i
].type
,
281 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
282 __func__
, __LINE__
);
286 if (!driFillInModes(&m
, fb_format_array
[i
].format
,
287 fb_format_array
[i
].type
,
294 fprintf( stderr
, "[%s:%u] Error creating FBConfig!\n",
295 __func__
, __LINE__
);
305 * This is the bootstrap function for the driver. libGL supplies all of the
306 * requisite information about the system, and the driver initializes itself.
307 * This routine also fills in the linked list pointed to by \c driver_modes
308 * with the \c __GLcontextModes that the driver can support for windows or
311 * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
315 void * __driCreateNewScreen_20050727( __DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
316 const __GLcontextModes
* modes
,
317 const __DRIversion
* ddx_version
,
318 const __DRIversion
* dri_version
,
319 const __DRIversion
* drm_version
,
320 const __DRIframebuffer
* frame_buffer
,
321 drmAddress pSAREA
, int fd
,
322 int internal_api_version
,
323 const __DRIinterfaceMethods
* interface
,
324 __GLcontextModes
** driver_modes
)
327 __DRIscreenPrivate
*psp
;
328 static const __DRIversion ddx_expected
= { 1, 2, 0 };
329 static const __DRIversion dri_expected
= { 4, 0, 0 };
330 static const __DRIversion drm_expected
= { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL
};
331 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 9
332 #error nouveau_drm.h version doesn't match expected version
334 dri_interface = interface;
336 if (!driCheckDriDdxDrmVersions2("nouveau",
337 dri_version, & dri_expected,
338 ddx_version, & ddx_expected,
339 drm_version, & drm_expected)) {
343 // temporary lock step versioning
344 if (drm_expected.patch!=drm_version->patch) {
345 __driUtilMessage("%s: wrong DRM version, expected %d, got %d\n",
347 drm_expected.patch, drm_version->patch);
351 psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
352 ddx_version, dri_version, drm_version,
353 frame_buffer, pSAREA, fd,
354 internal_api_version, &nouveauAPI);
356 NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
358 *driver_modes = nouveauFillInModes(dri_priv->bpp,
359 (dri_priv->bpp == 16) ? 16 : 24,
360 (dri_priv->bpp == 16) ? 0 : 8,
364 /* Calling driInitExtensions here, with a NULL context pointer, does not actually
365 * enable the extensions. It just makes sure that all the dispatch offsets for all
366 * the extensions that *might* be enables are known. This is needed because the
367 * dispatch offsets need to be known when _mesa_context_create is called, but we can't
368 * enable the extensions until we have a context pointer
.
370 * Hello chicken
. Hello egg
. How are you two today
?
372 driInitExtensions( NULL
, common_extensions
, GL_FALSE
);
373 driInitExtensions( NULL
, nv10_extensions
, GL_FALSE
);
374 driInitExtensions( NULL
, nv10_extensions
, GL_FALSE
);
375 driInitExtensions( NULL
, nv30_extensions
, GL_FALSE
);
376 driInitExtensions( NULL
, nv40_extensions
, GL_FALSE
);
377 driInitExtensions( NULL
, nv50_extensions
, GL_FALSE
);