Esempio n. 1
0
int freerds_client_inbound_paint_rect(rdsModuleConnector* connector, RDS_MSG_PAINT_RECT* msg)
{
	int bpp;
	int inFlightFrames;
	SURFACE_FRAME* frame;
	rdsConnection* connection;
	rdpSettings* settings;

	connection = connector->connection;
	settings = connection->settings;

	bpp = msg->framebuffer->fbBitsPerPixel;

	if (connection->codecMode)
	{
		inFlightFrames = ListDictionary_Count(connection->FrameList);

		if (inFlightFrames > settings->FrameAcknowledge)
			connector->fps = (100 / (inFlightFrames + 1) * connector->MaxFps) / 100;
		else
			connector->fps = connector->MaxFps;

		if (connector->fps < 1)
			connector->fps = 1;

		frame = (SURFACE_FRAME*) malloc(sizeof(SURFACE_FRAME));

		frame->frameId = ++connection->frameId;
		ListDictionary_Add(connection->FrameList, (void*) (size_t) frame->frameId, frame);

		freerds_orders_send_frame_marker(connection, SURFACECMD_FRAMEACTION_BEGIN, frame->frameId);
		freerds_send_surface_bits(connection, bpp, msg);
		freerds_orders_send_frame_marker(connection, SURFACECMD_FRAMEACTION_END, frame->frameId);
	}
	else
	{
		freerds_send_bitmap_update(connection, bpp, msg);
	}

	return 0;
}
Esempio n. 2
0
int freerds_send_bitmap_update(rdsConnection* connection, int bpp, RDS_MSG_PAINT_RECT* msg)
{
	BYTE* data;
	BYTE* tile;
	BYTE* buffer;
	int i, j, k;
	wStream* s;
	wStream* ts;
	int e, lines;
	int scanline;
	int rows, cols;
	int MaxRegionWidth;
	int MaxRegionHeight;
	INT32 nWidth, nHeight;
	pixman_image_t* image;
	pixman_image_t* fbImage;
	BITMAP_DATA* bitmapData;
	BITMAP_UPDATE bitmapUpdate;
	rdpUpdate* update = connection->client->update;

	//printf("%s\n", __FUNCTION__);

	MaxRegionWidth = 64 * 4;
	MaxRegionHeight = 64 * 1;

	if ((msg->nLeftRect % 4) != 0)
	{
		msg->nWidth += (msg->nLeftRect % 4);
		msg->nLeftRect -= (msg->nLeftRect % 4);
	}

	if ((msg->nTopRect % 4) != 0)
	{
		msg->nHeight += (msg->nTopRect % 4);
		msg->nTopRect -= (msg->nTopRect % 4);
	}

	if ((msg->nWidth * msg->nHeight) > (MaxRegionWidth * MaxRegionHeight))
	{
		RDS_MSG_PAINT_RECT subMsg;

		rows = (msg->nWidth + (MaxRegionWidth - (msg->nWidth % MaxRegionWidth))) / MaxRegionWidth;
		cols = (msg->nHeight + (MaxRegionHeight - (msg->nHeight % MaxRegionHeight))) / MaxRegionHeight;

		//printf("Partitioning x: %d y: %d width: %d height: %d in %d partitions (%d rows, %d cols)\n",
		//		msg->nLeftRect, msg->nTopRect, msg->nWidth, msg->nHeight, rows * cols, rows, cols);

		for (i = 0; i < rows; i++)
		{
			for (j = 0; j < cols; j++)
			{
				CopyMemory(&subMsg, msg, sizeof(RDS_MSG_PAINT_RECT));

				subMsg.nLeftRect = msg->nLeftRect + (i * MaxRegionWidth);
				subMsg.nTopRect = msg->nTopRect + (j * MaxRegionHeight);

				subMsg.nWidth = (i < (rows - 1)) ? MaxRegionWidth : msg->nWidth - (i * MaxRegionWidth);
				subMsg.nHeight = (j < (cols - 1)) ? MaxRegionHeight : msg->nHeight - (j * MaxRegionHeight);

				//printf("\t[%d, %d]: x: %d y: %d width: %d height: %d\n",
				//		i, j, subMsg.nLeftRect, subMsg.nTopRect, subMsg.nWidth, subMsg.nHeight);

				if ((subMsg.nWidth * subMsg.nHeight) > 0)
					freerds_send_bitmap_update(connection, bpp, &subMsg);
			}
		}

		return 0;
	}

	tile = (BYTE*) malloc(64 * 64 * 4);
	fbImage = (pixman_image_t*) msg->framebuffer->image;

	rows = (msg->nWidth + (64 - (msg->nWidth % 64))) / 64;
	cols = (msg->nHeight + (64 - (msg->nHeight % 64))) / 64;

	k = 0;
	bitmapUpdate.count = bitmapUpdate.number = rows * cols;
	bitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * bitmapUpdate.number);
	bitmapUpdate.rectangles = bitmapData;

	if ((msg->nWidth % 4) != 0)
	{
		msg->nLeftRect -= (msg->nWidth % 4);
		msg->nWidth += (msg->nWidth % 4);
	}

	if ((msg->nHeight % 4) != 0)
	{
		msg->nTopRect -= (msg->nHeight % 4);
		msg->nHeight += (msg->nHeight % 4);
	}

	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			nWidth = (i < (rows - 1)) ? 64 : msg->nWidth - (i * 64);
			nHeight = (j < (cols - 1)) ? 64 : msg->nHeight - (j * 64);

			bitmapData[k].bitsPerPixel = 16;
			bitmapData[k].width = nWidth;
			bitmapData[k].height = nHeight;
			bitmapData[k].destLeft = msg->nLeftRect + (i * 64);
			bitmapData[k].destTop = msg->nTopRect + (j * 64);
			bitmapData[k].destRight = bitmapData[k].destLeft + nWidth - 1;
			bitmapData[k].destBottom = bitmapData[k].destTop + nHeight - 1;
			bitmapData[k].compressed = TRUE;

			if (((nWidth * nHeight) > 0) && (nWidth >= 4) && (nHeight >= 4))
			{
				e = nWidth % 4;

				if (e != 0)
					e = 4 - e;

				//printf("k: %d destLeft: %d destTop: %d destRight: %d destBottom: %d nWidth: %d nHeight: %d\n",
				//		k, bitmapData[k].destLeft, bitmapData[k].destTop,
				//		bitmapData[k].destRight, bitmapData[k].destBottom, nWidth, nHeight);

				s = connection->encoder->bs;
				ts = connection->encoder->bts;

				Stream_SetPosition(s, 0);
				Stream_SetPosition(ts, 0);

				data = msg->framebuffer->fbSharedMemory;
				data = &data[(bitmapData[k].destTop * msg->framebuffer->fbScanline) +
				             (bitmapData[k].destLeft * msg->framebuffer->fbBytesPerPixel)];

				scanline = msg->framebuffer->fbScanline;

				if (bpp > 16)
				{
					int dstSize;
					UINT32 format;

					format = FREERDP_PIXEL_FORMAT(msg->framebuffer->fbBitsPerPixel,
							FREERDP_PIXEL_FORMAT_TYPE_ARGB, FREERDP_PIXEL_FLIP_NONE);

					buffer = connection->encoder->grid[k];

					buffer = freerdp_bitmap_compress_planar(connection->encoder->planar_context,
							data, format, nWidth, nHeight, scanline, buffer, &dstSize);

					bitmapData[k].bitmapDataStream = buffer;
					bitmapData[k].bitmapLength = dstSize;

					bitmapData[k].bitsPerPixel = 32;
					bitmapData[k].cbScanWidth = nWidth * 4;
					bitmapData[k].cbUncompressedSize = nWidth * nHeight * 4;
				}
				else
				{
					image = pixman_image_create_bits(PIXMAN_r5g6b5, nWidth, nHeight, (uint32_t*) tile, nWidth * 2);

					pixman_image_composite(PIXMAN_OP_OVER, fbImage, NULL, image,
							bitmapData[k].destLeft, bitmapData[k].destTop, 0, 0, 0, 0, nWidth, nHeight);

					lines = freerdp_bitmap_compress((char*) pixman_image_get_data(image),
							nWidth, nHeight, s, 16, 16384, nHeight - 1, ts, e);
					Stream_SealLength(s);

					bitmapData[k].bitmapDataStream = Stream_Buffer(s);
					bitmapData[k].bitmapLength = Stream_Length(s);

					buffer = connection->encoder->grid[k];
					CopyMemory(buffer, bitmapData[k].bitmapDataStream, bitmapData[k].bitmapLength);
					bitmapData[k].bitmapDataStream = buffer;

					bitmapData[k].bitsPerPixel = 16;
					bitmapData[k].cbScanWidth = nWidth * 2;
					bitmapData[k].cbUncompressedSize = nWidth * nHeight * 2;

					pixman_image_unref(image);
				}

				bitmapData[k].cbCompFirstRowSize = 0;
				bitmapData[k].cbCompMainBodySize = bitmapData[k].bitmapLength;

				k++;
			}
		}
	}

	bitmapUpdate.count = bitmapUpdate.number = k;

	IFCALL(update->BitmapUpdate, (rdpContext*) connection, &bitmapUpdate);

	free(bitmapData);
	free(tile);

	return 0;
}