• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019-2020 Collabora, Ltd.
3  * © Copyright 2018 Alyssa Rosenzweig
4  * Copyright © 2014-2017 Broadcom
5  * Copyright (C) 2017 Intel Corporation
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  *
26  */
27 
28 #include <errno.h>
29 #include <poll.h>
30 
31 #include "pan_bo.h"
32 #include "pan_context.h"
33 #include "pan_minmax_cache.h"
34 
35 #include "util/format/u_format.h"
36 #include "util/half_float.h"
37 #include "util/libsync.h"
38 #include "util/macros.h"
39 #include "util/u_debug_cb.h"
40 #include "util/u_helpers.h"
41 #include "util/u_inlines.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
44 #include "util/u_prim.h"
45 #include "util/u_prim_restart.h"
46 #include "util/u_surface.h"
47 #include "util/u_upload_mgr.h"
48 #include "util/u_vbuf.h"
49 
50 #include "compiler/nir/nir_serialize.h"
51 #include "util/pan_lower_framebuffer.h"
52 #include "decode.h"
53 #include "pan_device.h"
54 #include "pan_fence.h"
55 #include "pan_screen.h"
56 #include "pan_util.h"
57 
58 static void
panfrost_clear(struct pipe_context * pipe,unsigned buffers,const struct pipe_scissor_state * scissor_state,const union pipe_color_union * color,double depth,unsigned stencil)59 panfrost_clear(struct pipe_context *pipe, unsigned buffers,
60                const struct pipe_scissor_state *scissor_state,
61                const union pipe_color_union *color, double depth,
62                unsigned stencil)
63 {
64    if (!panfrost_render_condition_check(pan_context(pipe)))
65       return;
66 
67    /* Only get batch after checking the render condition, since the check can
68     * cause the batch to be flushed.
69     */
70    struct panfrost_context *ctx = pan_context(pipe);
71    struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
72    if (!batch)
73       return;
74 
75    /* At the start of the batch, we can clear for free */
76    if (batch->draw_count == 0) {
77       panfrost_batch_clear(batch, buffers, color, depth, stencil);
78       return;
79    }
80 
81    /* Once there is content, clear with a fullscreen quad */
82    panfrost_blitter_save(ctx, PAN_RENDER_CLEAR);
83 
84    perf_debug(ctx, "Clearing with quad");
85    util_blitter_clear(
86       ctx->blitter, ctx->pipe_framebuffer.width, ctx->pipe_framebuffer.height,
87       util_framebuffer_get_num_layers(&ctx->pipe_framebuffer), buffers, color,
88       depth, stencil,
89       util_framebuffer_get_num_samples(&ctx->pipe_framebuffer) > 1);
90 }
91 
92 bool
panfrost_writes_point_size(struct panfrost_context * ctx)93 panfrost_writes_point_size(struct panfrost_context *ctx)
94 {
95    struct panfrost_compiled_shader *vs = ctx->prog[PIPE_SHADER_VERTEX];
96    assert(vs != NULL);
97 
98    return vs->info.vs.writes_point_size && ctx->active_prim == MESA_PRIM_POINTS;
99 }
100 
101 /* The entire frame is in memory -- send it off to the kernel! */
102 
103 void
panfrost_flush(struct pipe_context * pipe,struct pipe_fence_handle ** fence,unsigned flags)104 panfrost_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence,
105                unsigned flags)
106 {
107    struct panfrost_context *ctx = pan_context(pipe);
108    struct panfrost_device *dev = pan_device(pipe->screen);
109 
110    /* Submit all pending jobs */
111    panfrost_flush_all_batches(ctx, NULL);
112 
113    if (fence) {
114       struct pipe_fence_handle *f = panfrost_fence_create(ctx);
115       pipe->screen->fence_reference(pipe->screen, fence, NULL);
116       *fence = f;
117    }
118 
119    if (dev->debug & PAN_DBG_TRACE)
120       pandecode_next_frame(dev->decode_ctx);
121 }
122 
123 static void
panfrost_texture_barrier(struct pipe_context * pipe,unsigned flags)124 panfrost_texture_barrier(struct pipe_context *pipe, unsigned flags)
125 {
126    struct panfrost_context *ctx = pan_context(pipe);
127    panfrost_flush_all_batches(ctx, "Texture barrier");
128 }
129 
130 static void
panfrost_set_frontend_noop(struct pipe_context * pipe,bool enable)131 panfrost_set_frontend_noop(struct pipe_context *pipe, bool enable)
132 {
133    struct panfrost_context *ctx = pan_context(pipe);
134    panfrost_flush_all_batches(ctx, "Frontend no-op change");
135    ctx->is_noop = enable;
136 }
137 
138 static void
panfrost_generic_cso_delete(struct pipe_context * pctx,void * hwcso)139 panfrost_generic_cso_delete(struct pipe_context *pctx, void *hwcso)
140 {
141    free(hwcso);
142 }
143 
144 static void
panfrost_bind_blend_state(struct pipe_context * pipe,void * cso)145 panfrost_bind_blend_state(struct pipe_context *pipe, void *cso)
146 {
147    struct panfrost_context *ctx = pan_context(pipe);
148    ctx->blend = cso;
149    ctx->dirty |= PAN_DIRTY_BLEND;
150 }
151 
152 static void
panfrost_set_blend_color(struct pipe_context * pipe,const struct pipe_blend_color * blend_color)153 panfrost_set_blend_color(struct pipe_context *pipe,
154                          const struct pipe_blend_color *blend_color)
155 {
156    struct panfrost_context *ctx = pan_context(pipe);
157    ctx->dirty |= PAN_DIRTY_BLEND;
158 
159    if (blend_color)
160       ctx->blend_color = *blend_color;
161 }
162 
163 /* Create a final blend given the context */
164 
165 uint64_t
panfrost_get_blend(struct panfrost_batch * batch,unsigned rti,struct panfrost_bo ** bo,unsigned * shader_offset)166 panfrost_get_blend(struct panfrost_batch *batch, unsigned rti,
167                    struct panfrost_bo **bo, unsigned *shader_offset)
168 {
169    struct panfrost_context *ctx = batch->ctx;
170    struct panfrost_device *dev = pan_device(ctx->base.screen);
171    struct panfrost_blend_state *blend = ctx->blend;
172    struct pan_blend_info info = blend->info[rti];
173    struct pipe_surface *surf = batch->key.cbufs[rti];
174    enum pipe_format fmt = surf->format;
175 
176    /* Use fixed-function if the equation permits, the format is blendable,
177     * and no more than one unique constant is accessed */
178    if (info.fixed_function && dev->blendable_formats[fmt].internal &&
179        !blend->base.alpha_to_one &&
180        pan_blend_is_homogenous_constant(info.constant_mask,
181                                         ctx->blend_color.color)) {
182       return 0;
183    }
184 
185    /* On all architectures, we can disable writes for a blend descriptor,
186     * at which point the format doesn't matter.
187     */
188    if (!info.enabled)
189       return 0;
190 
191    /* On Bifrost and newer, we can also use fixed-function for opaque
192     * output regardless of the format by configuring the appropriate
193     * conversion descriptor in the internal blend descriptor. (Midgard
194     * requires a blend shader even for this case.)
195     */
196    if (dev->arch >= 6 && info.opaque && !blend->base.alpha_to_one)
197       return 0;
198 
199    /* Otherwise, we need to grab a shader */
200    struct pan_blend_state pan_blend = blend->pan;
201    unsigned nr_samples = surf->nr_samples ?: surf->texture->nr_samples;
202 
203    pan_blend.rts[rti].format = fmt;
204    pan_blend.rts[rti].nr_samples = nr_samples;
205    memcpy(pan_blend.constants, ctx->blend_color.color,
206           sizeof(pan_blend.constants));
207 
208    /* Upload the shader, sharing a BO */
209    if (!(*bo)) {
210       *bo = panfrost_batch_create_bo(batch, 4096, PAN_BO_EXECUTE,
211                                      PIPE_SHADER_FRAGMENT, "Blend shader");
212       if (!(*bo)) {
213          mesa_loge("failed to allocate blend-shader");
214          return 0;
215       }
216    }
217 
218    struct panfrost_compiled_shader *ss = ctx->prog[PIPE_SHADER_FRAGMENT];
219 
220    /* Default for Midgard */
221    nir_alu_type col0_type = nir_type_float32;
222    nir_alu_type col1_type = nir_type_float32;
223 
224    /* Bifrost has per-output types, respect them */
225    if (dev->arch >= 6) {
226       col0_type = ss->info.bifrost.blend[rti].type;
227       col1_type = ss->info.bifrost.blend_src1_type;
228    }
229 
230    pthread_mutex_lock(&dev->blend_shaders.lock);
231    struct pan_blend_shader_variant *shader =
232       pan_screen(ctx->base.screen)
233          ->vtbl.get_blend_shader(&dev->blend_shaders, &pan_blend, col0_type,
234                                  col1_type, rti);
235 
236    /* Size check and upload */
237    unsigned offset = *shader_offset;
238    assert((offset + shader->binary.size) < 4096);
239    memcpy((*bo)->ptr.cpu + offset, shader->binary.data, shader->binary.size);
240    *shader_offset += shader->binary.size;
241    pthread_mutex_unlock(&dev->blend_shaders.lock);
242 
243    return ((*bo)->ptr.gpu + offset) | shader->first_tag;
244 }
245 
246 static void
panfrost_bind_rasterizer_state(struct pipe_context * pctx,void * hwcso)247 panfrost_bind_rasterizer_state(struct pipe_context *pctx, void *hwcso)
248 {
249    struct panfrost_context *ctx = pan_context(pctx);
250    ctx->rasterizer = hwcso;
251 
252    /* We can assume rasterizer is always dirty, the dependencies are
253     * too intricate to bother tracking in detail. However we could
254     * probably diff the renderers for viewport dirty tracking, that
255     * just cares about the scissor enable and the depth clips. */
256    ctx->dirty |= PAN_DIRTY_SCISSOR | PAN_DIRTY_RASTERIZER;
257 }
258 
259 static void
panfrost_set_shader_images(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start_slot,unsigned count,unsigned unbind_num_trailing_slots,const struct pipe_image_view * iviews)260 panfrost_set_shader_images(struct pipe_context *pctx,
261                            enum pipe_shader_type shader, unsigned start_slot,
262                            unsigned count, unsigned unbind_num_trailing_slots,
263                            const struct pipe_image_view *iviews)
264 {
265    struct panfrost_context *ctx = pan_context(pctx);
266    ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_IMAGE;
267 
268    /* Unbind start_slot...start_slot+count */
269    if (!iviews) {
270       for (int i = start_slot;
271            i < start_slot + count + unbind_num_trailing_slots; i++) {
272          pipe_resource_reference(&ctx->images[shader][i].resource, NULL);
273       }
274 
275       ctx->image_mask[shader] &= ~(((1ull << count) - 1) << start_slot);
276       return;
277    }
278 
279    /* fix up AFBC/AFRC; we do this before starting setup because it involves a
280       blit, so we need a consistent image state */
281    for (int i = 0; i < count; i++) {
282       const struct pipe_image_view *image = &iviews[i];
283       if (!image->resource)
284          continue;
285 
286       struct panfrost_resource *rsrc = pan_resource(image->resource);
287 
288       /* Images don't work with AFBC/AFRC, since they require pixel-level
289        * granularity */
290       if (drm_is_afbc(rsrc->image.layout.modifier) ||
291           drm_is_afrc(rsrc->image.layout.modifier)) {
292          pan_resource_modifier_convert(
293             ctx, rsrc, DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, true,
294             "Shader image");
295       }
296    }
297 
298    /* Bind start_slot...start_slot+count */
299    for (int i = 0; i < count; i++) {
300       const struct pipe_image_view *image = &iviews[i];
301       SET_BIT(ctx->image_mask[shader], 1 << (start_slot + i), image->resource);
302       if (!image->resource) {
303          util_copy_image_view(&ctx->images[shader][start_slot + i], NULL);
304          continue;
305       }
306       util_copy_image_view(&ctx->images[shader][start_slot + i], image);
307    }
308 
309    /* Unbind start_slot+count...start_slot+count+unbind_num_trailing_slots */
310    for (int i = 0; i < unbind_num_trailing_slots; i++) {
311       SET_BIT(ctx->image_mask[shader], 1 << (start_slot + count + i), NULL);
312       util_copy_image_view(&ctx->images[shader][start_slot + count + i], NULL);
313    }
314 }
315 
316 static void
panfrost_bind_vertex_elements_state(struct pipe_context * pctx,void * hwcso)317 panfrost_bind_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
318 {
319    struct panfrost_context *ctx = pan_context(pctx);
320    ctx->vertex = hwcso;
321    ctx->dirty |= PAN_DIRTY_VERTEX;
322 }
323 
324 static void
panfrost_bind_sampler_states(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start_slot,unsigned num_sampler,void ** sampler)325 panfrost_bind_sampler_states(struct pipe_context *pctx,
326                              enum pipe_shader_type shader, unsigned start_slot,
327                              unsigned num_sampler, void **sampler)
328 {
329    struct panfrost_context *ctx = pan_context(pctx);
330    ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_SAMPLER;
331 
332    for (unsigned i = 0; i < num_sampler; i++) {
333       unsigned p = start_slot + i;
334       ctx->samplers[shader][p] = sampler ? sampler[i] : NULL;
335       if (ctx->samplers[shader][p])
336          ctx->valid_samplers[shader] |= BITFIELD_BIT(p);
337       else
338          ctx->valid_samplers[shader] &= ~BITFIELD_BIT(p);
339    }
340 
341    ctx->sampler_count[shader] = util_last_bit(ctx->valid_samplers[shader]);
342 }
343 
344 static void
panfrost_set_vertex_buffers(struct pipe_context * pctx,unsigned num_buffers,const struct pipe_vertex_buffer * buffers)345 panfrost_set_vertex_buffers(struct pipe_context *pctx, unsigned num_buffers,
346                             const struct pipe_vertex_buffer *buffers)
347 {
348    struct panfrost_context *ctx = pan_context(pctx);
349 
350    util_set_vertex_buffers_mask(ctx->vertex_buffers, &ctx->vb_mask, buffers,
351                                 num_buffers, true);
352 
353    ctx->dirty |= PAN_DIRTY_VERTEX;
354 }
355 
356 static void
panfrost_set_constant_buffer(struct pipe_context * pctx,enum pipe_shader_type shader,uint index,bool take_ownership,const struct pipe_constant_buffer * buf)357 panfrost_set_constant_buffer(struct pipe_context *pctx,
358                              enum pipe_shader_type shader, uint index,
359                              bool take_ownership,
360                              const struct pipe_constant_buffer *buf)
361 {
362    struct panfrost_context *ctx = pan_context(pctx);
363    struct panfrost_constant_buffer *pbuf = &ctx->constant_buffer[shader];
364 
365    util_copy_constant_buffer(&pbuf->cb[index], buf, take_ownership);
366 
367    unsigned mask = (1 << index);
368 
369    if (unlikely(!buf)) {
370       pbuf->enabled_mask &= ~mask;
371       return;
372    }
373 
374    pbuf->enabled_mask |= mask;
375    ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_CONST;
376 }
377 
378 static void
panfrost_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref ref)379 panfrost_set_stencil_ref(struct pipe_context *pctx,
380                          const struct pipe_stencil_ref ref)
381 {
382    struct panfrost_context *ctx = pan_context(pctx);
383    ctx->stencil_ref = ref;
384    ctx->dirty |= PAN_DIRTY_ZS;
385 }
386 
387 static void
panfrost_set_sampler_views(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start_slot,unsigned num_views,unsigned unbind_num_trailing_slots,bool take_ownership,struct pipe_sampler_view ** views)388 panfrost_set_sampler_views(struct pipe_context *pctx,
389                            enum pipe_shader_type shader, unsigned start_slot,
390                            unsigned num_views,
391                            unsigned unbind_num_trailing_slots,
392                            bool take_ownership,
393                            struct pipe_sampler_view **views)
394 {
395    struct panfrost_context *ctx = pan_context(pctx);
396    ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_TEXTURE;
397 
398    unsigned new_nr = 0;
399    unsigned i;
400 
401    for (i = 0; i < num_views; ++i) {
402       struct pipe_sampler_view *view = views ? views[i] : NULL;
403       unsigned p = i + start_slot;
404 
405       if (view)
406          new_nr = p + 1;
407 
408       if (take_ownership) {
409          pipe_sampler_view_reference(
410             (struct pipe_sampler_view **)&ctx->sampler_views[shader][p], NULL);
411          ctx->sampler_views[shader][i] = (struct panfrost_sampler_view *)view;
412       } else {
413          pipe_sampler_view_reference(
414             (struct pipe_sampler_view **)&ctx->sampler_views[shader][p], view);
415       }
416    }
417 
418    for (; i < num_views + unbind_num_trailing_slots; i++) {
419       unsigned p = i + start_slot;
420       pipe_sampler_view_reference(
421          (struct pipe_sampler_view **)&ctx->sampler_views[shader][p], NULL);
422    }
423 
424    /* If the sampler view count is higher than the greatest sampler view
425     * we touch, it can't change */
426    if (ctx->sampler_view_count[shader] >
427        start_slot + num_views + unbind_num_trailing_slots)
428       return;
429 
430    /* If we haven't set any sampler views here, search lower numbers for
431     * set sampler views */
432    if (new_nr == 0) {
433       for (i = 0; i < start_slot; ++i) {
434          if (ctx->sampler_views[shader][i])
435             new_nr = i + 1;
436       }
437    }
438 
439    ctx->sampler_view_count[shader] = new_nr;
440 }
441 
442 static void
panfrost_set_shader_buffers(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned count,const struct pipe_shader_buffer * buffers,unsigned writable_bitmask)443 panfrost_set_shader_buffers(struct pipe_context *pctx,
444                             enum pipe_shader_type shader, unsigned start,
445                             unsigned count,
446                             const struct pipe_shader_buffer *buffers,
447                             unsigned writable_bitmask)
448 {
449    struct panfrost_context *ctx = pan_context(pctx);
450 
451    util_set_shader_buffers_mask(ctx->ssbo[shader], &ctx->ssbo_mask[shader],
452                                 buffers, start, count);
453 
454    ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_SSBO;
455 }
456 
457 static void
panfrost_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * fb)458 panfrost_set_framebuffer_state(struct pipe_context *pctx,
459                                const struct pipe_framebuffer_state *fb)
460 {
461    struct panfrost_context *ctx = pan_context(pctx);
462 
463    util_copy_framebuffer_state(&ctx->pipe_framebuffer, fb);
464    ctx->batch = NULL;
465 
466    /* Hot draw call path needs the mask of active render targets */
467    ctx->fb_rt_mask = 0;
468 
469    for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) {
470       if (ctx->pipe_framebuffer.cbufs[i])
471          ctx->fb_rt_mask |= BITFIELD_BIT(i);
472    }
473 }
474 
475 static void
panfrost_bind_depth_stencil_state(struct pipe_context * pipe,void * cso)476 panfrost_bind_depth_stencil_state(struct pipe_context *pipe, void *cso)
477 {
478    struct panfrost_context *ctx = pan_context(pipe);
479    ctx->depth_stencil = cso;
480    ctx->dirty |= PAN_DIRTY_ZS;
481 }
482 
483 static void
panfrost_set_sample_mask(struct pipe_context * pipe,unsigned sample_mask)484 panfrost_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
485 {
486    struct panfrost_context *ctx = pan_context(pipe);
487    ctx->sample_mask = sample_mask;
488    ctx->dirty |= PAN_DIRTY_MSAA;
489 }
490 
491 static void
panfrost_set_min_samples(struct pipe_context * pipe,unsigned min_samples)492 panfrost_set_min_samples(struct pipe_context *pipe, unsigned min_samples)
493 {
494    struct panfrost_context *ctx = pan_context(pipe);
495    ctx->min_samples = min_samples;
496    ctx->dirty |= PAN_DIRTY_MSAA;
497 }
498 
499 static void
panfrost_set_clip_state(struct pipe_context * pipe,const struct pipe_clip_state * clip)500 panfrost_set_clip_state(struct pipe_context *pipe,
501                         const struct pipe_clip_state *clip)
502 {
503    // struct panfrost_context *panfrost = pan_context(pipe);
504 }
505 
506 static void
panfrost_set_viewport_states(struct pipe_context * pipe,unsigned start_slot,unsigned num_viewports,const struct pipe_viewport_state * viewports)507 panfrost_set_viewport_states(struct pipe_context *pipe, unsigned start_slot,
508                              unsigned num_viewports,
509                              const struct pipe_viewport_state *viewports)
510 {
511    struct panfrost_context *ctx = pan_context(pipe);
512 
513    assert(start_slot == 0);
514    assert(num_viewports == 1);
515 
516    ctx->pipe_viewport = *viewports;
517    ctx->dirty |= PAN_DIRTY_VIEWPORT;
518 }
519 
520 static void
panfrost_set_scissor_states(struct pipe_context * pipe,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * scissors)521 panfrost_set_scissor_states(struct pipe_context *pipe, unsigned start_slot,
522                             unsigned num_scissors,
523                             const struct pipe_scissor_state *scissors)
524 {
525    struct panfrost_context *ctx = pan_context(pipe);
526 
527    assert(start_slot == 0);
528    assert(num_scissors == 1);
529 
530    ctx->scissor = *scissors;
531    ctx->dirty |= PAN_DIRTY_SCISSOR;
532 }
533 
534 static void
panfrost_set_polygon_stipple(struct pipe_context * pipe,const struct pipe_poly_stipple * stipple)535 panfrost_set_polygon_stipple(struct pipe_context *pipe,
536                              const struct pipe_poly_stipple *stipple)
537 {
538    // struct panfrost_context *panfrost = pan_context(pipe);
539 }
540 
541 static void
panfrost_set_active_query_state(struct pipe_context * pipe,bool enable)542 panfrost_set_active_query_state(struct pipe_context *pipe, bool enable)
543 {
544    struct panfrost_context *ctx = pan_context(pipe);
545    ctx->active_queries = enable;
546    ctx->dirty |= PAN_DIRTY_OQ;
547 }
548 
549 static void
panfrost_render_condition(struct pipe_context * pipe,struct pipe_query * query,bool condition,enum pipe_render_cond_flag mode)550 panfrost_render_condition(struct pipe_context *pipe, struct pipe_query *query,
551                           bool condition, enum pipe_render_cond_flag mode)
552 {
553    struct panfrost_context *ctx = pan_context(pipe);
554 
555    ctx->cond_query = (struct panfrost_query *)query;
556    ctx->cond_cond = condition;
557    ctx->cond_mode = mode;
558 }
559 
560 static void
panfrost_destroy(struct pipe_context * pipe)561 panfrost_destroy(struct pipe_context *pipe)
562 {
563    struct panfrost_context *panfrost = pan_context(pipe);
564    struct panfrost_device *dev = pan_device(pipe->screen);
565 
566    pan_screen(pipe->screen)->vtbl.context_cleanup(panfrost);
567 
568    if (panfrost->writers)
569       _mesa_hash_table_destroy(panfrost->writers, NULL);
570 
571    if (panfrost->blitter)
572       util_blitter_destroy(panfrost->blitter);
573 
574    util_unreference_framebuffer_state(&panfrost->pipe_framebuffer);
575    if (pipe->stream_uploader)
576       u_upload_destroy(pipe->stream_uploader);
577 
578    panfrost_pool_cleanup(&panfrost->descs);
579    panfrost_pool_cleanup(&panfrost->shaders);
580    panfrost_afbc_context_destroy(panfrost);
581 
582    util_dynarray_foreach(&panfrost->global_buffers, struct pipe_resource *, res) {
583       pipe_resource_reference(res, NULL);
584    }
585 
586    util_dynarray_fini(&panfrost->global_buffers);
587 
588    drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->in_sync_obj);
589    if (panfrost->in_sync_fd != -1) {
590       close(panfrost->in_sync_fd);
591       panfrost->in_sync_fd = -1;
592    }
593 
594    drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->syncobj);
595    ralloc_free(pipe);
596 }
597 
598 static struct pipe_query *
panfrost_create_query(struct pipe_context * pipe,unsigned type,unsigned index)599 panfrost_create_query(struct pipe_context *pipe, unsigned type, unsigned index)
600 {
601    struct panfrost_context *ctx = pan_context(pipe);
602    struct panfrost_device *dev = pan_device(ctx->base.screen);
603    struct panfrost_query *q = rzalloc(pipe, struct panfrost_query);
604 
605    q->type = type;
606    q->index = index;
607 
608    unsigned size = 0;
609 
610    switch (q->type) {
611    case PIPE_QUERY_OCCLUSION_COUNTER:
612    case PIPE_QUERY_OCCLUSION_PREDICATE:
613    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
614       size = sizeof(uint64_t) * dev->core_id_range;
615       break;
616    case PIPE_QUERY_TIMESTAMP:
617       size = sizeof(uint64_t);
618       break;
619    case PIPE_QUERY_TIME_ELAPSED:
620       size = sizeof(uint64_t) * 2;
621       break;
622    default:
623       break;
624    }
625 
626    /* Allocate a resource for the query results to be stored */
627    if (size > 0) {
628       q->rsrc =
629          pipe_buffer_create(ctx->base.screen, PIPE_BIND_QUERY_BUFFER, 0, size);
630 
631       if (!q->rsrc) {
632          ralloc_free(q);
633          return NULL;
634       }
635 
636       /* Default to 0 if nothing at all drawn. */
637       uint8_t *zeroes = alloca(size);
638       memset(zeroes, 0, size);
639       pipe_buffer_write(pipe, q->rsrc, 0, size, zeroes);
640    }
641 
642    return (struct pipe_query *)q;
643 }
644 
645 static void
panfrost_destroy_query(struct pipe_context * pipe,struct pipe_query * q)646 panfrost_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
647 {
648    struct panfrost_query *query = (struct panfrost_query *)q;
649 
650    if (query->rsrc)
651       pipe_resource_reference(&query->rsrc, NULL);
652 
653    ralloc_free(q);
654 }
655 
656 static void
panfrost_emit_write_timestamp(struct panfrost_context * ctx,struct panfrost_resource * rsrc,unsigned offset,const char * reason)657 panfrost_emit_write_timestamp(struct panfrost_context *ctx,
658                               struct panfrost_resource *rsrc, unsigned offset,
659                               const char *reason)
660 {
661    struct panfrost_screen *screen = pan_screen(ctx->base.screen);
662    struct panfrost_batch *batch = panfrost_get_fresh_batch_for_fbo(ctx, reason);
663 
664    screen->vtbl.emit_write_timestamp(batch, rsrc, offset);
665 }
666 
667 static bool
panfrost_begin_query(struct pipe_context * pipe,struct pipe_query * q)668 panfrost_begin_query(struct pipe_context *pipe, struct pipe_query *q)
669 {
670    struct panfrost_context *ctx = pan_context(pipe);
671    struct panfrost_device *dev = pan_device(ctx->base.screen);
672    struct panfrost_query *query = (struct panfrost_query *)q;
673 
674    switch (query->type) {
675    case PIPE_QUERY_OCCLUSION_COUNTER:
676    case PIPE_QUERY_OCCLUSION_PREDICATE:
677    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
678       unsigned size = sizeof(uint64_t) * dev->core_id_range;
679 
680       /* Default to 0 if nothing at all drawn. */
681       uint8_t *zeroes = alloca(size);
682       memset(zeroes, 0, size);
683       pipe_buffer_write(pipe, query->rsrc, 0, size, zeroes);
684 
685       query->msaa = (ctx->pipe_framebuffer.samples > 1);
686       ctx->occlusion_query = query;
687       ctx->dirty |= PAN_DIRTY_OQ;
688       break;
689    }
690 
691    case PIPE_QUERY_TIMESTAMP:
692    case PIPE_QUERY_TIMESTAMP_DISJOINT:
693       /* This is a no op on query start */
694       break;
695 
696    case PIPE_QUERY_TIME_ELAPSED: {
697       struct panfrost_resource *rsrc = pan_resource(query->rsrc);
698       panfrost_emit_write_timestamp(ctx, rsrc, 0, "TIME_ELAPSED begin_query");
699       break;
700    }
701 
702       /* Geometry statistics are computed in the driver. XXX: geom/tess
703        * shaders.. */
704 
705    case PIPE_QUERY_PRIMITIVES_GENERATED:
706       query->start = ctx->prims_generated;
707       break;
708    case PIPE_QUERY_PRIMITIVES_EMITTED:
709       query->start = ctx->tf_prims_generated;
710       break;
711 
712    case PAN_QUERY_DRAW_CALLS:
713       query->start = ctx->draw_calls;
714       break;
715 
716    default:
717       break;
718    }
719 
720    return true;
721 }
722 
723 static bool
panfrost_end_query(struct pipe_context * pipe,struct pipe_query * q)724 panfrost_end_query(struct pipe_context *pipe, struct pipe_query *q)
725 {
726    struct panfrost_context *ctx = pan_context(pipe);
727    struct panfrost_query *query = (struct panfrost_query *)q;
728 
729    switch (query->type) {
730    case PIPE_QUERY_OCCLUSION_COUNTER:
731    case PIPE_QUERY_OCCLUSION_PREDICATE:
732    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
733       ctx->occlusion_query = NULL;
734       ctx->dirty |= PAN_DIRTY_OQ;
735       break;
736    case PIPE_QUERY_TIMESTAMP: {
737       struct panfrost_resource *rsrc = pan_resource(query->rsrc);
738       panfrost_emit_write_timestamp(ctx, rsrc, 0, "TIMESTAMP end_query");
739       break;
740    }
741    case PIPE_QUERY_TIMESTAMP_DISJOINT:
742       /* This is a no op */
743       break;
744    case PIPE_QUERY_TIME_ELAPSED: {
745       struct panfrost_resource *rsrc = pan_resource(query->rsrc);
746       panfrost_emit_write_timestamp(ctx, rsrc, sizeof(uint64_t),
747                                     "TIME_ELAPSED end_query");
748       break;
749    }
750    case PIPE_QUERY_PRIMITIVES_GENERATED:
751       query->end = ctx->prims_generated;
752       break;
753    case PIPE_QUERY_PRIMITIVES_EMITTED:
754       query->end = ctx->tf_prims_generated;
755       break;
756    case PAN_QUERY_DRAW_CALLS:
757       query->end = ctx->draw_calls;
758       break;
759    }
760 
761    return true;
762 }
763 
764 static bool
panfrost_get_query_result(struct pipe_context * pipe,struct pipe_query * q,bool wait,union pipe_query_result * vresult)765 panfrost_get_query_result(struct pipe_context *pipe, struct pipe_query *q,
766                           bool wait, union pipe_query_result *vresult)
767 {
768    struct panfrost_query *query = (struct panfrost_query *)q;
769    struct panfrost_context *ctx = pan_context(pipe);
770    struct panfrost_device *dev = pan_device(ctx->base.screen);
771    struct panfrost_resource *rsrc = pan_resource(query->rsrc);
772 
773    switch (query->type) {
774    case PIPE_QUERY_OCCLUSION_COUNTER:
775    case PIPE_QUERY_OCCLUSION_PREDICATE:
776    case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
777       panfrost_flush_writer(ctx, rsrc, "Occlusion query");
778       panfrost_bo_wait(rsrc->bo, INT64_MAX, false);
779 
780       /* Read back the query results */
781       uint64_t *result = (uint64_t *)rsrc->bo->ptr.cpu;
782 
783       if (query->type == PIPE_QUERY_OCCLUSION_COUNTER) {
784          uint64_t passed = 0;
785          for (int i = 0; i < dev->core_id_range; ++i)
786             passed += result[i];
787 
788          if (dev->arch <= 5 && !query->msaa)
789             passed /= 4;
790 
791          vresult->u64 = passed;
792       } else {
793          vresult->b = !!result[0];
794       }
795 
796       break;
797 
798    case PIPE_QUERY_TIMESTAMP: {
799       panfrost_flush_writer(ctx, rsrc, "Timestamp query");
800       panfrost_bo_wait(rsrc->bo, INT64_MAX, false);
801       uint64_t *timestamp = (uint64_t *)rsrc->bo->ptr.cpu;
802 
803       vresult->u64 = pan_gpu_time_to_ns(dev, *timestamp);
804       break;
805    }
806 
807    case PIPE_QUERY_TIMESTAMP_DISJOINT: {
808       vresult->timestamp_disjoint.frequency =
809          dev->kmod.props.timestamp_frequency;
810       vresult->timestamp_disjoint.disjoint = false;
811       break;
812    }
813 
814    case PIPE_QUERY_TIME_ELAPSED: {
815       panfrost_flush_writer(ctx, rsrc, "Time elapsed query");
816       panfrost_bo_wait(rsrc->bo, INT64_MAX, false);
817       uint64_t *timestamp = (uint64_t *)rsrc->bo->ptr.cpu;
818 
819       vresult->u64 = pan_gpu_time_to_ns(dev, timestamp[1] - timestamp[0]);
820       break;
821    }
822 
823    case PIPE_QUERY_PRIMITIVES_GENERATED:
824    case PIPE_QUERY_PRIMITIVES_EMITTED:
825       panfrost_flush_all_batches(ctx, "Primitive count query");
826       vresult->u64 = query->end - query->start;
827       break;
828 
829    case PAN_QUERY_DRAW_CALLS:
830       vresult->u64 = query->end - query->start;
831       break;
832 
833    default:
834       /* TODO: more queries */
835       break;
836    }
837 
838    return true;
839 }
840 
841 /*
842  * Check the render condition for software condition rendering.
843  *
844  * Note: this may invalidate the batch!
845  */
846 bool
panfrost_render_condition_check(struct panfrost_context * ctx)847 panfrost_render_condition_check(struct panfrost_context *ctx)
848 {
849    if (!ctx->cond_query)
850       return true;
851 
852    perf_debug(ctx, "Implementing conditional rendering on the CPU");
853 
854    union pipe_query_result res = {0};
855    bool wait = ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT &&
856                ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT;
857 
858    struct pipe_query *pq = (struct pipe_query *)ctx->cond_query;
859 
860    if (panfrost_get_query_result(&ctx->base, pq, wait, &res))
861       return res.u64 != ctx->cond_cond;
862 
863    return true;
864 }
865 
866 static struct pipe_stream_output_target *
panfrost_create_stream_output_target(struct pipe_context * pctx,struct pipe_resource * prsc,unsigned buffer_offset,unsigned buffer_size)867 panfrost_create_stream_output_target(struct pipe_context *pctx,
868                                      struct pipe_resource *prsc,
869                                      unsigned buffer_offset,
870                                      unsigned buffer_size)
871 {
872    struct pipe_stream_output_target *target;
873 
874    target = &rzalloc(pctx, struct panfrost_streamout_target)->base;
875 
876    if (!target)
877       return NULL;
878 
879    pipe_reference_init(&target->reference, 1);
880    pipe_resource_reference(&target->buffer, prsc);
881 
882    target->context = pctx;
883    target->buffer_offset = buffer_offset;
884    target->buffer_size = buffer_size;
885 
886    return target;
887 }
888 
889 static void
panfrost_stream_output_target_destroy(struct pipe_context * pctx,struct pipe_stream_output_target * target)890 panfrost_stream_output_target_destroy(struct pipe_context *pctx,
891                                       struct pipe_stream_output_target *target)
892 {
893    pipe_resource_reference(&target->buffer, NULL);
894    ralloc_free(target);
895 }
896 
897 static void
panfrost_set_stream_output_targets(struct pipe_context * pctx,unsigned num_targets,struct pipe_stream_output_target ** targets,const unsigned * offsets,enum mesa_prim output_prim)898 panfrost_set_stream_output_targets(struct pipe_context *pctx,
899                                    unsigned num_targets,
900                                    struct pipe_stream_output_target **targets,
901                                    const unsigned *offsets,
902                                    enum mesa_prim output_prim)
903 {
904    struct panfrost_context *ctx = pan_context(pctx);
905    struct panfrost_streamout *so = &ctx->streamout;
906 
907    assert(num_targets <= ARRAY_SIZE(so->targets));
908 
909    for (unsigned i = 0; i < num_targets; i++) {
910       if (targets[i] && offsets[i] != -1)
911          pan_so_target(targets[i])->offset = offsets[i];
912 
913       pipe_so_target_reference(&so->targets[i], targets[i]);
914    }
915 
916    for (unsigned i = num_targets; i < so->num_targets; i++)
917       pipe_so_target_reference(&so->targets[i], NULL);
918 
919    so->num_targets = num_targets;
920    ctx->dirty |= PAN_DIRTY_SO;
921 }
922 
923 static void
panfrost_set_global_binding(struct pipe_context * pctx,unsigned first,unsigned count,struct pipe_resource ** resources,uint32_t ** handles)924 panfrost_set_global_binding(struct pipe_context *pctx, unsigned first,
925                             unsigned count, struct pipe_resource **resources,
926                             uint32_t **handles)
927 {
928    struct panfrost_context *ctx = pan_context(pctx);
929 
930    unsigned old_size =
931       util_dynarray_num_elements(&ctx->global_buffers, *resources);
932 
933    if (old_size < first + count) {
934       /* we are screwed no matter what */
935       if (!util_dynarray_grow(&ctx->global_buffers, *resources,
936                               (first + count) - old_size))
937          unreachable("out of memory");
938 
939       for (unsigned i = old_size; i < first + count; i++)
940          *util_dynarray_element(&ctx->global_buffers, struct pipe_resource *,
941                                 i) = NULL;
942    }
943 
944    for (unsigned i = 0; i < count; ++i) {
945       struct pipe_resource **res = util_dynarray_element(
946          &ctx->global_buffers, struct pipe_resource *, first + i);
947       if (resources && resources[i]) {
948          pipe_resource_reference(res, resources[i]);
949 
950          /* The handle points to uint32_t, but space is allocated for 64
951           * bits. We need to respect the offset passed in. This interface
952           * is so bad.
953           */
954          uint64_t addr = 0;
955          struct panfrost_resource *rsrc = pan_resource(resources[i]);
956 
957          memcpy(&addr, handles[i], sizeof(addr));
958          addr += rsrc->bo->ptr.gpu;
959          memcpy(handles[i], &addr, sizeof(addr));
960       } else {
961          pipe_resource_reference(res, NULL);
962       }
963    }
964 }
965 
966 static void
panfrost_memory_barrier(struct pipe_context * pctx,unsigned flags)967 panfrost_memory_barrier(struct pipe_context *pctx, unsigned flags)
968 {
969    /* TODO: Be smart and only flush the minimum needed, maybe emitting a
970     * cache flush job if that would help */
971    panfrost_flush_all_batches(pan_context(pctx), "Memory barrier");
972 }
973 
974 static void
panfrost_create_fence_fd(struct pipe_context * pctx,struct pipe_fence_handle ** pfence,int fd,enum pipe_fd_type type)975 panfrost_create_fence_fd(struct pipe_context *pctx,
976                          struct pipe_fence_handle **pfence, int fd,
977                          enum pipe_fd_type type)
978 {
979    *pfence = panfrost_fence_from_fd(pan_context(pctx), fd, type);
980 }
981 
982 static void
panfrost_fence_server_sync(struct pipe_context * pctx,struct pipe_fence_handle * f)983 panfrost_fence_server_sync(struct pipe_context *pctx,
984                            struct pipe_fence_handle *f)
985 {
986    struct panfrost_device *dev = pan_device(pctx->screen);
987    struct panfrost_context *ctx = pan_context(pctx);
988    int fd = -1, ret;
989 
990    ret = drmSyncobjExportSyncFile(panfrost_device_fd(dev), f->syncobj, &fd);
991    assert(!ret);
992 
993    sync_accumulate("panfrost", &ctx->in_sync_fd, fd);
994    close(fd);
995 }
996 
997 struct pipe_context *
panfrost_create_context(struct pipe_screen * screen,void * priv,unsigned flags)998 panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
999 {
1000    struct panfrost_context *ctx = rzalloc(NULL, struct panfrost_context);
1001 
1002    if (!ctx)
1003       return NULL;
1004 
1005    ctx->flags = flags;
1006 
1007    struct pipe_context *gallium = (struct pipe_context *)ctx;
1008    struct panfrost_device *dev = pan_device(screen);
1009 
1010    int ret;
1011 
1012    /* Create a syncobj in a signaled state. Will be updated to point to the
1013     * last queued job out_sync every time we submit a new job.
1014     */
1015    ret = drmSyncobjCreate(panfrost_device_fd(dev), DRM_SYNCOBJ_CREATE_SIGNALED,
1016                           &ctx->syncobj);
1017    if (ret) {
1018       ralloc_free(ctx);
1019       return NULL;
1020    }
1021 
1022    gallium->screen = screen;
1023 
1024    gallium->destroy = panfrost_destroy;
1025 
1026    gallium->set_framebuffer_state = panfrost_set_framebuffer_state;
1027    gallium->set_debug_callback = u_default_set_debug_callback;
1028 
1029    gallium->create_fence_fd = panfrost_create_fence_fd;
1030    gallium->fence_server_sync = panfrost_fence_server_sync;
1031 
1032    gallium->flush = panfrost_flush;
1033    gallium->clear = panfrost_clear;
1034    gallium->clear_texture = u_default_clear_texture;
1035    gallium->texture_barrier = panfrost_texture_barrier;
1036    gallium->set_frontend_noop = panfrost_set_frontend_noop;
1037 
1038    gallium->set_vertex_buffers = panfrost_set_vertex_buffers;
1039    gallium->set_constant_buffer = panfrost_set_constant_buffer;
1040    gallium->set_shader_buffers = panfrost_set_shader_buffers;
1041    gallium->set_shader_images = panfrost_set_shader_images;
1042 
1043    gallium->set_stencil_ref = panfrost_set_stencil_ref;
1044 
1045    gallium->set_sampler_views = panfrost_set_sampler_views;
1046 
1047    gallium->bind_rasterizer_state = panfrost_bind_rasterizer_state;
1048    gallium->delete_rasterizer_state = panfrost_generic_cso_delete;
1049 
1050    gallium->bind_vertex_elements_state = panfrost_bind_vertex_elements_state;
1051    gallium->delete_vertex_elements_state = panfrost_generic_cso_delete;
1052 
1053    gallium->delete_sampler_state = panfrost_generic_cso_delete;
1054    gallium->bind_sampler_states = panfrost_bind_sampler_states;
1055 
1056    gallium->bind_depth_stencil_alpha_state = panfrost_bind_depth_stencil_state;
1057    gallium->delete_depth_stencil_alpha_state = panfrost_generic_cso_delete;
1058 
1059    gallium->set_sample_mask = panfrost_set_sample_mask;
1060    gallium->set_min_samples = panfrost_set_min_samples;
1061 
1062    gallium->set_clip_state = panfrost_set_clip_state;
1063    gallium->set_viewport_states = panfrost_set_viewport_states;
1064    gallium->set_scissor_states = panfrost_set_scissor_states;
1065    gallium->set_polygon_stipple = panfrost_set_polygon_stipple;
1066    gallium->set_active_query_state = panfrost_set_active_query_state;
1067    gallium->render_condition = panfrost_render_condition;
1068 
1069    gallium->create_query = panfrost_create_query;
1070    gallium->destroy_query = panfrost_destroy_query;
1071    gallium->begin_query = panfrost_begin_query;
1072    gallium->end_query = panfrost_end_query;
1073    gallium->get_query_result = panfrost_get_query_result;
1074 
1075    gallium->create_stream_output_target = panfrost_create_stream_output_target;
1076    gallium->stream_output_target_destroy =
1077       panfrost_stream_output_target_destroy;
1078    gallium->set_stream_output_targets = panfrost_set_stream_output_targets;
1079 
1080    gallium->bind_blend_state = panfrost_bind_blend_state;
1081    gallium->delete_blend_state = panfrost_generic_cso_delete;
1082 
1083    gallium->set_blend_color = panfrost_set_blend_color;
1084 
1085    gallium->set_global_binding = panfrost_set_global_binding;
1086    gallium->memory_barrier = panfrost_memory_barrier;
1087 
1088    pan_screen(screen)->vtbl.context_populate_vtbl(gallium);
1089 
1090    panfrost_resource_context_init(gallium);
1091    panfrost_shader_context_init(gallium);
1092    panfrost_afbc_context_init(ctx);
1093 
1094    gallium->stream_uploader = u_upload_create_default(gallium);
1095    gallium->const_uploader = gallium->stream_uploader;
1096 
1097    if (panfrost_pool_init(&ctx->descs, ctx, dev, 0, 4096, "Descriptors", true,
1098                           false) ||
1099 
1100        panfrost_pool_init(&ctx->shaders, ctx, dev, PAN_BO_EXECUTE, 4096,
1101                           "Shaders", true, false)) {
1102       goto failed;
1103    }
1104 
1105    ctx->blitter = util_blitter_create(gallium);
1106 
1107    ctx->writers = _mesa_hash_table_create(gallium, _mesa_hash_pointer,
1108                                           _mesa_key_pointer_equal);
1109 
1110    assert(ctx->blitter);
1111 
1112    /* Prepare for render! */
1113 
1114    /* By default mask everything on */
1115    ctx->sample_mask = ~0;
1116    ctx->active_queries = true;
1117 
1118    util_dynarray_init(&ctx->global_buffers, ctx);
1119 
1120    /* Sync object/FD used for NATIVE_FENCE_FD. */
1121    ctx->in_sync_fd = -1;
1122    ret = drmSyncobjCreate(panfrost_device_fd(dev), 0, &ctx->in_sync_obj);
1123    assert(!ret);
1124 
1125    ret = pan_screen(screen)->vtbl.context_init(ctx);
1126 
1127    if (ret)
1128       goto failed;
1129 
1130    return gallium;
1131 
1132 failed:
1133    gallium->destroy(gallium);
1134    return NULL;
1135 }
1136 
1137 void
panfrost_context_reinit(struct panfrost_context * ctx)1138 panfrost_context_reinit(struct panfrost_context *ctx)
1139 {
1140    pan_screen(ctx->base.screen)->vtbl.context_cleanup(ctx);
1141    ASSERTED int ret = pan_screen(ctx->base.screen)->vtbl.context_init(ctx);
1142    assert(!ret);
1143 }
1144