NvEglRenderer.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. /*
  2. * Copyright (c) 2016-2022, NVIDIA CORPORATION. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of NVIDIA CORPORATION nor the names of its
  13. * contributors may be used to endorse or promote products derived
  14. * from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  20. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  21. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  22. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  23. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  24. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "NvEglRenderer.h"
  29. #include "NvLogging.h"
  30. #include "nvbufsurface.h"
  31. #include <cstring>
  32. #include <sys/time.h>
  33. #define CAT_NAME "EglRenderer"
  34. #define ERROR_GOTO_FAIL(val, string) \
  35. do { \
  36. if (val) {\
  37. CAT_DEBUG_MSG(string); \
  38. goto fail; \
  39. } \
  40. } while (0)
  41. PFNEGLCREATEIMAGEKHRPROC NvEglRenderer::eglCreateImageKHR;
  42. PFNEGLDESTROYIMAGEKHRPROC NvEglRenderer::eglDestroyImageKHR;
  43. PFNEGLCREATESYNCKHRPROC NvEglRenderer::eglCreateSyncKHR;
  44. PFNEGLDESTROYSYNCKHRPROC NvEglRenderer::eglDestroySyncKHR;
  45. PFNEGLCLIENTWAITSYNCKHRPROC NvEglRenderer::eglClientWaitSyncKHR;
  46. PFNEGLGETSYNCATTRIBKHRPROC NvEglRenderer::eglGetSyncAttribKHR;
  47. PFNGLEGLIMAGETARGETTEXTURE2DOESPROC NvEglRenderer::glEGLImageTargetTexture2DOES;
  48. using namespace std;
  49. NvEglRenderer::NvEglRenderer(const char *name, uint32_t width, uint32_t height,
  50. uint32_t x_offset, uint32_t y_offset)
  51. :NvElement(name, valid_fields)
  52. {
  53. int depth;
  54. int screen_num;
  55. XSetWindowAttributes window_attributes;
  56. x_window = 0;
  57. x_display = NULL;
  58. texture_id = 0;
  59. gc = NULL;
  60. fontinfo = NULL;
  61. egl_surface = EGL_NO_SURFACE;
  62. egl_context = EGL_NO_CONTEXT;
  63. egl_display = EGL_NO_DISPLAY;
  64. egl_config = NULL;
  65. memset(&last_render_time, 0, sizeof(last_render_time));
  66. stop_thread = false;
  67. render_thread = 0;
  68. render_fd = 0;
  69. memset(overlay_str, 0, sizeof(overlay_str));
  70. overlay_str_x_offset = 0;
  71. overlay_str_y_offset = 0;
  72. pthread_mutex_init(&render_lock, NULL);
  73. pthread_cond_init(&render_cond, NULL);
  74. setFPS(30);
  75. if (initEgl() < 0)
  76. {
  77. COMP_ERROR_MSG("Error getting EGL function addresses");
  78. goto error;
  79. }
  80. x_display = XOpenDisplay(NULL);
  81. if (NULL == x_display)
  82. {
  83. COMP_ERROR_MSG("Error in opening display");
  84. goto error;
  85. }
  86. screen_num = DefaultScreen(x_display);
  87. if (!width || !height)
  88. {
  89. width = DisplayWidth(x_display, screen_num);
  90. height = DisplayHeight(x_display, screen_num);
  91. x_offset = 0;
  92. y_offset = 0;
  93. }
  94. COMP_INFO_MSG("Setting Screen width " << width << " height " << height);
  95. COMP_DEBUG_MSG("Display opened successfully " << (size_t) x_display);
  96. depth = DefaultDepth(x_display, DefaultScreen(x_display));
  97. window_attributes.background_pixel =
  98. BlackPixel(x_display, DefaultScreen(x_display));
  99. window_attributes.override_redirect = 1;
  100. x_window = XCreateWindow(x_display,
  101. DefaultRootWindow(x_display), x_offset,
  102. y_offset, width, height,
  103. 0,
  104. depth, CopyFromParent,
  105. CopyFromParent,
  106. (CWBackPixel | CWOverrideRedirect),
  107. &window_attributes);
  108. XSelectInput(x_display, (int32_t) x_window, ExposureMask);
  109. XMapWindow(x_display, (int32_t) x_window);
  110. gc = XCreateGC(x_display, x_window, 0, NULL);
  111. XSetForeground(x_display, gc,
  112. WhitePixel(x_display, DefaultScreen(x_display)) );
  113. fontinfo = XLoadQueryFont(x_display, "9x15bold");
  114. pthread_mutex_lock(&render_lock);
  115. pthread_create(&render_thread, NULL, renderThread, this);
  116. pthread_setname_np(render_thread, "EglRenderer");
  117. pthread_cond_wait(&render_cond, &render_lock);
  118. pthread_mutex_unlock(&render_lock);
  119. if(isInError())
  120. {
  121. pthread_join(render_thread, NULL);
  122. goto error;
  123. }
  124. COMP_DEBUG_MSG("Renderer started successfully")
  125. return;
  126. error:
  127. COMP_ERROR_MSG("Got ERROR closing display");
  128. is_in_error = 1;
  129. }
  130. int
  131. NvEglRenderer::getDisplayResolution(uint32_t &width, uint32_t &height)
  132. {
  133. int screen_num;
  134. Display * x_display = XOpenDisplay(NULL);
  135. if (NULL == x_display)
  136. {
  137. return -1;
  138. }
  139. screen_num = DefaultScreen(x_display);
  140. width = DisplayWidth(x_display, screen_num);
  141. height = DisplayHeight(x_display, screen_num);
  142. XCloseDisplay(x_display);
  143. x_display = NULL;
  144. return 0;
  145. }
  146. void *
  147. NvEglRenderer::renderThread(void *arg)
  148. {
  149. EGLBoolean egl_status;
  150. NvEglRenderer *renderer = (NvEglRenderer *) arg;
  151. const char *comp_name = renderer->comp_name;
  152. static EGLint rgba8888[] = {
  153. EGL_RED_SIZE, 8,
  154. EGL_GREEN_SIZE, 8,
  155. EGL_BLUE_SIZE, 8,
  156. EGL_ALPHA_SIZE, 8,
  157. EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
  158. EGL_NONE,
  159. };
  160. int num_configs = 0;
  161. EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
  162. renderer->egl_display = eglGetDisplay(renderer->x_display);
  163. if (EGL_NO_DISPLAY == renderer->egl_display)
  164. {
  165. COMP_ERROR_MSG("Unable to get egl display");
  166. goto error;
  167. }
  168. COMP_DEBUG_MSG("Egl Got display " << (size_t) renderer->egl_display);
  169. egl_status = eglInitialize(renderer->egl_display, 0, 0);
  170. if (!egl_status)
  171. {
  172. COMP_ERROR_MSG("Unable to initialize egl library");
  173. goto error;
  174. }
  175. egl_status =
  176. eglChooseConfig(renderer->egl_display, rgba8888,
  177. &renderer->egl_config, 1, &num_configs);
  178. if (!egl_status)
  179. {
  180. COMP_ERROR_MSG("Error at eglChooseConfig");
  181. goto error;
  182. }
  183. COMP_DEBUG_MSG("Got numconfigs as " << num_configs);
  184. renderer->egl_context =
  185. eglCreateContext(renderer->egl_display, renderer->egl_config,
  186. EGL_NO_CONTEXT, context_attribs);
  187. if (eglGetError() != EGL_SUCCESS)
  188. {
  189. COMP_ERROR_MSG("Got Error in eglCreateContext " << eglGetError());
  190. goto error;
  191. }
  192. renderer->egl_surface =
  193. eglCreateWindowSurface(renderer->egl_display, renderer->egl_config,
  194. (EGLNativeWindowType) renderer->x_window, NULL);
  195. if (renderer->egl_surface == EGL_NO_SURFACE)
  196. {
  197. COMP_ERROR_MSG("Error in creating egl surface " << eglGetError());
  198. goto error;
  199. }
  200. eglMakeCurrent(renderer->egl_display, renderer->egl_surface,
  201. renderer->egl_surface, renderer->egl_context);
  202. if (eglGetError() != EGL_SUCCESS)
  203. {
  204. COMP_ERROR_MSG("Error in eglMakeCurrent " << eglGetError());
  205. goto error;
  206. }
  207. if (renderer->InitializeShaders() < 0)
  208. {
  209. COMP_ERROR_MSG("Error while initializing shaders");
  210. goto error;
  211. }
  212. renderer->create_texture();
  213. pthread_mutex_lock(&renderer->render_lock);
  214. pthread_cond_broadcast(&renderer->render_cond);
  215. COMP_DEBUG_MSG("Starting render thread");
  216. while (!renderer->isInError() && !renderer->stop_thread)
  217. {
  218. pthread_cond_wait(&renderer->render_cond, &renderer->render_lock);
  219. pthread_mutex_unlock(&renderer->render_lock);
  220. if(renderer->stop_thread)
  221. {
  222. pthread_mutex_lock(&renderer->render_lock);
  223. break;
  224. }
  225. renderer->renderInternal();
  226. COMP_DEBUG_MSG("Rendered fd=" << renderer->render_fd);
  227. pthread_mutex_lock(&renderer->render_lock);
  228. pthread_cond_broadcast(&renderer->render_cond);
  229. }
  230. pthread_mutex_unlock(&renderer->render_lock);
  231. COMP_DEBUG_MSG("Stopped render thread");
  232. finish:
  233. if (renderer->texture_id)
  234. {
  235. glDeleteTextures(1, &renderer->texture_id);
  236. }
  237. if (renderer->egl_display != EGL_NO_DISPLAY)
  238. {
  239. eglMakeCurrent(renderer->egl_display, EGL_NO_SURFACE,
  240. EGL_NO_SURFACE, EGL_NO_CONTEXT);
  241. }
  242. if (renderer->egl_surface != EGL_NO_SURFACE)
  243. {
  244. egl_status = eglDestroySurface(renderer->egl_display,
  245. renderer->egl_surface);
  246. if (egl_status == EGL_FALSE)
  247. {
  248. COMP_ERROR_MSG("EGL surface destruction failed");
  249. }
  250. }
  251. if (renderer->egl_context != EGL_NO_CONTEXT)
  252. {
  253. egl_status = eglDestroyContext(renderer->egl_display,
  254. renderer->egl_context);
  255. if (egl_status == EGL_FALSE)
  256. {
  257. COMP_ERROR_MSG("EGL context destruction failed");
  258. }
  259. }
  260. if (renderer->egl_display != EGL_NO_DISPLAY)
  261. {
  262. eglReleaseThread();
  263. eglTerminate(renderer->egl_display);
  264. }
  265. pthread_mutex_lock(&renderer->render_lock);
  266. pthread_cond_broadcast(&renderer->render_cond);
  267. pthread_mutex_unlock(&renderer->render_lock);
  268. return NULL;
  269. error:
  270. renderer->is_in_error = 1;
  271. goto finish;
  272. }
  273. NvEglRenderer::~NvEglRenderer()
  274. {
  275. stop_thread = true;
  276. pthread_mutex_lock(&render_lock);
  277. pthread_cond_broadcast(&render_cond);
  278. pthread_mutex_unlock(&render_lock);
  279. pthread_join(render_thread, NULL);
  280. pthread_mutex_destroy(&render_lock);
  281. pthread_cond_destroy(&render_cond);
  282. if (fontinfo)
  283. {
  284. XFreeFont(x_display, fontinfo);
  285. }
  286. if (gc)
  287. {
  288. XFreeGC(x_display, gc);
  289. }
  290. if (x_window)
  291. {
  292. XUnmapWindow(x_display, (int32_t) x_window);
  293. XFlush(x_display);
  294. XDestroyWindow(x_display, (int32_t) x_window);
  295. }
  296. if (x_display)
  297. {
  298. XCloseDisplay(x_display);
  299. }
  300. }
  301. int
  302. NvEglRenderer::render(int fd)
  303. {
  304. this->render_fd = fd;
  305. pthread_mutex_lock(&render_lock);
  306. pthread_cond_broadcast(&render_cond);
  307. COMP_DEBUG_MSG("Rendering fd=" << fd);
  308. pthread_cond_wait(&render_cond, &render_lock);
  309. pthread_mutex_unlock(&render_lock);
  310. return 0;
  311. }
  312. int
  313. NvEglRenderer::renderInternal()
  314. {
  315. EGLImageKHR hEglImage;
  316. bool frame_is_late = false;
  317. EGLSyncKHR egl_sync;
  318. int iErr;
  319. NvBufSurface *nvbuf_surf = 0;
  320. NvBufSurfaceFromFd(render_fd, (void**)(&nvbuf_surf));
  321. NvBufSurfaceMapEglImage(nvbuf_surf, 0);
  322. hEglImage = nvbuf_surf->surfaceList->mappedAddr.eglImage;
  323. if (!hEglImage)
  324. {
  325. COMP_ERROR_MSG("Could not get EglImage from fd. Not rendering");
  326. return -1;
  327. }
  328. glActiveTexture(GL_TEXTURE0);
  329. glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
  330. glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, hEglImage);
  331. glDrawArrays(GL_TRIANGLES, 0, 6);
  332. iErr = glGetError();
  333. if (iErr != GL_NO_ERROR)
  334. {
  335. COMP_ERROR_MSG("glDrawArrays arrays failed:" << iErr);
  336. return -1;
  337. }
  338. egl_sync = eglCreateSyncKHR(egl_display, EGL_SYNC_FENCE_KHR, NULL);
  339. if (egl_sync == EGL_NO_SYNC_KHR)
  340. {
  341. COMP_ERROR_MSG("eglCreateSyncKHR() failed");
  342. return -1;
  343. }
  344. if (last_render_time.tv_sec != 0)
  345. {
  346. pthread_mutex_lock(&render_lock);
  347. last_render_time.tv_sec += render_time_sec;
  348. last_render_time.tv_nsec += render_time_nsec;
  349. last_render_time.tv_sec += last_render_time.tv_nsec / 1000000000UL;
  350. last_render_time.tv_nsec %= 1000000000UL;
  351. if (isProfilingEnabled())
  352. {
  353. struct timeval cur_time;
  354. gettimeofday(&cur_time, NULL);
  355. if ((cur_time.tv_sec * 1000000.0 + cur_time.tv_usec) >
  356. (last_render_time.tv_sec * 1000000.0 +
  357. last_render_time.tv_nsec / 1000.0))
  358. {
  359. frame_is_late = true;
  360. }
  361. }
  362. pthread_cond_timedwait(&render_cond, &render_lock,
  363. &last_render_time);
  364. pthread_mutex_unlock(&render_lock);
  365. }
  366. else
  367. {
  368. struct timeval now;
  369. gettimeofday(&now, NULL);
  370. last_render_time.tv_sec = now.tv_sec;
  371. last_render_time.tv_nsec = now.tv_usec * 1000L;
  372. }
  373. eglSwapBuffers(egl_display, egl_surface);
  374. if (eglGetError() != EGL_SUCCESS)
  375. {
  376. COMP_ERROR_MSG("Got Error in eglSwapBuffers " << eglGetError());
  377. return -1;
  378. }
  379. if (eglClientWaitSyncKHR (egl_display, egl_sync,
  380. EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR) == EGL_FALSE)
  381. {
  382. COMP_ERROR_MSG("eglClientWaitSyncKHR failed!");
  383. }
  384. if (eglDestroySyncKHR(egl_display, egl_sync) != EGL_TRUE)
  385. {
  386. COMP_ERROR_MSG("eglDestroySyncKHR failed!");
  387. }
  388. /* Destroy EGLImage */
  389. if (NvBufSurfaceFromFd(render_fd, (void**)(&nvbuf_surf)) != 0)
  390. {
  391. COMP_ERROR_MSG("Unable to extract NvBufSurfaceFromFd");
  392. }
  393. if (NvBufSurfaceUnMapEglImage(nvbuf_surf, 0) != 0)
  394. {
  395. COMP_ERROR_MSG("Unable to unmap EGL Image");
  396. }
  397. if (strlen(overlay_str) != 0)
  398. {
  399. XSetForeground(x_display, gc,
  400. BlackPixel(x_display, DefaultScreen(x_display)));
  401. XSetFont(x_display, gc, fontinfo->fid);
  402. XDrawString(x_display, x_window, gc, overlay_str_x_offset,
  403. overlay_str_y_offset, overlay_str, strlen(overlay_str));
  404. }
  405. profiler.finishProcessing(0, frame_is_late);
  406. return 0;
  407. }
  408. int
  409. NvEglRenderer::setOverlayText(char *str, uint32_t x, uint32_t y)
  410. {
  411. strncpy(overlay_str, str, sizeof(overlay_str));
  412. overlay_str[sizeof(overlay_str) - 1] = '\0';
  413. overlay_str_x_offset = x;
  414. overlay_str_y_offset = y;
  415. return 0;
  416. }
  417. int
  418. NvEglRenderer::setFPS(float fps)
  419. {
  420. uint64_t render_time_usec;
  421. if (fps == 0)
  422. {
  423. COMP_WARN_MSG("Fps 0 is not allowed. Not changing fps");
  424. return -1;
  425. }
  426. pthread_mutex_lock(&render_lock);
  427. this->fps = fps;
  428. render_time_usec = 1000000L / fps;
  429. render_time_sec = render_time_usec / 1000000;
  430. render_time_nsec = (render_time_usec % 1000000) * 1000L;
  431. pthread_mutex_unlock(&render_lock);
  432. return 0;
  433. }
  434. NvEglRenderer *
  435. NvEglRenderer::createEglRenderer(const char *name, uint32_t width,
  436. uint32_t height, uint32_t x_offset,
  437. uint32_t y_offset)
  438. {
  439. NvEglRenderer* renderer = new NvEglRenderer(name, width, height,
  440. x_offset, y_offset);
  441. if (renderer->isInError())
  442. {
  443. delete renderer;
  444. return NULL;
  445. }
  446. return renderer;
  447. }
  448. int
  449. NvEglRenderer::initEgl()
  450. {
  451. eglCreateImageKHR =
  452. (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR");
  453. ERROR_GOTO_FAIL(!eglCreateImageKHR,
  454. "ERROR getting proc addr of eglCreateImageKHR\n");
  455. eglDestroyImageKHR =
  456. (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR");
  457. ERROR_GOTO_FAIL(!eglDestroyImageKHR,
  458. "ERROR getting proc addr of eglDestroyImageKHR\n");
  459. eglCreateSyncKHR =
  460. (PFNEGLCREATESYNCKHRPROC) eglGetProcAddress("eglCreateSyncKHR");
  461. ERROR_GOTO_FAIL(!eglCreateSyncKHR,
  462. "ERROR getting proc addr of eglCreateSyncKHR\n");
  463. eglDestroySyncKHR =
  464. (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress("eglDestroySyncKHR");
  465. ERROR_GOTO_FAIL(!eglDestroySyncKHR,
  466. "ERROR getting proc addr of eglDestroySyncKHR\n");
  467. eglClientWaitSyncKHR =
  468. (PFNEGLCLIENTWAITSYNCKHRPROC) eglGetProcAddress("eglClientWaitSyncKHR");
  469. ERROR_GOTO_FAIL(!eglClientWaitSyncKHR,
  470. "ERROR getting proc addr of eglClientWaitSyncKHR\n");
  471. eglGetSyncAttribKHR =
  472. (PFNEGLGETSYNCATTRIBKHRPROC) eglGetProcAddress("eglGetSyncAttribKHR");
  473. ERROR_GOTO_FAIL(!eglGetSyncAttribKHR,
  474. "ERROR getting proc addr of eglGetSyncAttribKHR\n");
  475. glEGLImageTargetTexture2DOES =
  476. (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
  477. eglGetProcAddress("glEGLImageTargetTexture2DOES");
  478. ERROR_GOTO_FAIL(!glEGLImageTargetTexture2DOES,
  479. "ERROR getting proc addr of glEGLImageTargetTexture2DOES\n");
  480. return 0;
  481. fail:
  482. return -1;
  483. }
  484. void
  485. NvEglRenderer::CreateShader(GLuint program, GLenum type, const char *source,
  486. int size)
  487. {
  488. char log[4096];
  489. int result = GL_FALSE;
  490. GLuint shader = glCreateShader(type);
  491. glShaderSource(shader, 1, &source, &size);
  492. glCompileShader(shader);
  493. glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
  494. if (!result)
  495. {
  496. glGetShaderInfoLog(shader, sizeof(log), NULL, log);
  497. COMP_DEBUG_MSG("Got Fatal Log as " << log);
  498. }
  499. glAttachShader(program, shader);
  500. if (glGetError() != GL_NO_ERROR)
  501. {
  502. COMP_ERROR_MSG("Got gl error as " << glGetError());
  503. }
  504. }
  505. int
  506. NvEglRenderer::InitializeShaders(void)
  507. {
  508. GLuint program;
  509. int result = GL_FALSE;
  510. char log[4096];
  511. uint32_t pos_location = 0;
  512. // pos_x, pos_y, uv_u, uv_v
  513. float vertexTexBuf[24] = {
  514. -1.0f, -1.0f, 0.0f, 1.0f,
  515. -1.0f, 1.0f, 0.0f, 0.0f,
  516. 1.0f, 1.0f, 1.0f, 0.0f,
  517. -1.0f, -1.0f, 0.0f, 1.0f,
  518. 1.0f, 1.0f, 1.0f, 0.0f,
  519. 1.0f, -1.0f, 1.0f, 1.0f,
  520. };
  521. static const char kVertexShader[] = "varying vec2 interp_tc;\n"
  522. "attribute vec4 in_pos;\n"
  523. "void main() { \n"
  524. "interp_tc = in_pos.zw; \n" "gl_Position = vec4(in_pos.xy, 0, 1); \n" "}\n";
  525. static const char kFragmentShader[] =
  526. "#extension GL_OES_EGL_image_external : require\n"
  527. "precision mediump float;\n" "varying vec2 interp_tc; \n"
  528. "uniform samplerExternalOES tex; \n" "void main() {\n"
  529. "gl_FragColor = texture2D(tex, interp_tc);\n" "}\n";
  530. glEnable(GL_SCISSOR_TEST);
  531. program = glCreateProgram();
  532. CreateShader(program, GL_VERTEX_SHADER, kVertexShader,
  533. sizeof(kVertexShader));
  534. CreateShader(program, GL_FRAGMENT_SHADER, kFragmentShader,
  535. sizeof(kFragmentShader));
  536. glLinkProgram(program);
  537. if (glGetError() != GL_NO_ERROR)
  538. {
  539. COMP_ERROR_MSG("Got gl error as " << glGetError());
  540. return -1;
  541. }
  542. glGetProgramiv(program, GL_LINK_STATUS, &result);
  543. if (!result)
  544. {
  545. glGetShaderInfoLog(program, sizeof(log), NULL, log);
  546. COMP_ERROR_MSG("Error while Linking " << log);
  547. return -1;
  548. }
  549. glUseProgram(program);
  550. if (glGetError() != GL_NO_ERROR)
  551. {
  552. COMP_ERROR_MSG("Got gl error as " << glGetError());
  553. return -1;
  554. }
  555. GLuint vbo; // Store vetex and tex coords
  556. glGenBuffers(1, &vbo);
  557. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  558. glBufferData(GL_ARRAY_BUFFER, sizeof(vertexTexBuf), vertexTexBuf, GL_STATIC_DRAW);
  559. glBindBuffer(GL_ARRAY_BUFFER, 0);
  560. pos_location = glGetAttribLocation(program, "in_pos");
  561. glBindBuffer(GL_ARRAY_BUFFER, vbo);
  562. glVertexAttribPointer(pos_location, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
  563. glEnableVertexAttribArray(pos_location);
  564. glActiveTexture(GL_TEXTURE0);
  565. glUniform1i(glGetUniformLocation(program, "texSampler"), 0);
  566. if (glGetError() != GL_NO_ERROR)
  567. {
  568. COMP_ERROR_MSG("Got gl error as " << glGetError());
  569. return -1;
  570. }
  571. COMP_DEBUG_MSG("Shaders intialized");
  572. return 0;
  573. }
  574. int
  575. NvEglRenderer::create_texture()
  576. {
  577. int viewport[4];
  578. glGetIntegerv(GL_VIEWPORT, viewport);
  579. glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
  580. glScissor(viewport[0], viewport[1], viewport[2], viewport[3]);
  581. glGenTextures(1, &texture_id);
  582. glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
  583. return 0;
  584. }