blob: 356b98ea2ea7afbc4495948c73342fcb73826559 [file] [log] [blame]
Haixia Shi4652b8c2014-11-19 17:55:38 -08001/*
2 * Copyright 2014 The Chromium OS 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 */
6
Zach Reizner38f0fd92016-02-18 14:28:02 -08007#include "bs_drm.h"
Haixia Shie04ddfd2014-11-11 19:14:32 -08008
Zach Reizner4dfdf602016-03-01 13:06:30 -08009static GLuint solid_shader_create()
Haixia Shie04ddfd2014-11-11 19:14:32 -080010{
Zach Reizner4dfdf602016-03-01 13:06:30 -080011 const GLchar *vert =
Zach Reizner38f0fd92016-02-18 14:28:02 -080012 "attribute vec4 vPosition;\n"
13 "attribute vec4 vColor;\n"
14 "varying vec4 vFillColor;\n"
15 "void main() {\n"
16 " gl_Position = vPosition;\n"
17 " vFillColor = vColor;\n"
18 "}\n";
Haixia Shie04ddfd2014-11-11 19:14:32 -080019
Zach Reizner4dfdf602016-03-01 13:06:30 -080020 const GLchar *frag =
Zach Reizner38f0fd92016-02-18 14:28:02 -080021 "precision mediump float;\n"
22 "varying vec4 vFillColor;\n"
23 "void main() {\n"
24 " gl_FragColor = vFillColor;\n"
25 "}\n";
Lauri Peltonen763ca462014-12-17 12:22:21 -080026
Zach Reizner4dfdf602016-03-01 13:06:30 -080027 struct bs_gl_program_create_binding bindings[] = {
28 { 0, "vPosition" }, { 1, "vColor" }, { 0, NULL },
29 };
Haixia Shie04ddfd2014-11-11 19:14:32 -080030
Zach Reizner4dfdf602016-03-01 13:06:30 -080031 return bs_gl_program_create_vert_frag_bind(vert, frag, bindings);
Haixia Shie04ddfd2014-11-11 19:14:32 -080032}
33
Lauri Peltonen95226da2014-12-18 16:39:54 -080034static float f(int i)
35{
Haixia Shie04ddfd2014-11-11 19:14:32 -080036 int a = i % 40;
37 int b = (i / 40) % 6;
38 switch (b) {
Zach Reizner38f0fd92016-02-18 14:28:02 -080039 case 0:
40 case 1:
41 return 0.0f;
42 case 3:
43 case 4:
44 return 1.0f;
45 case 2:
46 return (a / 40.0f);
47 case 5:
48 return 1.0f - (a / 40.0f);
49 default:
50 return 0.0f;
Haixia Shie04ddfd2014-11-11 19:14:32 -080051 }
52}
53
Zach Reizner38f0fd92016-02-18 14:28:02 -080054static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
55 void *data)
Haixia Shi4652b8c2014-11-19 17:55:38 -080056{
57 int *waiting_for_flip = data;
58 *waiting_for_flip = 0;
59}
60
Zach Reizner38f0fd92016-02-18 14:28:02 -080061int main(int argc, char **argv)
Haixia Shie04ddfd2014-11-11 19:14:32 -080062{
Zach Reizner38f0fd92016-02-18 14:28:02 -080063 int fd = -1;
64 if (argc >= 2) {
65 fd = open(argv[1], O_RDWR);
66 if (fd < 0) {
67 bs_debug_error("failed to open card %s", argv[1]);
68 return 1;
69 }
Haixia Shie04ddfd2014-11-11 19:14:32 -080070 }
Zach Reizner38f0fd92016-02-18 14:28:02 -080071 else {
72 fd = bs_drm_open_main_display();
73 if (fd < 0) {
74 bs_debug_error("failed to open card for display");
75 return 1;
76 }
Haixia Shie04ddfd2014-11-11 19:14:32 -080077 }
78
Zach Reizner38f0fd92016-02-18 14:28:02 -080079 struct gbm_device *gbm = gbm_create_device(fd);
80 if (!gbm) {
81 bs_debug_error("failed to create gbm");
82 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -080083 }
84
Zach Reizner4dfdf602016-03-01 13:06:30 -080085 struct bs_drm_pipe pipe = { 0 };
Zach Reizner38f0fd92016-02-18 14:28:02 -080086 if (!bs_drm_pipe_make(fd, &pipe)) {
87 bs_debug_error("failed to make pipe");
88 return 1;
89 }
Haixia Shie04ddfd2014-11-11 19:14:32 -080090
Zach Reizner38f0fd92016-02-18 14:28:02 -080091 drmModeConnector *connector = drmModeGetConnector(fd, pipe.connector_id);
92 assert(connector);
93 drmModeModeInfo *mode = &connector->modes[0];
94
95 struct bs_egl *egl = bs_egl_new();
96 if (!bs_egl_setup(egl)) {
97 bs_debug_error("failed to setup egl context");
98 return 1;
99 }
100
101 struct gbm_bo *bos[2];
102 uint32_t ids[2];
103 struct bs_egl_fb *egl_fbs[2];
104 for (size_t fb_index = 0; fb_index < 2; fb_index++) {
105 bos[fb_index] =
106 gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, GBM_FORMAT_XRGB8888,
107 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
108 if (bos[fb_index] == NULL) {
109 bs_debug_error("failed to allocate framebuffer");
110 return 1;
111 }
112
113 ids[fb_index] = bs_drm_fb_create_gbm(bos[fb_index]);
114 if (ids[fb_index] == 0) {
115 bs_debug_error("failed to create framebuffer id");
116 return 1;
117 }
118
119 EGLImageKHR egl_image = bs_egl_image_create_gbm(egl, bos[fb_index]);
120 if (egl_image == EGL_NO_IMAGE_KHR) {
121 bs_debug_error("failed to create EGLImageKHR from framebuffer");
122 return 1;
123 }
124
125 egl_fbs[fb_index] = bs_egl_fb_new(egl, egl_image);
126 if (!egl_fbs[fb_index]) {
127 bs_debug_error("failed to create framebuffer from EGLImageKHR");
128 return 1;
129 }
130 }
131
132 int ret = drmModeSetCrtc(fd, pipe.crtc_id, ids[0], 0 /* x */, 0 /* y */, &pipe.connector_id,
133 1 /* connector count */, mode);
134 if (ret) {
135 bs_debug_error("failed to set CRTC");
136 return 1;
137 }
138
139 GLuint program = solid_shader_create();
Haixia Shie04ddfd2014-11-11 19:14:32 -0800140 if (!program) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800141 bs_debug_error("failed to create solid shader");
142 return 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800143 }
144
Haixia Shi4652b8c2014-11-19 17:55:38 -0800145 int fb_idx = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800146 for (int i = 0; i <= 500; i++) {
Haixia Shi4652b8c2014-11-19 17:55:38 -0800147 int waiting_for_flip = 1;
Zach Reizner38f0fd92016-02-18 14:28:02 -0800148 // clang-format off
Haixia Shie04ddfd2014-11-11 19:14:32 -0800149 GLfloat verts[] = {
150 0.0f, -0.5f, 0.0f,
151 -0.5f, 0.5f, 0.0f,
152 0.5f, 0.5f, 0.0f
153 };
154 GLfloat colors[] = {
155 1.0f, 0.0f, 0.0f, 1.0f,
156 0.0f, 1.0f, 0.0f, 1.0f,
157 0.0f, 0.0f, 1.0f, 1.0f
158 };
Zach Reizner38f0fd92016-02-18 14:28:02 -0800159 // clang-format on
Haixia Shie04ddfd2014-11-11 19:14:32 -0800160
Zach Reizner38f0fd92016-02-18 14:28:02 -0800161 glBindFramebuffer(GL_FRAMEBUFFER, bs_egl_fb_name(egl_fbs[fb_idx]));
162 glViewport(0, 0, (GLint)mode->hdisplay, (GLint)mode->vdisplay);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800163
Haixia Shie04ddfd2014-11-11 19:14:32 -0800164 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
165 glClear(GL_COLOR_BUFFER_BIT);
166
167 glUseProgram(program);
168 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
169 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
170 glEnableVertexAttribArray(0);
171 glEnableVertexAttribArray(1);
172 glDrawArrays(GL_TRIANGLES, 0, 3);
173
174 usleep(1e6 / 120); /* 120 Hz */
175 glFinish();
Zach Reizner38f0fd92016-02-18 14:28:02 -0800176 ret = drmModePageFlip(fd, pipe.crtc_id, ids[fb_idx], DRM_MODE_PAGE_FLIP_EVENT,
177 &waiting_for_flip);
178 if (ret) {
179 bs_debug_error("failed page flip: %d", ret);
180 return 1;
181 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800182
183 while (waiting_for_flip) {
184 drmEventContext evctx = {
Zach Reizner4dfdf602016-03-01 13:06:30 -0800185 .version = DRM_EVENT_CONTEXT_VERSION,
186 .page_flip_handler = page_flip_handler,
Haixia Shi4652b8c2014-11-19 17:55:38 -0800187 };
188
189 fd_set fds;
190 FD_ZERO(&fds);
191 FD_SET(0, &fds);
Zach Reizner38f0fd92016-02-18 14:28:02 -0800192 FD_SET(fd, &fds);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800193
Zach Reizner38f0fd92016-02-18 14:28:02 -0800194 ret = select(fd + 1, &fds, NULL, NULL, NULL);
Haixia Shi4652b8c2014-11-19 17:55:38 -0800195 if (ret < 0) {
Zach Reizner38f0fd92016-02-18 14:28:02 -0800196 bs_debug_error("select err: %s", strerror(errno));
197 return 1;
Haixia Shi4652b8c2014-11-19 17:55:38 -0800198 }
Zach Reizner38f0fd92016-02-18 14:28:02 -0800199 else if (ret == 0) {
200 bs_debug_error("select timeout");
201 return 1;
202 }
203 else if (FD_ISSET(0, &fds)) {
204 bs_debug_error("user interrupted");
205 return 1;
206 }
207 ret = drmHandleEvent(fd, &evctx);
208 if (ret) {
209 bs_debug_error("failed to wait for page flip: %d", ret);
210 return 1;
211 }
Haixia Shi4652b8c2014-11-19 17:55:38 -0800212 }
213 fb_idx = fb_idx ^ 1;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800214 }
215
Zach Reizner38f0fd92016-02-18 14:28:02 -0800216 return 0;
Haixia Shie04ddfd2014-11-11 19:14:32 -0800217}