• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &registry_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