i965/perf: restore mdapi statistics query metrics
[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 "swrast/s_renderbuffer.h"
42
43 #include <nvif/class.h>
44 #include <nvif/cl0080.h>
45
46 static const __DRIextension *nouveau_screen_extensions[];
47
48 static void
49 nouveau_destroy_screen(__DRIscreen *dri_screen);
50
51 static const __DRIconfig **
52 nouveau_get_configs(uint32_t chipset)
53 {
54 __DRIconfig **configs = NULL;
55 int i;
56
57 const uint8_t depth_bits[] = { 0, 16, 24, 24 };
58 const uint8_t stencil_bits[] = { 0, 0, 0, 8 };
59 const uint8_t msaa_samples[] = { 0 };
60
61 static const mesa_format formats[3] = {
62 MESA_FORMAT_B5G6R5_UNORM,
63 MESA_FORMAT_B8G8R8A8_UNORM,
64 MESA_FORMAT_B8G8R8X8_UNORM,
65 };
66
67 const GLenum back_buffer_modes[] = {
68 __DRI_ATTRIB_SWAP_NONE, __DRI_ATTRIB_SWAP_UNDEFINED
69 };
70
71 for (i = 0; i < ARRAY_SIZE(formats); i++) {
72 __DRIconfig **config;
73
74 config = driCreateConfigs(formats[i],
75 depth_bits, stencil_bits,
76 ARRAY_SIZE(depth_bits),
77 back_buffer_modes,
78 ARRAY_SIZE(back_buffer_modes),
79 msaa_samples,
80 ARRAY_SIZE(msaa_samples),
81 GL_TRUE, chipset < 0x10, GL_FALSE);
82 assert(config);
83
84 configs = driConcatConfigs(configs, config);
85 }
86
87 return (const __DRIconfig **)configs;
88 }
89
90 static const __DRIconfig **
91 nouveau_init_screen2(__DRIscreen *dri_screen)
92 {
93 const __DRIconfig **configs;
94 struct nouveau_screen *screen;
95 int ret;
96
97 /* Allocate the screen. */
98 screen = CALLOC_STRUCT(nouveau_screen);
99 if (!screen)
100 return NULL;
101
102 dri_screen->driverPrivate = screen;
103
104 /* Open the DRM device. */
105 ret = nouveau_drm_new(dri_screen->fd, &screen->drm);
106 if (ret) {
107 nouveau_error("Error opening the DRM device.\n");
108 goto fail;
109 }
110
111 ret = nouveau_device_new(&screen->drm->client, NV_DEVICE,
112 &(struct nv_device_v0) {
113 .device = ~0ULL,
114 }, sizeof(struct nv_device_v0),
115 &screen->device);
116 if (ret) {
117 nouveau_error("Error creating device object.\n");
118 goto fail;
119 }
120
121 /* Choose the card specific function pointers. */
122 switch (screen->device->chipset & 0xf0) {
123 case 0x00:
124 screen->driver = &nv04_driver;
125 dri_screen->max_gl_compat_version = 12;
126 break;
127 case 0x10:
128 screen->driver = &nv10_driver;
129 dri_screen->max_gl_compat_version = 12;
130 dri_screen->max_gl_es1_version = 10;
131 break;
132 case 0x20:
133 case 0x30:
134 screen->driver = &nv20_driver;
135 dri_screen->max_gl_compat_version = 13;
136 dri_screen->max_gl_es1_version = 10;
137 break;
138 default:
139 nouveau_error("Unknown chipset: %02X\n",
140 screen->device->chipset);
141 goto fail;
142 }
143
144 dri_screen->extensions = nouveau_screen_extensions;
145 screen->dri_screen = dri_screen;
146
147 configs = nouveau_get_configs(screen->device->chipset);
148 if (!configs)
149 goto fail;
150
151 return configs;
152 fail:
153 nouveau_destroy_screen(dri_screen);
154 return NULL;
155
156 }
157
158 static int
159 nouveau_query_renderer_integer(__DRIscreen *psp, int param,
160 unsigned int *value)
161 {
162 const struct nouveau_screen *const screen =
163 (struct nouveau_screen *) psp->driverPrivate;
164
165 switch (param) {
166 case __DRI2_RENDERER_VENDOR_ID:
167 value[0] = 0x10de;
168 return 0;
169 case __DRI2_RENDERER_DEVICE_ID: {
170 uint64_t device_id;
171
172 if (nouveau_getparam(screen->device,
173 NOUVEAU_GETPARAM_PCI_DEVICE,
174 &device_id)) {
175 nouveau_error("Error retrieving the device PCIID.\n");
176 device_id = -1;
177 }
178 value[0] = (unsigned int) device_id;
179 return 0;
180 }
181 case __DRI2_RENDERER_ACCELERATED:
182 value[0] = 1;
183 return 0;
184 case __DRI2_RENDERER_VIDEO_MEMORY:
185 /* XXX: return vram_size or vram_limit ? */
186 value[0] = screen->device->vram_size >> 20;
187 return 0;
188 case __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE:
189 value[0] = 0;
190 return 0;
191 default:
192 return driQueryRendererIntegerCommon(psp, param, value);
193 }
194 }
195
196 static int
197 nouveau_query_renderer_string(__DRIscreen *psp, int param, const char **value)
198 {
199 const struct nouveau_screen *const screen =
200 (struct nouveau_screen *) psp->driverPrivate;
201
202 switch (param) {
203 case __DRI2_RENDERER_VENDOR_ID:
204 value[0] = nouveau_vendor_string;
205 return 0;
206 case __DRI2_RENDERER_DEVICE_ID:
207 value[0] = nouveau_get_renderer_string(screen->device->chipset);
208 return 0;
209 default:
210 return -1;
211 }
212 }
213
214 static const __DRI2rendererQueryExtension nouveau_renderer_query_extension = {
215 .base = { __DRI2_RENDERER_QUERY, 1 },
216
217 .queryInteger = nouveau_query_renderer_integer,
218 .queryString = nouveau_query_renderer_string
219 };
220
221 static void
222 nouveau_destroy_screen(__DRIscreen *dri_screen)
223 {
224 struct nouveau_screen *screen = dri_screen->driverPrivate;
225
226 if (!screen)
227 return;
228
229 nouveau_device_del(&screen->device);
230 nouveau_drm_del(&screen->drm);
231
232 free(screen);
233 dri_screen->driverPrivate = NULL;
234 }
235
236 static GLboolean
237 nouveau_create_buffer(__DRIscreen *dri_screen,
238 __DRIdrawable *drawable,
239 const struct gl_config *visual,
240 GLboolean is_pixmap)
241 {
242 struct gl_renderbuffer *rb;
243 struct gl_framebuffer *fb;
244 GLenum color_format;
245
246 if (is_pixmap)
247 return GL_FALSE; /* not implemented */
248
249 if (visual->redBits == 5)
250 color_format = GL_RGB5;
251 else if (visual->alphaBits == 0)
252 color_format = GL_RGB8;
253 else
254 color_format = GL_RGBA8;
255
256 fb = nouveau_framebuffer_dri_new(visual);
257 if (!fb)
258 return GL_FALSE;
259
260 /* Front buffer. */
261 rb = nouveau_renderbuffer_dri_new(color_format, drawable);
262 _mesa_attach_and_own_rb(fb, BUFFER_FRONT_LEFT, rb);
263
264 /* Back buffer */
265 if (visual->doubleBufferMode) {
266 rb = nouveau_renderbuffer_dri_new(color_format, drawable);
267 _mesa_attach_and_own_rb(fb, BUFFER_BACK_LEFT, rb);
268 }
269
270 /* Depth/stencil buffer. */
271 if (visual->depthBits == 24 && visual->stencilBits == 8) {
272 rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable);
273 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
274 _mesa_attach_and_reference_rb(fb, BUFFER_STENCIL, rb);
275
276 } else if (visual->depthBits == 24) {
277 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable);
278 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
279
280 } else if (visual->depthBits == 16) {
281 rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable);
282 _mesa_attach_and_own_rb(fb, BUFFER_DEPTH, rb);
283 }
284
285 /* Software renderbuffers. */
286 _swrast_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE,
287 visual->accumRedBits > 0,
288 GL_FALSE, GL_FALSE);
289
290 drawable->driverPrivate = fb;
291
292 return GL_TRUE;
293 }
294
295 static void
296 nouveau_destroy_buffer(__DRIdrawable *drawable)
297 {
298 _mesa_reference_framebuffer(
299 (struct gl_framebuffer **)&drawable->driverPrivate, NULL);
300 }
301
302 static void
303 nouveau_drawable_flush(__DRIdrawable *draw)
304 {
305 }
306
307 static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
308 .base = { __DRI2_FLUSH, 3 },
309
310 .flush = nouveau_drawable_flush,
311 .invalidate = dri2InvalidateDrawable,
312 };
313
314 static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
315 .base = { __DRI_TEX_BUFFER, 3 },
316
317 .setTexBuffer = NULL,
318 .setTexBuffer2 = nouveau_set_texbuffer,
319 .releaseTexBuffer = NULL,
320 };
321
322 static const __DRIextension *nouveau_screen_extensions[] = {
323 &nouveau_flush_extension.base,
324 &nouveau_texbuffer_extension.base,
325 &nouveau_renderer_query_extension.base,
326 &dri2ConfigQueryExtension.base,
327 &dri2NoErrorExtension.base,
328 NULL
329 };
330
331 const struct __DriverAPIRec nouveau_driver_api = {
332 .InitScreen = nouveau_init_screen2,
333 .DestroyScreen = nouveau_destroy_screen,
334 .CreateBuffer = nouveau_create_buffer,
335 .DestroyBuffer = nouveau_destroy_buffer,
336 .CreateContext = nouveau_context_create,
337 .DestroyContext = nouveau_context_destroy,
338 .MakeCurrent = nouveau_context_make_current,
339 .UnbindContext = nouveau_context_unbind,
340 };
341
342 static const struct __DRIDriverVtableExtensionRec nouveau_vtable = {
343 .base = { __DRI_DRIVER_VTABLE, 1 },
344 .vtable = &nouveau_driver_api,
345 };
346
347 /* This is the table of extensions that the loader will dlsym() for. */
348 static const __DRIextension *nouveau_driver_extensions[] = {
349 &driCoreExtension.base,
350 &driDRI2Extension.base,
351 &nouveau_vtable.base,
352 NULL
353 };
354
355 PUBLIC const __DRIextension **__driDriverGetExtensions_nouveau_vieux(void)
356 {
357 globalDriverAPI = &nouveau_driver_api;
358
359 return nouveau_driver_extensions;
360 }