xref: /aosp_15_r20/external/libdrm/tests/tegra/vic40.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1 /*
2  * Copyright © 2018 NVIDIA Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include <errno.h>
24 #include <string.h>
25 
26 #include "private.h"
27 #include "tegra.h"
28 #include "vic.h"
29 #include "vic40.h"
30 
31 struct vic40 {
32     struct vic base;
33 
34     struct {
35         struct drm_tegra_mapping *map;
36         struct drm_tegra_bo *bo;
37     } config;
38 
39     struct {
40         struct drm_tegra_mapping *map;
41         struct drm_tegra_bo *bo;
42     } filter;
43 };
44 
vic40_fill(struct vic * v,struct vic_image * output,unsigned int left,unsigned int top,unsigned int right,unsigned int bottom,unsigned int alpha,unsigned int red,unsigned int green,unsigned int blue)45 static int vic40_fill(struct vic *v, struct vic_image *output,
46                       unsigned int left, unsigned int top,
47                       unsigned int right, unsigned int bottom,
48                       unsigned int alpha, unsigned int red,
49                       unsigned int green, unsigned int blue)
50 {
51     struct vic40 *vic = container_of(v, struct vic40, base);
52     ConfigStruct *c;
53     int err;
54 
55     err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
56     if (err < 0) {
57         fprintf(stderr, "failed to map configuration structure: %s\n",
58                 strerror(-err));
59         return err;
60     }
61 
62     memset(c, 0, sizeof(*c));
63 
64     c->outputConfig.TargetRectTop = top;
65     c->outputConfig.TargetRectLeft = left;
66     c->outputConfig.TargetRectRight = right;
67     c->outputConfig.TargetRectBottom = bottom;
68     c->outputConfig.BackgroundAlpha = alpha;
69     c->outputConfig.BackgroundR = red;
70     c->outputConfig.BackgroundG = green;
71     c->outputConfig.BackgroundB = blue;
72 
73     c->outputSurfaceConfig.OutPixelFormat = output->format;
74     c->outputSurfaceConfig.OutBlkKind = output->kind;
75     c->outputSurfaceConfig.OutBlkHeight = 0;
76     c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
77     c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
78     c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
79     c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
80     c->outputSurfaceConfig.OutChromaWidth = 16383;
81     c->outputSurfaceConfig.OutChromaHeight = 16383;
82 
83     drm_tegra_bo_unmap(vic->config.bo);
84 
85     return 0;
86 }
87 
vic40_blit(struct vic * v,struct vic_image * output,struct vic_image * input)88 static int vic40_blit(struct vic *v, struct vic_image *output,
89                       struct vic_image *input)
90 {
91     struct vic40 *vic = container_of(v, struct vic40, base);
92     SlotSurfaceConfig *surface;
93     SlotConfig *slot;
94     ConfigStruct *c;
95     int err;
96 
97     err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
98     if (err < 0) {
99         fprintf(stderr, "failed to map configuration structure: %s\n",
100                 strerror(-err));
101         return err;
102     }
103 
104     memset(c, 0, sizeof(*c));
105 
106     c->outputConfig.TargetRectTop = 0;
107     c->outputConfig.TargetRectLeft = 0;
108     c->outputConfig.TargetRectRight = output->width - 1;
109     c->outputConfig.TargetRectBottom = output->height - 1;
110     c->outputConfig.BackgroundAlpha = 1023;
111     c->outputConfig.BackgroundR = 1023;
112     c->outputConfig.BackgroundG = 1023;
113     c->outputConfig.BackgroundB = 1023;
114 
115     c->outputSurfaceConfig.OutPixelFormat = output->format;
116     c->outputSurfaceConfig.OutBlkKind = output->kind;
117     c->outputSurfaceConfig.OutBlkHeight = 0;
118     c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
119     c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
120     c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
121     c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
122     c->outputSurfaceConfig.OutChromaWidth = 16383;
123     c->outputSurfaceConfig.OutChromaHeight = 16383;
124 
125     slot = &c->slotStruct[0].slotConfig;
126     slot->SlotEnable = 1;
127     slot->CurrentFieldEnable = 1;
128     slot->PlanarAlpha = 1023;
129     slot->ConstantAlpha = 1;
130     slot->SourceRectLeft = 0 << 16;
131     slot->SourceRectRight = (input->width - 1) << 16;
132     slot->SourceRectTop = 0 << 16;
133     slot->SourceRectBottom = (input->height - 1) << 16;
134     slot->DestRectLeft = 0;
135     slot->DestRectRight = output->width - 1;
136     slot->DestRectTop = 0;
137     slot->DestRectBottom = output->height - 1;
138     slot->SoftClampHigh = 1023;
139 
140     surface = &c->slotStruct[0].slotSurfaceConfig;
141     surface->SlotPixelFormat = input->format;
142     surface->SlotBlkKind = input->kind;
143     surface->SlotBlkHeight = 0; /* XXX */
144     surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
145     surface->SlotSurfaceWidth = input->width - 1;
146     surface->SlotSurfaceHeight = input->height - 1;
147     surface->SlotLumaWidth = input->stride - 1;
148     surface->SlotLumaHeight = input->height - 1;
149     surface->SlotChromaWidth = 16383;
150     surface->SlotChromaHeight = 16383;
151 
152     drm_tegra_bo_unmap(vic->config.bo);
153 
154     return 0;
155 }
156 
vic40_flip(struct vic * v,struct vic_image * output,struct vic_image * input)157 static int vic40_flip(struct vic *v, struct vic_image *output,
158                       struct vic_image *input)
159 {
160     struct vic40 *vic = container_of(v, struct vic40, base);
161     SlotSurfaceConfig *surface;
162     SlotConfig *slot;
163     ConfigStruct *c;
164     int err;
165 
166     err = drm_tegra_bo_map(vic->config.bo, (void **)&c);
167     if (err < 0) {
168         fprintf(stderr, "failed to map configuration structure: %s\n",
169                 strerror(-err));
170         return err;
171     }
172 
173     memset(c, 0, sizeof(*c));
174 
175     c->outputConfig.TargetRectTop = 0;
176     c->outputConfig.TargetRectLeft = 0;
177     c->outputConfig.TargetRectRight = output->width - 1;
178     c->outputConfig.TargetRectBottom = output->height - 1;
179     c->outputConfig.BackgroundAlpha = 1023;
180     c->outputConfig.BackgroundR = 1023;
181     c->outputConfig.BackgroundG = 1023;
182     c->outputConfig.BackgroundB = 1023;
183     c->outputConfig.OutputFlipY = 1;
184 
185     c->outputSurfaceConfig.OutPixelFormat = output->format;
186     c->outputSurfaceConfig.OutBlkKind = output->kind;
187     c->outputSurfaceConfig.OutBlkHeight = 0;
188     c->outputSurfaceConfig.OutSurfaceWidth = output->width - 1;
189     c->outputSurfaceConfig.OutSurfaceHeight = output->height - 1;
190     c->outputSurfaceConfig.OutLumaWidth = output->stride - 1;
191     c->outputSurfaceConfig.OutLumaHeight = output->height - 1;
192     c->outputSurfaceConfig.OutChromaWidth = 16383;
193     c->outputSurfaceConfig.OutChromaHeight = 16383;
194 
195     slot = &c->slotStruct[0].slotConfig;
196     slot->SlotEnable = 1;
197     slot->CurrentFieldEnable = 1;
198     slot->PlanarAlpha = 1023;
199     slot->ConstantAlpha = 1;
200     slot->SourceRectLeft = 0 << 16;
201     slot->SourceRectRight = (input->width - 1) << 16;
202     slot->SourceRectTop = 0 << 16;
203     slot->SourceRectBottom = (input->height - 1) << 16;
204     slot->DestRectLeft = 0;
205     slot->DestRectRight = output->width - 1;
206     slot->DestRectTop = 0;
207     slot->DestRectBottom = output->height - 1;
208     slot->SoftClampHigh = 1023;
209 
210     surface = &c->slotStruct[0].slotSurfaceConfig;
211     surface->SlotPixelFormat = input->format;
212     surface->SlotBlkKind = input->kind;
213     surface->SlotBlkHeight = 0; /* XXX */
214     surface->SlotCacheWidth = VIC_CACHE_WIDTH_64Bx4; /* XXX */
215     surface->SlotSurfaceWidth = input->width - 1;
216     surface->SlotSurfaceHeight = input->height - 1;
217     surface->SlotLumaWidth = input->stride - 1;
218     surface->SlotLumaHeight = input->height - 1;
219     surface->SlotChromaWidth = 16383;
220     surface->SlotChromaHeight = 16383;
221 
222     drm_tegra_bo_unmap(vic->config.bo);
223 
224     return 0;
225 }
226 
vic40_execute(struct vic * v,struct drm_tegra_pushbuf * pushbuf,uint32_t ** ptrp,struct vic_image * output,struct vic_image ** inputs,unsigned int num_inputs)227 static int vic40_execute(struct vic *v, struct drm_tegra_pushbuf *pushbuf,
228                          uint32_t **ptrp, struct vic_image *output,
229                          struct vic_image **inputs, unsigned int num_inputs)
230 {
231     struct vic40 *vic = container_of(v, struct vic40, base);
232     unsigned int i;
233 
234     if (num_inputs > 1)
235         return -EINVAL;
236 
237     VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_APPLICATION_ID, 1);
238     VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONTROL_PARAMS, (sizeof(ConfigStruct) / 16) << 16);
239     VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_CONFIG_STRUCT_OFFSET, vic->config.map, 0, 0);
240     VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_OUTPUT_SURFACE_LUMA_OFFSET, output->map, 0, 0);
241 
242     for (i = 0; i < num_inputs; i++)
243         VIC_PUSH_BUFFER(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_SET_SURFACE0_SLOT0_LUMA_OFFSET, inputs[i]->map, 0, 0);
244 
245     VIC_PUSH_METHOD(pushbuf, ptrp, NVB0B6_VIDEO_COMPOSITOR_EXECUTE, 1 << 8);
246 
247     return 0;
248 }
249 
vic40_free(struct vic * v)250 static void vic40_free(struct vic *v)
251 {
252     struct vic40 *vic = container_of(v, struct vic40, base);
253 
254     drm_tegra_channel_unmap(vic->filter.map);
255     drm_tegra_bo_unref(vic->filter.bo);
256 
257     drm_tegra_channel_unmap(vic->config.map);
258     drm_tegra_bo_unref(vic->config.bo);
259 
260     drm_tegra_syncpoint_free(v->syncpt);
261 
262     free(vic);
263 }
264 
265 static const struct vic_ops vic40_ops = {
266     .fill = vic40_fill,
267     .blit = vic40_blit,
268     .flip = vic40_flip,
269     .execute = vic40_execute,
270     .free = vic40_free,
271 };
272 
vic40_new(struct drm_tegra * drm,struct drm_tegra_channel * channel,struct vic ** vicp)273 int vic40_new(struct drm_tegra *drm, struct drm_tegra_channel *channel,
274               struct vic **vicp)
275 {
276     struct vic40 *vic;
277     void *ptr;
278     int err;
279 
280     vic = calloc(1, sizeof(*vic));
281     if (!vic)
282         return -ENOMEM;
283 
284     vic->base.drm = drm;
285     vic->base.channel = channel;
286     vic->base.ops = &vic40_ops;
287     vic->base.version = 0x21;
288 
289     err = drm_tegra_syncpoint_new(drm, &vic->base.syncpt);
290     if (err < 0) {
291         fprintf(stderr, "failed to allocate syncpoint: %s\n", strerror(-err));
292         return err;
293     }
294 
295     err = drm_tegra_bo_new(drm, 0, 16384, &vic->config.bo);
296     if (err < 0) {
297         fprintf(stderr, "failed to allocate configuration structurer: %s\n",
298                 strerror(-err));
299         return err;
300     }
301 
302     err = drm_tegra_channel_map(channel, vic->config.bo, DRM_TEGRA_CHANNEL_MAP_READ,
303                                 &vic->config.map);
304     if (err < 0) {
305         fprintf(stderr, "failed to map configuration structure: %s\n",
306                 strerror(-err));
307         return err;
308     }
309 
310     err = drm_tegra_bo_new(drm, 0, 16384, &vic->filter.bo);
311     if (err < 0) {
312         fprintf(stderr, "failed to allocate filter buffer: %s\n",
313                 strerror(-err));
314         return err;
315     }
316 
317     err = drm_tegra_bo_map(vic->filter.bo, &ptr);
318     if (err < 0) {
319         fprintf(stderr, "failed to map filter buffer: %s\n", strerror(-err));
320         return err;
321     }
322 
323     memset(ptr, 0, 16384);
324     drm_tegra_bo_unmap(vic->filter.bo);
325 
326     err = drm_tegra_channel_map(channel, vic->filter.bo, DRM_TEGRA_CHANNEL_MAP_READ,
327                                 &vic->filter.map);
328     if (err < 0) {
329         fprintf(stderr, "failed to map filter buffer: %s\n",
330                 strerror(-err));
331         return err;
332     }
333 
334     if (vicp)
335         *vicp = &vic->base;
336 
337     return 0;
338 }
339