Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_screen.c
1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include <stdio.h>
28 #include <xf86drm.h>
29 #include <nouveau_drm.h>
30 #include "nouveau_driver.h"
31 #include "nouveau_context.h"
32 #include "nouveau_fbo.h"
33 #include "nouveau_texture.h"
34 #include "nv04_driver.h"
35 #include "nv10_driver.h"
36 #include "nv20_driver.h"
37
38 #include "main/framebuffer.h"
39 #include "main/fbobject.h"
40 #include "main/renderbuffer.h"
41 #include "util/u_memory.h"
42 #include "swrast/s_renderbuffer.h"
43
44 #include <nvif/class.h>
45 #include <nvif/cl0080.h>
46
47 static const __DRIextension *nouveau_screen_extensions[];
48
49 static void
50 nouveau_destroy_screen(__DRIscreen *dri_screen);
51
52 static const __DRIconfig **
53 nouveau_get_configs(uint32_t chipset)
54 {
55 __DRIconfig **configs = NULL;
56 int i;
57
58 const uint8_t depth_bits[] = { 0, 16, 24, 24 };
59 const uint8_t stencil_bits[] = { 0, 0, 0, 8 };
60 const uint8_t msaa_samples[] = { 0 };
61
62 static const mesa_format formats[3] = {
63 MESA_FORMAT_B5G6R5_UNORM,
64 MESA_FORMAT_B8G8R8A8_UNORM,
65 MESA_FORMAT_B8G8R8X8_UNORM,
66 };
67
68 const GLenum back_buffer_modes[] = {
69 __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED
70 };
71
72 for (i = 0; i < ARRAY_SIZE(formats); i++) {
73 __DRIconfig **config;
74
75 config = driCreateConfigs(formats[i],
76 depth_bits, stencil_bits,
77 ARRAY_SIZE(depth_bits),
78 back_buffer_modes,
79 ARRAY_SIZE(back_buffer_modes),
80 msaa_samples,
81 ARRAY_SIZE(msaa_samples),
82 GL_TRUE, chipset < 0x10, GL_FALSE);
83 assert(config);
84
85 configs = driConcatConfigs(configs, config);
86 }
87
88 return (const __DRIconfig **)configs;
89 }
90
91 static const __DRIconfig **
92 nouveau_init_screen2(__DRIscreen *dri_screen)
93 {
94 const __DRIconfig **configs;
95 struct nouveau_screen *screen;
96 int ret;
97
98 /* Allocate the screen. */
99 screen = CALLOC_STRUCT(nouveau_screen);
100 if (!screen)
101 return NULL;
102
103 dri_screen->driverPrivate = screen;
104
105 /* Open the DRM device. */
106 ret = nouveau_drm_new(dri_screen->fd, &screen->drm);
107 if (ret) {
108 nouveau_error("Error opening the DRM device.\n");
109 goto fail;
110 }
111
112 ret = nouveau_device_new(&screen->drm->client, NV_DEVICE,
113 &(struct nv_device_v0) {
114 .device = ~0ULL,
115 }, sizeof(struct nv_device_v0),
116 &screen->device);
117 if (ret) {
118 nouveau_error("Error creating device object.\n");
119 goto fail;
120 }
121
122 /* Choose the card specific function pointers. */
123 switch (screen->device->chipset & 0xf0) {
124 case 0x00:
125 screen->driver = &nv04_driver;
126 dri_screen->max_gl_compat_version = 12;
127 break;
128 case 0x10:
129 screen->driver = &nv10_driver;
130 dri_screen->max_gl_compat_version = 12;
131 dri_screen->max_gl_es1_version = 10;
132 break;
133 case 0x20:
134 case 0x30:
135 screen->driver = &nv20_driver;
136 dri_screen->max_gl_compat_version = 13;
137 dri_screen->max_gl_es1_version = 10;
138 break;
139 default:
140 nouveau_error("Unknown chipset: %02X\n",
141 screen->device->chipset);
142 goto fail;
143 }
144
145 dri_screen->extensions = nouveau_screen_extensions;
146 screen->dri_screen = dri_screen;
147
148 configs = nouveau_get_configs(screen->device->chipset);
149 if (!configs)
150 goto fail;
151
152 return configs;
153 fail:
154 nouveau_destroy_screen(dri_screen);
155 return NULL;
156
157 }
158
159 static int
160 nouveau_query_renderer_integer(__DRIscreen *psp, int param,
161 unsigned int *value)
162 {
163 const struct nouveau_screen *const screen =
164 (struct nouveau_screen *) psp->driverPrivate;
165
166 switch (param) {
167 case __DRI2_RENDERER_VENDOR_ID:
168 value[0] = 0x10de;
169 return 0;
170 case __DRI2_RENDERER_DEVICE_ID: {
171 uint64_t device_id;
172
173 if (nouveau_getparam(screen->device,
174 NOUVEAU_GETPARAM_PCI_DEVICE,
175 &device_id)) {
176 nouveau_error("Error retrieving the device PCIID.\n");
177 device_id = -1;
178 }
179 value[0] = (unsigned int) device_id;
180 return 0;
181 }
182 case __DRI2_RENDERER_ACCELERATED:
183 value[0] = 1;
184 return 0;
185 case __DRI2_RENDERER_VIDEO_MEMORY:
186 /* XXX: return vram_size or vram_limit ? */
187 value[0] = screen->device->vram_size >> 20;
188 return 0;
189 case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
190 value[0] = 0;
191 return 0;
192 default:
193 return driQueryRendererIntegerCommon(psp, param, value);
194 }
195 }
196
197 static int
198 nouveau_query_renderer_string(__DRIscreen *psp, int param, const char **value)
199 {
200 const struct nouveau_screen *const screen =
201 (struct nouveau_screen *) psp->driverPrivate;
202
203 switch (param) {
204 case __DRI2_RENDERER_VENDOR_ID:
205 value[0] = nouveau_vendor_string;
206 return 0;
207 case __DRI2_RENDERER_DEVICE_ID:
208 value[0] = nouveau_get_renderer_string(screen->device->chipset);
209 return 0;
210 default:
211 return -1;
212 }
213 }
214
215 static const __DRI2rendererQueryExtension nouveau_renderer_query_extension = {
216 .base = { __DRI2_RENDERER_QUERY, 1 },
217
218 .queryInteger = nouveau_query_renderer_integer,
219 .queryString = nouveau_query_renderer_string
220 };
221
222 static void
223 nouveau_destroy_screen(__DRIscreen *dri_screen)
224 {
225 struct nouveau_screen *screen = dri_screen->driverPrivate;
226
227 if (!screen)
228 return;
229
230 nouveau_device_del(&screen->device);
231 nouveau_drm_del(&screen->drm);
232
233 free(screen);
234 dri_screen->driverPrivate = NULL;
235 }
236
237 static GLboolean
238 nouveau_create_buffer(__DRIscreen *dri_screen,
239 __DRIdrawable *drawable,
240 const struct gl_config *visual,
241 GLboolean is_pixmap)
242 {
243 struct gl_renderbuffer *rb;
244 struct gl_framebuffer *fb;
245 GLenum color_format;
246
247 if (is_pixmap)
248 return GL_FALSE; /* not implemented */
249
250 if (visual->redBits == 5)
251 color_format = GL_RGB5;
252 else if (visual->alphaBits == 0)
253 color_format = GL_RGB8;
254 else
255 color_format = GL_RGBA8;
256
257 fb = nouveau_framebuffer_dri_new(visual);
258 if (!fb)
259 return GL_FALSE;
260
261 /* Front buffer. */
262 rb = nouveau_renderbuffer_dri_new(color_format, drawable);
263 _mesa_attach_and_own_rb(fb, BUFFER_FRONT_LEFT, rb);
264
265 /* Back buffer */
266 if (visual->doubleBufferMode) {
267 rb = nouveau_renderbuffer_dri_new(color_format, drawable);
268 _mesa_attach_and_own_rb(fb, BUFFER_BACK_LEFT, rb);
269 }
270
271 /* Depth/stencil buffer. */
272 if (visual->depthBits == 24 && visual->stencilBits == 8) {
273 rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable);
274 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
275 _mesa_attach_and_reference_rb(fb, BUFFER_STENCIL, rb);
276
277 } else if (visual->depthBits == 24) {
278 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable);
279 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
280
281 } else if (visual->depthBits == 16) {
282 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable);
283 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
284 }
285
286 /* Software renderbuffers. */
287 _swrast_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE,
288 visual->accumRedBits > 0,
289 GL_FALSE, GL_FALSE);
290
291 drawable->driverPrivate = fb;
292
293 return GL_TRUE;
294 }
295
296 static void
297 nouveau_destroy_buffer(__DRIdrawable *drawable)
298 {
299 _mesa_reference_framebuffer(
300 (struct gl_framebuffer **)&drawable->driverPrivate, NULL);
301 }
302
303 static void
304 nouveau_drawable_flush(__DRIdrawable *draw)
305 {
306 }
307
308 static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
309 .base = { __DRI2_FLUSH, 3 },
310
311 .flush = nouveau_drawable_flush,
312 .invalidate = dri2InvalidateDrawable,
313 };
314
315 static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
316 .base = { __DRI_TEX_BUFFER, 3 },
317
318 .setTexBuffer = NULL,
319 .setTexBuffer2 = nouveau_set_texbuffer,
320 .releaseTexBuffer = NULL,
321 };
322
323 static const __DRIextension *nouveau_screen_extensions[] = {
324 &nouveau_flush_extension.base,
325 &nouveau_texbuffer_extension.base,
326 &nouveau_renderer_query_extension.base,
327 &dri2ConfigQueryExtension.base,
328 &dri2NoErrorExtension.base,
329 NULL
330 };
331
332 const struct __DriverAPIRec nouveau_driver_api = {
333 .InitScreen = nouveau_init_screen2,
334 .DestroyScreen = nouveau_destroy_screen,
335 .CreateBuffer = nouveau_create_buffer,
336 .DestroyBuffer = nouveau_destroy_buffer,
337 .CreateContext = nouveau_context_create,
338 .DestroyContext = nouveau_context_destroy,
339 .MakeCurrent = nouveau_context_make_current,
340 .UnbindContext = nouveau_context_unbind,
341 };
342
343 static const struct __DRIDriverVtableExtensionRec nouveau_vtable = {
344 .base = { __DRI_DRIVER_VTABLE, 1 },
345 .vtable = &nouveau_driver_api,
346 };
347
348 /* This is the table of extensions that the loader will dlsym() for. */
349 static const __DRIextension *nouveau_driver_extensions[] = {
350 &driCoreExtension.base,
351 &driDRI2Extension.base,
352 &nouveau_vtable.base,
353 NULL
354 };
355
356 PUBLIC const __DRIextension **__driDriverGetExtensions_nouveau_vieux(void)
357 {
358 globalDriverAPI = &nouveau_driver_api;
359
360 return nouveau_driver_extensions;
361 }