mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 734404 - Part 3: Add code to test plugin to support DXGI async drawing. r=roc
This commit is contained in:
parent
6ad63375bf
commit
5a13b4286b
@ -14,12 +14,23 @@ simply returns 0;
|
||||
|
||||
By default, the plugin fills its rectangle with gray, with a black border, and
|
||||
renders the user-agent string (obtained from NPN_UserAgent) centered in black.
|
||||
This rendering method is not supported for the async drawing models.
|
||||
|
||||
The test plugin supports the following parameters:
|
||||
|
||||
* drawmode="solid"
|
||||
The plugin will draw a solid color instead of the default rendering described
|
||||
above. The default solid color is completely transparent black (i.e., nothing).
|
||||
This should be specified when using one of the async models.
|
||||
|
||||
* asyncmodel="bitmap"
|
||||
The plugin will use the NPAPI Async Bitmap drawing model extension. On
|
||||
unsupported platforms this will fallback to non-async rendering.
|
||||
|
||||
* asyncmodel="dxgi"
|
||||
The plugin will use the NPAPI Async DXGI drawing model extension. Only
|
||||
supported on Windows Vista or higher. On unsupported platforms this will
|
||||
fallback to non-async rendering.
|
||||
|
||||
* color
|
||||
This specifies the color to use for drawmode="solid". The value should be 8 hex
|
||||
|
@ -824,6 +824,11 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
|
||||
instanceData->asyncDrawing = AD_BITMAP;
|
||||
}
|
||||
}
|
||||
if (strcmp(argv[i], "dxgi") == 0) {
|
||||
if (pluginSupportsAsyncDXGIDrawing()) {
|
||||
instanceData->asyncDrawing = AD_DXGI;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp(argn[i], "streammode") == 0) {
|
||||
if (strcmp(argv[i], "normal") == 0) {
|
||||
@ -936,6 +941,17 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
|
||||
instanceData->asyncDrawing = AD_NONE;
|
||||
}
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
else if (instanceData->asyncDrawing == AD_DXGI) {
|
||||
NPBool supportsAsyncDXGI = false;
|
||||
if ((NPN_GetValue(instance, NPNVsupportsAsyncWindowsDXGISurfaceBool, &supportsAsyncDXGI) == NPERR_NO_ERROR) &&
|
||||
supportsAsyncDXGI) {
|
||||
NPN_SetValue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelAsyncWindowsDXGISurface);
|
||||
} else {
|
||||
instanceData->asyncDrawing = AD_NONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
instanceData->lastReportedPrivateModeState = false;
|
||||
instanceData->lastMouseX = instanceData->lastMouseY = -1;
|
||||
@ -2737,6 +2753,11 @@ setColor(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* r
|
||||
} else if (id->asyncDrawing == AD_BITMAP) {
|
||||
drawAsyncBitmapColor(id);
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
else if (id->asyncDrawing == AD_DXGI) {
|
||||
pluginDrawAsyncDxgiColor(id);
|
||||
}
|
||||
#endif
|
||||
|
||||
VOID_TO_NPVARIANT(*result);
|
||||
return true;
|
||||
|
@ -63,7 +63,8 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
AD_NONE,
|
||||
AD_BITMAP
|
||||
AD_BITMAP,
|
||||
AD_DXGI
|
||||
} AsyncDrawing;
|
||||
|
||||
typedef enum {
|
||||
|
@ -53,6 +53,18 @@ bool pluginSupportsWindowlessMode();
|
||||
*/
|
||||
bool pluginSupportsAsyncBitmapDrawing();
|
||||
|
||||
/**
|
||||
* Returns true if the plugin supports DXGI bitmap drawing.
|
||||
*/
|
||||
static bool pluginSupportsAsyncDXGIDrawing()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the plugin instance. Returning an error here will cause the
|
||||
* plugin instantiation to fail.
|
||||
@ -81,6 +93,10 @@ void pluginWidgetInit(InstanceData* instanceData, void* oldWindow);
|
||||
*/
|
||||
int16_t pluginHandleEvent(InstanceData* instanceData, void* event);
|
||||
|
||||
#ifdef XP_WIN
|
||||
void pluginDrawAsyncDxgiColor(InstanceData* instanceData);
|
||||
#endif
|
||||
|
||||
enum RectEdge {
|
||||
EDGE_LEFT = 0,
|
||||
EDGE_TOP = 1,
|
||||
|
@ -38,6 +38,23 @@
|
||||
#include <windowsx.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <d3d10_1.h>
|
||||
|
||||
typedef HRESULT (WINAPI*D3D10CreateDevice1Func)(
|
||||
IDXGIAdapter *pAdapter,
|
||||
D3D10_DRIVER_TYPE DriverType,
|
||||
HMODULE Software,
|
||||
UINT Flags,
|
||||
D3D10_FEATURE_LEVEL1 HardwareLevel,
|
||||
UINT SDKVersion,
|
||||
ID3D10Device1 **ppDevice
|
||||
);
|
||||
|
||||
typedef HRESULT(WINAPI*CreateDXGIFactory1Func)(
|
||||
REFIID riid,
|
||||
void **ppFactory
|
||||
);
|
||||
|
||||
using namespace std;
|
||||
|
||||
void SetSubclass(HWND hWnd, InstanceData* instanceData);
|
||||
@ -46,6 +63,9 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||
|
||||
struct _PlatformData {
|
||||
HWND childWindow;
|
||||
ID3D10Device1 *device;
|
||||
ID3D10Texture2D *frontBuffer;
|
||||
ID3D10Texture2D *backBuffer;
|
||||
};
|
||||
|
||||
bool
|
||||
@ -77,21 +97,139 @@ pluginInstanceInit(InstanceData* instanceData)
|
||||
return NPERR_OUT_OF_MEMORY_ERROR;
|
||||
|
||||
instanceData->platformData->childWindow = NULL;
|
||||
instanceData->platformData->device = NULL;
|
||||
instanceData->platformData->frontBuffer = NULL;
|
||||
instanceData->platformData->backBuffer = NULL;
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
pluginInstanceShutdown(InstanceData* instanceData)
|
||||
{
|
||||
PlatformData *pd = instanceData->platformData;
|
||||
if (pd->frontBuffer) {
|
||||
pd->frontBuffer->Release();
|
||||
}
|
||||
if (pd->backBuffer) {
|
||||
pd->backBuffer->Release();
|
||||
}
|
||||
if (pd->device) {
|
||||
pd->device->Release();
|
||||
}
|
||||
NPN_MemFree(instanceData->platformData);
|
||||
instanceData->platformData = 0;
|
||||
}
|
||||
|
||||
static ID3D10Device1*
|
||||
getD3D10Device()
|
||||
{
|
||||
ID3D10Device1 *device;
|
||||
|
||||
HMODULE d3d10module = LoadLibraryA("d3d10_1.dll");
|
||||
D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
|
||||
GetProcAddress(d3d10module, "D3D10CreateDevice1");
|
||||
|
||||
if (createD3DDevice) {
|
||||
HMODULE dxgiModule = LoadLibraryA("dxgi.dll");
|
||||
CreateDXGIFactory1Func createDXGIFactory1 = (CreateDXGIFactory1Func)
|
||||
GetProcAddress(dxgiModule, "CreateDXGIFactory1");
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
// Try to use a DXGI 1.1 adapter in order to share resources
|
||||
// across processes.
|
||||
IDXGIAdapter1 *adapter1;
|
||||
if (createDXGIFactory1) {
|
||||
IDXGIFactory1 *factory1;
|
||||
hr = createDXGIFactory1(__uuidof(IDXGIFactory1),
|
||||
(void**)&factory1);
|
||||
|
||||
if (FAILED(hr) || !factory1) {
|
||||
// Uh-oh
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hr = factory1->EnumAdapters1(0, &adapter1);
|
||||
|
||||
if (SUCCEEDED(hr) && adapter1) {
|
||||
hr = adapter1->CheckInterfaceSupport(__uuidof(ID3D10Device),
|
||||
NULL);
|
||||
if (FAILED(hr)) {
|
||||
adapter1 = NULL;
|
||||
}
|
||||
}
|
||||
factory1->Release();
|
||||
}
|
||||
|
||||
hr = createD3DDevice(
|
||||
adapter1,
|
||||
D3D10_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
D3D10_CREATE_DEVICE_BGRA_SUPPORT |
|
||||
D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS,
|
||||
D3D10_FEATURE_LEVEL_10_0,
|
||||
D3D10_1_SDK_VERSION,
|
||||
&device);
|
||||
|
||||
adapter1->Release();
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void
|
||||
pluginDoSetWindow(InstanceData* instanceData, NPWindow* newWindow)
|
||||
{
|
||||
instanceData->window = *newWindow;
|
||||
NPP npp = instanceData->npp;
|
||||
|
||||
if (instanceData->asyncDrawing == AD_DXGI) {
|
||||
if (instanceData->frontBuffer &&
|
||||
instanceData->frontBuffer->size.width == newWindow->width &&
|
||||
instanceData->frontBuffer->size.height == newWindow->height) {
|
||||
return;
|
||||
}
|
||||
if (instanceData->frontBuffer) {
|
||||
instanceData->platformData->frontBuffer->Release();
|
||||
instanceData->platformData->frontBuffer = NULL;
|
||||
NPN_FinalizeAsyncSurface(npp, instanceData->frontBuffer);
|
||||
NPN_MemFree(instanceData->frontBuffer);
|
||||
}
|
||||
if (instanceData->backBuffer) {
|
||||
instanceData->platformData->backBuffer->Release();
|
||||
instanceData->platformData->backBuffer = NULL;
|
||||
NPN_FinalizeAsyncSurface(npp, instanceData->backBuffer);
|
||||
NPN_MemFree(instanceData->backBuffer);
|
||||
}
|
||||
|
||||
if (!instanceData->platformData->device) {
|
||||
instanceData->platformData->device = getD3D10Device();
|
||||
}
|
||||
|
||||
ID3D10Device1 *dev = instanceData->platformData->device;
|
||||
|
||||
if (!dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
instanceData->frontBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
|
||||
instanceData->backBuffer = (NPAsyncSurface*)NPN_MemAlloc(sizeof(NPAsyncSurface));
|
||||
|
||||
NPSize size;
|
||||
size.width = newWindow->width;
|
||||
size.height = newWindow->height;
|
||||
|
||||
memset(instanceData->frontBuffer, 0, sizeof(NPAsyncSurface));
|
||||
memset(instanceData->backBuffer, 0, sizeof(NPAsyncSurface));
|
||||
|
||||
NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, NULL, instanceData->frontBuffer);
|
||||
NPN_InitAsyncSurface(npp, &size, NPImageFormatBGRA32, NULL, instanceData->backBuffer);
|
||||
|
||||
dev->OpenSharedResource(instanceData->frontBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->frontBuffer);
|
||||
dev->OpenSharedResource(instanceData->backBuffer->sharedHandle, __uuidof(ID3D10Texture2D), (void**)&instanceData->platformData->backBuffer);
|
||||
|
||||
pluginDrawAsyncDxgiColor(instanceData);
|
||||
}
|
||||
}
|
||||
|
||||
#define CHILD_WIDGET_SIZE 10
|
||||
@ -575,3 +713,45 @@ void pluginDoInternalConsistencyCheck(InstanceData* instanceData, string& error)
|
||||
checkEquals(childRect.bottom, childRect.top + CHILD_WIDGET_SIZE, "Child widget height", error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pluginDrawAsyncDxgiColor(InstanceData* id)
|
||||
{
|
||||
PlatformData *pd = id->platformData;
|
||||
|
||||
ID3D10Device1 *dev = pd->device;
|
||||
|
||||
IDXGIKeyedMutex *mutex;
|
||||
pd->backBuffer->QueryInterface(&mutex);
|
||||
|
||||
mutex->AcquireSync(0, INFINITE);
|
||||
ID3D10RenderTargetView *rtView;
|
||||
dev->CreateRenderTargetView(pd->backBuffer, NULL, &rtView);
|
||||
|
||||
PRUint32 rgba = id->scriptableObject->drawColor;
|
||||
|
||||
unsigned char subpixels[4];
|
||||
subpixels[0] = rgba & 0xFF;
|
||||
subpixels[1] = (rgba & 0xFF00) >> 8;
|
||||
subpixels[2] = (rgba & 0xFF0000) >> 16;
|
||||
subpixels[3] = (rgba & 0xFF000000) >> 24;
|
||||
|
||||
float color[4];
|
||||
color[2] = float(subpixels[3] * subpixels[0]) / 0xFE01;
|
||||
color[1] = float(subpixels[3] * subpixels[1]) / 0xFE01;
|
||||
color[0] = float(subpixels[3] * subpixels[2]) / 0xFE01;
|
||||
color[3] = float(subpixels[3]) / 0xFF;
|
||||
dev->ClearRenderTargetView(rtView, color);
|
||||
rtView->Release();
|
||||
|
||||
mutex->ReleaseSync(0);
|
||||
mutex->Release();
|
||||
|
||||
NPN_SetCurrentAsyncSurface(id->npp, id->backBuffer, NULL);
|
||||
NPAsyncSurface *oldFront = id->frontBuffer;
|
||||
id->frontBuffer = id->backBuffer;
|
||||
id->backBuffer = oldFront;
|
||||
ID3D10Texture2D *oldFrontT = pd->frontBuffer;
|
||||
pd->frontBuffer = pd->backBuffer;
|
||||
pd->backBuffer = oldFrontT;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user