Skip to content

Commit c852dc6

Browse files
committed
hwcomposer: Correctly synchronize buffer release
* A buffer may be reused * The buffer cache may be invalidated before one of its buffers is released
1 parent 48dd99a commit c852dc6

File tree

3 files changed

+47
-22
lines changed

3 files changed

+47
-22
lines changed

hwcomposer/hwcomposer.cpp

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -188,24 +188,28 @@ static struct buffer *get_wl_buffer(struct waydroid_hwc_composer_device_1 *pdev,
188188

189189
auto it = pdev->display->buffer_map.find(layer->handle);
190190
if (it != pdev->display->buffer_map.end()) {
191+
std::lock_guard(pdev->display->buffers_mutex);
191192
if (it->second->isShm) {
192193
if (width != it->second->width || height != it->second->height) {
193-
if (it->second->buffer)
194-
wl_buffer_destroy(it->second->buffer);
195-
delete (it->second);
194+
it->second->refcount--;
195+
if (it->second->refcount == 0)
196+
destroy_buffer(it->second);
196197
pdev->display->buffer_map.erase(it);
197198
} else {
199+
it->second->refcount++;
198200
update_shm_buffer(pdev->display, it->second);
199201
return it->second;
200202
}
201-
} else
203+
} else {
204+
it->second->refcount++;
202205
return it->second;
206+
}
203207
}
204208

205209
struct buffer *buf;
206210
int ret = 0;
207211

208-
buf = new struct buffer();
212+
buf = create_buffer(pdev->display);
209213
if (pdev->display->gtype == GRALLOC_GBM) {
210214
struct gralloc_handle_t *drm_handle = (struct gralloc_handle_t *)layer->handle;
211215
if (pdev->display->dmabuf) {
@@ -236,7 +240,7 @@ static struct buffer *get_wl_buffer(struct waydroid_hwc_composer_device_1 *pdev,
236240
return NULL;
237241
}
238242
pdev->display->buffer_map[layer->handle] = buf;
239-
243+
buf->refcount++;
240244
return pdev->display->buffer_map[layer->handle];
241245
}
242246

@@ -414,14 +418,11 @@ static int hwc_set(struct hwc_composer_device_1* dev,size_t numDisplays,
414418
int err = 0;
415419

416420
if (pdev->display->geo_changed) {
421+
std::lock_guard(pdev->display->buffers_mutex);
417422
for (auto it = pdev->display->buffer_map.begin(); it != pdev->display->buffer_map.end(); it++) {
418-
if (it->second) {
419-
if (it->second->buffer)
420-
wl_buffer_destroy(it->second->buffer);
421-
if (it->second->isShm)
422-
munmap(it->second->shm_data, it->second->size);
423-
delete (it->second);
424-
}
423+
it->second->refcount--;
424+
if (it->second->refcount == 0)
425+
destroy_buffer(it->second);
425426
}
426427
pdev->display->buffer_map.clear();
427428
}
@@ -769,12 +770,8 @@ static int hwc_set(struct hwc_composer_device_1* dev,size_t numDisplays,
769770
if (fb_layer->compositionType != HWC_FRAMEBUFFER &&
770771
fb_layer->compositionType != HWC_SIDEBAND)
771772
{
772-
int timeline_fd = sw_sync_timeline_create();
773773
/* To be signaled when the compositor releases the buffer */
774-
fb_layer->releaseFenceFd = sw_sync_fence_create(timeline_fd, "wayland_release", 1);
775-
buf->timeline_fd = timeline_fd;
776-
} else {
777-
buf->timeline_fd = -1;
774+
fb_layer->releaseFenceFd = sw_sync_fence_create(buf->timeline_fd, "wayland_release", ++buf->sync_point);
778775
}
779776

780777
struct wl_surface *surface = get_surface(pdev, fb_layer, window, pdev->use_subsurface);

hwcomposer/wayland-hwc.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,34 @@
7272

7373
using ::android::hardware::hidl_string;
7474

75-
struct buffer;
75+
struct buffer*
76+
create_buffer(struct display* display) {
77+
struct buffer* buf = new struct buffer();
78+
buf->display = display;
79+
buf->timeline_fd = sw_sync_timeline_create();
80+
buf->refcount = 1;
81+
return buf;
82+
}
83+
84+
void
85+
destroy_buffer(struct buffer* buf) {
86+
close(buf->timeline_fd);
87+
wl_buffer_destroy(buf->buffer);
88+
if (buf->isShm)
89+
munmap(buf->shm_data, buf->size);
90+
delete buf;
91+
}
7692

7793
static void
7894
buffer_release(void *data, struct wl_buffer *)
7995
{
8096
struct buffer *mybuf = (struct buffer*)data;
8197

8298
sw_sync_timeline_inc(mybuf->timeline_fd, 1);
83-
close(mybuf->timeline_fd);
84-
mybuf->timeline_fd = -1;
99+
std::lock_guard(mybuf->display->buffers_mutex);
100+
mybuf->refcount--;
101+
if (mybuf->refcount == 0)
102+
destroy_buffer(mybuf);
85103
}
86104

87105
static const struct wl_buffer_listener buffer_listener = {
@@ -296,7 +314,7 @@ void snapshot_inactive_app_window(struct display *display, struct window *window
296314
ALOGI("Making inactive window snapshot for %s", window->taskID.c_str());
297315

298316
struct buffer *old_buf = window->last_layer_buffer;
299-
struct buffer *new_buf = new struct buffer();
317+
struct buffer *new_buf = create_buffer(display);
300318
// FIXME won't work as expected if there are multiple surfaces
301319
struct wl_surface *surface = window->surface;
302320

hwcomposer/wayland-hwc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ struct display {
155155
std::map<uint32_t, struct handleExt> layer_handles_ext;
156156
struct handleExt target_layer_handle_ext;
157157
std::map<buffer_handle_t, struct buffer *> buffer_map;
158+
std::mutex buffers_mutex;
158159
std::array<uint8_t, 239> keysDown;
159160

160161
bool isWinResSet;
@@ -174,9 +175,13 @@ struct buffer {
174175
uint32_t hal_format;
175176

176177
int timeline_fd;
178+
int sync_point;
177179
bool isShm;
178180
void *shm_data;
179181
int size;
182+
183+
int refcount;
184+
struct display* display;
180185
};
181186

182187
struct window {
@@ -219,6 +224,11 @@ create_shm_wl_buffer(struct display *display, struct buffer *buffer,
219224
void
220225
snapshot_inactive_app_window(struct display *display, struct window *window);
221226

227+
void
228+
destroy_buffer(struct buffer* buffer);
229+
struct buffer*
230+
create_buffer(struct display* display);
231+
222232
struct display *
223233
create_display(const char* gralloc);
224234
void

0 commit comments

Comments
 (0)