123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225 |
- // Copyright (C) 2013 Patryk Nadrowski
- // Heavily based on the OpenGL driver implemented by Nikolaus Gebhardt
- // OpenGL ES driver implemented by Christian Stehno and first OpenGL ES 2.0
- // driver implemented by Amundis.
- // This file is part of the "Irrlicht Engine".
- // For conditions of distribution and use, see copyright notice in Irrlicht.h
- #include "COGLES2Driver.h"
- // needed here also because of the create methods' parameters
- #include "CNullDriver.h"
- #ifdef _IRR_COMPILE_WITH_OGLES2_
- #include "COGLES2Texture.h"
- #include "COGLES2MaterialRenderer.h"
- #include "COGLES2FixedPipelineRenderer.h"
- #include "COGLES2NormalMapRenderer.h"
- #include "COGLES2ParallaxMapRenderer.h"
- #include "COGLES2Renderer2D.h"
- #include "CImage.h"
- #include "os.h"
- #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
- #include <OpenGLES/ES2/gl.h>
- #include <OpenGLES/ES2/glext.h>
- #else
- #include <EGL/egl.h>
- #include <GLES2/gl2.h>
- #endif
- namespace irr
- {
- namespace video
- {
- bool useCoreContext = true;
- //! constructor and init code
- COGLES2Driver::COGLES2Driver(const SIrrlichtCreationParameters& params,
- const SExposedVideoData& data, io::IFileSystem* io
- #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
- , CIrrDeviceIPhone* device
- #endif
- )
- : CNullDriver(io, params.WindowSize), COGLES2ExtensionHandler(),
- BridgeCalls(0), CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
- Transformation3DChanged(true), AntiAlias(params.AntiAlias),
- RenderTargetTexture(0), CurrentRendertargetSize(0, 0), ColorFormat(ECF_R8G8B8)
- #ifdef EGL_VERSION_1_0
- , EglDisplay(EGL_NO_DISPLAY)
- #endif
- #if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
- , HDc(0)
- #elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
- , ViewFramebuffer(0)
- , ViewRenderbuffer(0)
- , ViewDepthRenderbuffer(0)
- #endif
- , Params(params)
- {
- #ifdef _DEBUG
- setDebugName("COGLES2Driver");
- #endif
- ExposedData = data;
- #if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
- EglWindow = (NativeWindowType)data.OpenGLWin32.HWnd;
- HDc = GetDC((HWND)EglWindow);
- EglDisplay = eglGetDisplay((NativeDisplayType)HDc);
- #elif defined(_IRR_COMPILE_WITH_X11_DEVICE_)
- EglWindow = (NativeWindowType)ExposedData.OpenGLLinux.X11Window;
- EglDisplay = eglGetDisplay((NativeDisplayType)ExposedData.OpenGLLinux.X11Display);
- #elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
- Device = device;
- #elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
- EglWindow = ((struct android_app *)(params.PrivateData))->window;
- EglDisplay = EGL_NO_DISPLAY;
- #endif
- #ifdef EGL_VERSION_1_0
- if (EglDisplay == EGL_NO_DISPLAY)
- {
- os::Printer::log("Getting OpenGL-ES2 display.");
- EglDisplay = eglGetDisplay((NativeDisplayType) EGL_DEFAULT_DISPLAY);
- }
- if (EglDisplay == EGL_NO_DISPLAY)
- {
- os::Printer::log("Could not get OpenGL-ES2 display.");
- }
- EGLint majorVersion, minorVersion;
- if (!eglInitialize(EglDisplay, &majorVersion, &minorVersion))
- {
- os::Printer::log("Could not initialize OpenGL-ES2 display.");
- }
- else
- {
- char text[64];
- sprintf(text, "EglDisplay initialized. Egl version %d.%d\n", majorVersion, minorVersion);
- os::Printer::log(text);
- }
- EGLint attribs[] =
- {
- #if defined( _IRR_COMPILE_WITH_ANDROID_DEVICE_ )
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_BLUE_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_RED_SIZE, 8,
- EGL_DEPTH_SIZE, 16,
- EGL_NONE
- #else
- EGL_RED_SIZE, 5,
- EGL_GREEN_SIZE, 5,
- EGL_BLUE_SIZE, 5,
- EGL_ALPHA_SIZE, params.WithAlphaChannel ? 1 : 0,
- EGL_BUFFER_SIZE, params.Bits,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- //EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
- EGL_DEPTH_SIZE, params.ZBufferBits,
- EGL_STENCIL_SIZE, params.Stencilbuffer,
- EGL_SAMPLE_BUFFERS, params.AntiAlias ? 1 : 0,
- EGL_SAMPLES, params.AntiAlias,
- #ifdef EGL_VERSION_1_3
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- #endif
- EGL_NONE, 0
- #endif
- };
- EGLint num_configs;
- #if defined( _IRR_COMPILE_WITH_ANDROID_DEVICE_ )
- u32 steps=0;
- #else
- u32 steps=5;
- #endif
- while (!eglChooseConfig(EglDisplay, attribs, &EglConfig, 1, &num_configs) || !num_configs)
- {
- switch (steps)
- {
- case 5: // samples
- if (attribs[19]>2)
- {
- --attribs[19];
- }
- else
- {
- attribs[17]=0;
- attribs[19]=0;
- --steps;
- }
- break;
- case 4: // alpha
- if (attribs[7])
- {
- attribs[7]=0;
- if (params.AntiAlias)
- {
- attribs[17]=1;
- attribs[19]=params.AntiAlias;
- steps=5;
- }
- }
- else
- --steps;
- break;
- case 3: // stencil
- if (attribs[15])
- {
- attribs[15]=0;
- if (params.AntiAlias)
- {
- attribs[17]=1;
- attribs[19]=params.AntiAlias;
- steps=5;
- }
- }
- else
- --steps;
- break;
- case 2: // depth size
- if (attribs[13]>16)
- {
- attribs[13]-=8;
- }
- else
- --steps;
- break;
- case 1: // buffer size
- if (attribs[9]>16)
- {
- attribs[9]-=8;
- }
- else
- --steps;
- break;
- default:
- os::Printer::log("Could not get config for OpenGL-ES2 display.");
- return;
- }
- }
- #if !defined( _IRR_COMPILE_WITH_ANDROID_DEVICE_ )
- if (params.AntiAlias && !attribs[17])
- os::Printer::log("No multisampling.");
- if (params.WithAlphaChannel && !attribs[7])
- os::Printer::log("No alpha.");
- if (params.Stencilbuffer && !attribs[15])
- os::Printer::log("No stencil buffer.");
- if (params.ZBufferBits > attribs[13])
- os::Printer::log("No full depth buffer.");
- if (params.Bits > attribs[9])
- os::Printer::log("No full color buffer.");
- #endif
- #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
- /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
- * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
- * As soon as we picked a EGLConfig, we can safely reconfigure the
- * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
- EGLint format;
- eglGetConfigAttrib(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &format);
- ANativeWindow_setBuffersGeometry(EglWindow, 0, 0, format);
- #endif
- os::Printer::log(" Creating EglSurface with nativeWindow...");
- EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, EglWindow, NULL);
- if (EGL_NO_SURFACE == EglSurface)
- {
- os::Printer::log("FAILED\n");
- EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, 0, NULL);
- os::Printer::log("Creating EglSurface without nativeWindows...");
- }
- else
- os::Printer::log("SUCCESS\n");
- if (EGL_NO_SURFACE == EglSurface)
- {
- os::Printer::log("FAILED\n");
- os::Printer::log("Could not create surface for OpenGL-ES2 display.");
- }
- else
- os::Printer::log("SUCCESS\n");
- #ifdef EGL_VERSION_1_2
- if (minorVersion>1)
- eglBindAPI(EGL_OPENGL_ES_API);
- #endif
- os::Printer::log("Creating EglContext...");
- EglContext = EGL_NO_CONTEXT;
- if (!Params.ForceLegacyDevice)
- {
- os::Printer::log("Trying to create Context for OpenGL-ES3.");
- EGLint contextAttrib[] =
- {
- #ifdef EGL_VERSION_1_3
- EGL_CONTEXT_CLIENT_VERSION, 3,
- #endif
- EGL_NONE, 0
- };
- EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, contextAttrib);
- }
- if (EGL_NO_CONTEXT == EglContext)
- {
- os::Printer::log("Trying to create Context for OpenGL-ES2.");
- useCoreContext = false;
- EGLint contextAttrib[] =
- {
- #ifdef EGL_VERSION_1_3
- EGL_CONTEXT_CLIENT_VERSION, 2,
- #endif
- EGL_NONE, 0
- };
- EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, contextAttrib);
- if (EGL_NO_CONTEXT == EglContext)
- {
- os::Printer::log("FAILED\n");
- os::Printer::log("Could not create Context for OpenGL-ES2 display.");
- }
- }
- eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext);
- if (testEGLError())
- {
- os::Printer::log("Could not make Context current for OpenGL-ES2 display.");
- }
- genericDriverInit(params.WindowSize, params.Stencilbuffer);
- #ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
- int backingWidth;
- int backingHeight;
- eglQuerySurface(EglDisplay, EglSurface, EGL_WIDTH, &backingWidth);
- eglQuerySurface(EglDisplay, EglSurface, EGL_HEIGHT, &backingHeight);
- core::dimension2d<u32> WindowSize(backingWidth, backingHeight);
- CNullDriver::ScreenSize = WindowSize;
- #endif
- // set vsync
- if (params.Vsync)
- eglSwapInterval(EglDisplay, 1);
- #elif defined(GL_ES_VERSION_2_0)
- glGenFramebuffers(1, &ViewFramebuffer);
- glGenRenderbuffers(1, &ViewRenderbuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, ViewRenderbuffer);
- #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
- ExposedData.OGLESIPhone.AppDelegate = Device;
- Device->displayInitialize(&ExposedData.OGLESIPhone.Context, &ExposedData.OGLESIPhone.View);
- #endif
- GLint backingWidth;
- GLint backingHeight;
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
- glGenRenderbuffers(1, &ViewDepthRenderbuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, ViewDepthRenderbuffer);
- GLenum depthComponent = GL_DEPTH_COMPONENT16;
- if(params.ZBufferBits >= 24)
- depthComponent = GL_DEPTH_COMPONENT24_OES;
- glRenderbufferStorage(GL_RENDERBUFFER, depthComponent, backingWidth, backingHeight);
- glBindFramebuffer(GL_FRAMEBUFFER, ViewFramebuffer);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ViewRenderbuffer);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ViewDepthRenderbuffer);
- core::dimension2d<u32> WindowSize(backingWidth, backingHeight);
- CNullDriver::ScreenSize = WindowSize;
- CNullDriver::ViewPort = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(WindowSize));
- genericDriverInit(WindowSize, params.Stencilbuffer);
- #endif
- }
- //! destructor
- COGLES2Driver::~COGLES2Driver()
- {
- deleteMaterialRenders();
- delete MaterialRenderer2D;
- deleteAllTextures();
- if (BridgeCalls)
- delete BridgeCalls;
- #if defined(EGL_VERSION_1_0)
- eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (EglContext != EGL_NO_CONTEXT)
- {
- eglDestroyContext(EglDisplay, EglContext);
- EglContext = EGL_NO_CONTEXT;
- }
- if (EglSurface != EGL_NO_SURFACE)
- {
- eglDestroySurface(EglDisplay, EglSurface);
- EglSurface = EGL_NO_SURFACE;
- }
- if (EglDisplay != EGL_NO_DISPLAY)
- {
- eglTerminate(EglDisplay);
- EglDisplay = EGL_NO_DISPLAY;
- }
- #if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
- if (HDc)
- ReleaseDC((HWND)EglWindow, HDc);
- #endif
- #elif defined(GL_ES_VERSION_2_0)
- if (0 != ViewFramebuffer)
- {
- glDeleteFramebuffers(1,&ViewFramebuffer);
- ViewFramebuffer = 0;
- }
- if (0 != ViewRenderbuffer)
- {
- glDeleteRenderbuffers(1,&ViewRenderbuffer);
- ViewRenderbuffer = 0;
- }
- if (0 != ViewDepthRenderbuffer)
- {
- glDeleteRenderbuffers(1,&ViewDepthRenderbuffer);
- ViewDepthRenderbuffer = 0;
- }
- #endif
- }
- // -----------------------------------------------------------------------
- // METHODS
- // -----------------------------------------------------------------------
- void COGLES2Driver::reloadEGLSurface(void* window)
- {
- os::Printer::log("Reload EGL surface.");
- #ifdef EGL_VERSION_1_0
- #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
- EglWindow = (ANativeWindow*)window;
- #endif
- if (!EglWindow)
- os::Printer::log("Invalid Egl window.");
- eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroySurface(EglDisplay, EglSurface);
- EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, EglWindow, 0);
- if (EGL_NO_SURFACE == EglSurface)
- os::Printer::log("Could not create EGL surface.");
- eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext);
- #endif
- }
- bool COGLES2Driver::genericDriverInit(const core::dimension2d<u32>& screenSize, bool stencilBuffer)
- {
- Name = glGetString(GL_VERSION);
- printVersion();
- #if defined(EGL_VERSION_1_0)
- os::Printer::log(eglQueryString(EglDisplay, EGL_CLIENT_APIS));
- #endif
- // print renderer information
- vendorName = glGetString(GL_VENDOR);
- os::Printer::log(vendorName.c_str(), ELL_INFORMATION);
- u32 i;
- for (i = 0; i < MATERIAL_MAX_TEXTURES; ++i)
- CurrentTexture[i] = 0;
- // load extensions
- initExtensions(this,
- #if defined(EGL_VERSION_1_0)
- EglDisplay,
- #endif
- stencilBuffer);
- if (!BridgeCalls)
- BridgeCalls = new COGLES2CallBridge(this);
- StencilBuffer = stencilBuffer;
- DriverAttributes->setAttribute("MaxTextures", MaxTextureUnits);
- DriverAttributes->setAttribute("MaxSupportedTextures", MaxSupportedTextures);
- // DriverAttributes->setAttribute("MaxLights", MaxLights);
- DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy);
- // DriverAttributes->setAttribute("MaxUserClipPlanes", MaxUserClipPlanes);
- // DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers);
- // DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets);
- DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices);
- DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize);
- DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias);
- DriverAttributes->setAttribute("Version", Version);
- DriverAttributes->setAttribute("AntiAlias", AntiAlias);
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- // Reset The Current Viewport
- BridgeCalls->setViewport(core::rect<s32>(0, 0, screenSize.Width, screenSize.Height));
- UserClipPlane.reallocate(0);
- setAmbientLight(SColorf(0.0f, 0.0f, 0.0f, 0.0f));
- glClearDepthf(1.0f);
- //TODO : OpenGL ES 2.0 Port : GL_PERSPECTIVE_CORRECTION_HINT
- //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
- glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
- glDepthFunc(GL_LEQUAL);
- glFrontFace(GL_CW);
- // create material renderers
- createMaterialRenderers();
- // set the renderstates
- setRenderStates3DMode();
- // set fog mode
- setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
- // create matrix for flipping textures
- TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0, 0), core::vector2df(0, 1.0f), core::vector2df(1.0f, -1.0f));
- // We need to reset once more at the beginning of the first rendering.
- // This fixes problems with intermediate changes to the material during texture load.
- ResetRenderStates = true;
- testGLError();
- return true;
- }
- void COGLES2Driver::createMaterialRenderers()
- {
- // Load shaders from files (in future shaders will be merged with source code).
- // Fixed pipeline.
- core::stringc shaders_path = IRR_OGLES2_SHADER_PATH;
- if (Params.ShadersPath.size() > 0)
- shaders_path = Params.ShadersPath;
- core::stringc FPVSPath = shaders_path;
- FPVSPath += "COGLES2FixedPipeline.vsh";
- core::stringc FPFSPath = shaders_path;
- FPFSPath += "COGLES2FixedPipeline.fsh";
- io::IReadFile* FPVSFile = FileSystem->createAndOpenFile(FPVSPath);
- io::IReadFile* FPFSFile = FileSystem->createAndOpenFile(FPFSPath);
- c8* FPVSData = 0;
- c8* FPFSData = 0;
- long Size = FPVSFile ? FPVSFile->getSize() : 0;
- if (Size)
- {
- FPVSData = new c8[Size+1];
- FPVSFile->read(FPVSData, Size);
- FPVSData[Size] = 0;
- }
- Size = FPFSFile ? FPFSFile->getSize() : 0;
- if (Size)
- {
- // if both handles are the same we must reset the file
- if (FPFSFile == FPVSFile)
- FPFSFile->seek(0);
- FPFSData = new c8[Size+1];
- FPFSFile->read(FPFSData, Size);
- FPFSData[Size] = 0;
- }
- if (FPVSFile)
- FPVSFile->drop();
- if (FPFSFile)
- FPFSFile->drop();
- // Normal Mapping.
- core::stringc NMVSPath = shaders_path;
- NMVSPath += "COGLES2NormalMap.vsh";
- core::stringc NMFSPath = shaders_path;
- NMFSPath += "COGLES2NormalMap.fsh";
- io::IReadFile* NMVSFile = FileSystem->createAndOpenFile(NMVSPath);
- io::IReadFile* NMFSFile = FileSystem->createAndOpenFile(NMFSPath);
- c8* NMVSData = 0;
- c8* NMFSData = 0;
- Size = NMVSFile ? NMVSFile->getSize() : 0;
- if (Size)
- {
- NMVSData = new c8[Size+1];
- NMVSFile->read(NMVSData, Size);
- NMVSData[Size] = 0;
- }
- Size = NMFSFile ? NMFSFile->getSize() : 0;
- if (Size)
- {
- // if both handles are the same we must reset the file
- if (NMFSFile == NMVSFile)
- NMFSFile->seek(0);
- NMFSData = new c8[Size+1];
- NMFSFile->read(NMFSData, Size);
- NMFSData[Size] = 0;
- }
- if (NMVSFile)
- NMVSFile->drop();
- if (NMFSFile)
- NMFSFile->drop();
- // Parallax Mapping.
- core::stringc PMVSPath = shaders_path;
- PMVSPath += "COGLES2ParallaxMap.vsh";
- core::stringc PMFSPath = shaders_path;
- PMFSPath += "COGLES2ParallaxMap.fsh";
- io::IReadFile* PMVSFile = FileSystem->createAndOpenFile(FPVSPath);
- io::IReadFile* PMFSFile = FileSystem->createAndOpenFile(FPFSPath);
- c8* PMVSData = 0;
- c8* PMFSData = 0;
- Size = PMVSFile ? PMVSFile->getSize() : 0;
- if (Size)
- {
- PMVSData = new c8[Size+1];
- PMVSFile->read(PMVSData, Size);
- PMVSData[Size] = 0;
- }
- Size = PMFSFile ? PMFSFile->getSize() : 0;
- if (Size)
- {
- // if both handles are the same we must reset the file
- if (PMFSFile == PMVSFile)
- PMFSFile->seek(0);
- PMFSData = new c8[Size+1];
- PMFSFile->read(PMFSData, Size);
- PMFSData[Size] = 0;
- }
- if (PMVSFile)
- PMVSFile->drop();
- if (PMFSFile)
- PMFSFile->drop();
- // Create materials.
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_SOLID, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_SOLID_2_LAYER, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_ADD, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_M2, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_M4, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_LIGHTING, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_LIGHTING_M2, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_LIGHTMAP_LIGHTING_M4, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_DETAIL_MAP, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_SPHERE_MAP, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_REFLECTION_2_LAYER, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_ADD_COLOR, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_ALPHA_CHANNEL, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_ALPHA_CHANNEL_REF, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_VERTEX_ALPHA, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_TRANSPARENT_REFLECTION_2_LAYER, this));
- if (!useCoreContext)
- {
- addAndDropMaterialRenderer(new COGLES2NormalMapRenderer(NMVSData, NMFSData, EMT_NORMAL_MAP_SOLID, this));
- addAndDropMaterialRenderer(new COGLES2NormalMapRenderer(NMVSData, NMFSData, EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR, this));
- addAndDropMaterialRenderer(new COGLES2NormalMapRenderer(NMVSData, NMFSData, EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA, this));
- }
- addAndDropMaterialRenderer(new COGLES2ParallaxMapRenderer(PMVSData, PMFSData, EMT_PARALLAX_MAP_SOLID, this));
- addAndDropMaterialRenderer(new COGLES2ParallaxMapRenderer(PMVSData, PMFSData, EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR, this));
- addAndDropMaterialRenderer(new COGLES2ParallaxMapRenderer(PMVSData, PMFSData, EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA, this));
- addAndDropMaterialRenderer(new COGLES2FixedPipelineRenderer(FPVSData, FPFSData, EMT_ONETEXTURE_BLEND, this));
- // Create 2D material renderer.
- core::stringc R2DVSPath = shaders_path;
- R2DVSPath += "COGLES2Renderer2D.vsh";
- core::stringc R2DFSPath = shaders_path;
- R2DFSPath += "COGLES2Renderer2D.fsh";
- io::IReadFile* R2DVSFile = FileSystem->createAndOpenFile(R2DVSPath);
- io::IReadFile* R2DFSFile = FileSystem->createAndOpenFile(R2DFSPath);
- c8* R2DVSData = 0;
- c8* R2DFSData = 0;
- Size = R2DVSFile ? R2DVSFile->getSize() : 0;
- if (Size)
- {
- R2DVSData = new c8[Size+1];
- R2DVSFile->read(R2DVSData, Size);
- R2DVSData[Size] = 0;
- }
- Size = R2DFSFile ? R2DFSFile->getSize() : 0;
- if (Size)
- {
- // if both handles are the same we must reset the file
- if (R2DFSFile == PMVSFile)
- R2DFSFile->seek(0);
- R2DFSData = new c8[Size+1];
- R2DFSFile->read(R2DFSData, Size);
- R2DFSData[Size] = 0;
- }
- if (R2DVSFile)
- R2DVSFile->drop();
- if (R2DFSFile)
- R2DFSFile->drop();
- MaterialRenderer2D = new COGLES2Renderer2D(R2DVSData, R2DFSData, this);
- }
- //! presents the rendered scene on the screen, returns false if failed
- bool COGLES2Driver::endScene()
- {
- CNullDriver::endScene();
- #if defined(EGL_VERSION_1_0)
- eglSwapBuffers(EglDisplay, EglSurface);
- EGLint g = eglGetError();
- if (EGL_SUCCESS != g)
- {
- if (EGL_CONTEXT_LOST == g)
- {
- // o-oh, ogl-es has lost contexts...
- os::Printer::log("Context lost, please restart your app.");
- }
- else
- os::Printer::log("Could not swap buffers for OpenGL-ES2 driver.");
- return false;
- }
- #elif defined(GL_ES_VERSION_2_0)
- glFlush();
- glBindRenderbuffer(GL_RENDERBUFFER, ViewRenderbuffer);
- #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
- Device->displayEnd();
- #endif
- #endif
- return true;
- }
- //! clears the zbuffer
- bool COGLES2Driver::beginScene(bool backBuffer, bool zBuffer, SColor color,
- const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
- {
- CNullDriver::beginScene(backBuffer, zBuffer, color);
- GLbitfield mask = 0;
- if (backBuffer)
- {
- const f32 inv = 1.0f / 255.0f;
- glClearColor(color.getRed() * inv, color.getGreen() * inv,
- color.getBlue() * inv, color.getAlpha() * inv);
- mask |= GL_COLOR_BUFFER_BIT;
- }
- if (zBuffer)
- {
- glDepthMask(GL_TRUE);
- LastMaterial.ZWriteEnable = true;
- mask |= GL_DEPTH_BUFFER_BIT;
- }
- glClear(mask);
- testGLError();
- return true;
- }
- //! Returns the transformation set by setTransform
- const core::matrix4& COGLES2Driver::getTransform(E_TRANSFORMATION_STATE state) const
- {
- return Matrices[state];
- }
- //! sets transformation
- void COGLES2Driver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
- {
- Matrices[state] = mat;
- Transformation3DChanged = true;
- }
- bool COGLES2Driver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
- {
- if (!HWBuffer)
- return false;
- const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
- const void* vertices = mb->getVertices();
- const u32 vertexCount = mb->getVertexCount();
- const E_VERTEX_TYPE vType = mb->getVertexType();
- const u32 vertexSize = getVertexPitchFromType(vType);
- //buffer vertex data, and convert colours...
- core::array<c8> buffer(vertexSize * vertexCount);
- memcpy(buffer.pointer(), vertices, vertexSize * vertexCount);
- //get or create buffer
- bool newBuffer = false;
- if (!HWBuffer->vbo_verticesID)
- {
- glGenBuffers(1, &HWBuffer->vbo_verticesID);
- if (!HWBuffer->vbo_verticesID) return false;
- newBuffer = true;
- }
- else if (HWBuffer->vbo_verticesSize < vertexCount*vertexSize)
- {
- newBuffer = true;
- }
- glBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID);
- //copy data to graphics card
- glGetError(); // clear error storage
- if (!newBuffer)
- glBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * vertexSize, buffer.const_pointer());
- else
- {
- HWBuffer->vbo_verticesSize = vertexCount * vertexSize;
- if (HWBuffer->Mapped_Vertex == scene::EHM_STATIC)
- glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, buffer.const_pointer(), GL_STATIC_DRAW);
- else
- glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, buffer.const_pointer(), GL_DYNAMIC_DRAW);
- }
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- return (glGetError() == GL_NO_ERROR);
- }
- bool COGLES2Driver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)
- {
- if (!HWBuffer)
- return false;
- const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
- const void* indices = mb->getIndices();
- u32 indexCount = mb->getIndexCount();
- GLenum indexSize;
- switch (mb->getIndexType())
- {
- case(EIT_16BIT):
- {
- indexSize = sizeof(u16);
- break;
- }
- case(EIT_32BIT):
- {
- indexSize = sizeof(u32);
- break;
- }
- default:
- {
- return false;
- }
- }
- //get or create buffer
- bool newBuffer = false;
- if (!HWBuffer->vbo_indicesID)
- {
- glGenBuffers(1, &HWBuffer->vbo_indicesID);
- if (!HWBuffer->vbo_indicesID) return false;
- newBuffer = true;
- }
- else if (HWBuffer->vbo_indicesSize < indexCount*indexSize)
- {
- newBuffer = true;
- }
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID);
- //copy data to graphics card
- glGetError(); // clear error storage
- if (!newBuffer)
- glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices);
- else
- {
- HWBuffer->vbo_indicesSize = indexCount * indexSize;
- if (HWBuffer->Mapped_Index == scene::EHM_STATIC)
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW);
- else
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_DYNAMIC_DRAW);
- }
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- return (glGetError() == GL_NO_ERROR);
- }
- //! updates hardware buffer if needed
- bool COGLES2Driver::updateHardwareBuffer(SHWBufferLink *HWBuffer)
- {
- if (!HWBuffer)
- return false;
- if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)
- {
- if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex()
- || !((SHWBufferLink_opengl*)HWBuffer)->vbo_verticesID)
- {
- HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex();
- if (!updateVertexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer))
- return false;
- }
- }
- if (HWBuffer->Mapped_Index != scene::EHM_NEVER)
- {
- if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index()
- || !((SHWBufferLink_opengl*)HWBuffer)->vbo_indicesID)
- {
- HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index();
- if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer))
- return false;
- }
- }
- return true;
- }
- //! Create hardware buffer from meshbuffer
- COGLES2Driver::SHWBufferLink *COGLES2Driver::createHardwareBuffer(const scene::IMeshBuffer* mb)
- {
- if (!mb || (mb->getHardwareMappingHint_Index() == scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER))
- return 0;
- SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(mb);
- //add to map
- HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer);
- HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex();
- HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index();
- HWBuffer->Mapped_Vertex = mb->getHardwareMappingHint_Vertex();
- HWBuffer->Mapped_Index = mb->getHardwareMappingHint_Index();
- HWBuffer->LastUsed = 0;
- HWBuffer->vbo_verticesID = 0;
- HWBuffer->vbo_indicesID = 0;
- HWBuffer->vbo_verticesSize = 0;
- HWBuffer->vbo_indicesSize = 0;
- if (!updateHardwareBuffer(HWBuffer))
- {
- deleteHardwareBuffer(HWBuffer);
- return 0;
- }
- return HWBuffer;
- }
- void COGLES2Driver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer)
- {
- if (!_HWBuffer)
- return;
- SHWBufferLink_opengl *HWBuffer = (SHWBufferLink_opengl*)_HWBuffer;
- if (HWBuffer->vbo_verticesID)
- {
- glDeleteBuffers(1, &HWBuffer->vbo_verticesID);
- HWBuffer->vbo_verticesID = 0;
- }
- if (HWBuffer->vbo_indicesID)
- {
- glDeleteBuffers(1, &HWBuffer->vbo_indicesID);
- HWBuffer->vbo_indicesID = 0;
- }
- CNullDriver::deleteHardwareBuffer(_HWBuffer);
- }
- //! Draw hardware buffer
- void COGLES2Driver::drawHardwareBuffer(SHWBufferLink *_HWBuffer)
- {
- if (!_HWBuffer)
- return;
- SHWBufferLink_opengl *HWBuffer = (SHWBufferLink_opengl*)_HWBuffer;
- updateHardwareBuffer(HWBuffer); //check if update is needed
- HWBuffer->LastUsed = 0;//reset count
- const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;
- const void *vertices = mb->getVertices();
- const void *indexList = mb->getIndices();
- if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)
- {
- glBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID);
- vertices = 0;
- }
- if (HWBuffer->Mapped_Index != scene::EHM_NEVER)
- {
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID);
- indexList = 0;
- }
- drawVertexPrimitiveList(vertices, mb->getVertexCount(),
- indexList, mb->getIndexCount() / 3,
- mb->getVertexType(), scene::EPT_TRIANGLES,
- mb->getIndexType());
- if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- if (HWBuffer->Mapped_Index != scene::EHM_NEVER)
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- // small helper function to create vertex buffer object adress offsets
- static inline u8* buffer_offset(const long offset)
- {
- return ((u8*)0 + offset);
- }
- //! draws a vertex primitive list
- void COGLES2Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
- const void* indexList, u32 primitiveCount,
- E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
- {
- testGLError();
- if (!checkPrimitiveCount(primitiveCount))
- return;
- setRenderStates3DMode();
- drawVertexPrimitiveList2d3d(vertices, vertexCount, (const u16*)indexList, primitiveCount, vType, pType, iType);
- }
- void COGLES2Driver::drawVertexPrimitiveList2d3d(const void* vertices, u32 vertexCount,
- const void* indexList, u32 primitiveCount,
- E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, bool threed)
- {
- if (!primitiveCount || !vertexCount)
- return;
- if (!threed && !checkPrimitiveCount(primitiveCount))
- return;
- CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
- //TODO: treat #ifdef GL_OES_point_size_array outside this if
- {
- glEnableVertexAttribArray(EVA_COLOR);
- glEnableVertexAttribArray(EVA_POSITION);
- if ((pType != scene::EPT_POINTS) && (pType != scene::EPT_POINT_SPRITES))
- {
- glEnableVertexAttribArray(EVA_TCOORD0);
- }
- #ifdef GL_OES_point_size_array
- else if (FeatureAvailable[IRR_OES_point_size_array] && (Material.Thickness == 0.0f))
- glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
- #endif
- if (threed && (pType != scene::EPT_POINTS) && (pType != scene::EPT_POINT_SPRITES))
- {
- glEnableVertexAttribArray(EVA_NORMAL);
- }
- switch (vType)
- {
- case EVT_STANDARD:
- if (vertices)
- {
- #ifdef GL_OES_point_size_array
- if ((pType == scene::EPT_POINTS) || (pType == scene::EPT_POINT_SPRITES))
- {
- if (FeatureAvailable[IRR_OES_point_size_array] && (Material.Thickness == 0.0f))
- glPointSizePointerOES(GL_FLOAT, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Normal.X);
- }
- else
- #endif
- glVertexAttribPointer(EVA_POSITION, (threed ? 3 : 2), GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);
- if (threed)
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Normal);
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);
- }
- else
- {
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), 0);
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex), buffer_offset(12));
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), buffer_offset(24));
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), buffer_offset(28));
- }
- //if (CurrentTexture[1])
- //{
- // // There must be some optimisation here as it uses the same texture coord !
- // glEnableVertexAttribArray(EVA_TCOORD1);
- // if (vertices)
- // glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);
- // else
- // glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex), buffer_offset(28));
- //}
- break;
- case EVT_2TCOORDS:
- //glEnableVertexAttribArray(EVA_TCOORD1);
- if (vertices)
- {
- glVertexAttribPointer(EVA_POSITION, (threed ? 3 : 2), GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Pos);
- if (threed)
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Normal);
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Color);
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords);
- //glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords2);
- }
- else
- {
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(0));
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(12));
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex2TCoords), buffer_offset(24));
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(28));
- //glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(36));
- }
- break;
- case EVT_TANGENTS:
- glEnableVertexAttribArray(EVA_TANGENT);
- glEnableVertexAttribArray(EVA_BINORMAL);
- if (vertices)
- {
- glVertexAttribPointer(EVA_POSITION, (threed ? 3 : 2), GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos);
- if (threed)
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Normal);
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color);
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords);
- glVertexAttribPointer(EVA_TANGENT, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Tangent);
- glVertexAttribPointer(EVA_BINORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Binormal);
- }
- else
- {
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(0));
- glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(12));
- glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertexTangents), buffer_offset(24));
- glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(28));
- glVertexAttribPointer(EVA_TANGENT, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(36));
- glVertexAttribPointer(EVA_BINORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(48));
- }
- break;
- default:
- break;
- }
- }
- // draw everything
- GLenum indexSize = 0;
- switch (iType)
- {
- case(EIT_16BIT):
- {
- indexSize = GL_UNSIGNED_SHORT;
- break;
- }
- case(EIT_32BIT):
- {
- #ifdef GL_OES_element_index_uint
- #ifndef GL_UNSIGNED_INT
- #define GL_UNSIGNED_INT 0x1405
- #endif
- if (FeatureAvailable[IRR_OES_element_index_uint])
- indexSize = GL_UNSIGNED_INT;
- else
- #endif
- indexSize = GL_UNSIGNED_SHORT;
- break;
- }
- }
- switch (pType)
- {
- case scene::EPT_POINTS:
- case scene::EPT_POINT_SPRITES:
- {
- #ifdef GL_OES_point_sprite
- if (pType == scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_OES_point_sprite])
- glEnable(GL_POINT_SPRITE_OES);
- #endif
- // if ==0 we use the point size array
- if (Material.Thickness != 0.f)
- {
- // float quadratic[] = {0.0f, 0.0f, 10.01f};
- //TODO : OpenGL ES 2.0 Port GL_POINT_DISTANCE_ATTENUATION
- //glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, quadratic);
- // float maxParticleSize = 1.0f;
- //TODO : OpenGL ES 2.0 Port GL_POINT_SIZE_MAX
- //glGetFloatv(GL_POINT_SIZE_MAX, &maxParticleSize);
- // maxParticleSize=maxParticleSize<Material.Thickness?maxParticleSize:Material.Thickness;
- // glPointParameterf(GL_POINT_SIZE_MAX,maxParticleSize);
- // glPointParameterf(GL_POINT_SIZE_MIN,Material.Thickness);
- //TODO : OpenGL ES 2.0 Port GL_POINT_FADE_THRESHOLD_SIZE
- //glPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE, 60.0f);
- //glPointSize(Material.Thickness);
- }
- #ifdef GL_OES_point_sprite
- if (pType == scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_OES_point_sprite])
- glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
- #endif
- glDrawArrays(GL_POINTS, 0, primitiveCount);
- #ifdef GL_OES_point_sprite
- if (pType == scene::EPT_POINT_SPRITES && FeatureAvailable[IRR_OES_point_sprite])
- {
- glDisable(GL_POINT_SPRITE_OES);
- glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_FALSE);
- }
- #endif
- }
- break;
- case scene::EPT_LINE_STRIP:
- glDrawElements(GL_LINE_STRIP, primitiveCount + 1, indexSize, indexList);
- break;
- case scene::EPT_LINE_LOOP:
- glDrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList);
- break;
- case scene::EPT_LINES:
- glDrawElements(GL_LINES, primitiveCount*2, indexSize, indexList);
- break;
- case scene::EPT_TRIANGLE_STRIP:
- glDrawElements(GL_TRIANGLE_STRIP, primitiveCount + 2, indexSize, indexList);
- break;
- case scene::EPT_TRIANGLE_FAN:
- glDrawElements(GL_TRIANGLE_FAN, primitiveCount + 2, indexSize, indexList);
- break;
- case scene::EPT_TRIANGLES:
- glDrawElements((LastMaterial.Wireframe) ? GL_LINES : (LastMaterial.PointCloud) ? GL_POINTS : GL_TRIANGLES, primitiveCount*3, indexSize, indexList);
- break;
- case scene::EPT_QUAD_STRIP:
- // TODO ogl-es
- // glDrawElements(GL_QUAD_STRIP, primitiveCount*2+2, indexSize, indexList);
- break;
- case scene::EPT_QUADS:
- // TODO ogl-es
- // glDrawElements(GL_QUADS, primitiveCount*4, indexSize, indexList);
- break;
- case scene::EPT_POLYGON:
- // TODO ogl-es
- // glDrawElements(GL_POLYGON, primitiveCount, indexSize, indexList);
- break;
- }
- {
- if (vType == EVT_TANGENTS)
- {
- glDisableVertexAttribArray(EVA_TANGENT);
- glDisableVertexAttribArray(EVA_BINORMAL);
- }
- //if ((vType != EVT_STANDARD) || CurrentTexture[1])
- //{
- // glDisableVertexAttribArray(EVA_TCOORD1);
- //}
- #ifdef GL_OES_point_size_array
- if (FeatureAvailable[IRR_OES_point_size_array] && (Material.Thickness == 0.0f))
- glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
- #endif
- glDisableVertexAttribArray(EVA_POSITION);
- glDisableVertexAttribArray(EVA_NORMAL);
- glDisableVertexAttribArray(EVA_COLOR);
- glDisableVertexAttribArray(EVA_TCOORD0);
- }
- testGLError();
- }
- //! draws a 2d image, using a color and the alpha channel of the texture
- void COGLES2Driver::draw2DImage(const video::ITexture* texture,
- const core::position2d<s32>& pos,
- const core::rect<s32>& sourceRect,
- const core::rect<s32>* clipRect, SColor color,
- bool useAlphaChannelOfTexture)
- {
- if (!texture)
- return;
- if (!sourceRect.isValid())
- return;
- core::position2d<s32> targetPos(pos);
- core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner);
- core::dimension2d<s32> sourceSize(sourceRect.getSize());
- if (clipRect)
- {
- if (targetPos.X < clipRect->UpperLeftCorner.X)
- {
- sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
- if (sourceSize.Width <= 0)
- return;
- sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
- targetPos.X = clipRect->UpperLeftCorner.X;
- }
- if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)
- {
- sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
- if (sourceSize.Width <= 0)
- return;
- }
- if (targetPos.Y < clipRect->UpperLeftCorner.Y)
- {
- sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
- if (sourceSize.Height <= 0)
- return;
- sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
- targetPos.Y = clipRect->UpperLeftCorner.Y;
- }
- if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)
- {
- sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
- if (sourceSize.Height <= 0)
- return;
- }
- }
- // clip these coordinates
- if (targetPos.X < 0)
- {
- sourceSize.Width += targetPos.X;
- if (sourceSize.Width <= 0)
- return;
- sourcePos.X -= targetPos.X;
- targetPos.X = 0;
- }
- const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
- if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
- {
- sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
- if (sourceSize.Width <= 0)
- return;
- }
- if (targetPos.Y < 0)
- {
- sourceSize.Height += targetPos.Y;
- if (sourceSize.Height <= 0)
- return;
- sourcePos.Y -= targetPos.Y;
- targetPos.Y = 0;
- }
- if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
- {
- sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
- if (sourceSize.Height <= 0)
- return;
- }
- // ok, we've clipped everything.
- // now draw it.
- // texcoords need to be flipped horizontally for RTTs
- const bool isRTT = texture->isRenderTarget();
- const core::dimension2d<u32>& ss = texture->getSize();
- const f32 invW = 1.f / static_cast<f32>(ss.Width);
- const f32 invH = 1.f / static_cast<f32>(ss.Height);
- const core::rect<f32> tcoords(
- sourcePos.X * invW,
- (isRTT ? (sourcePos.Y + sourceSize.Height) : sourcePos.Y) * invH,
- (sourcePos.X + sourceSize.Width) * invW,
- (isRTT ? sourcePos.Y : (sourcePos.Y + sourceSize.Height)) * invH);
- const core::rect<s32> poss(targetPos, sourceSize);
- disableTextures(1);
- if (!setActiveTexture(0, texture))
- return;
- setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);
- u16 indices[] = {0, 1, 2, 3};
- S3DVertex vertices[4];
- vertices[0] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
- vertices[1] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
- vertices[2] = S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
- vertices[3] = S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
- drawVertexPrimitiveList2d3d(vertices, 4, indices, 2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT, false);
- }
- void COGLES2Driver::draw2DImageBatch(const video::ITexture* texture,
- const core::array<core::position2d<s32> >& positions,
- const core::array<core::rect<s32> >& sourceRects,
- const core::rect<s32>* clipRect,
- SColor color, bool useAlphaChannelOfTexture)
- {
- if (!texture)
- return;
- if (!setActiveTexture(0, const_cast<video::ITexture*>(texture)))
- return;
- const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());
- core::array<S3DVertex> vtx(drawCount * 4);
- core::array<u16> indices(drawCount * 6);
- for (u32 i = 0; i < drawCount; i++)
- {
- core::position2d<s32> targetPos = positions[i];
- core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;
- // This needs to be signed as it may go negative.
- core::dimension2d<s32> sourceSize(sourceRects[i].getSize());
- if (clipRect)
- {
- if (targetPos.X < clipRect->UpperLeftCorner.X)
- {
- sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;
- if (sourceSize.Width <= 0)
- continue;
- sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;
- targetPos.X = clipRect->UpperLeftCorner.X;
- }
- if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)
- {
- sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;
- if (sourceSize.Width <= 0)
- continue;
- }
- if (targetPos.Y < clipRect->UpperLeftCorner.Y)
- {
- sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;
- if (sourceSize.Height <= 0)
- continue;
- sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;
- targetPos.Y = clipRect->UpperLeftCorner.Y;
- }
- if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)
- {
- sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;
- if (sourceSize.Height <= 0)
- continue;
- }
- }
- // clip these coordinates
- if (targetPos.X < 0)
- {
- sourceSize.Width += targetPos.X;
- if (sourceSize.Width <= 0)
- continue;
- sourcePos.X -= targetPos.X;
- targetPos.X = 0;
- }
- const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
- if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)
- {
- sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;
- if (sourceSize.Width <= 0)
- continue;
- }
- if (targetPos.Y < 0)
- {
- sourceSize.Height += targetPos.Y;
- if (sourceSize.Height <= 0)
- continue;
- sourcePos.Y -= targetPos.Y;
- targetPos.Y = 0;
- }
- if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)
- {
- sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;
- if (sourceSize.Height <= 0)
- continue;
- }
- // ok, we've clipped everything.
- // now draw it.
- core::rect<f32> tcoords;
- tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getSize().Width ;
- tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getSize().Height;
- tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getSize().Width);
- tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getSize().Height);
- const core::rect<s32> poss(targetPos, sourceSize);
- setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);
- vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
- 0.0f, 0.0f, 0.0f, color,
- tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));
- vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f,
- 0.0f, 0.0f, 0.0f, color,
- tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));
- vtx.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
- 0.0f, 0.0f, 0.0f, color,
- tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));
- vtx.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f,
- 0.0f, 0.0f, 0.0f, color,
- tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));
- const u32 curPos = vtx.size() - 4;
- indices.push_back(0 + curPos);
- indices.push_back(1 + curPos);
- indices.push_back(2 + curPos);
- indices.push_back(0 + curPos);
- indices.push_back(2 + curPos);
- indices.push_back(3 + curPos);
- }
- if (vtx.size())
- {
- drawVertexPrimitiveList2d3d(vtx.pointer(), vtx.size(),
- indices.pointer(), indices.size() / 3,
- EVT_STANDARD, scene::EPT_TRIANGLES,
- EIT_16BIT, false);
- }
- }
- //! The same, but with a four element array of colors, one for each vertex
- void COGLES2Driver::draw2DImage(const video::ITexture* texture,
- const core::rect<s32>& destRect,
- const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
- const video::SColor* const colors, bool useAlphaChannelOfTexture)
- {
- if (!texture)
- return;
- // texcoords need to be flipped horizontally for RTTs
- const bool isRTT = texture->isRenderTarget();
- const core::dimension2du& ss = texture->getSize();
- const f32 invW = 1.f / static_cast<f32>(ss.Width);
- const f32 invH = 1.f / static_cast<f32>(ss.Height);
- const core::rect<f32> tcoords(
- sourceRect.UpperLeftCorner.X * invW,
- (isRTT ? sourceRect.LowerRightCorner.Y : sourceRect.UpperLeftCorner.Y) * invH,
- sourceRect.LowerRightCorner.X * invW,
- (isRTT ? sourceRect.UpperLeftCorner.Y : sourceRect.LowerRightCorner.Y) *invH);
- const video::SColor temp[4] =
- {
- 0xFFFFFFFF,
- 0xFFFFFFFF,
- 0xFFFFFFFF,
- 0xFFFFFFFF
- };
- const video::SColor* const useColor = colors ? colors : temp;
- disableTextures(1);
- setActiveTexture(0, texture);
- setRenderStates2DMode(useColor[0].getAlpha() < 255 || useColor[1].getAlpha() < 255 ||
- useColor[2].getAlpha() < 255 || useColor[3].getAlpha() < 255,
- true, useAlphaChannelOfTexture);
- if (clipRect)
- {
- if (!clipRect->isValid())
- return;
- glEnable(GL_SCISSOR_TEST);
- const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
- glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
- clipRect->getWidth(), clipRect->getHeight());
- }
- u16 indices[] = {0, 1, 2, 3};
- S3DVertex vertices[4];
- vertices[0] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.UpperLeftCorner.Y, 0, 0, 0, 1, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
- vertices[1] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.UpperLeftCorner.Y, 0, 0, 0, 1, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
- vertices[2] = S3DVertex((f32)destRect.LowerRightCorner.X, (f32)destRect.LowerRightCorner.Y, 0, 0, 0, 1, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
- vertices[3] = S3DVertex((f32)destRect.UpperLeftCorner.X, (f32)destRect.LowerRightCorner.Y, 0, 0, 0, 1, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
- drawVertexPrimitiveList2d3d(vertices, 4, indices, 2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT, false);
- if (clipRect)
- glDisable(GL_SCISSOR_TEST);
- testGLError();
- }
- //! draws a set of 2d images, using a color and the alpha channel
- void COGLES2Driver::draw2DImageBatch(const video::ITexture* texture,
- const core::position2d<s32>& pos,
- const core::array<core::rect<s32> >& sourceRects,
- const core::array<s32>& indices, s32 kerningWidth,
- const core::rect<s32>* clipRect, SColor color,
- bool useAlphaChannelOfTexture)
- {
- if (!texture)
- return;
- disableTextures(1);
- if (!setActiveTexture(0, texture))
- return;
- setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);
- if (clipRect)
- {
- if (!clipRect->isValid())
- return;
- glEnable(GL_SCISSOR_TEST);
- const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
- glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
- clipRect->getWidth(), clipRect->getHeight());
- }
- const core::dimension2du& ss = texture->getSize();
- core::position2d<s32> targetPos(pos);
- // texcoords need to be flipped horizontally for RTTs
- const bool isRTT = texture->isRenderTarget();
- const f32 invW = 1.f / static_cast<f32>(ss.Width);
- const f32 invH = 1.f / static_cast<f32>(ss.Height);
- core::array<S3DVertex> vertices;
- core::array<u16> quadIndices;
- vertices.reallocate(indices.size()*4);
- quadIndices.reallocate(indices.size()*3);
- for (u32 i = 0; i < indices.size(); ++i)
- {
- const s32 currentIndex = indices[i];
- if (!sourceRects[currentIndex].isValid())
- break;
- const core::rect<f32> tcoords(
- sourceRects[currentIndex].UpperLeftCorner.X * invW,
- (isRTT ? sourceRects[currentIndex].LowerRightCorner.Y : sourceRects[currentIndex].UpperLeftCorner.Y) * invH,
- sourceRects[currentIndex].LowerRightCorner.X * invW,
- (isRTT ? sourceRects[currentIndex].UpperLeftCorner.Y : sourceRects[currentIndex].LowerRightCorner.Y) * invH);
- const core::rect<s32> poss(targetPos, sourceRects[currentIndex].getSize());
- const u32 vstart = vertices.size();
- vertices.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));
- vertices.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));
- vertices.push_back(S3DVertex((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));
- vertices.push_back(S3DVertex((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));
- quadIndices.push_back(vstart);
- quadIndices.push_back(vstart+1);
- quadIndices.push_back(vstart+2);
- quadIndices.push_back(vstart);
- quadIndices.push_back(vstart+2);
- quadIndices.push_back(vstart+3);
- targetPos.X += sourceRects[currentIndex].getWidth();
- }
- if (vertices.size())
- drawVertexPrimitiveList2d3d(vertices.pointer(), vertices.size(),
- quadIndices.pointer(), vertices.size()/2,
- video::EVT_STANDARD, scene::EPT_TRIANGLES,
- EIT_16BIT, false);
- if (clipRect)
- glDisable(GL_SCISSOR_TEST);
- testGLError();
- }
- //! draw a 2d rectangle
- void COGLES2Driver::draw2DRectangle(SColor color,
- const core::rect<s32>& position,
- const core::rect<s32>* clip)
- {
- disableTextures();
- setRenderStates2DMode(color.getAlpha() < 255, false, false);
- core::rect<s32> pos = position;
- if (clip)
- pos.clipAgainst(*clip);
- if (!pos.isValid())
- return;
- u16 indices[] = {0, 1, 2, 3};
- S3DVertex vertices[4];
- vertices[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0, 0, 0, 1, color, 0, 0);
- vertices[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0, 0, 0, 1, color, 0, 0);
- vertices[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0, 0, 0, 1, color, 0, 0);
- vertices[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0, 0, 0, 1, color, 0, 0);
- drawVertexPrimitiveList2d3d(vertices, 4, indices, 2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT, false);
- }
- //! draw an 2d rectangle
- void COGLES2Driver::draw2DRectangle(const core::rect<s32>& position,
- SColor colorLeftUp, SColor colorRightUp,
- SColor colorLeftDown, SColor colorRightDown,
- const core::rect<s32>* clip)
- {
- core::rect<s32> pos = position;
- if (clip)
- pos.clipAgainst(*clip);
- if (!pos.isValid())
- return;
- disableTextures();
- setRenderStates2DMode(colorLeftUp.getAlpha() < 255 ||
- colorRightUp.getAlpha() < 255 ||
- colorLeftDown.getAlpha() < 255 ||
- colorRightDown.getAlpha() < 255, false, false);
- u16 indices[] = {0, 1, 2, 3};
- S3DVertex vertices[4];
- vertices[0] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.UpperLeftCorner.Y, 0, 0, 0, 1, colorLeftUp, 0, 0);
- vertices[1] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.UpperLeftCorner.Y, 0, 0, 0, 1, colorRightUp, 0, 0);
- vertices[2] = S3DVertex((f32)pos.LowerRightCorner.X, (f32)pos.LowerRightCorner.Y, 0, 0, 0, 1, colorRightDown, 0, 0);
- vertices[3] = S3DVertex((f32)pos.UpperLeftCorner.X, (f32)pos.LowerRightCorner.Y, 0, 0, 0, 1, colorLeftDown, 0, 0);
- drawVertexPrimitiveList2d3d(vertices, 4, indices, 2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT, false);
- }
- //! Draws a 2d line.
- void COGLES2Driver::draw2DLine(const core::position2d<s32>& start,
- const core::position2d<s32>& end, SColor color)
- {
- disableTextures();
- setRenderStates2DMode(color.getAlpha() < 255, false, false);
- u16 indices[] = {0, 1};
- S3DVertex vertices[2];
- vertices[0] = S3DVertex((f32)start.X, (f32)start.Y, 0, 0, 0, 1, color, 0, 0);
- vertices[1] = S3DVertex((f32)end.X, (f32)end.Y, 0, 0, 0, 1, color, 1, 1);
- drawVertexPrimitiveList2d3d(vertices, 2, indices, 1, video::EVT_STANDARD, scene::EPT_LINES, EIT_16BIT, false);
- }
- //! Draws a pixel
- void COGLES2Driver::drawPixel(u32 x, u32 y, const SColor &color)
- {
- const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();
- if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height)
- return;
- disableTextures();
- setRenderStates2DMode(color.getAlpha() < 255, false, false);
- u16 indices[] = {0};
- S3DVertex vertices[1];
- vertices[0] = S3DVertex((f32)x, (f32)y, 0, 0, 0, 1, color, 0, 0);
- drawVertexPrimitiveList2d3d(vertices, 1, indices, 1, video::EVT_STANDARD, scene::EPT_POINTS, EIT_16BIT, false);
- }
- bool COGLES2Driver::setActiveTexture(u32 stage, const video::ITexture* texture)
- {
- if (stage >= MaxSupportedTextures)
- return false;
- if (CurrentTexture[stage]==texture)
- return true;
- CurrentTexture[stage] = texture;
- if (!texture)
- return true;
- else if (texture->getDriverType() != EDT_OGLES2)
- {
- CurrentTexture[stage] = 0;
- os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
- return false;
- }
- return true;
- }
- bool COGLES2Driver::isActiveTexture(u32 stage)
- {
- return (CurrentTexture[stage]) ? true : false;
- }
- //! disables all textures beginning with the optional fromStage parameter.
- bool COGLES2Driver::disableTextures(u32 fromStage)
- {
- bool result = true;
- for (u32 i = fromStage; i < MaxTextureUnits; ++i)
- result &= setActiveTexture(i, 0);
- return result;
- }
- //! creates a matrix in supplied GLfloat array to pass to OGLES1
- inline void COGLES2Driver::createGLMatrix(float gl_matrix[16], const core::matrix4& m)
- {
- memcpy(gl_matrix, m.pointer(), 16 * sizeof(f32));
- }
- //! creates a opengltexturematrix from a D3D style texture matrix
- inline void COGLES2Driver::createGLTextureMatrix(float *o, const core::matrix4& m)
- {
- o[0] = m[0];
- o[1] = m[1];
- o[2] = 0.f;
- o[3] = 0.f;
- o[4] = m[4];
- o[5] = m[5];
- o[6] = 0.f;
- o[7] = 0.f;
- o[8] = 0.f;
- o[9] = 0.f;
- o[10] = 1.f;
- o[11] = 0.f;
- o[12] = m[8];
- o[13] = m[9];
- o[14] = 0.f;
- o[15] = 1.f;
- }
- //! returns a device dependent texture from a software surface (IImage)
- video::ITexture* COGLES2Driver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData)
- {
- return new COGLES2Texture(surface, name, mipmapData, this);
- }
- //! Sets a material.
- void COGLES2Driver::setMaterial(const SMaterial& material)
- {
- Material = material;
- OverrideMaterial.apply(Material);
- for (u32 i = 0; i < MaxTextureUnits; ++i)
- setActiveTexture(i, material.getTexture(i));
- }
- //! prints error if an error happened.
- bool COGLES2Driver::testGLError()
- {
- #ifdef _DEBUG
- GLenum g = glGetError();
- switch (g)
- {
- case GL_NO_ERROR:
- return false;
- case GL_INVALID_ENUM:
- os::Printer::log("GL_INVALID_ENUM", ELL_ERROR);
- break;
- case GL_INVALID_VALUE:
- os::Printer::log("GL_INVALID_VALUE", ELL_ERROR);
- break;
- case GL_INVALID_OPERATION:
- os::Printer::log("GL_INVALID_OPERATION", ELL_ERROR);
- break;
- case GL_OUT_OF_MEMORY:
- os::Printer::log("GL_OUT_OF_MEMORY", ELL_ERROR);
- break;
- };
- return true;
- #else
- return false;
- #endif
- }
- //! prints error if an error happened.
- bool COGLES2Driver::testEGLError()
- {
- #if defined(EGL_VERSION_1_0) && defined(_DEBUG)
- EGLint g = eglGetError();
- switch (g)
- {
- case EGL_SUCCESS:
- return false;
- case EGL_NOT_INITIALIZED :
- os::Printer::log("Not Initialized", ELL_ERROR);
- break;
- case EGL_BAD_ACCESS:
- os::Printer::log("Bad Access", ELL_ERROR);
- break;
- case EGL_BAD_ALLOC:
- os::Printer::log("Bad Alloc", ELL_ERROR);
- break;
- case EGL_BAD_ATTRIBUTE:
- os::Printer::log("Bad Attribute", ELL_ERROR);
- break;
- case EGL_BAD_CONTEXT:
- os::Printer::log("Bad Context", ELL_ERROR);
- break;
- case EGL_BAD_CONFIG:
- os::Printer::log("Bad Config", ELL_ERROR);
- break;
- case EGL_BAD_CURRENT_SURFACE:
- os::Printer::log("Bad Current Surface", ELL_ERROR);
- break;
- case EGL_BAD_DISPLAY:
- os::Printer::log("Bad Display", ELL_ERROR);
- break;
- case EGL_BAD_SURFACE:
- os::Printer::log("Bad Surface", ELL_ERROR);
- break;
- case EGL_BAD_MATCH:
- os::Printer::log("Bad Match", ELL_ERROR);
- break;
- case EGL_BAD_PARAMETER:
- os::Printer::log("Bad Parameter", ELL_ERROR);
- break;
- case EGL_BAD_NATIVE_PIXMAP:
- os::Printer::log("Bad Native Pixmap", ELL_ERROR);
- break;
- case EGL_BAD_NATIVE_WINDOW:
- os::Printer::log("Bad Native Window", ELL_ERROR);
- break;
- case EGL_CONTEXT_LOST:
- os::Printer::log("Context Lost", ELL_ERROR);
- break;
- };
- return true;
- #else
- return false;
- #endif
- }
- void COGLES2Driver::setRenderStates3DMode()
- {
- if (useCoreContext)
- return;
- if (CurrentRenderMode != ERM_3D)
- {
- // Reset Texture Stages
- BridgeCalls->setBlend(false);
- BridgeCalls->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- ResetRenderStates = true;
- }
- if (ResetRenderStates || LastMaterial != Material)
- {
- // unset old material
- // unset last 3d material
- if (CurrentRenderMode == ERM_2D)
- MaterialRenderer2D->OnUnsetMaterial();
- else if (LastMaterial.MaterialType != Material.MaterialType &&
- static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())
- MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();
- // set new material.
- if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())
- MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial(
- Material, LastMaterial, ResetRenderStates, this);
- LastMaterial = Material;
- ResetRenderStates = false;
- }
- if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())
- MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, video::EVT_STANDARD);
- CurrentRenderMode = ERM_3D;
- }
- //! Can be called by an IMaterialRenderer to make its work easier.
- void COGLES2Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderStates)
- {
- if (useCoreContext)
- return;
- // ZBuffer
- if (resetAllRenderStates || lastmaterial.ZBuffer != material.ZBuffer)
- {
- switch (material.ZBuffer)
- {
- case ECFN_NEVER: // it will be ECFN_DISABLED after merge
- BridgeCalls->setDepthTest(false);
- break;
- case ECFN_LESSEQUAL:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_LEQUAL);
- break;
- case ECFN_EQUAL:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_EQUAL);
- break;
- case ECFN_LESS:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_LESS);
- break;
- case ECFN_NOTEQUAL:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_NOTEQUAL);
- break;
- case ECFN_GREATEREQUAL:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_GEQUAL);
- break;
- case ECFN_GREATER:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_GREATER);
- break;
- case ECFN_ALWAYS:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_ALWAYS);
- break;
- /*case ECFN_NEVER:
- BridgeCalls->setDepthTest(true);
- BridgeCalls->setDepthFunc(GL_NEVER);
- break;*/
- }
- }
- // ZWrite
- // if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable)
- {
- if (material.ZWriteEnable && (AllowZWriteOnTransparent || !material.isTransparent()))
- BridgeCalls->setDepthMask(true);
- else
- BridgeCalls->setDepthMask(false);
- }
- // Back face culling
- if (resetAllRenderStates || (lastmaterial.FrontfaceCulling != material.FrontfaceCulling) || (lastmaterial.BackfaceCulling != material.BackfaceCulling))
- {
- if ((material.FrontfaceCulling) && (material.BackfaceCulling))
- {
- BridgeCalls->setCullFaceFunc(GL_FRONT_AND_BACK);
- BridgeCalls->setCullFace(true);
- }
- else
- if (material.BackfaceCulling)
- {
- BridgeCalls->setCullFaceFunc(GL_BACK);
- BridgeCalls->setCullFace(true);
- }
- else
- if (material.FrontfaceCulling)
- {
- BridgeCalls->setCullFaceFunc(GL_FRONT);
- BridgeCalls->setCullFace(true);
- }
- else
- BridgeCalls->setCullFace(false);
- }
- // Color Mask
- if (resetAllRenderStates || lastmaterial.ColorMask != material.ColorMask)
- {
- glColorMask(
- (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE,
- (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE,
- (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE,
- (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE);
- }
- // Blend operation
- if (resetAllRenderStates|| lastmaterial.BlendOperation != material.BlendOperation)
- {
- if (material.BlendOperation==EBO_NONE)
- BridgeCalls->setBlend(false);
- else
- {
- BridgeCalls->setBlend(true);
- switch (material.BlendOperation)
- {
- case EBO_ADD:
- glBlendEquation(GL_FUNC_ADD);
- break;
- case EBO_SUBTRACT:
- glBlendEquation(GL_FUNC_SUBTRACT);
- break;
- case EBO_REVSUBTRACT:
- glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
- break;
- default:
- break;
- }
- }
- }
- // Anti aliasing
- if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing)
- {
- if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)
- glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)
- glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
- }
- // Texture parameters
- setTextureRenderStates(material, resetAllRenderStates);
- }
- //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call.
- void COGLES2Driver::setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates)
- {
- if (useCoreContext)
- return;
- // Set textures to TU/TIU and apply filters to them
- for (s32 i = MaxTextureUnits-1; i>= 0; --i)
- {
- const COGLES2Texture* tmpTexture = static_cast<const COGLES2Texture*>(CurrentTexture[i]);
- if (CurrentTexture[i])
- BridgeCalls->setTexture(i);
- else
- continue;
- // This code causes issues on some devices with legacy pipeline
- // and also mipmaps should be handled in STK texture manager,
- // so just disable this part of code
- continue;
- if(resetAllRenderstates)
- tmpTexture->getStatesCache().IsCached = false;
- if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
- material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
- tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
- tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
- }
- if (material.UseMipMaps && CurrentTexture[i]->hasMipMaps())
- {
- if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
- material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || !tmpTexture->getStatesCache().MipMapStatus)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
- material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
- GL_NEAREST_MIPMAP_NEAREST);
- tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
- tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
- tmpTexture->getStatesCache().MipMapStatus = true;
- }
- }
- else
- {
- if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
- material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || tmpTexture->getStatesCache().MipMapStatus)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
- tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
- tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
- tmpTexture->getStatesCache().MipMapStatus = false;
- }
- }
- #ifdef GL_EXT_texture_filter_anisotropic
- if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic] &&
- (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].AnisotropicFilter != tmpTexture->getStatesCache().AnisotropicFilter))
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1);
- tmpTexture->getStatesCache().AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter;
- }
- #endif
- if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapU != tmpTexture->getStatesCache().WrapU)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[i].TextureWrapU));
- tmpTexture->getStatesCache().WrapU = material.TextureLayer[i].TextureWrapU;
- }
- if(!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapV != tmpTexture->getStatesCache().WrapV)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[i].TextureWrapV));
- tmpTexture->getStatesCache().WrapV = material.TextureLayer[i].TextureWrapV;
- }
- tmpTexture->getStatesCache().IsCached = true;
- }
- }
- // Get OpenGL ES2.0 texture wrap mode from Irrlicht wrap mode.
- GLint COGLES2Driver::getTextureWrapMode(u8 clamp) const
- {
- switch (clamp)
- {
- case ETC_CLAMP:
- case ETC_CLAMP_TO_EDGE:
- case ETC_CLAMP_TO_BORDER:
- return GL_CLAMP_TO_EDGE;
- case ETC_MIRROR:
- return GL_REPEAT;
- default:
- return GL_REPEAT;
- }
- }
- //! sets the needed renderstates
- void COGLES2Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel)
- {
- if (useCoreContext)
- return;
- if (CurrentRenderMode != ERM_2D)
- {
- // unset last 3d material
- if (CurrentRenderMode == ERM_3D)
- {
- if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())
- MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();
- }
- CurrentRenderMode = ERM_2D;
- }
- if (!OverrideMaterial2DEnabled)
- Material = InitMaterial2D;
- if (OverrideMaterial2DEnabled)
- {
- OverrideMaterial2D.Lighting=false;
- OverrideMaterial2D.ZWriteEnable=false;
- OverrideMaterial2D.ZBuffer=ECFN_NEVER; // it will be ECFN_DISABLED after merge
- OverrideMaterial2D.Lighting=false;
- Material = OverrideMaterial2D;
- }
- if (texture)
- MaterialRenderer2D->setTexture(CurrentTexture[0]);
- else
- MaterialRenderer2D->setTexture(0);
- MaterialRenderer2D->OnSetMaterial(Material, LastMaterial, true, 0);
- LastMaterial = Material;
- // no alphaChannel without texture
- alphaChannel &= texture;
- if (alphaChannel || alpha)
- {
- BridgeCalls->setBlend(true);
- BridgeCalls->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- else
- BridgeCalls->setBlend(false);
- MaterialRenderer2D->OnRender(this, video::EVT_STANDARD);
- }
- //! \return Returns the name of the video driver.
- const wchar_t* COGLES2Driver::getName() const
- {
- return Name.c_str();
- }
- //! deletes all dynamic lights there are
- void COGLES2Driver::deleteAllDynamicLights()
- {
- RequestedLights.clear();
- CNullDriver::deleteAllDynamicLights();
- }
- //! adds a dynamic light
- s32 COGLES2Driver::addDynamicLight(const SLight& light)
- {
- CNullDriver::addDynamicLight(light);
- RequestedLights.push_back(RequestedLight(light));
- u32 newLightIndex = RequestedLights.size() - 1;
- return (s32)newLightIndex;
- }
- //! Turns a dynamic light on or off
- //! \param lightIndex: the index returned by addDynamicLight
- //! \param turnOn: true to turn the light on, false to turn it off
- void COGLES2Driver::turnLightOn(s32 lightIndex, bool turnOn)
- {
- if (lightIndex < 0 || lightIndex >= (s32)RequestedLights.size())
- return;
- RequestedLight & requestedLight = RequestedLights[lightIndex];
- requestedLight.DesireToBeOn = turnOn;
- }
- //! returns the maximal amount of dynamic lights the device can handle
- u32 COGLES2Driver::getMaximalDynamicLightAmount() const
- {
- return 8;
- }
- //! Sets the dynamic ambient light color.
- void COGLES2Driver::setAmbientLight(const SColorf& color)
- {
- AmbientLight = color;
- }
- //! returns the dynamic ambient light color.
- const SColorf& COGLES2Driver::getAmbientLight() const
- {
- return AmbientLight;
- }
- // this code was sent in by Oliver Klems, thank you
- void COGLES2Driver::setViewPort(const core::rect<s32>& area)
- {
- core::rect<s32> vp = area;
- core::rect<s32> rendert(0, 0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height);
- vp.clipAgainst(rendert);
- if (vp.getHeight() > 0 && vp.getWidth() > 0)
- BridgeCalls->setViewport(core::rect<s32>(vp.UpperLeftCorner.X, getCurrentRenderTargetSize().Height - vp.UpperLeftCorner.Y - vp.getHeight(), vp.getWidth(), vp.getHeight()));
- ViewPort = vp;
- testGLError();
- }
- //! Draws a shadow volume into the stencil buffer.
- void COGLES2Driver::drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail)
- {
- if (!StencilBuffer || !count)
- return;
- // unset last 3d material
- if (CurrentRenderMode == ERM_3D &&
- static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())
- {
- MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial();
- ResetRenderStates = true;
- }
- // store current OGLES state
- const GLboolean cullFaceEnabled = glIsEnabled(GL_CULL_FACE);
- GLint cullFaceMode;
- glGetIntegerv(GL_CULL_FACE_MODE, &cullFaceMode);
- GLint depthFunc;
- glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
- GLboolean depthMask;
- glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
- glDepthFunc(GL_LEQUAL);
- glDepthMask(GL_FALSE); // no depth buffer writing
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color buffer drawing
- glEnable(GL_STENCIL_TEST);
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(0.0f, 1.0f);
- glEnableVertexAttribArray(EVA_POSITION);
- glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(core::vector3df), &triangles[0]);
- glStencilMask(~0);
- glStencilFunc(GL_ALWAYS, 0, ~0);
- GLenum decr = GL_DECR;
- GLenum incr = GL_INCR;
- #if defined(GL_OES_stencil_wrap)
- if (FeatureAvailable[IRR_OES_stencil_wrap])
- {
- decr = GL_DECR_WRAP_OES;
- incr = GL_INCR_WRAP_OES;
- }
- #endif
- glEnable(GL_CULL_FACE);
- if (!zfail)
- {
- // ZPASS Method
- glCullFace(GL_BACK);
- glStencilOp(GL_KEEP, GL_KEEP, incr);
- glDrawArrays(GL_TRIANGLES, 0, count);
- glCullFace(GL_FRONT);
- glStencilOp(GL_KEEP, GL_KEEP, decr);
- glDrawArrays(GL_TRIANGLES, 0, count);
- }
- else
- {
- // ZFAIL Method
- glStencilOp(GL_KEEP, incr, GL_KEEP);
- glCullFace(GL_FRONT);
- glDrawArrays(GL_TRIANGLES, 0, count);
- glStencilOp(GL_KEEP, decr, GL_KEEP);
- glCullFace(GL_BACK);
- glDrawArrays(GL_TRIANGLES, 0, count);
- }
- glDisableVertexAttribArray(EVA_POSITION);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glDisable(GL_STENCIL_TEST);
- if (cullFaceEnabled)
- glEnable(GL_CULL_FACE);
- else
- glDisable(GL_CULL_FACE);
- glCullFace(cullFaceMode);
- glDepthFunc(depthFunc);
- glDepthMask(depthMask);
- testGLError();
- }
- void COGLES2Driver::drawStencilShadow(bool clearStencilBuffer,
- video::SColor leftUpEdge, video::SColor rightUpEdge,
- video::SColor leftDownEdge, video::SColor rightDownEdge)
- {
- if (!StencilBuffer)
- return;
- disableTextures();
- // store attributes
- GLboolean depthMask;
- glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
- // GLint shadeModel;
- //TODO : OpenGL ES 2.0 Port glGetIntegerv
- //glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
- glDepthMask(GL_FALSE);
- //TODO : OpenGL ES 2.0 Port glShadeModel
- //glShadeModel(GL_FLAT);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_NOTEQUAL, 0, ~0);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- // draw a shadow rectangle covering the entire screen using stencil buffer
- //Wrapper->glMatrixMode(GL_MODELVIEW);
- //TODO : OpenGL ES 2.0 Port glPushMatrix
- //glPushMatrix();
- //Wrapper->glLoadIdentity();
- //Wrapper->glMatrixMode(GL_PROJECTION);
- //TODO : OpenGL ES 2.0 Port glPushMatrix
- //glPushMatrix();
- //Wrapper->glLoadIdentity();
- u16 indices[] = {0, 1, 2, 3};
- S3DVertex vertices[4];
- vertices[0] = S3DVertex(-1.f, -1.f, 0.9f, 0, 0, 1, leftDownEdge, 0, 0);
- vertices[1] = S3DVertex(-1.f, 1.f, 0.9f, 0, 0, 1, leftUpEdge, 0, 0);
- vertices[2] = S3DVertex(1.f, 1.f, 0.9f, 0, 0, 1, rightUpEdge, 0, 0);
- vertices[3] = S3DVertex(1.f, -1.f, 0.9f, 0, 0, 1, rightDownEdge, 0, 0);
- drawVertexPrimitiveList2d3d(vertices, 4, indices, 2, video::EVT_STANDARD, scene::EPT_TRIANGLE_FAN, EIT_16BIT, false);
- if (clearStencilBuffer)
- glClear(GL_STENCIL_BUFFER_BIT);
- // restore settings
- //TODO : OpenGL ES 2.0 Port glPopMatrix
- //glPopMatrix();
- //Wrapper->glMatrixMode(GL_MODELVIEW);
- //TODO : OpenGL ES 2.0 Port glPopMatrix
- //glPopMatrix();
- glDisable(GL_STENCIL_TEST);
- glDepthMask(depthMask);
- //TODO : OpenGL ES 2.0 Port glShadeModel
- //glShadeModel(shadeModel);
- }
- //! Draws a 3d line.
- void COGLES2Driver::draw3DLine(const core::vector3df& start,
- const core::vector3df& end, SColor color)
- {
- setRenderStates3DMode();
- u16 indices[] = {0, 1};
- S3DVertex vertices[2];
- vertices[0] = S3DVertex(start.X, start.Y, start.Z, 0, 0, 1, color, 0, 0);
- vertices[1] = S3DVertex(end.X, end.Y, end.Z, 0, 0, 1, color, 0, 0);
- drawVertexPrimitiveList2d3d(vertices, 2, indices, 1, video::EVT_STANDARD, scene::EPT_LINES);
- }
- //! Only used by the internal engine. Used to notify the driver that
- //! the window was resized.
- void COGLES2Driver::OnResize(const core::dimension2d<u32>& size)
- {
- CNullDriver::OnResize(size);
- BridgeCalls->setViewport(core::rect<s32>(0, 0, size.Width, size.Height));
- testGLError();
- }
- //! Returns type of video driver
- E_DRIVER_TYPE COGLES2Driver::getDriverType() const
- {
- return EDT_OGLES2;
- }
- //! returns color format
- ECOLOR_FORMAT COGLES2Driver::getColorFormat() const
- {
- return ColorFormat;
- }
- //! Get a vertex shader constant index.
- s32 COGLES2Driver::getVertexShaderConstantID(const c8* name)
- {
- return getPixelShaderConstantID(name);
- }
- //! Get a pixel shader constant index.
- s32 COGLES2Driver::getPixelShaderConstantID(const c8* name)
- {
- os::Printer::log("Error: Please call services->getPixelShaderConstantID(), not VideoDriver->getPixelShaderConstantID().");
- return -1;
- }
- //! Sets a vertex shader constant.
- void COGLES2Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
- {
- os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setPixelShaderConstant().");
- }
- //! Sets a pixel shader constant.
- void COGLES2Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
- {
- os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");
- }
- //! Sets a constant for the vertex shader based on an index.
- bool COGLES2Driver::setVertexShaderConstant(s32 index, const f32* floats, int count)
- {
- //pass this along, as in GLSL the same routine is used for both vertex and fragment shaders
- return setPixelShaderConstant(index, floats, count);
- }
- //! Int interface for the above.
- bool COGLES2Driver::setVertexShaderConstant(s32 index, const s32* ints, int count)
- {
- return setPixelShaderConstant(index, ints, count);
- }
- //! Sets a constant for the pixel shader based on an index.
- bool COGLES2Driver::setPixelShaderConstant(s32 index, const f32* floats, int count)
- {
- os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");
- return false;
- }
- //! Int interface for the above.
- bool COGLES2Driver::setPixelShaderConstant(s32 index, const s32* ints, int count)
- {
- os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");
- return false;
- }
- //! Adds a new material renderer to the VideoDriver, using pixel and/or
- //! vertex shaders to render geometry.
- s32 COGLES2Driver::addShaderMaterial(const c8* vertexShaderProgram,
- const c8* pixelShaderProgram,
- IShaderConstantSetCallBack* callback,
- E_MATERIAL_TYPE baseMaterial, s32 userData)
- {
- os::Printer::log("No shader support.");
- return -1;
- }
- //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.
- s32 COGLES2Driver::addHighLevelShaderMaterial(
- const c8* vertexShaderProgram,
- const c8* vertexShaderEntryPointName,
- E_VERTEX_SHADER_TYPE vsCompileTarget,
- const c8* pixelShaderProgram,
- const c8* pixelShaderEntryPointName,
- E_PIXEL_SHADER_TYPE psCompileTarget,
- const c8* geometryShaderProgram,
- const c8* geometryShaderEntryPointName,
- E_GEOMETRY_SHADER_TYPE gsCompileTarget,
- scene::E_PRIMITIVE_TYPE inType,
- scene::E_PRIMITIVE_TYPE outType,
- u32 verticesOut,
- IShaderConstantSetCallBack* callback,
- E_MATERIAL_TYPE baseMaterial,
- s32 userData, E_GPU_SHADING_LANGUAGE shadingLang)
- {
- s32 nr = -1;
- COGLES2MaterialRenderer* r = new COGLES2MaterialRenderer(
- this, nr, vertexShaderProgram,
- pixelShaderProgram,
- callback, baseMaterial, userData);
- r->drop();
- return nr;
- }
- //! Returns a pointer to the IVideoDriver interface. (Implementation for
- //! IMaterialRendererServices)
- IVideoDriver* COGLES2Driver::getVideoDriver()
- {
- return this;
- }
- //! Returns pointer to the IGPUProgrammingServices interface.
- IGPUProgrammingServices* COGLES2Driver::getGPUProgrammingServices()
- {
- return this;
- }
- ITexture* COGLES2Driver::addRenderTargetTexture(const core::dimension2d<u32>& size,
- const io::path& name,
- const ECOLOR_FORMAT format,
- const bool useStencil)
- {
- //disable mip-mapping
- const bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
- setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);
- video::ITexture* rtt = 0;
- rtt = new COGLES2FBOTexture(size, name, this, format);
- if (rtt)
- {
- bool success = false;
- addTexture(rtt);
- ITexture* tex = createDepthTexture(rtt);
- if (tex)
- {
- success = static_cast<video::COGLES2FBODepthTexture*>(tex)->attach(rtt);
- if (!success)
- {
- removeDepthTexture(tex);
- }
- tex->drop();
- }
- rtt->drop();
- if (!success)
- {
- removeTexture(rtt);
- rtt=0;
- }
- }
- //restore mip-mapping
- setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels);
- return rtt;
- }
- //! Returns the maximum amount of primitives
- u32 COGLES2Driver::getMaximalPrimitiveCount() const
- {
- return 65535;
- }
- //! set or reset render target
- bool COGLES2Driver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
- bool clearZBuffer, SColor color)
- {
- // check for right driver type
- if (texture && texture->getDriverType() != EDT_OGLES2)
- {
- os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
- return false;
- }
- // check if we should set the previous RT back
- setActiveTexture(0, 0);
- ResetRenderStates = true;
- if (RenderTargetTexture != 0)
- {
- RenderTargetTexture->unbindRTT();
- }
- if (texture)
- {
- // we want to set a new target. so do this.
- BridgeCalls->setViewport(core::rect<s32>(0, 0, texture->getSize().Width, texture->getSize().Height));
- RenderTargetTexture = static_cast<COGLES2Texture*>(texture);
- RenderTargetTexture->bindRTT();
- CurrentRendertargetSize = texture->getSize();
- }
- else
- {
- BridgeCalls->setViewport(core::rect<s32>(0, 0, ScreenSize.Width, ScreenSize.Height));
- RenderTargetTexture = 0;
- CurrentRendertargetSize = core::dimension2d<u32>(0, 0);
- }
- GLbitfield mask = 0;
- if (clearBackBuffer)
- {
- const f32 inv = 1.0f / 255.0f;
- glClearColor(color.getRed() * inv, color.getGreen() * inv,
- color.getBlue() * inv, color.getAlpha() * inv);
- mask |= GL_COLOR_BUFFER_BIT;
- }
- if (clearZBuffer)
- {
- glDepthMask(GL_TRUE);
- LastMaterial.ZWriteEnable = true;
- mask |= GL_DEPTH_BUFFER_BIT;
- }
- glClear(mask);
- testGLError();
- return true;
- }
- // returns the current size of the screen or rendertarget
- const core::dimension2d<u32>& COGLES2Driver::getCurrentRenderTargetSize() const
- {
- if (CurrentRendertargetSize.Width == 0)
- return ScreenSize;
- else
- return CurrentRendertargetSize;
- }
- //! Clears the ZBuffer.
- void COGLES2Driver::clearZBuffer()
- {
- GLboolean enabled = GL_TRUE;
- glGetBooleanv(GL_DEPTH_WRITEMASK, &enabled);
- glDepthMask(GL_TRUE);
- glClear(GL_DEPTH_BUFFER_BIT);
- glDepthMask(enabled);
- testGLError();
- }
- //! Returns an image created from the last rendered frame.
- // We want to read the front buffer to get the latest render finished.
- // This is not possible under ogl-es, though, so one has to call this method
- // outside of the render loop only.
- IImage* COGLES2Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
- {
- if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS)
- return 0;
- GLint internalformat = GL_RGBA;
- GLint type = GL_UNSIGNED_BYTE;
- {
- // glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &internalformat);
- // glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);
- // there's a format we don't support ATM
- if (GL_UNSIGNED_SHORT_4_4_4_4 == type)
- {
- internalformat = GL_RGBA;
- type = GL_UNSIGNED_BYTE;
- }
- }
- IImage* newImage = 0;
- if (GL_RGBA == internalformat)
- {
- if (GL_UNSIGNED_BYTE == type)
- newImage = new CImage(ECF_A8R8G8B8, ScreenSize);
- else
- newImage = new CImage(ECF_A1R5G5B5, ScreenSize);
- }
- else
- {
- if (GL_UNSIGNED_BYTE == type)
- newImage = new CImage(ECF_R8G8B8, ScreenSize);
- else
- newImage = new CImage(ECF_R5G6B5, ScreenSize);
- }
- if (!newImage)
- return 0;
- u8* pixels = static_cast<u8*>(newImage->lock());
- if (!pixels)
- {
- newImage->unlock();
- newImage->drop();
- return 0;
- }
- glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, internalformat, type, pixels);
- testGLError();
- // opengl images are horizontally flipped, so we have to fix that here.
- const s32 pitch = newImage->getPitch();
- u8* p2 = pixels + (ScreenSize.Height - 1) * pitch;
- u8* tmpBuffer = new u8[pitch];
- for (u32 i = 0; i < ScreenSize.Height; i += 2)
- {
- memcpy(tmpBuffer, pixels, pitch);
- memcpy(pixels, p2, pitch);
- memcpy(p2, tmpBuffer, pitch);
- pixels += pitch;
- p2 -= pitch;
- }
- delete [] tmpBuffer;
- newImage->unlock();
- if (testGLError())
- {
- newImage->drop();
- return 0;
- }
- testGLError();
- return newImage;
- }
- //! get depth texture for the given render target texture
- ITexture* COGLES2Driver::createDepthTexture(ITexture* texture, bool shared)
- {
- if ((texture->getDriverType() != EDT_OGLES2) || (!texture->isRenderTarget()))
- return 0;
- COGLES2Texture* tex = static_cast<COGLES2Texture*>(texture);
- if (!tex->isFrameBufferObject())
- return 0;
- if (shared)
- {
- for (u32 i = 0; i < DepthTextures.size(); ++i)
- {
- if (DepthTextures[i]->getSize() == texture->getSize())
- {
- DepthTextures[i]->grab();
- return DepthTextures[i];
- }
- }
- DepthTextures.push_back(new COGLES2FBODepthTexture(texture->getSize(), "depth1", this));
- return DepthTextures.getLast();
- }
- return (new COGLES2FBODepthTexture(texture->getSize(), "depth1", this));
- }
- void COGLES2Driver::removeDepthTexture(ITexture* texture)
- {
- for (u32 i = 0; i < DepthTextures.size(); ++i)
- {
- if (texture == DepthTextures[i])
- {
- DepthTextures.erase(i);
- return;
- }
- }
- }
- void COGLES2Driver::deleteFramebuffers(s32 n, const u32 *framebuffers)
- {
- glDeleteFramebuffers(n, framebuffers);
- }
- void COGLES2Driver::deleteRenderbuffers(s32 n, const u32 *renderbuffers)
- {
- glDeleteRenderbuffers(n, renderbuffers);
- }
- //! Set/unset a clipping plane.
- bool COGLES2Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)
- {
- if (index >= UserClipPlane.size())
- UserClipPlane.push_back(SUserClipPlane());
- UserClipPlane[index].Plane = plane;
- UserClipPlane[index].Enabled = enable;
- return true;
- }
- //! Enable/disable a clipping plane.
- void COGLES2Driver::enableClipPlane(u32 index, bool enable)
- {
- UserClipPlane[index].Enabled = enable;
- }
- //! Get the ClipPlane Count
- u32 COGLES2Driver::getClipPlaneCount() const
- {
- return UserClipPlane.size();
- }
- const core::plane3df& COGLES2Driver::getClipPlane(irr::u32 index) const
- {
- if (index < UserClipPlane.size())
- return UserClipPlane[index].Plane;
- else
- return *((core::plane3df*)0);
- }
- core::dimension2du COGLES2Driver::getMaxTextureSize() const
- {
- return core::dimension2du(MaxTextureSize, MaxTextureSize);
- }
- GLenum COGLES2Driver::getGLBlend(E_BLEND_FACTOR factor) const
- {
- GLenum r = 0;
- switch (factor)
- {
- case EBF_ZERO: r = GL_ZERO; break;
- case EBF_ONE: r = GL_ONE; break;
- case EBF_DST_COLOR: r = GL_DST_COLOR; break;
- case EBF_ONE_MINUS_DST_COLOR: r = GL_ONE_MINUS_DST_COLOR; break;
- case EBF_SRC_COLOR: r = GL_SRC_COLOR; break;
- case EBF_ONE_MINUS_SRC_COLOR: r = GL_ONE_MINUS_SRC_COLOR; break;
- case EBF_SRC_ALPHA: r = GL_SRC_ALPHA; break;
- case EBF_ONE_MINUS_SRC_ALPHA: r = GL_ONE_MINUS_SRC_ALPHA; break;
- case EBF_DST_ALPHA: r = GL_DST_ALPHA; break;
- case EBF_ONE_MINUS_DST_ALPHA: r = GL_ONE_MINUS_DST_ALPHA; break;
- case EBF_SRC_ALPHA_SATURATE: r = GL_SRC_ALPHA_SATURATE; break;
- }
- return r;
- }
- GLenum COGLES2Driver::getZBufferBits() const
- {
- /*#if defined(GL_OES_depth24)
- if (Driver->queryOpenGLFeature(COGLES2ExtensionHandler::IRR_OES_depth24))
- InternalFormat = GL_DEPTH_COMPONENT24_OES;
- else
- #endif
- #if defined(GL_OES_depth32)
- if (Driver->queryOpenGLFeature(COGLES2ExtensionHandler::IRR_OES_depth32))
- InternalFormat = GL_DEPTH_COMPONENT32_OES;
- else
- #endif*/
- GLenum bits = GL_DEPTH_COMPONENT16;//0;
- /*switch (Params.ZBufferBits)
- {
- case 16:
- bits = GL_DEPTH_COMPONENT16;
- break;
- case 24:
- bits = GL_DEPTH_COMPONENT24;
- break;
- case 32:
- bits = GL_DEPTH_COMPONENT32;
- break;
- default:
- bits = GL_DEPTH_COMPONENT;
- break;
- }*/
- return bits;
- }
- const SMaterial& COGLES2Driver::getCurrentMaterial() const
- {
- return Material;
- }
- COGLES2CallBridge* COGLES2Driver::getBridgeCalls() const
- {
- return BridgeCalls;
- }
- COGLES2CallBridge::COGLES2CallBridge(COGLES2Driver* driver) : Driver(driver),
- BlendSource(GL_ONE), BlendDestination(GL_ZERO), Blend(false),
- CullFaceMode(GL_BACK), CullFace(false),
- DepthFunc(GL_LESS), DepthMask(true), DepthTest(false),
- Program(0), ActiveTexture(GL_TEXTURE0), Viewport(core::rect<s32>(0, 0, 0, 0))
- {
- // Initial OpenGL values from specification.
- for (u32 i = 0; i < MATERIAL_MAX_TEXTURES; ++i)
- Texture[i] = 0;
- glBlendFunc(GL_ONE, GL_ZERO);
- glDisable(GL_BLEND);
- glCullFace(GL_BACK);
- glDisable(GL_CULL_FACE);
- glDepthFunc(GL_LESS);
- glDepthMask(GL_TRUE);
- glDisable(GL_DEPTH_TEST);
- }
- void COGLES2CallBridge::setBlendFunc(GLenum source, GLenum destination)
- {
- if(BlendSource != source || BlendDestination != destination)
- {
- glBlendFunc(source, destination);
- BlendSource = source;
- BlendDestination = destination;
- }
- }
- void COGLES2CallBridge::setBlend(bool enable)
- {
- if(Blend != enable)
- {
- if (enable)
- glEnable(GL_BLEND);
- else
- glDisable(GL_BLEND);
- Blend = enable;
- }
- }
- void COGLES2CallBridge::setCullFaceFunc(GLenum mode)
- {
- if(CullFaceMode != mode)
- {
- glCullFace(mode);
- CullFaceMode = mode;
- }
- }
- void COGLES2CallBridge::setCullFace(bool enable)
- {
- if(CullFace != enable)
- {
- if (enable)
- glEnable(GL_CULL_FACE);
- else
- glDisable(GL_CULL_FACE);
- CullFace = enable;
- }
- }
- void COGLES2CallBridge::setDepthFunc(GLenum mode)
- {
- if(DepthFunc != mode)
- {
- glDepthFunc(mode);
- DepthFunc = mode;
- }
- }
- void COGLES2CallBridge::setDepthMask(bool enable)
- {
- if(DepthMask != enable)
- {
- if (enable)
- glDepthMask(GL_TRUE);
- else
- glDepthMask(GL_FALSE);
- DepthMask = enable;
- }
- }
- void COGLES2CallBridge::setDepthTest(bool enable)
- {
- if(DepthTest != enable)
- {
- if (enable)
- glEnable(GL_DEPTH_TEST);
- else
- glDisable(GL_DEPTH_TEST);
- DepthTest = enable;
- }
- }
- void COGLES2CallBridge::setProgram(GLuint program)
- {
- if (Program != program)
- {
- glUseProgram(program);
- Program = program;
- }
- }
- void COGLES2CallBridge::setActiveTexture(GLenum texture)
- {
- if (ActiveTexture != texture)
- {
- glActiveTexture(texture);
- ActiveTexture = texture;
- }
- }
- void COGLES2CallBridge::setTexture(u32 stage)
- {
- if (stage < MATERIAL_MAX_TEXTURES)
- {
- if(Texture[stage] != Driver->CurrentTexture[stage])
- {
- setActiveTexture(GL_TEXTURE0 + stage);
- if(Driver->CurrentTexture[stage])
- glBindTexture(GL_TEXTURE_2D, Driver->CurrentTexture[stage]->getOpenGLTextureName());
- Texture[stage] = Driver->CurrentTexture[stage];
- }
- }
- }
- void COGLES2CallBridge::setViewport(const core::rect<s32>& viewport)
- {
- if (Viewport != viewport)
- {
- glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
- Viewport = viewport;
- }
- }
- } // end namespace
- } // end namespace
- #endif // _IRR_COMPILE_WITH_OGLES2_
- namespace irr
- {
- namespace video
- {
- #if !defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) && (defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_COMPILE_WITH_SDL_DEVICE_) || defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) || defined(_IRR_COMPILE_WITH_CONSOLE_DEVICE_))
- IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
- video::SExposedVideoData& data, io::IFileSystem* io)
- {
- #ifdef _IRR_COMPILE_WITH_OGLES2_
- return new COGLES2Driver(params, data, io);
- #else
- return 0;
- #endif // _IRR_COMPILE_WITH_OGLES2_
- }
- #endif
- // -----------------------------------
- // MACOSX VERSION
- // -----------------------------------
- #if defined(_IRR_COMPILE_WITH_OSX_DEVICE_)
- IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
- io::IFileSystem* io, CIrrDeviceMacOSX *device)
- {
- #ifdef _IRR_COMPILE_WITH_OGLES2_
- return new COGLES2Driver(params, io, device);
- #else
- return 0;
- #endif // _IRR_COMPILE_WITH_OGLES2_
- }
- #endif // _IRR_COMPILE_WITH_OSX_DEVICE_
- // -----------------------------------
- // IPHONE VERSION
- // -----------------------------------
- #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
- IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
- video::SExposedVideoData& data, io::IFileSystem* io,
- CIrrDeviceIPhone* device)
- {
- #ifdef _IRR_COMPILE_WITH_OGLES2_
- return new COGLES2Driver(params, data, io, device);
- #else
- return 0;
- #endif // _IRR_COMPILE_WITH_OGLES2_
- }
- #endif // _IRR_COMPILE_WITH_IPHONE_DEVICE_
- } // end namespace
- } // end namespace
|