12c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland/*
22c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * Copyright (C) 2013 The Android Open Source Project
32c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland *
42c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * Licensed under the Apache License, Version 2.0 (the "License");
52c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * you may not use this file except in compliance with the License.
62c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * You may obtain a copy of the License at
72c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland *
82c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland *      http://www.apache.org/licenses/LICENSE-2.0
92c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland *
102c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * Unless required by applicable law or agreed to in writing, software
112c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * distributed under the License is distributed on an "AS IS" BASIS,
122c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * See the License for the specific language governing permissions and
142c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland * limitations under the License.
152c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland */
162c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
172c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <stdio.h>
182c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <stdlib.h>
192c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <stdarg.h>
202c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <string.h>
212c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <errno.h>
222c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
232c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <pthread.h>
242c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
252c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <hardware/hardware.h>
262c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <hardware/gralloc.h>
272c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <hardware/hwcomposer.h>
282c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
292c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <system/window.h>
302c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#include <cutils/native_handle.h>
312c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
322c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland// normalize and shorten type names
332c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandtypedef struct android_native_base_t aBase;
342c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandtypedef struct ANativeWindowBuffer aBuffer;
352c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandtypedef struct ANativeWindow aWindow;
362c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
372c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int trace_level = 1;
382c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
392c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#define _TRACE(n,fmt...) \
402c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	do { if (trace_level >= n) fprintf(stderr, "CNW: " fmt); } while (0)
412c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
422c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#define ERROR(fmt...) _TRACE(0, fmt)
432c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#define INFO(fmt...) _TRACE(1, fmt)
442c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#define LOG(fmt...) _TRACE(2, fmt)
452c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#define TRACE(fmt...) _TRACE(3, fmt)
462c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
472c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland#define QCT_WORKAROUND 1
482c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
492c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandtypedef struct CNativeBuffer {
502c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	aBuffer base;
512c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	struct CNativeBuffer *next;
522c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	struct CNativeBuffer *prev;
532c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int ffd;
542c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland} CNativeBuffer;
552c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
562c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandtypedef struct CNativeWindow {
572c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	aWindow base;
582c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
592c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc_composer_device_1_t *hwc;
602c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	framebuffer_device_t *fb;
612c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	alloc_device_t *gr;
622c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
632c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_t lock;
642c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_cond_t cvar;
652c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
662c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	aBuffer *front;
672c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	aBuffer *spare;
682c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
692c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeBuffer free_buffer_queue;
702c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
712c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	unsigned width;
722c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	unsigned height;
732c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	unsigned xdpi;
742c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	unsigned ydpi;
752c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	unsigned format;
762c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
77fc0ff2a8700eb11aef7a961b279d846c8a1c04c5Jesse Hall	hwc_display_contents_1_t *dclist[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
782c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
792c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc_display_contents_1_t dc;
802c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc_layer_1_t layer[4];
812c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland} CNativeWindow;
822c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
832c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic inline CNativeBuffer *from_abuffer(aBuffer *buf) {
842c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return (CNativeBuffer*) buf;
852c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
862c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
872c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic CNativeBuffer *get_front(struct CNativeBuffer *queue) {
882c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeBuffer *buf = queue->next;
892c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (buf == queue)
902c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
912c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->next->prev = queue;
922c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	queue->next = buf->next;
932c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->next = buf->prev = 0;
942c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return buf;
952c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
962c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
972c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void put_front(struct CNativeBuffer *queue, aBuffer *_buf) {
982c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf;
992c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->prev = queue;
1002c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->next = queue->next;
1012c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	queue->next->prev = buf;
1022c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	queue->next = buf;
1032c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1042c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1052c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void put_back(struct CNativeBuffer *queue, aBuffer *_buf) {
1062c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	struct CNativeBuffer *buf = (struct CNativeBuffer *) _buf;
1072c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->next = queue;
1082c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->prev = queue->prev;
1092c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	queue->prev->next = buf;
1102c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	queue->prev = buf;
1112c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1122c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1132c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void cnw_inc_ref(aBase *base) { TRACE("buf %p ref++\n",base); }
1142c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void cnw_dec_ref(aBase *base) { TRACE("buf %p ref--\n",base); }
1152c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1162c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic inline CNativeWindow *from_base(aWindow *base) {
1172c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return (CNativeWindow *) base;
1182c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1192c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1202c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic inline CNativeWindow *from_base_const(const aWindow *base) {
1212c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return (CNativeWindow *) base;
1222c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1232c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1242c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_set_swap_interval(aWindow *base, int interval) {
1252c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeWindow *win = from_base(base);
1262c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (win->fb && win->fb->setSwapInterval)
1272c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return win->fb->setSwapInterval(win->fb, interval);
1282c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return 0;
1292c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1302c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1312c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_dequeue_buffer1(aWindow *base, aBuffer **buf, int *ffd) {
1322c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeWindow *win = from_base(base);
1332c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeBuffer *cnb;
1342c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1352c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_lock(&win->lock);
1362c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1372c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	while ((cnb = get_front(&win->free_buffer_queue)) == 0) {
1382c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		pthread_cond_wait(&win->cvar, &win->lock);
1392c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
1402c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1412c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*ffd = cnb->ffd;
1422c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*buf = &cnb->base;
1432c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	cnb->ffd = -1;
1442c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	LOG("<< dequeue buffer %p %d\n", *buf, *ffd);
1452c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1462c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_unlock(&win->lock);
1472c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return 0;
1482c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1492c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1502c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_lock_buffer0(aWindow *base, aBuffer *buffer) {
1512c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return 0;
1522c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1532c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1542c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void set_layer(hwc_layer_1_t *dl, aBuffer *buf, int ffd) {
1552c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int right = buf->width;
1562c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int bottom = buf->height;
1572c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1582c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->compositionType = HWC_FRAMEBUFFER;
1592c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->hints = 0;
1602c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->flags = 0;
1612c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1622c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->handle = buf->handle;
1632c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->transform = 0;
1642c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->blending = HWC_BLENDING_NONE;
1652c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->sourceCrop.left = 0;
1662c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->sourceCrop.top = 0;
1672c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->sourceCrop.right = right;
1682c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->sourceCrop.bottom = bottom;
1692c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->displayFrame.left = 0;
1702c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->displayFrame.top = 0;
1712c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->displayFrame.right = right;
1722c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->displayFrame.bottom = bottom;
1732c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->visibleRegionScreen.numRects = 1;
1742c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->visibleRegionScreen.rects = &dl->displayFrame;
1752c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1762c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->acquireFenceFd = ffd;
1772c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dl->releaseFenceFd = -1;
1782c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
1792c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1802c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void hwc_post(CNativeWindow *win, aBuffer *buf, int ffd) {
1812c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc_composer_device_1_t *hwc = win->hwc;
1822c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc_display_contents_1_t *dc = &(win->dc);
1832c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc_layer_1_t *dl = win->dc.hwLayers;
1842c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int r, i;
1852c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1862c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dc->retireFenceFd = -1;
1872c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dc->outbufAcquireFenceFd = -1;
1882c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dc->flags = HWC_GEOMETRY_CHANGED;
1892c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dc->numHwLayers = 1;
1902c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1912c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	// some hwcomposers fail if these are NULL
1922c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dc->dpy = (void*) 0xdeadbeef;
1932c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	dc->sur = (void*) 0xdeadbeef;
1942c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1952c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	set_layer(&dl[0], buf, ffd);
1962c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
1972c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (QCT_WORKAROUND) {
1982c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		set_layer(&dl[1], win->spare, -1);
1992c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		dl[1].compositionType = HWC_FRAMEBUFFER_TARGET;
2002c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		dc->numHwLayers++;
2012c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
2022c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
203fc0ff2a8700eb11aef7a961b279d846c8a1c04c5Jesse Hall	r = hwc->prepare(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist);
2042c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (r) {
2052c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("hwc->prepare failed r=%d\n",r);
2062c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return;
2072c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
2082c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2092c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland//	for (i = 0; i < dc->numHwLayers; i++)
2102c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland//		LOG("dl[%d] ctype=0x%08x hints=0x%08x flags=0x%08x\n", i,
2112c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland//			dl[i].compositionType, dl[0].hints, dl[0].flags);
2122c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
213fc0ff2a8700eb11aef7a961b279d846c8a1c04c5Jesse Hall	r = hwc->set(hwc, HWC_NUM_PHYSICAL_DISPLAY_TYPES, win->dclist);
2142c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (r) {
2152c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("hwc->set failed, r=%d\n", r);
2162c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return;
2172c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
2182c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2192c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (dc->retireFenceFd != -1)
2202c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		close(dc->retireFenceFd);
2212c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (dl->releaseFenceFd != -1) {
2222c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		CNativeBuffer *cnb = from_abuffer(buf);
2232c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		cnb->ffd = dl->releaseFenceFd;
2242c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
2252c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (QCT_WORKAROUND)
2262c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		if (dl[1].releaseFenceFd != -1)
2272c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			close(dl[1].releaseFenceFd);
2282c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
2292c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2302c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_queue_buffer1(aWindow *base, aBuffer *buffer, int ffd) {
2312c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeWindow *win = from_base(base);
2322c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int res;
2332c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	LOG(">> queue buffer %p %d\n", buffer, ffd);
2342c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (win->fb) {
2352c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		res = win->fb->post(win->fb, buffer->handle);
2362c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		if (ffd != -1)
2372c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			close(ffd);
2382c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	} else {
2392c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		hwc_post(win, buffer, ffd);
2402c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		res = 0;
2412c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
2422c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_lock(&win->lock);
2432c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (win->front)
2442c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		put_back(&win->free_buffer_queue, win->front);
2452c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->front = buffer;
2462c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_cond_signal(&win->cvar);
2472c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_unlock(&win->lock);
2482c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2492c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return res;
2502c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
2512c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2522c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_cancel_buffer1(aWindow *base, aBuffer *buf, int ffd) {
2532c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeWindow *win = from_base(base);
2542c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeBuffer *cnb = from_abuffer(buf);
2552c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	LOG("<< cancel buffer %p %d\n", buf, ffd);
2562c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	cnb->ffd = ffd;
2572c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_lock(&win->lock);
2582c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	put_front(&win->free_buffer_queue, buf);
2592c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_unlock(&win->lock);
2602c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return 0;
2612c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
2622c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2632c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_dequeue_buffer0(aWindow *base, aBuffer **buf) {
2642c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int ffd = -1;
2652c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int r;
2662c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	r = cnw_dequeue_buffer1(base, buf, &ffd);
2672c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (ffd != -1)
2682c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		close(ffd);
2692c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return r;
2702c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
2712c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2722c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_queue_buffer0(aWindow *base, aBuffer *buf) {
2732c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return cnw_queue_buffer1(base, buf, -1);
2742c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
2752c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2762c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_cancel_buffer0(aWindow *base, aBuffer *buf) {
2772c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return cnw_cancel_buffer1(base, buf, -1);
2782c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
2792c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2802c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_query(const aWindow *base, int what, int *value) {
2812c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeWindow *win = from_base_const(base);
2822c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
2832c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	switch (what) {
2842c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_WIDTH:
2852c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_DEFAULT_WIDTH:
2862c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		*value = win->width;
2872c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("query window width: %d\n", *value);
2882c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
2892c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_HEIGHT:
2902c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_DEFAULT_HEIGHT:
2912c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		*value = win->height;
2922c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("query window height: %d\n", *value);
2932c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
2942c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_FORMAT:
2952c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		*value = win->format;
2962c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("query window format: %d\n", *value);
2972c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
2982c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_TRANSFORM_HINT:
2992c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("query transform hint: 0\n");
3002c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		*value = 0;
3012c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3022c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
3032c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("query min undequeued buffers: 1\n");
3042c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		*value = 1;
3052c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3062c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	default:
3072c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		*value = 0;
3082c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("query %d unknown!\n", what);
3092c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -EINVAL;
3102c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
3112c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
3122c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3132c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_perform(aWindow *base, int op, ...) {
3142c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeWindow *win = from_base(base);
3152c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	va_list ap;
3162c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	va_start(ap, op);
3172c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3182c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	switch (op) {
3192c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_SET_USAGE:
3202c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("set usage %d\n", va_arg(ap,int));
3212c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3222c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_CONNECT:
3232c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_DISCONNECT:
3242c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_API_CONNECT:
3252c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_API_DISCONNECT:
3262c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3272c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
3282c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("set buffers format %d\n", va_arg(ap,int));
3292c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3302c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
3312c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("set buffers transform %d\n", va_arg(ap,int));
3322c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3332c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
3342c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("set buffers timestamp %lld\n", va_arg(ap,long long));
3352c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3362c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_SET_SCALING_MODE:
3372c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		TRACE("set scaling mode %d\n", va_arg(ap,int));
3382c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
3392c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
3402c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		int w = va_arg(ap,int);
3412c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		int h = va_arg(ap,int);
3422c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		if ((w == win->width) && (h == win->height)) {
3432c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			TRACE("set buffers dimensions %d x %d\n", w, h);
3442c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			return 0;
3452c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		}
3462c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("cannot resize buffers to %d x %d\n", w, h);
3472c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -1;
3482c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
3492c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	default:
3502c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("perform %d unknown!\n", op);
3512c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
3522c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
3532c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
3542c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3552c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void hwc_invalidate(const struct hwc_procs *procs) {}
3562c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void hwc_vsync(const struct hwc_procs *procs, int disp, int64_t ts) {}
3572c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic void hwc_hotplug(const struct hwc_procs *procs, int disp, int conn) {}
3582c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3592c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstruct hwc_procs hprocs = {
3602c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	.invalidate = hwc_invalidate,
3612c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	.vsync = hwc_vsync,
3622c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	.hotplug = hwc_hotplug,
3632c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland};
3642c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3652c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlanduint32_t attrs[] = {
3662c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	HWC_DISPLAY_WIDTH,
3672c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	HWC_DISPLAY_HEIGHT,
3682c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	HWC_DISPLAY_VSYNC_PERIOD,
3692c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	HWC_DISPLAY_DPI_X,
3702c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	HWC_DISPLAY_DPI_Y,
3712c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	HWC_DISPLAY_NO_ATTRIBUTE,
3722c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland};
3732c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3742c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int hwc_init(CNativeWindow *win) {
3752c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hw_module_t const* module;
3762c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc_composer_device_1_t *hwc;
3772c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	unsigned i;
3782c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int r;
3792c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	uint32_t configs[32];
3802c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	uint32_t numconfigs = 32;
3812c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int32_t values[8];
3822c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3832c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
3842c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("cannot open hw composer module\n");
3852c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
3862c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
3872c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3882c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (hwc_open_1(module, &hwc)) {
3892c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("cannot open hwc device\n");
3902c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
3912c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
3922c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->hwc = hwc;
3932c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3942c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	LOG("hwc version 0x%08x\n", hwc->common.version);
3952c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
3962c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if ((hwc->common.version & 0xFFFF0000) < 0x01010000) {
3972c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("hwc version less than 1.1\n");
3982c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		hwc_close_1(hwc);
3992c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
4002c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
4012c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4022c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc->registerProcs(hwc, &hprocs);
4032c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4042c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (hwc->getDisplayConfigs(hwc, 0, configs, &numconfigs)) {
4052c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("cannot get configs\n");
4062c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
4072c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
4082c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	for (i = 0; i < numconfigs; i++)
4092c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		LOG("cfg[%d] = 0x%08x\n", i, configs[i]);
4102c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4112c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if ((r = hwc->getDisplayAttributes(hwc, 0, configs[0], attrs, values))) {
4122c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("cannot get attributes %d\n", r);
4132c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
4142c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
4152c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4162c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->width = values[0];
4172c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->height = values[1];
4182c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->xdpi = values[3];
4192c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->ydpi = values[4];
4202c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->format = HAL_PIXEL_FORMAT_RGBA_8888;
4212c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4222c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hwc->blank(hwc, 0, 0);
4232c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4242c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->dclist[0] = &(win->dc);
4252c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return 0;
4262c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
4272c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4282c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic aBuffer *cnw_alloc(CNativeWindow *win, unsigned format, unsigned usage) {
4292c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeBuffer *cnb;
4302c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	aBuffer *buf;
4312c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int err;
4322c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4332c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (!(cnb = malloc(sizeof(CNativeBuffer))))
4342c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
4352c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4362c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf = &cnb->base;
4372c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	cnb->ffd = -1;
4382c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4392c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
4402c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->common.version = sizeof(aBuffer);
4412c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->common.incRef = cnw_inc_ref;
4422c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->common.decRef = cnw_dec_ref;
4432c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4442c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->width = win->width;
4452c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->height = win->height;
4462c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->format = format;
4472c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	buf->usage = usage;
4482c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4492c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	err = win->gr->alloc(win->gr, win->width, win->height,
4502c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		format, usage, &buf->handle, &buf->stride);
4512c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (err) {
4522c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("gralloc of %d x %d failed: err=%d\n",
4532c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			win->width, win->height, err);
4542c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		free(buf);
4552c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return 0;
4562c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
4572c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	INFO("alloc buffer %p %d x %d\n", buf, win->width, win->height);
4582c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return buf;
4592c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
4602c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4612c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandstatic int cnw_init(CNativeWindow *win) {
4622c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	hw_module_t const* module;
4632c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	framebuffer_device_t *fb = NULL;
4642c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	alloc_device_t *gr;
4652c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	int err, i, n;
4662c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	unsigned usage, format;
4672c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4682c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	memset(win, 0, sizeof(CNativeWindow));
4692c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4702c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->free_buffer_queue.next = &(win->free_buffer_queue);
4712c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->free_buffer_queue.prev = &(win->free_buffer_queue);
4722c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4732c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
4742c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("cannot open gralloc module\n");
4752c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
4762c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
4772c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4782c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (hwc_init(win)) {
4792c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("cannot open hwcomposer, trying legacy fb HAL\n");
4802c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		err = framebuffer_open(module, &fb);
4812c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		if (err) {
4822c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			ERROR("cannot open fb HAL (%s)", strerror(-err));
4832c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			return -ENODEV;
4842c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		}
4852c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->width = fb->width;
4862c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->height = fb->height;
4872c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->format = fb->format;
4882c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->xdpi = fb->xdpi;
4892c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->ydpi = fb->ydpi;
4902c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->fb = fb;
4912c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
4922c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4932c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	INFO("display %d x %d fmt=%d\n",
4942c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->width, win->height, win->format);
4952c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
4962c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	err = gralloc_open(module, &gr);
4972c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (err) {
4982c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		ERROR("couldn't open gralloc HAL (%s)", strerror(-err));
4992c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return -ENODEV;
5002c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
5012c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->gr = gr;
5022c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5032c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	usage = GRALLOC_USAGE_HW_FB |
5042c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		GRALLOC_USAGE_HW_COMPOSER |
5052c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		GRALLOC_USAGE_HW_RENDER;
5062c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5072c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	for (i = 0; i < 2; i++) {
5082c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		aBuffer *buf = cnw_alloc(win, win->format, usage);
5092c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		if (!buf)
5102c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			return -ENOMEM;
5112c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		put_back(&win->free_buffer_queue, buf);
5122c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
5132c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5142c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (!win->fb && QCT_WORKAROUND) {
5152c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		win->spare = cnw_alloc(win, win->format, usage);
5162c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		if (!win->spare)
5172c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland			return -ENOMEM;
5182c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
5192c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5202c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	// Disgusting, but we need to init these "const" fields
5212c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	// and unlike C++ we can't use const_cast<>
5222c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*((float*) &win->base.xdpi) = win->xdpi;
5232c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*((float*) &win->base.ydpi) = win->ydpi;
5242c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*((int*) &win->base.minSwapInterval) = 1;
5252c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*((int*) &win->base.maxSwapInterval) = 1;
5262c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5272c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
5282c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.common.version = sizeof(aWindow);
5292c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.common.incRef = cnw_inc_ref;
5302c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.common.decRef = cnw_dec_ref;
5312c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5322c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.setSwapInterval = cnw_set_swap_interval;
5332c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.dequeueBuffer_DEPRECATED = cnw_dequeue_buffer0;
5342c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.lockBuffer_DEPRECATED = cnw_lock_buffer0;
5352c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.queueBuffer_DEPRECATED = cnw_queue_buffer0;
5362c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.query = cnw_query;
5372c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.perform = cnw_perform;
5382c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.cancelBuffer_DEPRECATED = cnw_cancel_buffer0;
5392c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.dequeueBuffer = cnw_dequeue_buffer1;
5402c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.queueBuffer = cnw_queue_buffer1;
5412c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	win->base.cancelBuffer = cnw_cancel_buffer1;
5422c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5432c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_mutex_init(&win->lock, NULL);
5442c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	pthread_cond_init(&win->cvar, NULL);
5452c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5462c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return 0;
5472c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
5482c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5492c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandvoid cnw_destroy(CNativeWindow *win) {
5502c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (win->fb)
5512c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		framebuffer_close(win->fb);
5522c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (win->hwc)
5532c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		hwc_close_1(win->hwc);
5542c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (win->gr)
5552c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		gralloc_close(win->gr);
5562c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	free(win);
5572c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
5582c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5592c7b08ad8aeedef1807560ea16d54d073bede2b2Brian SwetlandCNativeWindow *cnw_create(void) {
5602c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	CNativeWindow *win;
5612c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	char *x;
5622c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if ((x = getenv("CNWDEBUG")))
5632c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		trace_level = atoi(x);
5642c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (!(win = malloc(sizeof(CNativeWindow))))
5652c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return NULL;
5662c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	if (cnw_init(win)) {
5672c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		cnw_destroy(win);
5682c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland		return NULL;
5692c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	}
5702c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	return win;
5712c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
5722c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
5732c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetlandvoid cnw_info(CNativeWindow *win, unsigned *w, unsigned *h, unsigned *fmt) {
5742c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*w = win->width;
5752c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*h = win->height;
5762c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland	*fmt = win->format;
5772c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland}
5782c7b08ad8aeedef1807560ea16d54d073bede2b2Brian Swetland
579