1 //
2 // Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // entry_points_ext.cpp : Implements the EGL extension entry points.
8 
9 #include "libGLESv2/entry_points_egl_ext.h"
10 #include "libGLESv2/global_state.h"
11 
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/Device.h"
15 #include "libANGLE/Surface.h"
16 #include "libANGLE/Stream.h"
17 #include "libANGLE/Thread.h"
18 #include "libANGLE/validationEGL.h"
19 
20 #include "common/debug.h"
21 
22 namespace egl
23 {
24 
25 // EGL_ANGLE_query_surface_pointer
QuerySurfacePointerANGLE(EGLDisplay dpy,EGLSurface surface,EGLint attribute,void ** value)26 EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
27 {
28     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
29           dpy, surface, attribute, value);
30     Thread *thread = GetCurrentThread();
31 
32     Display *display = static_cast<Display*>(dpy);
33     Surface *eglSurface = static_cast<Surface*>(surface);
34 
35     Error error = ValidateSurface(display, eglSurface);
36     if (error.isError())
37     {
38         thread->setError(error);
39         return EGL_FALSE;
40     }
41 
42     if (!display->getExtensions().querySurfacePointer)
43     {
44         thread->setError(NoError());
45         return EGL_FALSE;
46     }
47 
48     if (surface == EGL_NO_SURFACE)
49     {
50         thread->setError(EglBadSurface());
51         return EGL_FALSE;
52     }
53 
54     // validate the attribute parameter
55     switch (attribute)
56     {
57       case EGL_DEVICE_EXT:
58         break;
59       case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
60         if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
61         {
62             thread->setError(EglBadAttribute());
63             return EGL_FALSE;
64         }
65         break;
66       case EGL_DXGI_KEYED_MUTEX_ANGLE:
67         if (!display->getExtensions().keyedMutex)
68         {
69             thread->setError(EglBadAttribute());
70             return EGL_FALSE;
71         }
72         break;
73       default:
74           thread->setError(EglBadAttribute());
75           return EGL_FALSE;
76     }
77 
78     error = eglSurface->querySurfacePointerANGLE(attribute, value);
79     thread->setError(error);
80     return (error.isError() ? EGL_FALSE : EGL_TRUE);
81 }
82 
83 
84 // EGL_NV_post_sub_buffer
PostSubBufferNV(EGLDisplay dpy,EGLSurface surface,EGLint x,EGLint y,EGLint width,EGLint height)85 EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
86 {
87     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
88     Thread *thread = GetCurrentThread();
89 
90     if (x < 0 || y < 0 || width < 0 || height < 0)
91     {
92         thread->setError(EglBadParameter());
93         return EGL_FALSE;
94     }
95 
96     Display *display = static_cast<Display*>(dpy);
97     Surface *eglSurface = static_cast<Surface*>(surface);
98 
99     Error error = ValidateSurface(display, eglSurface);
100     if (error.isError())
101     {
102         thread->setError(error);
103         return EGL_FALSE;
104     }
105 
106     if (display->testDeviceLost())
107     {
108         thread->setError(EglContextLost());
109         return EGL_FALSE;
110     }
111 
112     if (surface == EGL_NO_SURFACE)
113     {
114         thread->setError(EglBadSurface());
115         return EGL_FALSE;
116     }
117 
118     if (!display->getExtensions().postSubBuffer)
119     {
120         // Spec is not clear about how this should be handled.
121         thread->setError(NoError());
122         return EGL_TRUE;
123     }
124 
125     // TODO(jmadill): Validate Surface is bound to the thread.
126     error = eglSurface->postSubBuffer(thread->getContext(), x, y, width, height);
127     if (error.isError())
128     {
129         thread->setError(error);
130         return EGL_FALSE;
131     }
132 
133     thread->setError(NoError());
134     return EGL_TRUE;
135 }
136 
137 // EGL_EXT_platform_base
GetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)138 EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
139 {
140     EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
141           platform, native_display, attrib_list);
142     Thread *thread = GetCurrentThread();
143 
144     Error err = ValidateGetPlatformDisplayEXT(platform, native_display, attrib_list);
145     thread->setError(err);
146     if (err.isError())
147     {
148         return EGL_NO_DISPLAY;
149     }
150 
151     const auto &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
152     if (platform == EGL_PLATFORM_ANGLE_ANGLE)
153     {
154         return Display::GetDisplayFromNativeDisplay(
155             gl::bitCast<EGLNativeDisplayType>(native_display), attribMap);
156     }
157     else if (platform == EGL_PLATFORM_DEVICE_EXT)
158     {
159         Device *eglDevice = reinterpret_cast<Device *>(native_display);
160         return Display::GetDisplayFromDevice(eglDevice, attribMap);
161     }
162     else
163     {
164         UNREACHABLE();
165         return EGL_NO_DISPLAY;
166     }
167 }
168 
169 // EGL_EXT_device_query
QueryDeviceAttribEXT(EGLDeviceEXT device,EGLint attribute,EGLAttrib * value)170 EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
171 {
172     EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
173           device, attribute, value);
174     Thread *thread = GetCurrentThread();
175 
176     Device *dev = static_cast<Device*>(device);
177     if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
178     {
179         thread->setError(EglBadAccess());
180         return EGL_FALSE;
181     }
182 
183     // If the device was created by (and is owned by) a display, and that display doesn't support
184     // device querying, then this call should fail
185     Display *owningDisplay = dev->getOwningDisplay();
186     if (owningDisplay != nullptr && !owningDisplay->getExtensions().deviceQuery)
187     {
188         thread->setError(EglBadAccess() << "Device wasn't created using eglCreateDeviceANGLE, "
189                                            "and the Display that created it doesn't support "
190                                            "device querying");
191         return EGL_FALSE;
192     }
193 
194     Error error(NoError());
195 
196     // validate the attribute parameter
197     switch (attribute)
198     {
199       case EGL_D3D11_DEVICE_ANGLE:
200       case EGL_D3D9_DEVICE_ANGLE:
201         if (!dev->getExtensions().deviceD3D || dev->getType() != attribute)
202         {
203             thread->setError(EglBadAttribute());
204             return EGL_FALSE;
205         }
206         error = dev->getDevice(value);
207         break;
208       default:
209           thread->setError(EglBadAttribute());
210           return EGL_FALSE;
211     }
212 
213     thread->setError(error);
214     return (error.isError() ? EGL_FALSE : EGL_TRUE);
215 }
216 
217 // EGL_EXT_device_query
QueryDeviceStringEXT(EGLDeviceEXT device,EGLint name)218 const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
219 {
220     EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint name = %d)",
221           device, name);
222     Thread *thread = GetCurrentThread();
223 
224     Device *dev = static_cast<Device*>(device);
225     if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
226     {
227         thread->setError(EglBadDevice());
228         return nullptr;
229     }
230 
231     const char *result;
232     switch (name)
233     {
234       case EGL_EXTENSIONS:
235         result = dev->getExtensionString().c_str();
236         break;
237       default:
238           thread->setError(EglBadDevice());
239           return nullptr;
240     }
241 
242     thread->setError(NoError());
243     return result;
244 }
245 
246 // EGL_EXT_device_query
QueryDisplayAttribEXT(EGLDisplay dpy,EGLint attribute,EGLAttrib * value)247 EGLBoolean EGLAPIENTRY QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
248 {
249     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
250           dpy, attribute, value);
251     Thread *thread = GetCurrentThread();
252 
253     Display *display = static_cast<Display*>(dpy);
254 
255     Error error = ValidateDisplay(display);
256     if (error.isError())
257     {
258         thread->setError(error);
259         return EGL_FALSE;
260     }
261 
262     if (!display->getExtensions().deviceQuery)
263     {
264         thread->setError(EglBadAccess());
265         return EGL_FALSE;
266     }
267 
268     // validate the attribute parameter
269     switch (attribute)
270     {
271       case EGL_DEVICE_EXT:
272         *value = reinterpret_cast<EGLAttrib>(display->getDevice());
273         break;
274 
275       default:
276           thread->setError(EglBadAttribute());
277           return EGL_FALSE;
278     }
279 
280     thread->setError(error);
281     return (error.isError() ? EGL_FALSE : EGL_TRUE);
282 }
283 
CreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)284 ANGLE_EXPORT EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy,
285                                                     EGLContext ctx,
286                                                     EGLenum target,
287                                                     EGLClientBuffer buffer,
288                                                     const EGLint *attrib_list)
289 {
290     EVENT(
291         "(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
292         "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
293         dpy, ctx, target, buffer, attrib_list);
294     Thread *thread = GetCurrentThread();
295 
296     Display *display     = static_cast<Display *>(dpy);
297     gl::Context *context = static_cast<gl::Context *>(ctx);
298     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
299 
300     Error error = ValidateCreateImageKHR(display, context, target, buffer, attributes);
301     if (error.isError())
302     {
303         thread->setError(error);
304         return EGL_NO_IMAGE;
305     }
306 
307     Image *image = nullptr;
308     error        = display->createImage(context, target, buffer, attributes, &image);
309     if (error.isError())
310     {
311         thread->setError(error);
312         return EGL_NO_IMAGE;
313     }
314 
315     return static_cast<EGLImage>(image);
316 }
317 
DestroyImageKHR(EGLDisplay dpy,EGLImageKHR image)318 ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
319 {
320     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image);
321     Thread *thread = GetCurrentThread();
322 
323     Display *display = static_cast<Display *>(dpy);
324     Image *img       = static_cast<Image *>(image);
325 
326     Error error = ValidateDestroyImageKHR(display, img);
327     if (error.isError())
328     {
329         thread->setError(error);
330         return EGL_FALSE;
331     }
332 
333     display->destroyImage(img);
334 
335     return EGL_TRUE;
336 }
337 
CreateDeviceANGLE(EGLint device_type,void * native_device,const EGLAttrib * attrib_list)338 ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
339                                                         void *native_device,
340                                                         const EGLAttrib *attrib_list)
341 {
342     EVENT(
343         "(EGLint device_type = %d, void* native_device = 0x%0.8p, const EGLAttrib* attrib_list = "
344         "0x%0.8p)",
345         device_type, native_device, attrib_list);
346     Thread *thread = GetCurrentThread();
347 
348     Error error = ValidateCreateDeviceANGLE(device_type, native_device, attrib_list);
349     if (error.isError())
350     {
351         thread->setError(error);
352         return EGL_NO_DEVICE_EXT;
353     }
354 
355     Device *device = nullptr;
356     error = Device::CreateDevice(native_device, device_type, &device);
357     if (error.isError())
358     {
359         ASSERT(device == nullptr);
360         thread->setError(error);
361         return EGL_NO_DEVICE_EXT;
362     }
363 
364     return device;
365 }
366 
ReleaseDeviceANGLE(EGLDeviceEXT device)367 ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device)
368 {
369     EVENT("(EGLDeviceEXT device = 0x%0.8p)", device);
370     Thread *thread = GetCurrentThread();
371 
372     Device *dev = static_cast<Device *>(device);
373 
374     Error error = ValidateReleaseDeviceANGLE(dev);
375     if (error.isError())
376     {
377         thread->setError(error);
378         return EGL_FALSE;
379     }
380 
381     SafeDelete(dev);
382 
383     return EGL_TRUE;
384 }
385 
386 // EGL_KHR_stream
CreateStreamKHR(EGLDisplay dpy,const EGLint * attrib_list)387 EGLStreamKHR EGLAPIENTRY CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
388 {
389     EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLAttrib* attrib_list = 0x%0.8p)", dpy, attrib_list);
390     Thread *thread = GetCurrentThread();
391 
392     Display *display = static_cast<Display *>(dpy);
393     AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
394 
395     Error error = ValidateCreateStreamKHR(display, attributes);
396     if (error.isError())
397     {
398         thread->setError(error);
399         return EGL_NO_STREAM_KHR;
400     }
401 
402     Stream *stream;
403     error = display->createStream(attributes, &stream);
404     if (error.isError())
405     {
406         thread->setError(error);
407         return EGL_NO_STREAM_KHR;
408     }
409 
410     thread->setError(error);
411     return static_cast<EGLStreamKHR>(stream);
412 }
413 
DestroyStreamKHR(EGLDisplay dpy,EGLStreamKHR stream)414 EGLBoolean EGLAPIENTRY DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
415 {
416     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
417     Thread *thread = GetCurrentThread();
418 
419     Display *display     = static_cast<Display *>(dpy);
420     Stream *streamObject = static_cast<Stream *>(stream);
421 
422     Error error = ValidateDestroyStreamKHR(display, streamObject);
423     if (error.isError())
424     {
425         thread->setError(error);
426         return EGL_FALSE;
427     }
428 
429     display->destroyStream(streamObject);
430     thread->setError(error);
431     return EGL_TRUE;
432 }
433 
StreamAttribKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint value)434 EGLBoolean EGLAPIENTRY StreamAttribKHR(EGLDisplay dpy,
435                                        EGLStreamKHR stream,
436                                        EGLenum attribute,
437                                        EGLint value)
438 {
439     EVENT(
440         "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
441         "EGLint value = 0x%X)",
442         dpy, stream, attribute, value);
443     Thread *thread = GetCurrentThread();
444 
445     Display *display     = static_cast<Display *>(dpy);
446     Stream *streamObject = static_cast<Stream *>(stream);
447 
448     Error error = ValidateStreamAttribKHR(display, streamObject, attribute, value);
449     if (error.isError())
450     {
451         thread->setError(error);
452         return EGL_FALSE;
453     }
454 
455     switch (attribute)
456     {
457         case EGL_CONSUMER_LATENCY_USEC_KHR:
458             streamObject->setConsumerLatency(value);
459             break;
460         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
461             streamObject->setConsumerAcquireTimeout(value);
462             break;
463         default:
464             UNREACHABLE();
465     }
466 
467     thread->setError(error);
468     return EGL_TRUE;
469 }
470 
QueryStreamKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint * value)471 EGLBoolean EGLAPIENTRY QueryStreamKHR(EGLDisplay dpy,
472                                       EGLStreamKHR stream,
473                                       EGLenum attribute,
474                                       EGLint *value)
475 {
476     EVENT(
477         "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
478         "EGLint value = 0x%0.8p)",
479         dpy, stream, attribute, value);
480     Thread *thread = GetCurrentThread();
481 
482     Display *display     = static_cast<Display *>(dpy);
483     Stream *streamObject = static_cast<Stream *>(stream);
484 
485     Error error = ValidateQueryStreamKHR(display, streamObject, attribute, value);
486     if (error.isError())
487     {
488         thread->setError(error);
489         return EGL_FALSE;
490     }
491 
492     switch (attribute)
493     {
494         case EGL_STREAM_STATE_KHR:
495             *value = streamObject->getState();
496             break;
497         case EGL_CONSUMER_LATENCY_USEC_KHR:
498             *value = streamObject->getConsumerLatency();
499             break;
500         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
501             *value = streamObject->getConsumerAcquireTimeout();
502             break;
503         default:
504             UNREACHABLE();
505     }
506 
507     thread->setError(error);
508     return EGL_TRUE;
509 }
510 
QueryStreamu64KHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLuint64KHR * value)511 EGLBoolean EGLAPIENTRY QueryStreamu64KHR(EGLDisplay dpy,
512                                          EGLStreamKHR stream,
513                                          EGLenum attribute,
514                                          EGLuint64KHR *value)
515 {
516     EVENT(
517         "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
518         "EGLuint64KHR value = 0x%0.8p)",
519         dpy, stream, attribute, value);
520     Thread *thread = GetCurrentThread();
521 
522     Display *display     = static_cast<Display *>(dpy);
523     Stream *streamObject = static_cast<Stream *>(stream);
524 
525     Error error = ValidateQueryStreamu64KHR(display, streamObject, attribute, value);
526     if (error.isError())
527     {
528         thread->setError(error);
529         return EGL_FALSE;
530     }
531 
532     switch (attribute)
533     {
534         case EGL_PRODUCER_FRAME_KHR:
535             *value = streamObject->getProducerFrame();
536             break;
537         case EGL_CONSUMER_FRAME_KHR:
538             *value = streamObject->getConsumerFrame();
539             break;
540         default:
541             UNREACHABLE();
542     }
543 
544     thread->setError(error);
545     return EGL_TRUE;
546 }
547 
StreamConsumerGLTextureExternalKHR(EGLDisplay dpy,EGLStreamKHR stream)548 EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream)
549 {
550     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
551     Thread *thread = GetCurrentThread();
552 
553     Display *display     = static_cast<Display *>(dpy);
554     Stream *streamObject = static_cast<Stream *>(stream);
555     gl::Context *context = gl::GetValidGlobalContext();
556 
557     Error error = ValidateStreamConsumerGLTextureExternalKHR(display, context, streamObject);
558     if (error.isError())
559     {
560         thread->setError(error);
561         return EGL_FALSE;
562     }
563 
564     error = streamObject->createConsumerGLTextureExternal(AttributeMap(), context);
565     if (error.isError())
566     {
567         thread->setError(error);
568         return EGL_FALSE;
569     }
570 
571     thread->setError(error);
572     return EGL_TRUE;
573 }
574 
StreamConsumerAcquireKHR(EGLDisplay dpy,EGLStreamKHR stream)575 EGLBoolean EGLAPIENTRY StreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream)
576 {
577     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
578     Thread *thread = GetCurrentThread();
579 
580     Display *display     = static_cast<Display *>(dpy);
581     Stream *streamObject = static_cast<Stream *>(stream);
582     gl::Context *context = gl::GetValidGlobalContext();
583 
584     Error error = ValidateStreamConsumerAcquireKHR(display, context, streamObject);
585     if (error.isError())
586     {
587         thread->setError(error);
588         return EGL_FALSE;
589     }
590 
591     error = streamObject->consumerAcquire(context);
592     if (error.isError())
593     {
594         thread->setError(error);
595         return EGL_FALSE;
596     }
597 
598     thread->setError(error);
599     return EGL_TRUE;
600 }
601 
StreamConsumerReleaseKHR(EGLDisplay dpy,EGLStreamKHR stream)602 EGLBoolean EGLAPIENTRY StreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream)
603 {
604     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
605     Thread *thread = GetCurrentThread();
606 
607     Display *display     = static_cast<Display *>(dpy);
608     Stream *streamObject = static_cast<Stream *>(stream);
609     gl::Context *context = gl::GetValidGlobalContext();
610 
611     Error error = ValidateStreamConsumerReleaseKHR(display, context, streamObject);
612     if (error.isError())
613     {
614         thread->setError(error);
615         return EGL_FALSE;
616     }
617 
618     error = streamObject->consumerRelease(context);
619     if (error.isError())
620     {
621         thread->setError(error);
622         return EGL_FALSE;
623     }
624 
625     thread->setError(error);
626     return EGL_TRUE;
627 }
628 
StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)629 EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
630                                                                 EGLStreamKHR stream,
631                                                                 const EGLAttrib *attrib_list)
632 {
633     EVENT(
634         "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLAttrib attrib_list = 0x%0.8p",
635         dpy, stream, attrib_list);
636     Thread *thread = GetCurrentThread();
637 
638     Display *display        = static_cast<Display *>(dpy);
639     Stream *streamObject    = static_cast<Stream *>(stream);
640     gl::Context *context    = gl::GetValidGlobalContext();
641     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
642 
643     Error error = ValidateStreamConsumerGLTextureExternalAttribsNV(display, context, streamObject,
644                                                                    attributes);
645     if (error.isError())
646     {
647         thread->setError(error);
648         return EGL_FALSE;
649     }
650 
651     error = streamObject->createConsumerGLTextureExternal(attributes, context);
652     if (error.isError())
653     {
654         thread->setError(error);
655         return EGL_FALSE;
656     }
657 
658     thread->setError(error);
659     return EGL_TRUE;
660 }
661 
CreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)662 EGLBoolean EGLAPIENTRY CreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,
663                                                                EGLStreamKHR stream,
664                                                                const EGLAttrib *attrib_list)
665 {
666     EVENT(
667         "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLAttrib attrib_list = 0x%0.8p",
668         dpy, stream, attrib_list);
669     Thread *thread = GetCurrentThread();
670 
671     Display *display        = static_cast<Display *>(dpy);
672     Stream *streamObject    = static_cast<Stream *>(stream);
673     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
674 
675     Error error =
676         ValidateCreateStreamProducerD3DTextureNV12ANGLE(display, streamObject, attributes);
677     if (error.isError())
678     {
679         thread->setError(error);
680         return EGL_FALSE;
681     }
682 
683     error = streamObject->createProducerD3D11TextureNV12(attributes);
684     if (error.isError())
685     {
686         thread->setError(error);
687         return EGL_FALSE;
688     }
689 
690     thread->setError(error);
691     return EGL_TRUE;
692 }
693 
StreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,EGLStreamKHR stream,void * texture,const EGLAttrib * attrib_list)694 EGLBoolean EGLAPIENTRY StreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
695                                                      EGLStreamKHR stream,
696                                                      void *texture,
697                                                      const EGLAttrib *attrib_list)
698 {
699     EVENT(
700         "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, void* texture = 0x%0.8p, "
701         "EGLAttrib attrib_list = 0x%0.8p",
702         dpy, stream, texture, attrib_list);
703     Thread *thread = GetCurrentThread();
704 
705     Display *display        = static_cast<Display *>(dpy);
706     Stream *streamObject    = static_cast<Stream *>(stream);
707     AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
708 
709     Error error = ValidateStreamPostD3DTextureNV12ANGLE(display, streamObject, texture, attributes);
710     if (error.isError())
711     {
712         thread->setError(error);
713         return EGL_FALSE;
714     }
715 
716     error = streamObject->postD3D11NV12Texture(texture, attributes);
717     if (error.isError())
718     {
719         thread->setError(error);
720         return EGL_FALSE;
721     }
722 
723     thread->setError(error);
724     return EGL_TRUE;
725 }
726 
GetSyncValuesCHROMIUM(EGLDisplay dpy,EGLSurface surface,EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)727 EGLBoolean EGLAPIENTRY GetSyncValuesCHROMIUM(EGLDisplay dpy,
728                                              EGLSurface surface,
729                                              EGLuint64KHR *ust,
730                                              EGLuint64KHR *msc,
731                                              EGLuint64KHR *sbc)
732 {
733     EVENT(
734         "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLuint64KHR* ust = 0x%0.8p, "
735         "EGLuint64KHR* msc = 0x%0.8p, EGLuint64KHR* sbc = 0x%0.8p",
736         dpy, surface, ust, msc, sbc);
737     Thread *thread = GetCurrentThread();
738 
739     Display *display    = static_cast<Display *>(dpy);
740     Surface *eglSurface = static_cast<Surface *>(surface);
741 
742     Error error = ValidateGetSyncValuesCHROMIUM(display, eglSurface, ust, msc, sbc);
743     if (error.isError())
744     {
745         thread->setError(error);
746         return EGL_FALSE;
747     }
748 
749     error = eglSurface->getSyncValues(ust, msc, sbc);
750     if (error.isError())
751     {
752         thread->setError(error);
753         return EGL_FALSE;
754     }
755 
756     thread->setError(error);
757     return EGL_TRUE;
758 }
759 
SwapBuffersWithDamageEXT(EGLDisplay dpy,EGLSurface surface,EGLint * rects,EGLint n_rects)760 ANGLE_EXPORT EGLBoolean SwapBuffersWithDamageEXT(EGLDisplay dpy,
761                                                  EGLSurface surface,
762                                                  EGLint *rects,
763                                                  EGLint n_rects)
764 {
765     EVENT(
766         "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint *rects = 0x%0.8p, EGLint "
767         "n_rects = %d)",
768         dpy, surface, rects, n_rects);
769     Thread *thread = GetCurrentThread();
770 
771     Display *display    = static_cast<Display *>(dpy);
772     Surface *eglSurface = static_cast<Surface *>(surface);
773 
774     Error error = ValidateSwapBuffersWithDamageEXT(display, eglSurface, rects, n_rects);
775     if (error.isError())
776     {
777         thread->setError(error);
778         return EGL_FALSE;
779     }
780 
781     error = eglSurface->swapWithDamage(thread->getContext(), rects, n_rects);
782     if (error.isError())
783     {
784         thread->setError(error);
785         return EGL_FALSE;
786     }
787 
788     return EGL_TRUE;
789 }
790 
ProgramCacheGetAttribANGLE(EGLDisplay dpy,EGLenum attrib)791 EGLint EGLAPIENTRY ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib)
792 {
793     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum attrib = 0x%X)", dpy, attrib);
794 
795     Display *display = static_cast<Display *>(dpy);
796     Thread *thread   = GetCurrentThread();
797 
798     ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheGetAttribANGLE(display, attrib), 0);
799 
800     return display->programCacheGetAttrib(attrib);
801 }
802 
ProgramCacheQueryANGLE(EGLDisplay dpy,EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)803 void EGLAPIENTRY ProgramCacheQueryANGLE(EGLDisplay dpy,
804                                         EGLint index,
805                                         void *key,
806                                         EGLint *keysize,
807                                         void *binary,
808                                         EGLint *binarysize)
809 {
810     EVENT(
811         "(EGLDisplay dpy = 0x%0.8p, EGLint index = %d, void *key = 0x%0.8p, EGLint *keysize = "
812         "0x%0.8p, void *binary = 0x%0.8p, EGLint *size = 0x%0.8p)",
813         dpy, index, key, keysize, binary, binarysize);
814 
815     Display *display = static_cast<Display *>(dpy);
816     Thread *thread   = GetCurrentThread();
817 
818     ANGLE_EGL_TRY(thread,
819                   ValidateProgramCacheQueryANGLE(display, index, key, keysize, binary, binarysize));
820 
821     ANGLE_EGL_TRY(thread, display->programCacheQuery(index, key, keysize, binary, binarysize));
822 }
823 
ProgramCachePopulateANGLE(EGLDisplay dpy,const void * key,EGLint keysize,const void * binary,EGLint binarysize)824 void EGLAPIENTRY ProgramCachePopulateANGLE(EGLDisplay dpy,
825                                            const void *key,
826                                            EGLint keysize,
827                                            const void *binary,
828                                            EGLint binarysize)
829 {
830     EVENT(
831         "(EGLDisplay dpy = 0x%0.8p, void *key = 0x%0.8p, EGLint keysize = %d, void *binary = "
832         "0x%0.8p, EGLint *size = 0x%0.8p)",
833         dpy, key, keysize, binary, binarysize);
834 
835     Display *display = static_cast<Display *>(dpy);
836     Thread *thread   = GetCurrentThread();
837 
838     ANGLE_EGL_TRY(thread,
839                   ValidateProgramCachePopulateANGLE(display, key, keysize, binary, binarysize));
840 
841     ANGLE_EGL_TRY(thread, display->programCachePopulate(key, keysize, binary, binarysize));
842 }
843 
ProgramCacheResizeANGLE(EGLDisplay dpy,EGLint limit,EGLenum mode)844 EGLint EGLAPIENTRY ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode)
845 {
846     EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint limit = %d, EGLenum mode = 0x%X)", dpy, limit, mode);
847 
848     Display *display = static_cast<Display *>(dpy);
849     Thread *thread   = GetCurrentThread();
850 
851     ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheResizeANGLE(display, limit, mode), 0);
852 
853     return display->programCacheResize(limit, mode);
854 }
855 
856 }  // namespace egl
857