add video buffer lock/unlock API
[glsdk/omapdrmtest.git] / util / util.c
1 /*
2  * Copyright (C) 2011 Texas Instruments
3  * Author: Rob Clark <rob.clark@linaro.org>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
18 #include "util.h"
20 #include <drm.h>
22 void disp_kms_usage(void);
23 struct display * disp_kms_open(int argc, char **argv);
25 #ifdef HAVE_X11
26 void disp_x11_usage(void);
27 struct display * disp_x11_open(int argc, char **argv);
28 #endif
30 void
31 disp_usage(void)
32 {
33 #ifdef HAVE_X11
34         disp_x11_usage();
35 #endif
36         disp_kms_usage();
37 }
39 struct display *
40 disp_open(int argc, char **argv)
41 {
42         struct display *disp;
44 #ifdef HAVE_X11
45         disp = disp_x11_open(argc, argv);
46         if (disp)
47                 return disp;
48 #endif
50         disp = disp_kms_open(argc, argv);
52         if (!disp) {
53                 ERROR("unable to create display");
54         }
56         return disp;
57 }
59 struct buffer **
60 disp_get_vid_buffers(struct display *disp, uint32_t n,
61                 uint32_t fourcc, uint32_t w, uint32_t h)
62 {
63         struct buffer **buffers;
64         int i;
66         buffers = disp->get_vid_buffers(disp, n, fourcc, w, h);
67         if (buffers) {
68                 /* if allocation succeeded, store in the unlocked
69                  * video buffer list
70                  */
71                 list_init(&disp->unlocked);
72                 for (i = 0; i < n; i++)
73                         list_add(&buffers[i]->unlocked, &disp->unlocked);
74         }
76         return buffers;
77 }
79 struct buffer *
80 disp_get_vid_buffer(struct display *disp)
81 {
82         struct buffer *buf = NULL;
83         if (!list_is_empty(&disp->unlocked)) {
84                 buf = list_last_entry(&disp->unlocked, struct buffer, unlocked);
85                 list_del(&buf->unlocked);
87                 /* barrier.. if we are using GPU blitting, we need to make sure
88                  * that the GPU is finished:
89                  */
90                 omap_bo_cpu_prep(buf->bo[0], OMAP_GEM_WRITE);
91                 omap_bo_cpu_fini(buf->bo[0], OMAP_GEM_WRITE);
92         }
93         return buf;
94 }
96 void
97 disp_put_vid_buffer(struct display *disp, struct buffer *buf)
98 {
99         list_add(&buf->unlocked, &disp->unlocked);
102 struct buffer *
103 disp_get_fb(struct display *disp)
105         struct buffer **bufs = disp_get_buffers(disp, 1);
106         if (!bufs)
107                 return NULL;
108         fill(bufs[0], 42);
109         disp_post_buffer(disp, bufs[0]);
110         return bufs[0];
114 int
115 check_args(int argc, char **argv)
117         int i;
118         for (i = 1; i < argc; i++) {
119                 if (argv[i]) {
120                         ERROR("invalid arg: %s", argv[i]);
121                         return -1;
122                 }
123         }
124         return 0;
127 /* stolen from modetest.c */
128 static void
129 fillRGB4(char *virtual, int n, int width, int height, int stride)
131         int i, j;
132         /* paint the buffer with colored tiles */
133         for (j = 0; j < height; j++) {
134                 uint32_t *fb_ptr = (uint32_t*)((char*)virtual + j * stride);
135                 for (i = 0; i < width; i++) {
136                         div_t d = div(n+i+j, width);
137                         fb_ptr[i] =
138                                         0x00130502 * (d.quot >> 6) +
139                                         0x000a1120 * (d.rem >> 6);
140                 }
141         }
145 /* swap these for big endian.. */
146 #define RED   2
147 #define GREEN 1
148 #define BLUE  0
150 static void
151 fill420(unsigned char *y, unsigned char *u, unsigned char *v,
152                 int cs /*chroma pixel stride */,
153                 int n, int width, int height, int stride)
155         int i, j;
157         /* paint the buffer with colored tiles, in blocks of 2x2 */
158         for (j = 0; j < height; j+=2) {
159                 unsigned char *y1p = y + j * stride;
160                 unsigned char *y2p = y1p + stride;
161                 unsigned char *up = u + (j/2) * stride * cs / 2;
162                 unsigned char *vp = v + (j/2) * stride * cs / 2;
164                 for (i = 0; i < width; i+=2) {
165                         div_t d = div(n+i+j, width);
166                         uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
167                         unsigned char *rgbp = (unsigned char *)&rgb;
168                         unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);
170                         *(y2p++) = *(y1p++) = y;
171                         *(y2p++) = *(y1p++) = y;
173                         *up = (rgbp[BLUE] - y) * 0.565 + 128;
174                         *vp = (rgbp[RED] - y) * 0.713 + 128;
175                         up += cs;
176                         vp += cs;
177                 }
178         }
181 static void
182 fill422(unsigned char *virtual, int n, int width, int height, int stride)
184         int i, j;
185         /* paint the buffer with colored tiles */
186         for (j = 0; j < height; j++) {
187                 uint8_t *ptr = (uint8_t*)((char*)virtual + j * stride);
188                 for (i = 0; i < width; i++) {
189                         div_t d = div(n+i+j, width);
190                         uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
191                         unsigned char *rgbp = (unsigned char *)&rgb;
192                         unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);
194                         *(ptr++) = y;
195                         *(ptr++) = (rgbp[BLUE] - y) * 0.565 + 128;
196                         *(ptr++) = y;
197                         *(ptr++) = (rgbp[RED] - y) * 0.713 + 128;
198                 }
199         }
203 void
204 fill(struct buffer *buf, int n)
206         int i;
208         for (i = 0; i < buf->nbo; i++)
209                 omap_bo_cpu_prep(buf->bo[i], OMAP_GEM_WRITE);
211         switch(buf->fourcc) {
212         case 0: {
213                 assert(buf->nbo == 1);
214                 fillRGB4(omap_bo_map(buf->bo[0]), n,
215                                 buf->width, buf->height, buf->pitches[0]);
216                 break;
217         }
218         case FOURCC('Y','U','Y','V'): {
219                 assert(buf->nbo == 1);
220                 fill422(omap_bo_map(buf->bo[0]), n,
221                                 buf->width, buf->height, buf->pitches[0]);
222                 break;
223         }
224         case FOURCC('N','V','1','2'): {
225                 unsigned char *y, *u, *v;
226                 assert(buf->nbo == 2);
227                 y = omap_bo_map(buf->bo[0]);
228                 u = omap_bo_map(buf->bo[1]);
229                 v = u + 1;
230                 fill420(y, u, v, 2, n, buf->width, buf->height, buf->pitches[0]);
231                 break;
232         }
233         case FOURCC('I','4','2','0'): {
234                 unsigned char *y, *u, *v;
235                 assert(buf->nbo == 3);
236                 y = omap_bo_map(buf->bo[0]);
237                 u = omap_bo_map(buf->bo[1]);
238                 v = omap_bo_map(buf->bo[2]);
239                 fill420(y, u, v, 1, n, buf->width, buf->height, buf->pitches[0]);
240                 break;
241         }
242         default:
243                 ERROR("invalid format: 0x%08x", buf->fourcc);
244                 break;
245         }
247         for (i = 0; i < buf->nbo; i++)
248                 omap_bo_cpu_fini(buf->bo[i], OMAP_GEM_WRITE);