Skip to content

Commit 7376fa4

Browse files
committed
fix rpi4 cursor unsync issue
1 parent 654341f commit 7376fa4

File tree

6 files changed

+454
-15
lines changed

6 files changed

+454
-15
lines changed
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
/*
2+
* Copyright 2019 The FydeOS Authors. All rights reserved.
3+
* Use of this source code is governed by a BSD-style license that can be
4+
* found in the LICENSE file.
5+
* Author: Yang Tsao <yang@fydeos.io>
6+
*/
7+
#ifdef DRV_V3D
8+
#include <errno.h>
9+
#include <stdio.h>
10+
#include <string.h>
11+
#include <sys/mman.h>
12+
#include <xf86drm.h>
13+
14+
#include "drv_priv.h"
15+
#include "helpers.h"
16+
#include "util.h"
17+
#include "external/v3d_drm.h"
18+
#define ARC_CALLOC (1<<7)
19+
#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
20+
21+
#define DEBUG 1
22+
23+
enum v3d_tiling_mode {
24+
/* Untiled resources. Not valid as texture inputs. */
25+
V3D_TILING_RASTER,
26+
27+
/* Single line of u-tiles. */
28+
V3D_TILING_LINEARTILE,
29+
30+
/* Departure from standard 4-UIF block column format. */
31+
V3D_TILING_UBLINEAR_1_COLUMN,
32+
33+
/* Departure from standard 4-UIF block column format. */
34+
V3D_TILING_UBLINEAR_2_COLUMN,
35+
36+
/* Normal tiling format: grouped in 4x4 UIFblocks, each of which is
37+
* split 2x2 into utiles.
38+
*/
39+
V3D_TILING_UIF_NO_XOR,
40+
41+
/* Normal tiling format: grouped in 4x4 UIFblocks, each of which is
42+
* split 2x2 into utiles.
43+
*/
44+
V3D_TILING_UIF_XOR,
45+
};
46+
47+
static const uint32_t render_target_formats[] = { DRM_FORMAT_RGB565,
48+
DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888 };
49+
50+
static const uint32_t texture_target_formats[] = {
51+
DRM_FORMAT_YVU420, DRM_FORMAT_NV12, DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_R8
52+
};
53+
54+
static int v3d_init(struct driver *drv) {
55+
uint64_t render_use_flags = BO_USE_RENDER_MASK | BO_USE_SCANOUT;
56+
uint64_t texture_use_flags = BO_USE_TEXTURE_MASK | BO_USE_HW_VIDEO_DECODER;
57+
uint64_t sw_flags = (BO_USE_RENDERSCRIPT | BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_FRONT_RENDERING);
58+
struct format_metadata metadata;
59+
drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
60+
&LINEAR_METADATA, render_use_flags);
61+
drv_add_combinations(drv, texture_target_formats, ARRAY_SIZE(texture_target_formats),
62+
&LINEAR_METADATA, BO_USE_TEXTURE_MASK);
63+
drv_modify_combination(drv, DRM_FORMAT_YVU420, &LINEAR_METADATA,
64+
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
65+
BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
66+
drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA,
67+
BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
68+
BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
69+
drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SCANOUT |
70+
BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER);
71+
72+
metadata.tiling = V3D_TILING_UIF_NO_XOR;
73+
metadata.priority = 2;
74+
metadata.modifier = DRM_FORMAT_MOD_BROADCOM_UIF;
75+
render_use_flags &= ~sw_flags;
76+
texture_use_flags &= ~sw_flags;
77+
drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats),
78+
&metadata, BO_USE_RENDER_MASK);
79+
drv_add_combinations(drv, texture_target_formats, ARRAY_SIZE(texture_target_formats),
80+
&metadata, texture_use_flags);
81+
drv_log("v3d driver init.\n");
82+
return drv_modify_linear_combinations(drv);
83+
}
84+
85+
static unsigned u_minify(unsigned value, unsigned levels) {
86+
return MAX2(1, value >> levels);
87+
}
88+
89+
static bool util_is_power_of_two_or_zero(unsigned v) {
90+
return (v & (v - 1)) == 0;
91+
}
92+
93+
static unsigned util_next_power_of_two(unsigned x) {
94+
unsigned val = x;
95+
96+
if (x <= 1)
97+
return 1;
98+
99+
if (util_is_power_of_two_or_zero(x))
100+
return x;
101+
102+
val--;
103+
val = (val >> 1) | val;
104+
val = (val >> 2) | val;
105+
val = (val >> 4) | val;
106+
val = (val >> 8) | val;
107+
val = (val >> 16) | val;
108+
val++;
109+
return val;
110+
}
111+
112+
static uint32_t v3d_utile_width(int cpp) {
113+
switch (cpp) {
114+
case 1:
115+
case 2:
116+
return 8;
117+
case 4:
118+
case 8:
119+
return 4;
120+
case 16:
121+
return 2;
122+
default:
123+
return 4;
124+
}
125+
}
126+
127+
/** Return the height in pixels of a 64-byte microtile. */
128+
static uint32_t v3d_utile_height(int cpp) {
129+
switch (cpp) {
130+
case 1:
131+
return 8;
132+
case 2:
133+
case 4:
134+
return 4;
135+
case 8:
136+
case 16:
137+
return 2;
138+
default:
139+
return 4;
140+
}
141+
}
142+
143+
#define V3D_UIFCFG_PAGE_SIZE 4096
144+
#define V3D_UBLOCK_SIZE 64
145+
#define V3D_UIFBLOCK_SIZE (4 * V3D_UBLOCK_SIZE)
146+
#define V3D_UIFBLOCK_ROW_SIZE (4 * V3D_UIFBLOCK_SIZE)
147+
#define PAGE_UB_ROWS (V3D_UIFCFG_PAGE_SIZE / V3D_UIFBLOCK_ROW_SIZE)
148+
#define PAGE_UB_ROWS_TIMES_1_5 ((PAGE_UB_ROWS * 3) >> 1)
149+
#define V3D_UIFCFG_PAGE_SIZE 4096
150+
#define V3D_UIFCFG_BANKS 8
151+
#define V3D_PAGE_CACHE_SIZE (V3D_UIFCFG_PAGE_SIZE * V3D_UIFCFG_BANKS)
152+
#define PAGE_CACHE_UB_ROWS (V3D_PAGE_CACHE_SIZE / V3D_UIFBLOCK_ROW_SIZE)
153+
#define PAGE_CACHE_MINUS_1_5_UB_ROWS (PAGE_CACHE_UB_ROWS - PAGE_UB_ROWS_TIMES_1_5)
154+
155+
static uint32_t v3d_get_ub_pad(int cpp, uint32_t height) {
156+
uint32_t utile_h = v3d_utile_height(cpp);
157+
uint32_t uif_block_h = utile_h * 2;
158+
uint32_t height_ub = height / uif_block_h;
159+
uint32_t height_offset_in_pc = height_ub % PAGE_CACHE_UB_ROWS;
160+
if (height_offset_in_pc == 0)
161+
return 0;
162+
if (height_offset_in_pc < PAGE_UB_ROWS_TIMES_1_5) {
163+
if (height_ub < PAGE_CACHE_UB_ROWS)
164+
return 0;
165+
else
166+
return PAGE_UB_ROWS_TIMES_1_5 - height_offset_in_pc;
167+
}
168+
if (height_offset_in_pc > PAGE_CACHE_MINUS_1_5_UB_ROWS)
169+
return PAGE_CACHE_UB_ROWS - height_offset_in_pc;
170+
return 0;
171+
}
172+
173+
static int v3d_bo_create_for_modifiers(struct bo *bo, uint32_t width, uint32_t height,
174+
uint32_t format, uint64_t modifier) {
175+
int ret;
176+
size_t plane;
177+
struct drm_v3d_create_bo bo_create;
178+
int cpp = 4;
179+
//bool uif_top = true;
180+
uint32_t pot_width = 2 * util_next_power_of_two(u_minify(width, 1));
181+
uint32_t pot_height = 2 * util_next_power_of_two(u_minify(height, 1));
182+
uint32_t pot_depth = 2 * util_next_power_of_two(u_minify(1, 1));
183+
uint32_t utile_w = v3d_utile_width(cpp);
184+
uint32_t utile_h = v3d_utile_height(cpp);
185+
uint32_t uif_block_w = utile_w * 2;
186+
uint32_t uif_block_h = utile_h * 2;
187+
uint32_t block_width = 1;
188+
uint32_t block_height = 1;
189+
uint32_t offset = 0;
190+
uint32_t level_width, level_height, level_depth;
191+
size_t num_planes = drv_num_planes_from_format(format);
192+
uint32_t page_align_offset = 0;
193+
194+
for (size_t i = 0; i < num_planes; i++) {
195+
if ( i < 2) {
196+
level_width = u_minify(width, i);
197+
level_height = u_minify(height, i);
198+
} else {
199+
level_width = u_minify(pot_width, i);
200+
level_height = u_minify(pot_height, i);
201+
}
202+
if (i < 1)
203+
level_depth = u_minify(1, i);
204+
else
205+
level_depth = u_minify(pot_depth, i);
206+
level_width = DIV_ROUND_UP(level_width, block_width);
207+
level_height = DIV_ROUND_UP(level_height, block_height);
208+
if (modifier == DRM_FORMAT_MOD_LINEAR) {
209+
bo->meta.tiling = V3D_TILING_RASTER;
210+
level_width = ALIGN(level_width, 8);
211+
} else {
212+
level_width = ALIGN(level_width, 4 * uif_block_w);
213+
level_height = ALIGN(level_height, uif_block_h);
214+
level_height += v3d_get_ub_pad(cpp, level_height) * uif_block_h;
215+
if ((level_height / uif_block_h) % (V3D_PAGE_CACHE_SIZE /
216+
V3D_UIFBLOCK_ROW_SIZE) == 0) {
217+
bo->meta.tiling = V3D_TILING_UIF_XOR;
218+
} else {
219+
bo->meta.tiling = V3D_TILING_UIF_NO_XOR;
220+
}
221+
}
222+
level_width = ALIGN(level_width * 12 / 10, 64);
223+
level_height = ALIGN(level_height * 12 / 10, 64);
224+
bo->meta.offsets[i] = offset;
225+
bo->meta.strides[i] = level_width * cpp;
226+
bo->meta.sizes[i] = bo->meta.strides[i] * level_height * level_depth;
227+
if (i == 1 &&
228+
level_width > 4 * uif_block_w &&
229+
level_height > PAGE_CACHE_MINUS_1_5_UB_ROWS * uif_block_h) {
230+
bo->meta.sizes[i] = ALIGN(bo->meta.sizes[i],
231+
V3D_UIFCFG_PAGE_SIZE);
232+
}
233+
offset += bo->meta.sizes[i];
234+
}
235+
236+
page_align_offset = (ALIGN(offset, 4096) - offset);
237+
if (page_align_offset) {
238+
offset += page_align_offset;
239+
for (size_t i = 0; i < num_planes; i++)
240+
bo->meta.offsets[i] += page_align_offset;
241+
}
242+
bo->meta.format_modifier = modifier;
243+
bo->meta.total_size = offset;
244+
245+
memset(&bo_create, 0, sizeof(bo_create));
246+
247+
//if (height * width > 1) // don't bother vc4 if only need 1 page.
248+
bo_create.flags = ARC_CALLOC;
249+
//else
250+
// bo_create.flags = 0;
251+
252+
bo_create.size = bo->meta.total_size;
253+
bo->meta.format_modifier = modifier;
254+
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_V3D_CREATE_BO, &bo_create);
255+
if (ret) {
256+
drv_log("DRM_IOCTL_V3D_CREATE_BO failed (size=%zu), ret=%d, format:%s\n", bo->meta.total_size, ret, getDrmFormatString(format));
257+
return -errno;
258+
}
259+
260+
for (plane = 0; plane < bo->meta.num_planes; plane++)
261+
bo->handles[plane].u32 = bo_create.handle;
262+
#ifdef DEBUG
263+
drv_log("create bo handler:0x%x, size:%zu, format:%s, width:%u, height:%u\n",
264+
bo_create.handle, bo->meta.total_size, getDrmFormatString(format), width, height);
265+
#endif
266+
return 0;
267+
}
268+
269+
static int v3d_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height,
270+
uint32_t format, const uint64_t *modifiers, uint32_t count) {
271+
static const uint64_t modifier_order[] = {
272+
DRM_FORMAT_MOD_BROADCOM_UIF,
273+
DRM_FORMAT_MOD_LINEAR,
274+
};
275+
uint64_t modifier =
276+
drv_pick_modifier(modifiers, count, modifier_order, ARRAY_SIZE(modifier_order));
277+
return v3d_bo_create_for_modifiers(bo, width, height, format, modifier/*modifier*/);
278+
}
279+
280+
static int v3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
281+
uint64_t use_flags) {
282+
return v3d_bo_create_for_modifiers(bo, width, height, format, DRM_FORMAT_MOD_LINEAR/*modifier*/);
283+
}
284+
285+
static void *v3d_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) {
286+
int ret;
287+
struct drm_v3d_mmap_bo bo_map;
288+
memset(&bo_map, 0, sizeof(bo_map));
289+
bo_map.handle = bo->handles[0].u32;
290+
291+
ret = drmIoctl(bo->drv->fd, DRM_IOCTL_V3D_MMAP_BO, &bo_map);
292+
if (ret) {
293+
drv_log("DRM_V3D_MMAP_BO failed\n");
294+
return MAP_FAILED;
295+
}
296+
vma->length = bo->meta.total_size;
297+
return mmap(NULL, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd,
298+
bo_map.offset);
299+
}
300+
301+
static uint32_t v3d_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags)
302+
{
303+
switch (format) {
304+
case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED:
305+
if (use_flags & (BO_USE_CAMERA_WRITE | BO_USE_CAMERA_READ))
306+
return DRM_FORMAT_NV12;
307+
308+
/*HACK: See b/28671744 */
309+
return DRM_FORMAT_XBGR8888;
310+
case DRM_FORMAT_FLEX_YCbCr_420_888:
311+
// TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well.
312+
if (use_flags & (BO_USE_HW_VIDEO_DECODER)) {
313+
return DRM_FORMAT_NV12;
314+
}
315+
if (use_flags &
316+
(BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) {
317+
return DRM_FORMAT_NV12;
318+
}
319+
return DRM_FORMAT_YVU420;
320+
default:
321+
return format;
322+
}
323+
}
324+
325+
const struct backend backend_v3d = {
326+
.name = "v3d",
327+
.init = v3d_init,
328+
.bo_create = v3d_bo_create,
329+
.bo_create_with_modifiers = v3d_bo_create_with_modifiers,
330+
.bo_import = drv_prime_bo_import,
331+
.bo_destroy = drv_gem_bo_destroy,
332+
.bo_map = v3d_bo_map,
333+
.bo_unmap = drv_bo_munmap,
334+
.resolve_format = v3d_resolve_format,
335+
};
336+
337+
#endif // DEV_V3D

0 commit comments

Comments
 (0)