1 /***************************************************************************
2 *
3 * Copyright 2012 BMW Car IT GmbH
4 * Copyright (C) 2016 Advanced Driver Information Technology Joint Venture GmbH
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ****************************************************************************/
20
21 #include "TestBase.h"
22 #include <cstring>
23 #include <stdexcept>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <sys/mman.h>
28
29 int
create_file(int size)30 create_file(int size)
31 {
32 static const char base_string[] = "/weston-shared-XXXXXX";
33 const char *path;
34 char *name;
35 int fd;
36 int ret;
37 long flags;
38
39 path = getenv("XDG_RUNTIME_DIR");
40 if (!path) {
41 errno = ENOENT;
42 return -1;
43 }
44
45 name = (char*) malloc(strlen(path) + sizeof(base_string));
46 if (!name)
47 return -1;
48
49 strcpy(name, path);
50 strcat(name, base_string);
51
52 fd = mkstemp(name);
53 if (fd >= 0) {
54 flags = fcntl(fd, F_GETFD);
55 fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
56 unlink(name);
57 }
58
59 free(name);
60
61 if (fd < 0)
62 return -1;
63
64 ret = ftruncate(fd, size);
65 if (ret < 0) {
66 close(fd);
67 return -1;
68 }
69
70 return fd;
71 }
72
73 static void
shm_format(void * data,struct wl_shm * wl_shm,uint32_t format)74 shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
75 {
76 TestBase* base = static_cast<TestBase*>(data);
77
78 base->SetShmFormats(format);
79 }
80
81 static struct wl_shm_listener shm_listener = {
82 shm_format
83 };
84
registry_listener_callback(void * data,struct wl_registry * registry,uint32_t id,const char * interface,uint32_t version)85 void registry_listener_callback(void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version)
86 {
87 TestBase* base = static_cast<TestBase*>(data);
88 struct wl_shm *shm;
89
90 if (0 == strcmp(interface, "wl_compositor"))
91 {
92 base->SetWLCompositor(reinterpret_cast<wl_compositor*>(wl_registry_bind(registry, id, &wl_compositor_interface, 1)));
93 }
94
95 if (0 == strcmp(interface, "wl_shm"))
96 {
97 shm = (struct wl_shm*) wl_registry_bind(registry, id, &wl_shm_interface, 1);
98 wl_shm_add_listener(shm, &shm_listener, base);
99 base->SetShm(shm);
100 }
101
102 if (0 == strcmp(interface, "ivi_application"))
103 {
104 base->SetIviApp(reinterpret_cast<ivi_application*>(wl_registry_bind(registry, id, &ivi_application_interface, 1)));
105
106 }
107 }
108
TestBase()109 TestBase::TestBase()
110 : wlDisplay(NULL)
111 , wlRegistry(NULL)
112 {
113 int fd = -1;
114 int size = 0;
115 struct wl_shm_pool *pool;
116 void* mmapData;
117
118 wlDisplay = wl_display_connect(NULL);
119 if (!wlDisplay)
120 {
121 throw std::runtime_error("could not connect to wayland display");
122 }
123 wlRegistry = wl_display_get_registry(wlDisplay);
124
125 static const struct wl_registry_listener registry_listener = {
126 registry_listener_callback,
127 NULL
128 };
129
130 shmFormats = 0;
131
132 wl_registry_add_listener(wlRegistry, ®istry_listener, this);
133
134 if (wl_display_roundtrip(wlDisplay) == -1 || wl_display_roundtrip(wlDisplay) == -1)
135 {
136 throw std::runtime_error("wl_display error");
137 }
138
139 if (!wlShm)
140 {
141 throw std::runtime_error("shared memory buffers are not supported");
142 }
143
144 if (wl_display_roundtrip(wlDisplay) == -1)
145 {
146 throw std::runtime_error("wl_display error");
147 }
148
149 if (!(shmFormats & (1 << WL_SHM_FORMAT_ARGB8888)))
150 {
151 throw std::runtime_error("shared memory buffers format ARGB888 is not supported");
152 }
153
154 wlSurfaces.reserve(10);
155 for (int i = 0; i < (int)wlSurfaces.capacity(); ++i)
156 {
157 wlSurfaces.push_back(wl_compositor_create_surface(wlCompositor));
158 }
159
160 // size = height * width * bpp * number_of_surfaces = 1 * 1 * 4 * 10
161 size = 4 * wlSurfaces.capacity();
162 fd = create_file(size);
163 if (fd < 0)
164 {
165 throw std::runtime_error("cannot create shared memory file");
166 }
167
168 mmapData = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
169 if (MAP_FAILED == mmapData) {
170 close(fd);
171 throw std::runtime_error("mmap failed");
172 }
173
174 pool = wl_shm_create_pool(wlShm, fd, size);
175 if (!pool)
176 {
177 throw std::runtime_error("wl_shm_create_pool error");
178 }
179
180 wlBuffers.reserve(10);
181 for (int i = 0; i < (int)wlBuffers.capacity(); ++i)
182 {
183 wlBuffers.push_back(wl_shm_pool_create_buffer(pool, 0, 1, 1, 4, WL_SHM_FORMAT_ARGB8888));
184 wl_surface_attach(wlSurfaces[i], wlBuffers[i], 0, 0);
185 wl_surface_damage(wlSurfaces[i], 0, 0, 1, 1);
186 wl_surface_commit(wlSurfaces[i]);
187 wl_display_flush(wlDisplay);
188 }
189
190 munmap(mmapData, size);
191 wl_shm_pool_destroy(pool);
192 close(fd);
193 }
194
~TestBase()195 TestBase::~TestBase()
196 {
197 for (std::vector<wl_buffer *>::reverse_iterator it = wlBuffers.rbegin();
198 it != wlBuffers.rend();
199 ++it)
200 {
201 wl_buffer_destroy(*it);
202 }
203 wlBuffers.clear();
204
205 for (std::vector<wl_surface *>::reverse_iterator it = wlSurfaces.rbegin();
206 it != wlSurfaces.rend();
207 ++it)
208 {
209 wl_surface_destroy(*it);
210 }
211 wlSurfaces.clear();
212 wl_shm_destroy(wlShm);
213 wl_compositor_destroy(wlCompositor);
214 ivi_application_destroy(iviApp);
215 wl_registry_destroy(wlRegistry);
216 wl_display_disconnect(wlDisplay);
217 }
218
219