5 #include <pipe/p_context.h>
6 #include <state_tracker/st_public.h>
7 #include <state_tracker/st_cb_fbo.h>
8 #include <state_tracker/drm_api.h>
10 #include "nouveau_context.h"
11 #include "nouveau_screen.h"
12 #include "nouveau_swapbuffers.h"
13 #include "nouveau_dri.h"
15 #include "nouveau_drm.h"
16 #include "nouveau_drmif.h"
18 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 12
19 #error nouveau_drm.h version does not match expected version
22 /* Extension stuff, enabling of extensions handled by Gallium's GL state
23 * tracker. But, we still need to define the entry points we want.
25 #define need_GL_ARB_fragment_program
26 #define need_GL_ARB_multisample
27 #define need_GL_ARB_occlusion_query
28 #define need_GL_ARB_point_parameters
29 #define need_GL_ARB_shader_objects
30 #define need_GL_ARB_texture_compression
31 #define need_GL_ARB_vertex_program
32 #define need_GL_ARB_vertex_shader
33 #define need_GL_ARB_vertex_buffer_object
34 #define need_GL_EXT_compiled_vertex_array
35 #define need_GL_EXT_fog_coord
36 #define need_GL_EXT_secondary_color
37 #define need_GL_EXT_framebuffer_object
38 #define need_GL_VERSION_2_0
39 #define need_GL_VERSION_2_1
40 #include "extension_helper.h"
42 const struct dri_extension card_extensions
[] =
44 { "GL_ARB_multisample", GL_ARB_multisample_functions
},
45 { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions
},
46 { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions
},
47 { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions
},
48 { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions
},
49 { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions
},
50 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions
},
51 { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions
},
52 { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions
},
53 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions
},
54 { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions
},
55 { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions
},
56 { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions
},
57 { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions
},
61 PUBLIC
const char __driConfigOptions
[] =
64 static const GLuint __driNConfigOptions
= 0;
66 extern const struct dri_extension common_extensions
[];
67 extern const struct dri_extension nv40_extensions
[];
70 nouveau_create_buffer(__DRIscreenPrivate
* driScrnPriv
,
71 __DRIdrawablePrivate
* driDrawPriv
,
72 const __GLcontextModes
*glVis
, GLboolean pixmapBuffer
)
74 struct nouveau_framebuffer
*nvfb
;
75 enum pipe_format colour
, depth
, stencil
;
80 nvfb
= CALLOC_STRUCT(nouveau_framebuffer
);
84 if (glVis
->redBits
== 5)
85 colour
= PIPE_FORMAT_R5G6B5_UNORM
;
87 colour
= PIPE_FORMAT_A8R8G8B8_UNORM
;
89 if (glVis
->depthBits
== 16)
90 depth
= PIPE_FORMAT_Z16_UNORM
;
91 else if (glVis
->depthBits
== 24)
92 depth
= PIPE_FORMAT_Z24S8_UNORM
;
94 depth
= PIPE_FORMAT_NONE
;
96 if (glVis
->stencilBits
== 8)
97 stencil
= PIPE_FORMAT_Z24S8_UNORM
;
99 stencil
= PIPE_FORMAT_NONE
;
101 nvfb
->stfb
= st_create_framebuffer(glVis
, colour
, depth
, stencil
,
102 driDrawPriv
->w
, driDrawPriv
->h
,
109 driDrawPriv
->driverPrivate
= (void *)nvfb
;
114 nouveau_destroy_buffer(__DRIdrawablePrivate
* driDrawPriv
)
116 struct nouveau_framebuffer
*nvfb
;
118 nvfb
= (struct nouveau_framebuffer
*)driDrawPriv
->driverPrivate
;
119 st_unreference_framebuffer(nvfb
->stfb
);
123 static __DRIconfig
**
124 nouveau_fill_in_modes(__DRIscreenPrivate
*psp
,
125 unsigned pixel_bits
, unsigned depth_bits
,
126 unsigned stencil_bits
, GLboolean have_back_buffer
)
128 __DRIconfig
**configs
;
129 unsigned depth_buffer_factor
;
130 unsigned back_buffer_factor
;
134 static const GLenum back_buffer_modes
[] = {
135 GLX_NONE
, GLX_SWAP_UNDEFINED_OML
,
138 uint8_t depth_bits_array
[3];
139 uint8_t stencil_bits_array
[3];
140 uint8_t msaa_samples_array
[1];
142 depth_bits_array
[0] = 0;
143 depth_bits_array
[1] = depth_bits
;
144 depth_bits_array
[2] = depth_bits
;
146 /* Just like with the accumulation buffer, always provide some modes
147 * with a stencil buffer. It will be a sw fallback, but some apps won't
150 stencil_bits_array
[0] = 0;
151 stencil_bits_array
[1] = 0;
152 if (depth_bits
== 24)
153 stencil_bits_array
[1] = (stencil_bits
== 0) ? 8 : stencil_bits
;
154 stencil_bits_array
[2] = (stencil_bits
== 0) ? 8 : stencil_bits
;
156 msaa_samples_array
[0] = 0;
158 depth_buffer_factor
=
159 ((depth_bits
!= 0) || (stencil_bits
!= 0)) ? 3 : 1;
160 back_buffer_factor
= (have_back_buffer
) ? 3 : 1;
162 if (pixel_bits
== 16) {
164 fb_type
= GL_UNSIGNED_SHORT_5_6_5
;
168 fb_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
171 configs
= driCreateConfigs(fb_format
, fb_type
,
172 depth_bits_array
, stencil_bits_array
,
173 depth_buffer_factor
, back_buffer_modes
,
174 back_buffer_factor
, msaa_samples_array
, 1);
175 if (configs
== NULL
) {
176 fprintf(stderr
, "[%s:%u] Error creating FBConfig!\n",
184 static struct pipe_surface
*
185 dri_surface_from_handle(struct pipe_screen
*screen
,
187 enum pipe_format format
,
192 struct pipe_surface
*surface
= NULL
;
193 struct pipe_texture
*texture
= NULL
;
194 struct pipe_texture templat
;
195 struct pipe_buffer
*buf
= NULL
;
197 buf
= drm_api_hooks
.buffer_from_handle(screen
, "front buffer", handle
);
201 memset(&templat
, 0, sizeof(templat
));
202 templat
.tex_usage
= PIPE_TEXTURE_USAGE_PRIMARY
|
203 NOUVEAU_TEXTURE_USAGE_LINEAR
;
204 templat
.target
= PIPE_TEXTURE_2D
;
205 templat
.last_level
= 0;
206 templat
.depth
[0] = 1;
207 templat
.format
= format
;
208 templat
.width
[0] = width
;
209 templat
.height
[0] = height
;
210 pf_get_block(templat
.format
, &templat
.block
);
212 texture
= screen
->texture_blanket(screen
,
217 /* we don't need the buffer from this point on */
218 pipe_buffer_reference(&buf
, NULL
);
223 surface
= screen
->get_tex_surface(screen
, texture
, 0, 0, 0,
224 PIPE_BUFFER_USAGE_GPU_READ
|
225 PIPE_BUFFER_USAGE_GPU_WRITE
);
227 /* we don't need the texture from this point on */
228 pipe_texture_reference(&texture
, NULL
);
232 static const __DRIconfig
**
233 nouveau_screen_create(__DRIscreenPrivate
*psp
)
235 struct nouveau_dri
*nv_dri
= psp
->pDevPriv
;
236 struct nouveau_screen
*nv_screen
;
237 static const __DRIversion ddx_expected
=
238 { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL
};
239 static const __DRIversion dri_expected
= { 4, 0, 0 };
240 static const __DRIversion drm_expected
=
241 { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL
};
243 if (!driCheckDriDdxDrmVersions2("nouveau",
244 &psp
->dri_version
, &dri_expected
,
245 &psp
->ddx_version
, &ddx_expected
,
246 &psp
->drm_version
, &drm_expected
)) {
250 if (drm_expected
.patch
!= psp
->drm_version
.patch
) {
251 fprintf(stderr
, "Incompatible DRM patch level.\n"
252 "Expected: %d\n" "Current : %d\n",
253 drm_expected
.patch
, psp
->drm_version
.patch
);
257 driInitExtensions(NULL
, card_extensions
, GL_FALSE
);
259 if (psp
->devPrivSize
!= sizeof(struct nouveau_dri
)) {
260 NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n");
264 nv_screen
= CALLOC_STRUCT(nouveau_screen
);
268 nouveau_device_open_existing(&nv_screen
->device
, 0, psp
->fd
, 0);
270 nv_screen
->pscreen
= drm_api_hooks
.create_screen(psp
->fd
, NULL
);
271 if (!nv_screen
->pscreen
) {
275 nv_screen
->pscreen
->flush_frontbuffer
= nouveau_flush_frontbuffer
;
278 enum pipe_format format
;
280 if (nv_dri
->bpp
== 16)
281 format
= PIPE_FORMAT_R5G6B5_UNORM
;
283 format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
285 nv_screen
->fb
= dri_surface_from_handle(nv_screen
->pscreen
,
286 nv_dri
->front_offset
,
290 nv_dri
->front_pitch
*
294 driParseOptionInfo(&nv_screen
->option_cache
,
295 __driConfigOptions
, __driNConfigOptions
);
297 nv_screen
->driScrnPriv
= psp
;
298 psp
->private = (void *)nv_screen
;
300 return (const __DRIconfig
**)
301 nouveau_fill_in_modes(psp
, nv_dri
->bpp
,
302 (nv_dri
->bpp
== 16) ? 16 : 24,
303 (nv_dri
->bpp
== 16) ? 0 : 8, 1);
307 nouveau_screen_destroy(__DRIscreenPrivate
*driScrnPriv
)
309 struct nouveau_screen
*nv_screen
= driScrnPriv
->private;
311 driScrnPriv
->private = NULL
;
315 const struct __DriverAPIRec
317 .InitScreen
= nouveau_screen_create
,
318 .DestroyScreen
= nouveau_screen_destroy
,
319 .CreateContext
= nouveau_context_create
,
320 .DestroyContext
= nouveau_context_destroy
,
321 .CreateBuffer
= nouveau_create_buffer
,
322 .DestroyBuffer
= nouveau_destroy_buffer
,
323 .SwapBuffers
= nouveau_swap_buffers
,
324 .MakeCurrent
= nouveau_context_bind
,
325 .UnbindContext
= nouveau_context_unbind
,
326 .CopySubBuffer
= nouveau_copy_sub_buffer
,
328 .InitScreen2
= NULL
, /* one day, I promise! */