Пример #1
0
__unused JNIEXPORT void JNICALL
Java_pl_droidsonroids_gif_GifInfoHandle_bindSurface(JNIEnv *env, jclass __unused handleClass, jlong gifInfo,
                                                    jobject jsurface, jlongArray savedState) {
	GifInfo *info = (GifInfo *) (intptr_t) gifInfo;
	SurfaceDescriptor *descriptor = info->frameBufferDescriptor;
	if (descriptor == NULL) {
		descriptor = malloc(sizeof(SurfaceDescriptor));
		if (descriptor == NULL) {
			throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE);
			return;
		}
		descriptor->eventPollFd.events = POLL_IN;
		descriptor->eventPollFd.fd = eventfd(0, 0);
		if (descriptor->eventPollFd.fd == -1) {
			throwException(env, RUNTIME_EXCEPTION_ERRNO, "Eventfd creation failed ");
			free(descriptor);
			return;
		}
		errno = pthread_cond_init(&descriptor->slurpCond, NULL);
		THROW_ON_NONZERO_RESULT(errno, "Slurp condition variable initialization failed ");
		errno = pthread_cond_init(&descriptor->renderCond, NULL);
		THROW_ON_NONZERO_RESULT(errno, "Render condition variable initialization failed ");
		errno = pthread_mutex_init(&descriptor->slurpMutex, NULL);
		THROW_ON_NONZERO_RESULT(errno, "Slurp mutex initialization failed ");
		errno = pthread_mutex_init(&descriptor->renderMutex, NULL);
		THROW_ON_NONZERO_RESULT(errno, "Render mutex initialization failed ");
		descriptor->frameBuffer = NULL;
		info->frameBufferDescriptor = descriptor;
		info->destructor = releaseSurfaceDescriptor;
	}

	eventfd_t eventValue;
	int pollResult;

	while (1) {
		pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, 0));
		if (pollResult == 0)
			break;
		else if (pollResult > 0) {
			const int readResult = TEMP_FAILURE_RETRY(eventfd_read(descriptor->eventPollFd.fd, &eventValue));
			if (readResult != 0) {
				throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not read from eventfd ");
				return;
			}
		}
		else {
			throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not poll on eventfd ");
			return;
		}
	}

	const int32_t windowFormat = info->isOpaque ? WINDOW_FORMAT_RGBX_8888 : WINDOW_FORMAT_RGBA_8888;
	struct ANativeWindow *window = ANativeWindow_fromSurface(env, jsurface);
	GifFileType *const gifFilePtr = info->gifFilePtr;
	if (ANativeWindow_setBuffersGeometry(window, (int32_t) gifFilePtr->SWidth, (int32_t) gifFilePtr->SHeight, windowFormat) != 0) {
		ANativeWindow_release(window);
		throwException(env, RUNTIME_EXCEPTION_ERRNO, "Buffers geometry setting failed ");
		return;
	}

	struct ANativeWindow_Buffer buffer = {.bits =NULL};
	void *oldBufferBits;

	if (ANativeWindow_lock(window, &buffer, NULL) != 0) {
#ifdef DEBUG
		LOGE("Window lock failed %d", errno);
#endif
		ANativeWindow_release(window);
		return;
	}
	const size_t bufferSize = buffer.stride * buffer.height * sizeof(argb);

	info->stride = buffer.stride;
	long long invalidationDelayMillis;
	if (descriptor->frameBuffer) {
		memcpy(buffer.bits, descriptor->frameBuffer, bufferSize);
		invalidationDelayMillis = 0;
		descriptor->renderHelper = 1;
		descriptor->slurpHelper = 0;
	} else {
		if (savedState != NULL) {
			invalidationDelayMillis = restoreSavedState(info, env, savedState, buffer.bits);
			if (invalidationDelayMillis < 0)
				invalidationDelayMillis = 0;
		} else
			invalidationDelayMillis = 0;
		descriptor->renderHelper = 0;
		descriptor->slurpHelper = 1;
	}

	info->lastFrameRemainder = -1;
	ANativeWindow_unlockAndPost(window);

	if (info->loopCount != 0 && info->currentLoop == info->loopCount) {
		ANativeWindow_release(window);
		pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, -1));
		if (pollResult < 0) {
			throwException(env, RUNTIME_EXCEPTION_ERRNO, "Animation end poll failed ");
		}
		return;
	}

	errno = pthread_create(&descriptor->slurpThread, NULL, slurp, info);
	if (errno != 0) {
		throwException(env, RUNTIME_EXCEPTION_ERRNO, "Slurp thread creation failed ");
		ANativeWindow_release(window);
		return;
	}

	while (1) {
		pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, (int) invalidationDelayMillis));
		long renderingStartTime = getRealTime();

		if (pollResult < 0) {
			throwException(env, RUNTIME_EXCEPTION_ERRNO, "Display loop poll failed ");
			break;
		} else if (pollResult > 0) {
			if (descriptor->frameBuffer == NULL) {
				descriptor->frameBuffer = malloc(bufferSize);
				if (descriptor->frameBuffer == NULL) {
					throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE);
					break;
				}
			}
			memcpy(descriptor->frameBuffer, buffer.bits, bufferSize);
			break;
		}
		oldBufferBits = buffer.bits;

		struct ARect *dirtyRectPtr;
		if (info->currentIndex == 0) {
			dirtyRectPtr = NULL;
		} else {
			const GifImageDesc imageDesc = gifFilePtr->SavedImages[info->currentIndex].ImageDesc;
			struct ARect dirtyRect = {
					.left = imageDesc.Left,
					.top = imageDesc.Top,
					.right = imageDesc.Left + imageDesc.Width,
					.bottom = imageDesc.Top + imageDesc.Height
			};
			dirtyRectPtr = &dirtyRect;
		}
		if (ANativeWindow_lock(window, &buffer, dirtyRectPtr) != 0) {
#ifdef DEBUG
			LOGE("Window lock failed %d", errno);
#endif
			break;
		}

		if (info->currentIndex == 0)
			prepareCanvas(buffer.bits, info);
		else
			memcpy(buffer.bits, oldBufferBits, bufferSize);

		pthread_mutex_lock(&descriptor->renderMutex);
		while (descriptor->renderHelper == 0) {
			pthread_cond_wait(&descriptor->renderCond, &descriptor->renderMutex);
		}
		descriptor->renderHelper = 0;
		pthread_mutex_unlock(&descriptor->renderMutex);

		const uint_fast32_t frameDuration = getBitmap(buffer.bits, info);

		pthread_mutex_lock(&descriptor->slurpMutex);
		descriptor->slurpHelper = 1;
		pthread_cond_signal(&descriptor->slurpCond);
		pthread_mutex_unlock(&descriptor->slurpMutex);

		ANativeWindow_unlockAndPost(window);

		invalidationDelayMillis = calculateInvalidationDelay(info, renderingStartTime, frameDuration);

		if (info->lastFrameRemainder >= 0) {
			invalidationDelayMillis = info->lastFrameRemainder;
			info->lastFrameRemainder = -1;
		}
	}

	ANativeWindow_release(window);
	pthread_mutex_lock(&descriptor->slurpMutex);
	descriptor->slurpHelper = 2;
	pthread_cond_signal(&descriptor->slurpCond);
	pthread_mutex_unlock(&descriptor->slurpMutex);
	errno = pthread_join(descriptor->slurpThread, NULL);
	THROW_ON_NONZERO_RESULT(errno, "Slurp thread join failed");
}

__unused JNIEXPORT void JNICALL
Java_pl_droidsonroids_gif_GifInfoHandle_postUnbindSurface(JNIEnv *env, jclass __unused handleClass, jlong gifInfo) {
	GifInfo *info = (GifInfo *) (intptr_t) gifInfo;
	if (info == NULL || info->frameBufferDescriptor == NULL) {
		return;
	}
	SurfaceDescriptor const *descriptor = info->frameBufferDescriptor;
	const int writeResult = TEMP_FAILURE_RETRY(eventfd_write(descriptor->eventPollFd.fd, 1));
	if (writeResult != 0 && errno != EBADF) {
		throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not write to eventfd ");
	}
}
Пример #2
0
void ponyint_asio_backend_final(asio_backend_t* b)
{
  atomic_store_explicit(&b->terminate, true, memory_order_relaxed);
  eventfd_write(b->wakeup, 1);
}
Пример #3
0
Файл: epoll.c Проект: DevL/ponyc
void asio_backend_terminate(asio_backend_t* b)
{
  b->terminate = true;
  eventfd_write(b->wakeup, 1);
}
Пример #4
0
int eventfd_send_state(int efd, eventfd_t s) {
        return eventfd_write(efd, s);
}
Пример #5
0
static void eventfd_wakeup(grpc_wakeup_fd *fd_info) {
  int err;
  do {
    err = eventfd_write(fd_info->read_fd, 1);
  } while (err < 0 && errno == EINTR);
}
Пример #6
0
 Device::~Device()
 {
     eventfd_write(mEventFd, 1);
     if (mFd >= 0) { close(mFd); mFd = -1; }
     if (mEventFd >= 0) { close(mEventFd); mEventFd = -1; }
 }
Пример #7
0
inline bool queue_push_element(queue_t *queue, void * element) {
    // Push an element in the queue
    // If successfull, write 1 in the file descriptor.
    return list_push_element(queue->elements, element)
        && (eventfd_write(queue->eventfd, 1) != -1);
}
Пример #8
0
static BOOL _purge(WINPR_COMM *pComm, const ULONG *pPurgeMask)
{
	if ((*pPurgeMask & ~(SERIAL_PURGE_TXABORT | SERIAL_PURGE_RXABORT | SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR)) > 0)
	{
		CommLog_Print(WLOG_WARN, "Invalid purge mask: 0x%lX\n", *pPurgeMask);
		SetLastError(ERROR_INVALID_PARAMETER);
		return FALSE;
	}

	/* FIXME: currently relying too much on the fact the server
	 * sends a single IRP_MJ_WRITE or IRP_MJ_READ at a time
	 * (taking care though that one IRP_MJ_WRITE and one
	 * IRP_MJ_READ can be sent simultaneously) */

	if (*pPurgeMask & SERIAL_PURGE_TXABORT)
	{
		/* Purges all write (IRP_MJ_WRITE) requests. */

		if (eventfd_write(pComm->fd_write_event, FREERDP_PURGE_TXABORT) < 0)
		{
			if (errno != EAGAIN)
			{
				CommLog_Print(WLOG_WARN, "eventfd_write failed, errno=[%d] %s", errno, strerror(errno));
			}

			assert(errno == EAGAIN); /* no reader <=> no pending IRP_MJ_WRITE */
		}
	}

	if (*pPurgeMask & SERIAL_PURGE_RXABORT)
	{
		/* Purges all read (IRP_MJ_READ) requests. */

		if (eventfd_write(pComm->fd_read_event, FREERDP_PURGE_RXABORT) < 0)
		{
			if (errno != EAGAIN)
			{
				CommLog_Print(WLOG_WARN, "eventfd_write failed, errno=[%d] %s", errno, strerror(errno));
			}

			assert(errno == EAGAIN); /* no reader <=> no pending IRP_MJ_READ */
		}
	}

	if (*pPurgeMask & SERIAL_PURGE_TXCLEAR)
	{
		/* Purges the transmit buffer, if one exists. */

		if (tcflush(pComm->fd, TCOFLUSH) < 0)
		{
			CommLog_Print(WLOG_WARN, "tcflush(TCOFLUSH) failure, errno=[%d] %s", errno, strerror(errno));
			SetLastError(ERROR_CANCELLED);
			return FALSE;
		}
	}


	if (*pPurgeMask & SERIAL_PURGE_RXCLEAR)
	{
		/* Purges the receive buffer, if one exists. */

		if (tcflush(pComm->fd, TCIFLUSH) < 0)
		{
			CommLog_Print(WLOG_WARN, "tcflush(TCIFLUSH) failure, errno=[%d] %s", errno, strerror(errno));
			SetLastError(ERROR_CANCELLED);
			return FALSE;
		}
	}

	return TRUE;
}