void egl_context_term(EGL_CONTEXT_T *context)
{
   /* If we're current then there should still be a reference to us */
   /* (if this wasn't the case we should call egl_context_release_surfaces here) */
   vcos_assert(!context->is_current);
   vcos_assert(context->is_destroyed);

   switch (context->type) {
#ifndef NO_OPENVG
   case OPENVG:
      RPC_CALL1(eglIntDestroyVG_impl,
                EGLINTDESTROYVG_ID,
                RPC_UINT(context->servercontext));
      vg_client_state_free((VG_CLIENT_STATE_T *)context->state);
      break;
#endif
   case OPENGL_ES_11:
   case OPENGL_ES_20:
      RPC_CALL1(eglIntDestroyGL_impl,
                EGLINTDESTROYGL_ID,
                RPC_UINT(context->servercontext));
      glxx_client_state_free((GLXX_CLIENT_STATE_T *)context->state);
      break;
   default:
      UNREACHABLE();
   }

   context->state = 0;
}
static void set_egl_image_color_data(EGLImageKHR egl_image, KHRN_IMAGE_WRAP_T *image)
{
   int line_size = (image->stride < 0) ? -image->stride : image->stride;
   int lines = KHDISPATCH_WORKSPACE_SIZE / line_size;
   int offset = 0;
   int height = image->height;

   if (khrn_image_is_tformat(image->format))
      lines &= ~63;

   assert(lines > 0);

   while (height > 0) {
      int batch = _min(lines, height);
      uint32_t len = batch * line_size;

      int adjusted_offset = (image->stride < 0) ? (offset + (batch - 1)) : offset;

      RPC_CALL7_IN_BULK(eglImageSetColorData_impl,
         EGLIMAGESETCOLORDATA_ID,
         RPC_EGLID(egl_image),
         RPC_UINT(image->format),
         RPC_UINT(image->width),
         RPC_INT(batch),
         RPC_UINT(image->stride),
         RPC_INT(offset),
         (const char *)image->storage + adjusted_offset * image->stride,
         len);

      offset += batch;
      height -= batch;
   }
}
void wfc_commit_callback(WFC_ELEMENT_T *element)
{
   WFCNativeStreamType source_stream =
      element->source ? element->source->stream : WFC_INVALID_HANDLE;
   WFCNativeStreamType mask_stream =
      element->mask ? element->mask->stream : WFC_INVALID_HANDLE;

#ifdef RPC_DIRECT
   wfcIntCommitAdd_impl((WFCContext) element->context,
      (WFCElement) element, &element->attributes, source_stream, mask_stream);
#else
   RPC_CALL18(wfcIntCommitAdd_impl,
      WFCINTCOMMITADD_ID,
      RPC_UINT((WFCContext) element->context),
      RPC_UINT((WFCElement) element),
      RPC_INT(element->attributes.dest_rect[0]),
      RPC_INT(element->attributes.dest_rect[1]),
      RPC_INT(element->attributes.dest_rect[2]),
      RPC_INT(element->attributes.dest_rect[3]),
      RPC_FLOAT(element->attributes.src_rect[0]),
      RPC_FLOAT(element->attributes.src_rect[1]),
      RPC_FLOAT(element->attributes.src_rect[2]),
      RPC_FLOAT(element->attributes.src_rect[3]),
      RPC_BOOLEAN(element->attributes.flip),
      RPC_ENUM(element->attributes.rotation),
      RPC_ENUM(element->attributes.scale_filter),
      RPC_BITFIELD(element->attributes.transparency_types),
      RPC_FLOAT(element->attributes.global_alpha),
      RPC_UINT(source_stream),
      RPC_UINT(mask_stream),
      RPC_UINT(0)); // dummy parameter; currently unused.
#endif

} // wfc_commit_callback()
GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
{
   CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();

   if (IS_OPENGLES_11_OR_20(thread)) {
#if EGL_BRCM_global_image
      if ((uintptr_t)image & (1u << 31)) {
         GLuint global_image_id[2];
         if (check_global_image_egl_image(global_image_id, image, thread, false)) {
            RPC_CALL3(glGlobalImageTexture2DOES_impl,
                      thread,
                      GLGLOBALIMAGETEXTURE2DOES_ID,
                      RPC_ENUM(target),
                      RPC_UINT(global_image_id[0]),
                      RPC_UINT(global_image_id[1]));
         } else {
            set_error(GLXX_GET_CLIENT_STATE(thread), GL_INVALID_VALUE);
         }
      } else {
#endif
         vcos_log_trace("[%s] target 0x%x image %d", __FUNCTION__, target, (uint32_t)image);
         RPC_CALL2(glEGLImageTargetTexture2DOES_impl,
                   thread,
                   GLEGLIMAGETARGETTEXTURE2DOES_ID,
                   RPC_ENUM(target),
                   RPC_EGLID(image));
         RPC_FLUSH(thread);
#if EGL_BRCM_global_image
      }
#endif
   }
}
WFC_CONTEXT_T *wfc_context_create
   (WFC_DEVICE_T *device_ptr, WFCContextType context_type,
      uint32_t screen_or_stream_num, WFCErrorCode *error)
{
   WFC_CONTEXT_T *context_ptr =
      khrn_platform_malloc(sizeof(WFC_CONTEXT_T), "WFC_CONTEXT_T");
   const WFC_CONTEXT_ATTRIB_T context_attrib_default = WFC_CONTEXT_ATTRIB_DEFAULT;

   if(context_ptr != NULL)
   {
      uint32_t response = RPC_CALL3_RES(wfcIntCreateContext_impl,
                                   WFCINTCREATECONTEXT_ID,
                                   RPC_UINT((uint32_t) context_ptr),
                                   RPC_ENUM(context_type),
                                   RPC_UINT(screen_or_stream_num));

      uint32_t height_or_err = WFC_CONTEXT_HEIGHT_OR_ERR(response);
      uint32_t width = WFC_CONTEXT_WIDTH(response);

      if(width != 0)
      {
         wfc_link_init_null(&context_ptr->link);

         context_ptr->device = device_ptr;
         wfc_link_init_empty(&context_ptr->sources);
         wfc_link_init_empty(&context_ptr->masks);

         wfc_link_init_empty(&context_ptr->elements_not_in_scene);
         wfc_link_init_empty(&context_ptr->elements_in_scene);
         context_ptr->active = false;

         context_ptr->type = context_type;
         context_ptr->height = height_or_err;
         context_ptr->width = width;
         context_ptr->attributes = context_attrib_default;
      } // if
      else
      {
         khrn_platform_free(context_ptr);

         context_ptr = NULL;

         *error = (WFCErrorCode) response;
      } // else
   } // if
   else
      {*error = WFC_ERROR_OUT_OF_MEMORY;}

   return context_ptr;
} // wfc_context_create()
void egl_sync_term(EGL_SYNC_T *sync)
{
   RPC_CALL1(eglIntDestroySync_impl,
             EGLINTDESTROYSYNC_ID,
             RPC_UINT(sync->serversync));

#ifdef __SYMBIAN32__ 
   RPC_FLUSH(); // now videocore requests semaphore deletion
#else
   khronos_platform_semaphore_destroy(&sync->master); 
#endif
}
static EGL_SYNC_T *egl_sync_create(EGLSyncKHR name, EGLint condition, EGLint threshold)
{
   EGL_SYNC_T *sync = (EGL_SYNC_T *)khrn_platform_malloc(sizeof(EGL_SYNC_T), "EGL_SYNC_T");
   uint64_t pid = khronos_platform_get_process_id();
   uint32_t token;

   if (!sync)
      return 0;

   sync->condition = condition;
   sync->threshold = threshold;

   sync->sem[0] = (int)pid;
   sync->sem[1] = (int)(pid >> 32);
   sync->sem[2] = (int)name;

   if (khronos_platform_semaphore_create(&sync->master, sync->sem, 0) != KHR_SUCCESS) {
      khrn_platform_free(sync);
      return 0;
   }

#ifdef __SYMBIAN32__
   token = (uint32_t)sync->master;
#else
   token = (uint32_t)name;
#endif
   sync->serversync = RPC_UINT_RES(RPC_CALL3_RES(eglIntCreateSync_impl,
                                                 EGLINTCREATESYNC_ID,
                                                 RPC_UINT(condition),
                                                 RPC_INT(threshold),
                                                 RPC_UINT(token)));

   if (sync->serversync)
      return sync;
   else {
      khronos_platform_semaphore_destroy(&sync->master);
      khrn_platform_free(sync);
      return 0;
   }
}
GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image)
{
   CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();

   if (IS_OPENGLES_11(thread)) {
      /* OES_framebuffer_object not supported for GLES1.1 */
      GLXX_CLIENT_STATE_T *state = GLXX_GET_CLIENT_STATE(thread);
      if (state->error == GL_NO_ERROR)
         state->error = GL_INVALID_OPERATION;
   }
   else if (IS_OPENGLES_20(thread)) {
#if EGL_BRCM_global_image
      if ((uintptr_t)image & (1u << 31)) {
         GLuint global_image_id[2];
         if (check_global_image_egl_image(global_image_id, image, thread, true)) {
            RPC_CALL3(glGlobalImageRenderbufferStorageOES_impl_20,
                      thread,
                      GLGLOBALIMAGERENDERBUFFERSTORAGEOES_ID_20,
                      RPC_ENUM(target),
                      RPC_UINT(global_image_id[0]),
                      RPC_UINT(global_image_id[1]));
         } else {
            set_error(GLXX_GET_CLIENT_STATE(thread), GL_INVALID_VALUE);
         }
      } else {
#endif
         RPC_CALL2(glEGLImageTargetRenderbufferStorageOES_impl_20,
                   thread,
                   GLEGLIMAGETARGETRENDERBUFFERSTORAGEOES_ID_20,
                   RPC_ENUM(target),
                   RPC_EGLID(image));
#if EGL_BRCM_global_image
      }
#endif
   }
}
void wfc_context_destroy(WFC_CONTEXT_T *context)
{
   // Remove from parent device's list of contexts.
   wfc_link_detach(&context->link);

   // Destroy all components
   wfc_link_iterate(&context->elements_in_scene, (WFC_LINK_CALLBACK_T) wfc_element_destroy);
   wfc_link_iterate(&context->elements_not_in_scene, (WFC_LINK_CALLBACK_T) wfc_element_destroy);
   wfc_link_iterate(&context->sources, (WFC_LINK_CALLBACK_T) wfc_source_or_mask_destroy_actual);
   wfc_link_iterate(&context->masks, (WFC_LINK_CALLBACK_T) wfc_source_or_mask_destroy_actual);

   RPC_CALL1(wfcIntDestroyContext_impl,
             WFCINTDESTROYCONTEXT_ID,
             RPC_UINT((WFCContext) context));
   RPC_FLUSH();

   khrn_platform_free(context);
} // wfc_context_destroy()