简介
本主题介绍如何在单独的线程中渲染图纸以提高性能。
ODA BimRv SDK 提供了一个简单的 API,用于为 OdBmMTDrawContext、OdBmMTDraw 和 OdBmMTDrawingMgr 类调用多线程功能。
OdBmMTDraw 类通过指定的上下文为单个 OdBmDBDrawing 元素提供线程安全的渲染功能。
OdBmMTDrawingMgr 类通过指定的上下文为 OdBmDBDrawing 元素数组提供线程安全的渲染功能。它只是启动多个 OdBmMTDraw 实例,以在单独的并发线程中渲染绘图数组。
您还需要 OdBmMTDrawContext 或其派生类的一个实例。请参阅下面的类型定义和构造函数:
typedef std::function<OdGsDevicePtr(const OdBmMTDrawContext*)> OdBmCreateGsDeviceFuncType;
typedef std::function<void(OdBmObjectId, OdGsDevice*, const OdBmMTDrawContext*)> OdBmPostProcessFuncType;
OdBmMTDrawContext(
OdMutex* pDbAccessMutex,
long picWidth,
long picHeight,
bool bZoomToExtents,
const OdBmCreateGsDeviceFuncType& deviceCreator,
const OdBmPostProcessFuncType& postProcessor)
最后两个参数是对需要实现的函数的引用。
第一个函数应满足 OdBmCreateGsDeviceFuncType 原型,创建适当的 GS 设备,并返回指向它的指针。
第二个函数应满足 OdBmPostProcessFuncType 原型,并执行渲染结果的后处理。
示例
以下示例通过 GLES2 设备渲染 DBDrawings 并将结果存储在位图数组中。您可以在 BmMTDrawingMgrEx 示例中找到以下代码。
首先,创建 OdBmMTDrawContext 类的派生类。
struct OdBmGLES2MTDrawContext : public OdBmMTDrawContext {
OdBmGLES2MTDrawContext(
OdMutex* dbAccessMutex,
long picWidth,
long picHeight,
bool bZoomToExtents,
const OdBmCreateGsDeviceFuncType& createGsDeviceFunc,
const OdBmPostProcessFuncType& postProcessFunc,
// discard back faces wile rendering
bool bDiscardBackFaces,
// use plot generation
bool bPlotGeneration,
// background color of result images
ODCOLORREF bgColor = ODRGB(255, 255, 255)):
OdBmMTDrawContext(
dbAccessMutex, picWidth,
picHeight, bZoomToExtents,
createGsDeviceFunc, postProcessFunc),
discardBackFaces(bDiscardBackFaces),
plotGeneration(bPlotGeneration),
bgColor(bgColor) {
}
bool discardBackFaces;
ODCOLORREF bgColor;
bool plotGeneration;
};
接下来,定义一个覆盖类,例如:
class OdBmMTRenderer {
public:
// type defenition for rendering results
typedef std::map Renditions;
/* execution params
param drawings - an array of drawings to be rendered.
param picWidth - width of result bitmaps in pixels.
param picHeight - height of result bitmaps in pixels.
param bZoomToExtents - use zoom to extents.
param bDiscardBackFaces - discard back faces while rendering.
param bgColor - result bitmaps background color.
*/
Renditions run(OdBmDBDrawingPtrArray& drawings,
long picWidth, long picHeight, bool bZoomToExtents = false,
bool bDiscardBackFaces = false, ODCOLORREF bgColor = ODRGB(255, 255, 255));
};
现在,实现它。首先,获取所有必需的包含文件:
#include "BmMTRenderer.h"
#include "DynamicLinker.h"
#include "RxVariantValue.h"
#include "Gi/GiRasterWrappers.h"
#include "Database/MTDrawingMgr/BmMTDrawingMgr.h"
#include "MTDrawingMgr/BmMTDraw.h"
#include "BmGLES2MTDrawContext.h"
接下来,实现 run() 函数。这是一个专门的过程,因此第一步是创建 OdBmCreateGsDeviceFuncType 类型的函数。
/******************************************************************/
/* GS device creation function */
/******************************************************************/
OdMutex m_createDevice;
auto createDevice = [&m_createDevice](const OdBmMTDrawContext* pContext) {
TD_AUTOLOCK(m_createDevice);
const OdBmGLES2MTDrawContext* pToImgContext =
static_cast(pContext);
OdGsModulePtr pGsModule = ::odrxDynamicLinker()->loadModule(OdWinGLES2ModuleName);
OdGsDevicePtr pGsDevice = pGsModule->createBitmapDevice();
// Enable HLR for Bitmap and WinGDI vectorizers
OdRxDictionaryPtr pProps = pGsDevice->properties();
if (pProps->has(OD_T("EnableSoftwareHLR"))) // Check if property is supported
pProps->putAt(OD_T("EnableSoftwareHLR"), OdRxVariantValue(true));
if (pProps->has(OD_T("DiscardBackFaces"))) // Check if property is supported
pProps->putAt(OD_T("DiscardBackFaces"), OdRxVariantValue(pToImgContext->discardBackFaces()));
OdRxThreadPoolServicePtr pThreadPool = ::odrxDynamicLinker()->loadApp(OdThreadPoolModuleName);
if (pThreadPool.isNull())
throw(L"ThreadPool.tx not found.\n");
OdUInt16 nCPUs = pThreadPool->numCPUs();
if (pGsDevice->properties()->has(OD_T("MaxRegenThreads")))
pGsDevice->properties()->putAt(OD_T("MaxRegenThreads"), OdRxVariantValue(nCPUs));
if (pGsDevice->properties()->has(OD_T("EnableMultithread")))
pGsDevice->properties()->putAt(OD_T("EnableMultithread"), OdRxVariantValue(true));
pGsDevice->setLogicalPalette(
(ODGETRED(pToImgContext->bgColor()) < 140) && (ODGETGREEN(pToImgContext->bgColor()) < 140) && (ODGETBLUE(pToImgContext->bgColor()) < 140) ?
(::odcmAcadDarkPalette()) : (::odcmAcadLightPalette()), 256);
pGsDevice->setBackgroundColor(pToImgContext->bgColor());
return pGsDevice;
};
接下来,创建 OdBmPostProcessFuncType 类型的函数。
/******************************************************************/
/* Rendering results processing function */
/******************************************************************/
OdMutex m_mutex;
Renditions renditions;
auto postPrecess = [&m_mutex, &renditions](OdBmObjectId id, OdGsDevice* pDevice, const OdBmMTDrawContext* pContext) {
TD_AUTOLOCK(m_mutex);
// Create clone of rendered raster image to correctly release all vectorizer resources in current thread
OdGiRasterImagePtr pRaster = OdGiRasterImageHolder::createObject(
OdGiRasterImagePtr(pDevice->properties().get()->getAt(OD_T("RasterImage"))));
renditions[id] = pRaster;
};
最后,创建 OdBmMTDrawContext 的实例:
/******************************************************************/
/* Instantiate the context and start MT rendering */
/******************************************************************/
OdBmGLES2MTDrawContext m_ctx(&m_mutex, picWidth, picHeight, bZoomToExtents,
(OdBmMTDrawContext::OdBmCreateGsDeviceFuncType)createDevice,
(OdBmMTDrawContext::OdBmPostProcessFuncType)postPrecess,
bDiscardBackFaces, bgColor);
OdBmMTDrawingMgr().draw(drawings, &m_ctx);
return renditions;
您可以在 BimRv/Examples/BmMTDrawingMgrEx/BmMTDrawingMgrEx.cpp 文件中找到 run() 方法的实现。