~thopiekar/arm-mali/libvdpau-sunxi

« back to all changes in this revision

Viewing changes to sunxi_disp2.c

  • Committer: Andreas Baierl
  • Author(s): Jens Kuske
  • Date: 2016-02-24 18:03:58 UTC
  • Revision ID: git-v1:5eecf086aa343692ab74c5cb0961b6da08b40792
Add OSD support for H3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2015 Jens Kuske <jenskuske@gmail.com>
 
2
 * Copyright (c) 2015-2016 Jens Kuske <jenskuske@gmail.com>
3
3
 *
4
4
 * This library is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU Lesser General Public
34
34
        int fd;
35
35
        disp_layer_config video_config;
36
36
        unsigned int screen_width;
 
37
        disp_layer_config osd_config;
37
38
};
38
39
 
39
40
static void sunxi_disp2_close(struct sunxi_disp *sunxi_disp);
64
65
        if (ioctl(disp->fd, DISP_LAYER_SET_CONFIG, args))
65
66
                goto err_video_layer;
66
67
 
 
68
        if (osd_enabled)
 
69
        {
 
70
                disp->osd_config.info.mode = LAYER_MODE_BUFFER;
 
71
                disp->osd_config.info.alpha_mode = 0;
 
72
                disp->osd_config.info.alpha_value = 255;
 
73
 
 
74
                disp->osd_config.enable = 0;
 
75
                disp->osd_config.channel = 2;
 
76
                disp->osd_config.layer_id = 0;
 
77
                disp->osd_config.info.zorder = 2;
 
78
 
 
79
                args[1] = (unsigned long)(&disp->osd_config);
 
80
                if (ioctl(disp->fd, DISP_LAYER_SET_CONFIG, args))
 
81
                        goto err_video_layer;
 
82
        }
 
83
 
67
84
        disp->screen_width = ioctl(disp->fd, DISP_GET_SCN_WIDTH, args);
68
85
 
69
86
        disp->pub.close = sunxi_disp2_close;
88
105
        unsigned long args[4] = { 0, (unsigned long)(&disp->video_config), 1, 0 };
89
106
 
90
107
        disp->video_config.enable = 0;
91
 
 
92
108
        ioctl(disp->fd, DISP_LAYER_SET_CONFIG, args);
93
109
 
 
110
        if (disp->osd_config.enable)
 
111
        {
 
112
                disp->osd_config.enable = 0;
 
113
                args[1] = (unsigned long)(&disp->osd_config);
 
114
                ioctl(disp->fd, DISP_LAYER_SET_CONFIG, args);
 
115
        }
 
116
 
94
117
        close(disp->fd);
95
118
        free(sunxi_disp);
96
119
}
97
120
 
 
121
static void clip(disp_rect *src, disp_rect *scn, unsigned int screen_width)
 
122
{
 
123
        if (scn->y < 0)
 
124
        {
 
125
                int scn_clip = -scn->y;
 
126
                int src_clip = scn_clip * src->height / scn->height;
 
127
                scn->y = 0;
 
128
                scn->height -= scn_clip;
 
129
                src->y += src_clip;
 
130
                src->height -= src_clip;
 
131
        }
 
132
        if (scn->x < 0)
 
133
        {
 
134
                int scn_clip = -scn->x;
 
135
                int src_clip = scn_clip * src->width / scn->width;
 
136
                scn->x = 0;
 
137
                scn->width -= scn_clip;
 
138
                src->x += src_clip;
 
139
                src->width -= src_clip;
 
140
        }
 
141
        if (scn->x + scn->width > screen_width)
 
142
        {
 
143
                int scn_clip = scn->x + scn->width - screen_width;
 
144
                int src_clip = scn_clip * src->width / scn->width;
 
145
                scn->width -= scn_clip;
 
146
                src->width -= src_clip;
 
147
        }
 
148
}
 
149
 
98
150
static int sunxi_disp2_set_video_layer(struct sunxi_disp *sunxi_disp, int x, int y, int width, int height, output_surface_ctx_t *surface)
99
151
{
100
152
        struct sunxi_disp2_private *disp = (struct sunxi_disp2_private *)sunxi_disp;
106
158
                          .width = surface->video_dst_rect.x1 - surface->video_dst_rect.x0,
107
159
                          .height = surface->video_dst_rect.y1 - surface->video_dst_rect.y0 };
108
160
 
109
 
        if (scn.y < 0)
110
 
        {
111
 
                int scn_clip = -scn.y;
112
 
                int src_clip = scn_clip * src.height / scn.height;
113
 
                scn.y = 0;
114
 
                scn.height -= scn_clip;
115
 
                src.y += src_clip;
116
 
                src.height -= src_clip;
117
 
        }
118
 
        if (scn.x < 0)
119
 
        {
120
 
                int scn_clip = -scn.x;
121
 
                int src_clip = scn_clip * src.width / scn.width;
122
 
                scn.x = 0;
123
 
                scn.width -= scn_clip;
124
 
                src.x += src_clip;
125
 
                src.width -= src_clip;
126
 
        }
127
 
        if (scn.x + scn.width > disp->screen_width)
128
 
        {
129
 
                int scn_clip = scn.x + scn.width - disp->screen_width;
130
 
                int src_clip = scn_clip * src.width / scn.width;
131
 
                scn.width -= scn_clip;
132
 
                src.width -= src_clip;
133
 
        }
 
161
        clip (&src, &scn, disp->screen_width);
134
162
 
135
163
        unsigned long args[4] = { 0, (unsigned long)(&disp->video_config), 1, 0 };
136
164
        switch (surface->vs->source_format)
190
218
 
191
219
static int sunxi_disp2_set_osd_layer(struct sunxi_disp *sunxi_disp, int x, int y, int width, int height, output_surface_ctx_t *surface)
192
220
{
193
 
        return -ENOTSUP;
 
221
        struct sunxi_disp2_private *disp = (struct sunxi_disp2_private *)sunxi_disp;
 
222
 
 
223
        unsigned long args[4] = { 0, (unsigned long)(&disp->osd_config), 1, 0 };
 
224
 
 
225
        disp_rect src = { .x = surface->rgba.dirty.x0, .y = surface->rgba.dirty.y0,
 
226
                          .width = surface->rgba.dirty.x1 - surface->rgba.dirty.x0,
 
227
                          .height = surface->rgba.dirty.y1 - surface->rgba.dirty.y0 };
 
228
        disp_rect scn = { .x = x + surface->rgba.dirty.x0, .y = y + surface->rgba.dirty.y0,
 
229
                          .width = min_nz(width, surface->rgba.dirty.x1) - surface->rgba.dirty.x0,
 
230
                          .height = min_nz(height, surface->rgba.dirty.y1) - surface->rgba.dirty.y0 };
 
231
 
 
232
        clip (&src, &scn, disp->screen_width);
 
233
 
 
234
        switch (surface->rgba.format)
 
235
        {
 
236
        case VDP_RGBA_FORMAT_R8G8B8A8:
 
237
                disp->osd_config.info.fb.format = DISP_FORMAT_ABGR_8888;
 
238
                break;
 
239
        case VDP_RGBA_FORMAT_B8G8R8A8:
 
240
        default:
 
241
                disp->osd_config.info.fb.format = DISP_FORMAT_ARGB_8888;
 
242
                break;
 
243
        }
 
244
 
 
245
        disp->osd_config.info.fb.addr[0] = cedrus_mem_get_phys_addr(surface->rgba.data);
 
246
        disp->osd_config.info.fb.size[0].width = surface->rgba.width;
 
247
        disp->osd_config.info.fb.size[0].height = surface->rgba.height;
 
248
        disp->osd_config.info.fb.align[0] = 1;
 
249
        disp->osd_config.info.fb.crop.x = (unsigned long long)(src.x) << 32;
 
250
        disp->osd_config.info.fb.crop.y = (unsigned long long)(src.y) << 32;
 
251
        disp->osd_config.info.fb.crop.width = (unsigned long long)(src.width) << 32;
 
252
        disp->osd_config.info.fb.crop.height = (unsigned long long)(src.height) << 32;
 
253
        disp->osd_config.info.screen_win = scn;
 
254
        disp->osd_config.enable = 1;
 
255
 
 
256
        if (ioctl(disp->fd, DISP_LAYER_SET_CONFIG, args))
 
257
                return -EINVAL;
 
258
 
 
259
        return 0;
194
260
}
195
261
 
196
262
static void sunxi_disp2_close_osd_layer(struct sunxi_disp *sunxi_disp)
197
263
{
198
 
        return;
 
264
        struct sunxi_disp2_private *disp = (struct sunxi_disp2_private *)sunxi_disp;
 
265
 
 
266
        unsigned long args[4] = { 0, (unsigned long)(&disp->osd_config), 1, 0 };
 
267
 
 
268
        disp->osd_config.enable = 0;
 
269
 
 
270
        ioctl(disp->fd, DISP_LAYER_SET_CONFIG, args);
199
271
}