コード例 #1
0
ファイル: polyxml.cpp プロジェクト: kevinzhwl/ObjectARXMod
AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
{
    switch(msg) {
    case AcRx::kInitAppMsg:
        acrxUnlockApplication(pkt);        // Try to allow unloading
        acrxRegisterAppMDIAware(pkt);

        if (acrxServiceIsRegistered("AsdkPoly") 
            && AsdkPoly::desc() != NULL
            && AcDbXmlObjectProtocol::desc() != NULL) {
            // add XML I/O protocol extension to AsdkPoly
            //
            gpPolyXmlExtension = new AcDbXmlPoly(AsdkPoly::desc());
            AsdkPoly::desc()->addX(AcDbXmlObjectProtocol::desc(), gpPolyXmlExtension);

            acrxBuildClassHierarchy();
            updateRegistry();
        }
        break;

    case AcRx::kUnloadAppMsg:
        if (acrxServiceIsRegistered("AsdkPoly") 
            && AsdkPoly::desc() != NULL
            && AcDbXmlObjectProtocol::desc() != NULL) {
            AsdkPoly::desc()->delX(AcDbXmlObjectProtocol::desc());
        }
        if (gpPolyXmlExtension)
            delete gpPolyXmlExtension;
        break;
    }
    return AcRx::kRetOK;
}
コード例 #2
0
void locateVJoyInstallDllAndInstall()
{
    for(int i=0; dll_locations[i]; ++i)
    {
        std::string dll_path = std::string(dll_locations[i]) + "vJoyInstall.dll";
        HMODULE vjoy_inst = LoadLibrary(dll_path.c_str());
        if(vjoy_inst)
        {
            std::unique_ptr<HMODULE, void(*)(HMODULE*)> guard_vjoy_inst(&vjoy_inst, [](HMODULE* p) { FreeLibrary(*p); });
            auto refresh_vjoy = reinterpret_cast<refresh_vjoy_T>(GetProcAddress(vjoy_inst, "refresh_vjoy"));
            auto is_vjoy_installed =
                reinterpret_cast<is_vjoy_installed_T>(GetProcAddress(vjoy_inst, "is_vjoy_installed"));
            if(refresh_vjoy && is_vjoy_installed)
            {
                if(is_vjoy_installed())
                {
                    LOG("Successfully loaded vJoyInstall from " << dll_path.c_str());
                    updateRegistry();
                    LOG("Reloading VJoy driver.");
                    refresh_vjoy();
                    LOG("Installation complete.");
                    return;
                }
            }
        }
    }
    LOG("Unable to locate vJoyInstall");
}
コード例 #3
0
ファイル: Main.cpp プロジェクト: kevinzhwl/ObjectARXMod
extern "C" AcRx::AppRetCode acrxEntryPoint( AcRx::AppMsgCode msg, void* pkt)
{
	switch( msg )
	{
		case AcRx::kInitAppMsg:
			if (!acrxLoadModule("curveText.dbx", false))
					return AcRx::kRetError;
			acrxDynamicLinker->unlockApplication(pkt);
			acrxRegisterAppMDIAware(pkt);
			initApp();
			updateRegistry();
			pCurvetextContextMenu = new curvetextContextMenu;
			pCurveContextMenu = new curveContextMenu;
			acedAddObjectContextMenu(AcDbCurve::desc(), pCurveContextMenu, pkt);
			acedAddObjectContextMenu(AdcgCurveText::desc(), pCurvetextContextMenu, pkt);
		break;
		case AcRx::kUnloadAppMsg:
			unloadApp(); 
			acedRemoveObjectContextMenu(AcDbCurve::desc(), pCurveContextMenu);
			acedRemoveObjectContextMenu(AdcgCurveText::desc(), pCurvetextContextMenu);
			acrxUnloadModule("curveText.dbx");
			delete pCurveContextMenu;
			delete pCurvetextContextMenu;
		break;
		default:
		break;
	}
	return AcRx::kRetOK;
}
コード例 #4
0
ファイル: updater.cpp プロジェクト: 600rr/tdesktop
int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParamarg, int cmdShow) {
	openLog();

#ifdef _NEED_WIN_GENERATE_DUMP
	_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
#endif

	writeLog(L"Updaters started..");

	LPWSTR *args;
	int argsCount;

	bool needupdate = false, autostart = false, debug = false;
	args = CommandLineToArgvW(GetCommandLine(), &argsCount);
	if (args) {
		for (int i = 1; i < argsCount; ++i) {
			if (equal(args[i], L"-update")) {
				needupdate = true;
			} else if (equal(args[i], L"-autostart")) {
				autostart = true;
			} else if (equal(args[i], L"-debug")) {
				debug = _debug = true;
				openLog();
			}
		}
		if (needupdate) writeLog(L"Need to update!");
		if (autostart) writeLog(L"From autostart!");

		exeName = args[0];
		writeLog(L"Exe name is: " + exeName);
		if (exeName.size() > 11) {
			if (equal(exeName.substr(exeName.size() - 11), L"Updater.exe")) {
				exeDir = exeName.substr(0, exeName.size() - 11);
				writeLog(L"Exe dir is: " + exeDir);
				if (needupdate && update()) {
					updateRegistry();
				}
			} else {
				writeLog(L"Error: bad exe name!");
			}
		} else {
			writeLog(L"Error: short exe name!");
		}
		LocalFree(args);
	} else {
		writeLog(L"Error: No command line arguments!");
	}

	wstring targs = L"-noupdate";
	if (autostart) targs += L" -autostart";
	if (debug) targs += L" -debug";

	ShellExecute(0, 0, (exeDir + L"Telegram.exe").c_str(), targs.c_str(), 0, SW_SHOWNORMAL);

	writeLog(L"Executed Telegram.exe, closing log and quiting..");
	closeLog();

	return 0;
}
コード例 #5
0
void NewstuffModelPrivate::unzip()
{
    MarbleZipReader zipReader(m_currentFile->fileName());
    QStringList files;
    for(const MarbleZipReader::FileInfo &fileInfo: zipReader.fileInfoList()) {
        files << fileInfo.filePath;
    }
    updateRegistry(files);
    zipReader.extractAll(m_targetDirectory);
    m_parent->mapInstalled(0);
}
コード例 #6
0
ファイル: cmdcount.cpp プロジェクト: kevinzhwl/ObjectARXMod
/* =================== Arx Interface Functions ================ */
extern "C" AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode msg, void* pAppId) {
    switch(msg) {
        case AcRx::kInitAppMsg:
            // Tell system that we are MDI-aware.
            acrxDynamicLinker->registerAppMDIAware(pAppId);
            initStats();
            updateRegistry();
            break;
        case AcRx::kUnloadAppMsg:
            termStats();
        default:
        break;
    }
    return AcRx::kRetOK;
}
コード例 #7
0
void
OpenSubdivPtexShader::draw(const MHWRender::MDrawContext &mDrawContext,
                           OsdPtexMeshData *data)
{
    MStatus status;

    glPushAttrib(GL_POLYGON_BIT|GL_ENABLE_BIT);

    // in ptexviewer, cull back face even in wireframe mode (for performance)
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    if (_wireframe) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    } else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

    CHECK_GL_ERROR("draw begin\n");

    // If shader source attribute has changed, update effectRegistry
    updateRegistry();

    GLuint bPosition = data->bindPositionVBO();
    GLuint bNormal = data->bindNormalVBO();
    OpenSubdiv::OsdGLDrawContext *osdDrawContext = data->getDrawContext();

    glBindBuffer(GL_ARRAY_BUFFER, bPosition);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
    glEnableVertexAttribArray(0);

    if (not _adaptive) {
        glBindBuffer(GL_ARRAY_BUFFER, bNormal);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
        glEnableVertexAttribArray(1);
    }

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, osdDrawContext->patchIndexBuffer);

    OpenSubdiv::OsdPatchArrayVector const & patches =
        osdDrawContext->patchArrays;

    for (size_t i = 0; i < patches.size(); ++i) {
        OpenSubdiv::OsdPatchArray const & patch = patches[i];

        GLint surfaceProgram = bindProgram(mDrawContext, osdDrawContext, patch);

        if (patch.desc.type != OpenSubdiv::kNonPatch) {
            glPatchParameteri(GL_PATCH_VERTICES, patch.desc.GetPatchSize());

            if (osdDrawContext->GetVertexTextureBuffer()) {
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_BUFFER,
                              osdDrawContext->GetVertexTextureBuffer());
                glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, bPosition);
            }
            if (osdDrawContext->GetVertexValenceTextureBuffer()) {
                glActiveTexture(GL_TEXTURE1);
                glBindTexture(GL_TEXTURE_BUFFER,
                              osdDrawContext->GetVertexValenceTextureBuffer());
            }
            if (osdDrawContext->GetQuadOffsetsTextureBuffer()) {
                glActiveTexture(GL_TEXTURE2);
                glBindTexture(GL_TEXTURE_BUFFER,
                              osdDrawContext->GetQuadOffsetsTextureBuffer());
            }
            if (osdDrawContext->GetPatchParamTextureBuffer()) {
                glActiveTexture(GL_TEXTURE3);
                glBindTexture(GL_TEXTURE_BUFFER,
                              osdDrawContext->GetPatchParamTextureBuffer());
            }
            glActiveTexture(GL_TEXTURE0);

            glDrawElements(GL_PATCHES,
                           patch.numIndices, GL_UNSIGNED_INT,
                           reinterpret_cast<void *>(patch.firstIndex *
                                                    sizeof(unsigned int)));
        } else {
            GLint nonAdaptiveLevel = glGetUniformLocation(surfaceProgram,
                                     "nonAdaptiveLevel");
            if (nonAdaptiveLevel != -1) {
                glProgramUniform1i(surfaceProgram, nonAdaptiveLevel, _level);
            }

            glDrawElements(_scheme == OsdPtexMeshData::kLoop ? GL_TRIANGLES : GL_LINES_ADJACENCY,
                           patch.numIndices, GL_UNSIGNED_INT,
                           reinterpret_cast<void *>(patch.firstIndex *
                                                    sizeof(unsigned int)));
        }
        CHECK_GL_ERROR("post draw\n");
    }

    glUseProgram(0);

    glDisableVertexAttribArray(0);
    if (not _adaptive)
        glDisableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glPopAttrib();

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    CHECK_GL_ERROR("draw end\n");
}
コード例 #8
0
// #### Main draw method
//
//      Called by OpenSubdivShaderOverride for each renderItem.
//      Binds the vertex buffer and calls glDrawElements for 
//      each patch.
//
void
OpenSubdivShader::draw(const MHWRender::MDrawContext &mDrawContext,
                             OsdMeshData *data)
{
    glPushAttrib(GL_POLYGON_BIT|GL_ENABLE_BIT);

    if (_wireframe) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    } else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

    CHECK_GL_ERROR("draw begin\n");

    // If shader source attribute has changed, update effectRegistry
    updateRegistry();

    // Bind position vertex buffer
    GLuint bPosition = data->bindPositionVBO();
    OpenSubdiv::OsdGLDrawContext *osdDrawContext = data->getDrawContext();

    glBindBuffer(GL_ARRAY_BUFFER, bPosition);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, osdDrawContext->GetPatchIndexBuffer());

    // Get list of patches from OSD
    OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches =
        osdDrawContext->patchArrays;

    // Draw patches
    for (size_t i = 0; i < patches.size(); ++i) {
        OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];

        GLuint program = bindProgram(mDrawContext, osdDrawContext, patch);

        GLuint uniformGregoryQuadOffsetBase =
            glGetUniformLocation(program, "OsdGregoryQuadOffsetBase");
        GLuint uniformPrimitiveIdBase =
            glGetUniformLocation(program, "OsdPrimitiveIdBase");
        glProgramUniform1i(program, uniformGregoryQuadOffsetBase,
                           patch.GetQuadOffsetIndex());
        glProgramUniform1i(program, uniformPrimitiveIdBase,
                           patch.GetPatchIndex());

        GLenum primType = GL_PATCHES;
        if (patch.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::QUADS) {
            primType = GL_LINES_ADJACENCY;
        } else if (patch.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::TRIANGLES) {
            primType = GL_TRIANGLES;
        } else if (patch.GetDescriptor().GetType() >= OpenSubdiv::FarPatchTables::REGULAR) {
            glPatchParameteri(GL_PATCH_VERTICES, patch.GetDescriptor().GetNumControlVertices());
        }
        glDrawElements(primType,
                       patch.GetNumIndices(), GL_UNSIGNED_INT,
                       reinterpret_cast<void *>(patch.GetVertIndex() *
                                                sizeof(unsigned int)));

        CHECK_GL_ERROR("post draw\n");
    }

    // Clear state
    glUseProgram(0);
    glDisableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glPopAttrib();

    CHECK_GL_ERROR("draw end\n");
}
コード例 #9
0
ファイル: main.cpp プロジェクト: kevinzhwl/ObjectARXMod
AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
{
    static AppEventCatcher* appEventCatcher = NULL;
    static void *moduleHandle;
    static HINSTANCE hDllAuto = NULL;

    switch(msg) {

    case AcRx::kInitAppMsg:

        if (!acrxLoadModule("asdkpolyobj.dbx", 0))
            return AcRx::kRetError;

        acrxUnlockApplication(pkt);		// Try to allow unloading
        acrxDynamicLinker->registerAppMDIAware(pkt);
        moduleHandle = pkt;
        // If match app server isn't present, then create and attach
        // a dynamic linker reactor to watch to see if ever loads up
        //
        if (!acrxClassDictionary->at("MatchProperties")) {
            appEventCatcher = new AppEventCatcher();
            acrxDynamicLinker->addReactor(appEventCatcher);
        }

        initModule();
        updateRegistry();

        if (!hDllAuto)
            hDllAuto = LoadLibrary("OemPolyApp.dll");
        if (hDllAuto)
        {
            HRESULT (*f)() = (HRESULT (*)()) GetProcAddress(hDllAuto, "initAutomation");
            if (f) f();
        }
        break;

    case AcRx::kUnloadAppMsg:

        if (appEventCatcher != NULL) {
            acrxDynamicLinker->removeReactor(appEventCatcher);
            delete appEventCatcher;
        }

        acedRegCmds->removeGroup("ASDK_POLYGON");
        CleanUpUserInterfaceForPolySamp();

        // If we are unloading because AutoCAD is shutting down,
        // then it's possible that the match.arx application is
        // already gone,  so we need to check to see if it's still
        // there.  If it's not,  then we can't remove the protocol
        // extension nor decrement the dependency counter.
        //
        AcRxObject* pTemp;
        if (pTemp = acrxServiceDictionary->at("MatchProperties"))
        {
            // remove the protocol extension.
            AsdkPoly::desc()->delX(AsdkPolyMatchProp::desc());
            delete pMatchPoly;

            AcRxService *pSvc = AcRxService::cast(pTemp);

            if (pSvc != NULL)
                pSvc->removeDependency();
        }

        //try to unload the object definition
        acrxUnloadModule("asdkpolyobj.dbx");

        if (hDllAuto)
        {
            HRESULT (*f)() = (HRESULT (*)()) GetProcAddress(hDllAuto, "exitAutomation");
            if (f) f();
        }
        break;
    }
    return AcRx::kRetOK;
}
コード例 #10
0
ファイル: updater.cpp プロジェクト: MonstreX/tdesktop
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) {
	openLog();

	_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
//	CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter);

	writeLog(L"Updaters started..");

	LPWSTR *args;
	int argsCount;

	bool needupdate = false, autostart = false, debug = false, writeprotected = false, startintray = false, testmode = false;
	args = CommandLineToArgvW(GetCommandLine(), &argsCount);
	if (args) {
		for (int i = 1; i < argsCount; ++i) {
			if (equal(args[i], L"-update")) {
				needupdate = true;
			} else if (equal(args[i], L"-autostart")) {
				autostart = true;
			} else if (equal(args[i], L"-debug")) {
				debug = _debug = true;
				openLog();
			} else if (equal(args[i], L"-startintray")) {
				startintray = true;
			} else if (equal(args[i], L"-testmode")) {
				testmode = true;
			} else if (equal(args[i], L"-writeprotected") && ++i < argsCount) {
				writeprotected = true;
				updateTo = args[i];
				for (int i = 0, l = updateTo.size(); i < l; ++i) {
					if (updateTo[i] == L'/') {
						updateTo[i] = L'\\';
					}
				}
			}
		}
		if (needupdate) writeLog(L"Need to update!");
		if (autostart) writeLog(L"From autostart!");
		if (writeprotected) writeLog(L"Write Protected folder!");

		exeName = args[0];
		writeLog(L"Exe name is: " + exeName);
		if (exeName.size() > 11) {
			if (equal(exeName.substr(exeName.size() - 11), L"Updater.exe")) {
				exeDir = exeName.substr(0, exeName.size() - 11);
				writeLog(L"Exe dir is: " + exeDir);
				if (!writeprotected) {
					updateTo = exeDir;
				}
				writeLog(L"Update to: " + updateTo);
				if (needupdate && update()) {
					updateRegistry();
				}
				if (writeprotected) { // if we can't clear all tupdates\ready (Updater.exe is there) - clear only version
					if (DeleteFile(L"tupdates\\temp\\tdata\\version") || DeleteFile(L"tupdates\\ready\\tdata\\version")) {
						writeLog(L"Version file deleted!");
					} else {
						writeLog(L"Error: could not delete version file");
					}
				}
			} else {
				writeLog(L"Error: bad exe name!");
			}
		} else {
			writeLog(L"Error: short exe name!");
		}
		LocalFree(args);
	} else {
		writeLog(L"Error: No command line arguments!");
	}

	wstring targs;
	if (autostart) targs += L" -autostart";
	if (debug) targs += L" -debug";
	if (startintray) targs += L" -startintray";
	if (testmode) targs += L" -testmode";

	bool executed = false;
	if (writeprotected) { // run un-elevated
		writeLog(L"Trying to run un-elevated by temp.lnk");

		HRESULT hres = CoInitialize(0);
		if (SUCCEEDED(hres)) {
			IShellLink* psl;
			HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
			if (SUCCEEDED(hres)) {
				IPersistFile* ppf;

				wstring exe = updateTo + L"Telegram.exe", dir = updateTo;
				psl->SetArguments((targs.size() ? targs.substr(1) : targs).c_str());
				psl->SetPath(exe.c_str());
				psl->SetWorkingDirectory(dir.c_str());
				psl->SetDescription(L"");

				hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);

				if (SUCCEEDED(hres)) {
					wstring lnk = L"tupdates\\temp\\temp.lnk";
					hres = ppf->Save(lnk.c_str(), TRUE);
					if (!SUCCEEDED(hres)) {
						lnk = L"tupdates\\ready\\temp.lnk"; // old
						hres = ppf->Save(lnk.c_str(), TRUE);
					}
					ppf->Release();

					if (SUCCEEDED(hres)) {
						writeLog(L"Executing un-elevated through link..");
						ShellExecute(0, 0, L"explorer.exe", lnk.c_str(), 0, SW_SHOWNORMAL);
						executed = true;
					} else {
						writeLog(L"Error: ppf->Save failed");
					}
				} else {
					writeLog(L"Error: Could not create interface IID_IPersistFile");
				}
				psl->Release();
			} else {
				writeLog(L"Error: could not create instance of IID_IShellLink");
			}
			CoUninitialize();
		} else {
			writeLog(L"Error: Could not initialize COM");
		}
	}
	if (!executed) {
		ShellExecute(0, 0, (updateTo + L"Telegram.exe").c_str(), (L"-noupdate" + targs).c_str(), 0, SW_SHOWNORMAL);
	}

	writeLog(L"Executed Telegram.exe, closing log and quiting..");
	closeLog();

	return 0;
}
コード例 #11
0
// #### Main draw method
//
//      Called by OpenSubdivShaderOverride for each renderItem.
//      Binds the vertex buffer and calls glDrawElements for 
//      each patch.
//
void
OpenSubdivShader::draw(const MHWRender::MDrawContext &mDrawContext,
                             OsdMeshData *data)
{
    glPushAttrib(GL_POLYGON_BIT|GL_ENABLE_BIT);

    if (_wireframe) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    } else {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

    CHECK_GL_ERROR("draw begin\n");

    // If shader source attribute has changed, update effectRegistry
    updateRegistry();

    // Bind position vertex buffer
    GLuint bPosition = data->bindPositionVBO();
    OpenSubdiv::OsdGLDrawContext *osdDrawContext = data->getDrawContext();

    glBindBuffer(GL_ARRAY_BUFFER, bPosition);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, osdDrawContext->patchIndexBuffer);

    // Get list of patches from OSD
    OpenSubdiv::OsdPatchArrayVector const & patches =
        osdDrawContext->patchArrays;

    // Draw patches
    for (size_t i = 0; i < patches.size(); ++i) {
        OpenSubdiv::OsdPatchArray const & patch = patches[i];

        bindProgram(mDrawContext, osdDrawContext, patch);

        if (patch.desc.type != OpenSubdiv::kNonPatch) {
            glPatchParameteri(GL_PATCH_VERTICES, patch.desc.GetPatchSize());

            glDrawElements(GL_PATCHES,
                           patch.numIndices, GL_UNSIGNED_INT,
                           reinterpret_cast<void *>(patch.firstIndex *
                                                    sizeof(unsigned int)));
        } else {
            glDrawElements(_scheme == OsdMeshData::kLoop ? GL_TRIANGLES : GL_LINES_ADJACENCY,
                           patch.numIndices, GL_UNSIGNED_INT,
                           reinterpret_cast<void *>(patch.firstIndex *
                                                    sizeof(unsigned int)));
        }
        CHECK_GL_ERROR("post draw\n");
    }

    // Clear state
    glUseProgram(0);
    glDisableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glPopAttrib();

    CHECK_GL_ERROR("draw end\n");
}